From bbb3b3e6f6e3c0f95873f22e6d0a4aaf350f49d9 Mon Sep 17 00:00:00 2001
From: Petr Mrázek <peterix@gmail.com>
Date: Sun, 15 Jul 2018 14:51:05 +0200
Subject: NOISSUE tabs -> spaces

---
 api/logic/BaseInstaller.cpp                        |   36 +-
 api/logic/BaseInstaller.h                          |   18 +-
 api/logic/BaseInstance.cpp                         |  240 +--
 api/logic/BaseInstance.h                           |  398 ++--
 api/logic/BaseInstanceProvider.h                   |   64 +-
 api/logic/BaseVersion.h                            |   54 +-
 api/logic/BaseVersionList.cpp                      |   86 +-
 api/logic/BaseVersionList.h                        |  134 +-
 api/logic/CMakeLists.txt                           |  748 ++++----
 api/logic/Commandline.cpp                          |  730 ++++----
 api/logic/Commandline.h                            |  324 ++--
 api/logic/DefaultVariable.h                        |   54 +-
 api/logic/Env.cpp                                  |  208 +--
 api/logic/Env.h                                    |   38 +-
 api/logic/Exception.h                              |   36 +-
 api/logic/FileSystem.cpp                           |  634 +++----
 api/logic/FileSystem.h                             |   50 +-
 api/logic/FileSystem_test.cpp                      |  274 +--
 api/logic/Filter.cpp                               |   16 +-
 api/logic/Filter.h                                 |   30 +-
 api/logic/FolderInstanceProvider.cpp               |  726 ++++----
 api/logic/FolderInstanceProvider.h                 |   88 +-
 api/logic/GZip.cpp                                 |  208 +--
 api/logic/GZip.h                                   |    4 +-
 api/logic/GZip_test.cpp                            |   74 +-
 api/logic/InstanceCopyTask.cpp                     |   64 +-
 api/logic/InstanceCopyTask.h                       |   20 +-
 api/logic/InstanceCreationTask.cpp                 |   34 +-
 api/logic/InstanceCreationTask.h                   |   10 +-
 api/logic/InstanceImportTask.cpp                   |  676 +++----
 api/logic/InstanceImportTask.h                     |   52 +-
 api/logic/InstanceList.cpp                         |  460 ++---
 api/logic/InstanceList.h                           |  118 +-
 api/logic/InstanceTask.h                           |   82 +-
 api/logic/Json.cpp                                 |  268 +--
 api/logic/Json.h                                   |  160 +-
 api/logic/LoggedProcess.cpp                        |  214 +--
 api/logic/LoggedProcess.h                          |   70 +-
 api/logic/MMCStrings.cpp                           |  126 +-
 api/logic/MMCStrings.h                             |    2 +-
 api/logic/MMCZip.cpp                               |  398 ++--
 api/logic/MMCZip.h                                 |   68 +-
 api/logic/MessageLevel.cpp                         |   54 +-
 api/logic/MessageLevel.h                           |   20 +-
 api/logic/NullInstance.h                           |  140 +-
 api/logic/ProblemProvider.h                        |   52 +-
 api/logic/QObjectPtr.h                             |  104 +-
 api/logic/RWStorage.h                              |  108 +-
 api/logic/RecursiveFileSystemWatcher.cpp           |  142 +-
 api/logic/RecursiveFileSystemWatcher.h             |   80 +-
 api/logic/SeparatorPrefixTree.h                    |  544 +++---
 api/logic/Usable.h                                 |   58 +-
 api/logic/Version.cpp                              |   94 +-
 api/logic/Version.h                                |  176 +-
 api/logic/Version_test.cpp                         |   96 +-
 api/logic/icons/IIconList.h                        |   24 +-
 api/logic/java/JavaChecker.cpp                     |  250 +--
 api/logic/java/JavaChecker.h                       |   66 +-
 api/logic/java/JavaCheckerJob.cpp                  |   32 +-
 api/logic/java/JavaCheckerJob.h                    |   52 +-
 api/logic/java/JavaInstall.cpp                     |   28 +-
 api/logic/java/JavaInstall.h                       |   48 +-
 api/logic/java/JavaInstallList.cpp                 |  222 +--
 api/logic/java/JavaInstallList.h                   |   58 +-
 api/logic/java/JavaUtils.cpp                       |  514 +++---
 api/logic/java/JavaUtils.h                         |   12 +-
 api/logic/java/JavaVersion.cpp                     |  164 +-
 api/logic/java/JavaVersion.h                       |   68 +-
 api/logic/java/JavaVersion_test.cpp                |  194 +-
 api/logic/java/launch/CheckJava.cpp                |  194 +-
 api/logic/java/launch/CheckJava.h                  |   28 +-
 api/logic/launch/LaunchStep.cpp                    |   12 +-
 api/logic/launch/LaunchStep.h                      |   30 +-
 api/logic/launch/LaunchTask.cpp                    |  324 ++--
 api/logic/launch/LaunchTask.h                      |  134 +-
 api/logic/launch/LogModel.cpp                      |  218 +--
 api/logic/launch/LogModel.h                        |   70 +-
 api/logic/launch/steps/PostLaunchCommand.cpp       |   94 +-
 api/logic/launch/steps/PostLaunchCommand.h         |   26 +-
 api/logic/launch/steps/PreLaunchCommand.cpp        |   96 +-
 api/logic/launch/steps/PreLaunchCommand.h          |   26 +-
 api/logic/launch/steps/TextPrint.cpp               |   18 +-
 api/logic/launch/steps/TextPrint.h                 |   18 +-
 api/logic/launch/steps/Update.cpp                  |   84 +-
 api/logic/launch/steps/Update.h                    |   22 +-
 api/logic/meta/BaseEntity.cpp                      |  200 +--
 api/logic/meta/BaseEntity.h                        |   52 +-
 api/logic/meta/Index.cpp                           |  162 +-
 api/logic/meta/Index.h                             |   48 +-
 api/logic/meta/Index_test.cpp                      |   52 +-
 api/logic/meta/JsonFormat.cpp                      |  258 +--
 api/logic/meta/JsonFormat.h                        |   42 +-
 api/logic/meta/Version.cpp                         |  104 +-
 api/logic/meta/Version.h                           |  136 +-
 api/logic/meta/VersionList.cpp                     |  276 +--
 api/logic/meta/VersionList.h                       |  116 +-
 api/logic/minecraft/AssetsUtils.cpp                |  340 ++--
 api/logic/minecraft/AssetsUtils.h                  |   20 +-
 api/logic/minecraft/Component.cpp                  |  604 +++----
 api/logic/minecraft/Component.h                    |  138 +-
 api/logic/minecraft/ComponentList.cpp              | 1896 ++++++++++----------
 api/logic/minecraft/ComponentList.h                |  138 +-
 api/logic/minecraft/ComponentList_p.h              |   44 +-
 api/logic/minecraft/ComponentUpdateTask.cpp        | 1120 ++++++------
 api/logic/minecraft/ComponentUpdateTask.h          |   30 +-
 api/logic/minecraft/ComponentUpdateTask_p.h        |   32 +-
 api/logic/minecraft/GradleSpecifier.h              |  266 +--
 api/logic/minecraft/GradleSpecifier_test.cpp       |  126 +-
 api/logic/minecraft/LaunchProfile.cpp              |  324 ++--
 api/logic/minecraft/LaunchProfile.h                |  140 +-
 api/logic/minecraft/Library.cpp                    |  538 +++---
 api/logic/minecraft/Library.h                      |  330 ++--
 api/logic/minecraft/Library_test.cpp               |  498 ++---
 api/logic/minecraft/MinecraftInstance.cpp          | 1410 +++++++--------
 api/logic/minecraft/MinecraftInstance.h            |  174 +-
 api/logic/minecraft/MinecraftLoadAndCheck.cpp      |   50 +-
 api/logic/minecraft/MinecraftLoadAndCheck.h        |   20 +-
 api/logic/minecraft/MinecraftUpdate.cpp            |  234 +--
 api/logic/minecraft/MinecraftUpdate.h              |   32 +-
 api/logic/minecraft/Mod.cpp                        |  572 +++---
 api/logic/minecraft/Mod.h                          |  228 +--
 api/logic/minecraft/ModsModel.cpp                  |  548 +++---
 api/logic/minecraft/ModsModel.h                    |  152 +-
 api/logic/minecraft/MojangDownloadInfo.h           |  110 +-
 api/logic/minecraft/MojangVersionFormat.cpp        |  578 +++---
 api/logic/minecraft/MojangVersionFormat.h          |   20 +-
 api/logic/minecraft/MojangVersionFormat_test.cpp   |   76 +-
 api/logic/minecraft/OneSixVersionFormat.cpp        |  650 +++----
 api/logic/minecraft/OneSixVersionFormat.h          |   28 +-
 api/logic/minecraft/OpSys.cpp                      |   36 +-
 api/logic/minecraft/OpSys.h                        |    8 +-
 api/logic/minecraft/ParseUtils.cpp                 |   36 +-
 api/logic/minecraft/ParseUtils_test.cpp            |   56 +-
 api/logic/minecraft/ProfileUtils.cpp               |  264 +--
 api/logic/minecraft/Rule.cpp                       |  106 +-
 api/logic/minecraft/Rule.h                         |   94 +-
 api/logic/minecraft/SimpleModList.cpp              |  552 +++---
 api/logic/minecraft/SimpleModList.h                |  152 +-
 api/logic/minecraft/SimpleModList_test.cpp         |   70 +-
 api/logic/minecraft/SkinUpload.cpp                 |   80 +-
 api/logic/minecraft/SkinUpload.h                   |   32 +-
 api/logic/minecraft/VersionFile.cpp                |   68 +-
 api/logic/minecraft/VersionFile.h                  |  118 +-
 api/logic/minecraft/VersionFilterData.cpp          |  104 +-
 api/logic/minecraft/VersionFilterData.h            |   24 +-
 api/logic/minecraft/World.cpp                      |  560 +++---
 api/logic/minecraft/World.h                        |  102 +-
 api/logic/minecraft/WorldList.cpp                  |  510 +++---
 api/logic/minecraft/WorldList.h                    |  174 +-
 api/logic/minecraft/auth/AuthSession.cpp           |   32 +-
 api/logic/minecraft/auth/AuthSession.h             |   70 +-
 api/logic/minecraft/auth/MojangAccount.cpp         |  442 ++---
 api/logic/minecraft/auth/MojangAccount.h           |  170 +-
 api/logic/minecraft/auth/MojangAccountList.cpp     |  682 +++----
 api/logic/minecraft/auth/MojangAccountList.h       |  304 ++--
 api/logic/minecraft/auth/YggdrasilTask.cpp         |  356 ++--
 api/logic/minecraft/auth/YggdrasilTask.h           |  212 +--
 .../minecraft/auth/flows/AuthenticateTask.cpp      |  312 ++--
 api/logic/minecraft/auth/flows/AuthenticateTask.h  |   14 +-
 api/logic/minecraft/auth/flows/RefreshTask.cpp     |  188 +-
 api/logic/minecraft/auth/flows/RefreshTask.h       |   12 +-
 api/logic/minecraft/auth/flows/ValidateTask.cpp    |   32 +-
 api/logic/minecraft/auth/flows/ValidateTask.h      |   12 +-
 api/logic/minecraft/forge/ForgeXzDownload.cpp      |  640 +++----
 api/logic/minecraft/forge/ForgeXzDownload.h        |   46 +-
 api/logic/minecraft/launch/ClaimAccount.cpp        |   20 +-
 api/logic/minecraft/launch/ClaimAccount.h          |   22 +-
 .../launch/CreateServerResourcePacksFolder.cpp     |   14 +-
 .../launch/CreateServerResourcePacksFolder.h       |   16 +-
 api/logic/minecraft/launch/DirectJavaLaunch.cpp    |  196 +-
 api/logic/minecraft/launch/DirectJavaLaunch.h      |   38 +-
 api/logic/minecraft/launch/ExtractNatives.cpp      |  120 +-
 api/logic/minecraft/launch/ExtractNatives.h        |   18 +-
 api/logic/minecraft/launch/LauncherPartLaunch.cpp  |  292 +--
 api/logic/minecraft/launch/LauncherPartLaunch.h    |   42 +-
 api/logic/minecraft/launch/ModMinecraftJar.cpp     |   90 +-
 api/logic/minecraft/launch/ModMinecraftJar.h       |   20 +-
 api/logic/minecraft/launch/PrintInstanceInfo.h     |   18 +-
 api/logic/minecraft/legacy/LegacyInstance.cpp      |  226 +--
 api/logic/minecraft/legacy/LegacyInstance.h        |  216 +--
 api/logic/minecraft/legacy/LegacyModList.cpp       |  262 +--
 api/logic/minecraft/legacy/LegacyModList.h         |   28 +-
 api/logic/minecraft/legacy/LegacyUpgradeTask.cpp   |  200 +--
 api/logic/minecraft/legacy/LegacyUpgradeTask.h     |   18 +-
 api/logic/minecraft/testdata/lib-native-arch.json  |   88 +-
 api/logic/minecraft/testdata/lib-native.json       |  100 +-
 api/logic/minecraft/testdata/lib-simple.json       |   18 +-
 api/logic/minecraft/update/AssetUpdateTask.cpp     |  124 +-
 api/logic/minecraft/update/AssetUpdateTask.h       |   22 +-
 api/logic/minecraft/update/FMLLibrariesTask.cpp    |  190 +-
 api/logic/minecraft/update/FMLLibrariesTask.h      |   22 +-
 api/logic/minecraft/update/FoldersTask.cpp         |   20 +-
 api/logic/minecraft/update/FoldersTask.h           |   10 +-
 api/logic/minecraft/update/LibrariesTask.cpp       |  124 +-
 api/logic/minecraft/update/LibrariesTask.h         |   18 +-
 api/logic/modplatform/flame/FileResolvingTask.cpp  |  202 +--
 api/logic/modplatform/flame/FileResolvingTask.h    |   24 +-
 api/logic/modplatform/flame/PackManifest.cpp       |   88 +-
 api/logic/modplatform/flame/PackManifest.h         |   64 +-
 api/logic/modplatform/ftb/FtbPackFetchTask.cpp     |  168 +-
 api/logic/modplatform/ftb/FtbPackFetchTask.h       |   28 +-
 api/logic/modplatform/ftb/FtbPackInstallTask.cpp   |  280 +--
 api/logic/modplatform/ftb/FtbPackInstallTask.h     |   46 +-
 api/logic/modplatform/ftb/PackHelpers.h            |   40 +-
 api/logic/net/ByteArraySink.h                      |   88 +-
 api/logic/net/ChecksumValidator.h                  |   76 +-
 api/logic/net/Download.cpp                         |  406 ++---
 api/logic/net/Download.h                           |   60 +-
 api/logic/net/FileSink.cpp                         |  138 +-
 api/logic/net/FileSink.h                           |   24 +-
 api/logic/net/HttpMetaCache.cpp                    |  366 ++--
 api/logic/net/HttpMetaCache.h                      |  152 +-
 api/logic/net/MetaCacheSink.cpp                    |   74 +-
 api/logic/net/MetaCacheSink.h                      |   14 +-
 api/logic/net/Mode.h                               |    4 +-
 api/logic/net/NetAction.h                          |  132 +-
 api/logic/net/NetJob.cpp                           |  312 ++--
 api/logic/net/NetJob.h                             |   96 +-
 api/logic/net/PasteUpload.cpp                      |  128 +-
 api/logic/net/PasteUpload.h                        |   62 +-
 api/logic/net/Sink.h                               |  102 +-
 api/logic/net/URLConstants.cpp                     |    4 +-
 api/logic/net/Validator.h                          |   12 +-
 api/logic/news/NewsChecker.cpp                     |  144 +-
 api/logic/news/NewsChecker.h                       |  116 +-
 api/logic/news/NewsEntry.cpp                       |   72 +-
 api/logic/news/NewsEntry.h                         |   52 +-
 api/logic/notifications/NotificationChecker.cpp    |  158 +-
 api/logic/notifications/NotificationChecker.h      |   74 +-
 api/logic/pathmatcher/FSTreeMatcher.h              |   18 +-
 api/logic/pathmatcher/IPathMatcher.h               |    6 +-
 api/logic/pathmatcher/MultiMatcher.h               |   42 +-
 api/logic/pathmatcher/RegexpMatcher.h              |   66 +-
 api/logic/screenshots/ImgurAlbumCreation.cpp       |  112 +-
 api/logic/screenshots/ImgurAlbumCreation.h         |   46 +-
 api/logic/screenshots/ImgurUpload.cpp              |  160 +-
 api/logic/screenshots/ImgurUpload.h                |   28 +-
 api/logic/screenshots/Screenshot.h                 |   16 +-
 api/logic/settings/INIFile.cpp                     |  180 +-
 api/logic/settings/INIFile.h                       |   16 +-
 api/logic/settings/INIFile_test.cpp                |   96 +-
 api/logic/settings/INISettingsObject.cpp           |  108 +-
 api/logic/settings/INISettingsObject.h             |   48 +-
 api/logic/settings/OverrideSetting.cpp             |   28 +-
 api/logic/settings/OverrideSetting.h               |   18 +-
 api/logic/settings/PassthroughSetting.cpp          |   58 +-
 api/logic/settings/PassthroughSetting.h            |   18 +-
 api/logic/settings/Setting.cpp                     |   32 +-
 api/logic/settings/Setting.h                       |  146 +-
 api/logic/settings/SettingsObject.cpp              |  140 +-
 api/logic/settings/SettingsObject.h                |  312 ++--
 api/logic/status/StatusChecker.cpp                 |  166 +-
 api/logic/status/StatusChecker.h                   |   36 +-
 api/logic/tasks/SequentialTask.cpp                 |   56 +-
 api/logic/tasks/SequentialTask.h                   |   22 +-
 api/logic/tasks/Task.cpp                           |  144 +-
 api/logic/tasks/Task.h                             |   98 +-
 api/logic/tools/BaseExternalTool.cpp               |   10 +-
 api/logic/tools/BaseExternalTool.h                 |   34 +-
 api/logic/tools/BaseProfiler.cpp                   |   24 +-
 api/logic/tools/BaseProfiler.h                     |   20 +-
 api/logic/tools/JProfiler.cpp                      |  114 +-
 api/logic/tools/JProfiler.h                        |   10 +-
 api/logic/tools/JVisualVM.cpp                      |   98 +-
 api/logic/tools/JVisualVM.h                        |   10 +-
 api/logic/tools/MCEditTool.cpp                     |   84 +-
 api/logic/tools/MCEditTool.h                       |   12 +-
 api/logic/translations/TranslationsModel.cpp       |  458 ++---
 api/logic/translations/TranslationsModel.h         |   48 +-
 api/logic/updater/DownloadTask.cpp                 |  182 +-
 api/logic/updater/DownloadTask.h                   |  110 +-
 api/logic/updater/DownloadTask_test.cpp            |  336 ++--
 api/logic/updater/GoUpdate.cpp                     |  382 ++--
 api/logic/updater/GoUpdate.h                       |  138 +-
 api/logic/updater/UpdateChecker.cpp                |  398 ++--
 api/logic/updater/UpdateChecker.h                  |  168 +-
 api/logic/updater/UpdateChecker_test.cpp           |  242 +--
 api/logic/updater/testdata/1.json                  |   82 +-
 api/logic/updater/testdata/2.json                  |   58 +-
 api/logic/updater/testdata/channels.json           |   42 +-
 api/logic/updater/testdata/errorChannels.json      |   42 +-
 api/logic/updater/testdata/garbageChannels.json    |   40 +-
 api/logic/updater/testdata/index.json              |   14 +-
 api/logic/updater/testdata/noChannels.json         |    6 +-
 api/logic/updater/testdata/oneChannel.json         |   18 +-
 285 files changed, 22132 insertions(+), 22132 deletions(-)

(limited to 'api/logic')

diff --git a/api/logic/BaseInstaller.cpp b/api/logic/BaseInstaller.cpp
index 51f66293..e25683a9 100644
--- a/api/logic/BaseInstaller.cpp
+++ b/api/logic/BaseInstaller.cpp
@@ -25,37 +25,37 @@ BaseInstaller::BaseInstaller()
 
 bool BaseInstaller::isApplied(MinecraftInstance *on)
 {
-	return QFile::exists(filename(on->instanceRoot()));
+    return QFile::exists(filename(on->instanceRoot()));
 }
 
 bool BaseInstaller::add(MinecraftInstance *to)
 {
-	if (!patchesDir(to->instanceRoot()).exists())
-	{
-		QDir(to->instanceRoot()).mkdir("patches");
-	}
-
-	if (isApplied(to))
-	{
-		if (!remove(to))
-		{
-			return false;
-		}
-	}
-
-	return true;
+    if (!patchesDir(to->instanceRoot()).exists())
+    {
+        QDir(to->instanceRoot()).mkdir("patches");
+    }
+
+    if (isApplied(to))
+    {
+        if (!remove(to))
+        {
+            return false;
+        }
+    }
+
+    return true;
 }
 
 bool BaseInstaller::remove(MinecraftInstance *from)
 {
-	return QFile::remove(filename(from->instanceRoot()));
+    return QFile::remove(filename(from->instanceRoot()));
 }
 
 QString BaseInstaller::filename(const QString &root) const
 {
-	return patchesDir(root).absoluteFilePath(id() + ".json");
+    return patchesDir(root).absoluteFilePath(id() + ".json");
 }
 QDir BaseInstaller::patchesDir(const QString &root) const
 {
-	return QDir(root + "/patches/");
+    return QDir(root + "/patches/");
 }
diff --git a/api/logic/BaseInstaller.h b/api/logic/BaseInstaller.h
index afe11d55..121d35ef 100644
--- a/api/logic/BaseInstaller.h
+++ b/api/logic/BaseInstaller.h
@@ -30,17 +30,17 @@ typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
 class MULTIMC_LOGIC_EXPORT BaseInstaller
 {
 public:
-	BaseInstaller();
-	virtual ~BaseInstaller(){};
-	bool isApplied(MinecraftInstance *on);
+    BaseInstaller();
+    virtual ~BaseInstaller(){};
+    bool isApplied(MinecraftInstance *on);
 
-	virtual bool add(MinecraftInstance *to);
-	virtual bool remove(MinecraftInstance *from);
+    virtual bool add(MinecraftInstance *to);
+    virtual bool remove(MinecraftInstance *from);
 
-	virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
+    virtual Task *createInstallTask(MinecraftInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
 
 protected:
-	virtual QString id() const = 0;
-	QString filename(const QString &root) const;
-	QDir patchesDir(const QString &root) const;
+    virtual QString id() const = 0;
+    QString filename(const QString &root) const;
+    QDir patchesDir(const QString &root) const;
 };
diff --git a/api/logic/BaseInstance.cpp b/api/logic/BaseInstance.cpp
index 7e652e0d..c81b70c6 100644
--- a/api/logic/BaseInstance.cpp
+++ b/api/logic/BaseInstance.cpp
@@ -27,281 +27,281 @@
 #include "Commandline.h"
 
 BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
-	: QObject()
+    : QObject()
 {
-	m_settings = settings;
-	m_rootDir = rootDir;
+    m_settings = settings;
+    m_rootDir = rootDir;
 
-	m_settings->registerSetting("name", "Unnamed Instance");
-	m_settings->registerSetting("iconKey", "default");
-	m_settings->registerSetting("notes", "");
-	m_settings->registerSetting("lastLaunchTime", 0);
-	m_settings->registerSetting("totalTimePlayed", 0);
+    m_settings->registerSetting("name", "Unnamed Instance");
+    m_settings->registerSetting("iconKey", "default");
+    m_settings->registerSetting("notes", "");
+    m_settings->registerSetting("lastLaunchTime", 0);
+    m_settings->registerSetting("totalTimePlayed", 0);
 
-	// Custom Commands
-	auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
-	m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"), commandSetting);
-	m_settings->registerOverride(globalSettings->getSetting("WrapperCommand"), commandSetting);
-	m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"), commandSetting);
+    // Custom Commands
+    auto commandSetting = m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
+    m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"), commandSetting);
+    m_settings->registerOverride(globalSettings->getSetting("WrapperCommand"), commandSetting);
+    m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"), commandSetting);
 
-	// Console
-	auto consoleSetting = m_settings->registerSetting("OverrideConsole", false);
-	m_settings->registerOverride(globalSettings->getSetting("ShowConsole"), consoleSetting);
-	m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"), consoleSetting);
-	m_settings->registerOverride(globalSettings->getSetting("ShowConsoleOnError"), consoleSetting);
-	m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"), consoleSetting);
+    // Console
+    auto consoleSetting = m_settings->registerSetting("OverrideConsole", false);
+    m_settings->registerOverride(globalSettings->getSetting("ShowConsole"), consoleSetting);
+    m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"), consoleSetting);
+    m_settings->registerOverride(globalSettings->getSetting("ShowConsoleOnError"), consoleSetting);
+    m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"), consoleSetting);
 
-	m_settings->registerPassthrough(globalSettings->getSetting("ConsoleMaxLines"), nullptr);
-	m_settings->registerPassthrough(globalSettings->getSetting("ConsoleOverflowStop"), nullptr);
+    m_settings->registerPassthrough(globalSettings->getSetting("ConsoleMaxLines"), nullptr);
+    m_settings->registerPassthrough(globalSettings->getSetting("ConsoleOverflowStop"), nullptr);
 }
 
 QString BaseInstance::getPreLaunchCommand()
 {
-	return settings()->get("PreLaunchCommand").toString();
+    return settings()->get("PreLaunchCommand").toString();
 }
 
 QString BaseInstance::getWrapperCommand()
 {
-	return settings()->get("WrapperCommand").toString();
+    return settings()->get("WrapperCommand").toString();
 }
 
 QString BaseInstance::getPostExitCommand()
 {
-	return settings()->get("PostExitCommand").toString();
+    return settings()->get("PostExitCommand").toString();
 }
 
 int BaseInstance::getConsoleMaxLines() const
 {
-	auto lineSetting = settings()->getSetting("ConsoleMaxLines");
-	bool conversionOk = false;
-	int maxLines = lineSetting->get().toInt(&conversionOk);
-	if(!conversionOk)
-	{
-		maxLines = lineSetting->defValue().toInt();
-		qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
-	}
-	return maxLines;
+    auto lineSetting = settings()->getSetting("ConsoleMaxLines");
+    bool conversionOk = false;
+    int maxLines = lineSetting->get().toInt(&conversionOk);
+    if(!conversionOk)
+    {
+        maxLines = lineSetting->defValue().toInt();
+        qWarning() << "ConsoleMaxLines has nonsensical value, defaulting to" << maxLines;
+    }
+    return maxLines;
 }
 
 bool BaseInstance::shouldStopOnConsoleOverflow() const
 {
-	return settings()->get("ConsoleOverflowStop").toBool();
+    return settings()->get("ConsoleOverflowStop").toBool();
 }
 
 void BaseInstance::iconUpdated(QString key)
 {
-	if(iconKey() == key)
-	{
-		emit propertiesChanged(this);
-	}
+    if(iconKey() == key)
+    {
+        emit propertiesChanged(this);
+    }
 }
 
 void BaseInstance::invalidate()
 {
-	changeStatus(Status::Gone);
-	qDebug() << "Instance" << id() << "has been invalidated.";
+    changeStatus(Status::Gone);
+    qDebug() << "Instance" << id() << "has been invalidated.";
 }
 
 void BaseInstance::nuke()
 {
-	changeStatus(Status::Gone);
-	qDebug() << "Instance" << id() << "has been deleted by MultiMC.";
-	FS::deletePath(instanceRoot());
+    changeStatus(Status::Gone);
+    qDebug() << "Instance" << id() << "has been deleted by MultiMC.";
+    FS::deletePath(instanceRoot());
 }
 
 void BaseInstance::changeStatus(BaseInstance::Status newStatus)
 {
-	Status status = currentStatus();
-	if(status != newStatus)
-	{
-		m_status = newStatus;
-		emit statusChanged(status, newStatus);
-	}
+    Status status = currentStatus();
+    if(status != newStatus)
+    {
+        m_status = newStatus;
+        emit statusChanged(status, newStatus);
+    }
 }
 
 BaseInstance::Status BaseInstance::currentStatus() const
 {
-	return m_status;
+    return m_status;
 }
 
 QString BaseInstance::id() const
 {
-	return QFileInfo(instanceRoot()).fileName();
+    return QFileInfo(instanceRoot()).fileName();
 }
 
 bool BaseInstance::isRunning() const
 {
-	return m_isRunning;
+    return m_isRunning;
 }
 
 void BaseInstance::setRunning(bool running)
 {
-	if(running == m_isRunning)
-		return;
+    if(running == m_isRunning)
+        return;
 
-	m_isRunning = running;
+    m_isRunning = running;
 
-	if(running)
-	{
-		m_timeStarted = QDateTime::currentDateTime();
-	}
-	else
-	{
-		qint64 current = settings()->get("totalTimePlayed").toLongLong();
-		QDateTime timeEnded = QDateTime::currentDateTime();
-		settings()->set("totalTimePlayed", current + m_timeStarted.secsTo(timeEnded));
-		emit propertiesChanged(this);
-	}
+    if(running)
+    {
+        m_timeStarted = QDateTime::currentDateTime();
+    }
+    else
+    {
+        qint64 current = settings()->get("totalTimePlayed").toLongLong();
+        QDateTime timeEnded = QDateTime::currentDateTime();
+        settings()->set("totalTimePlayed", current + m_timeStarted.secsTo(timeEnded));
+        emit propertiesChanged(this);
+    }
 
-	emit runningStatusChanged(running);
+    emit runningStatusChanged(running);
 }
 
 int64_t BaseInstance::totalTimePlayed() const
 {
-	qint64 current = settings()->get("totalTimePlayed").toLongLong();
-	if(m_isRunning)
-	{
-		QDateTime timeNow = QDateTime::currentDateTime();
-		return current + m_timeStarted.secsTo(timeNow);
-	}
-	return current;
+    qint64 current = settings()->get("totalTimePlayed").toLongLong();
+    if(m_isRunning)
+    {
+        QDateTime timeNow = QDateTime::currentDateTime();
+        return current + m_timeStarted.secsTo(timeNow);
+    }
+    return current;
 }
 
 void BaseInstance::resetTimePlayed()
 {
-	settings()->reset("totalTimePlayed");
+    settings()->reset("totalTimePlayed");
 }
 
 QString BaseInstance::instanceType() const
 {
-	return m_settings->get("InstanceType").toString();
+    return m_settings->get("InstanceType").toString();
 }
 
 QString BaseInstance::instanceRoot() const
 {
-	return m_rootDir;
+    return m_rootDir;
 }
 
 InstancePtr BaseInstance::getSharedPtr()
 {
-	return shared_from_this();
+    return shared_from_this();
 }
 
 SettingsObjectPtr BaseInstance::settings() const
 {
-	return m_settings;
+    return m_settings;
 }
 
 bool BaseInstance::canLaunch() const
 {
-	return (!hasVersionBroken() && !isRunning());
+    return (!hasVersionBroken() && !isRunning());
 }
 
 bool BaseInstance::reloadSettings()
 {
-	return m_settings->reload();
+    return m_settings->reload();
 }
 
 qint64 BaseInstance::lastLaunch() const
 {
-	return m_settings->get("lastLaunchTime").value<qint64>();
+    return m_settings->get("lastLaunchTime").value<qint64>();
 }
 
 void BaseInstance::setLastLaunch(qint64 val)
 {
-	//FIXME: if no change, do not set. setting involves saving a file.
-	m_settings->set("lastLaunchTime", val);
-	emit propertiesChanged(this);
+    //FIXME: if no change, do not set. setting involves saving a file.
+    m_settings->set("lastLaunchTime", val);
+    emit propertiesChanged(this);
 }
 
 void BaseInstance::setGroupInitial(QString val)
 {
-	if(m_group == val)
-	{
-		return;
-	}
-	m_group = val;
-	emit propertiesChanged(this);
+    if(m_group == val)
+    {
+        return;
+    }
+    m_group = val;
+    emit propertiesChanged(this);
 }
 
 void BaseInstance::setGroupPost(QString val)
 {
-	if(m_group == val)
-	{
-		return;
-	}
-	setGroupInitial(val);
-	emit groupChanged();
+    if(m_group == val)
+    {
+        return;
+    }
+    setGroupInitial(val);
+    emit groupChanged();
 }
 
 QString BaseInstance::group() const
 {
-	return m_group;
+    return m_group;
 }
 
 void BaseInstance::setNotes(QString val)
 {
-	//FIXME: if no change, do not set. setting involves saving a file.
-	m_settings->set("notes", val);
+    //FIXME: if no change, do not set. setting involves saving a file.
+    m_settings->set("notes", val);
 }
 
 QString BaseInstance::notes() const
 {
-	return m_settings->get("notes").toString();
+    return m_settings->get("notes").toString();
 }
 
 void BaseInstance::setIconKey(QString val)
 {
-	//FIXME: if no change, do not set. setting involves saving a file.
-	m_settings->set("iconKey", val);
-	emit propertiesChanged(this);
+    //FIXME: if no change, do not set. setting involves saving a file.
+    m_settings->set("iconKey", val);
+    emit propertiesChanged(this);
 }
 
 QString BaseInstance::iconKey() const
 {
-	return m_settings->get("iconKey").toString();
+    return m_settings->get("iconKey").toString();
 }
 
 void BaseInstance::setName(QString val)
 {
-	//FIXME: if no change, do not set. setting involves saving a file.
-	m_settings->set("name", val);
-	emit propertiesChanged(this);
+    //FIXME: if no change, do not set. setting involves saving a file.
+    m_settings->set("name", val);
+    emit propertiesChanged(this);
 }
 
 QString BaseInstance::name() const
 {
-	return m_settings->get("name").toString();
+    return m_settings->get("name").toString();
 }
 
 QString BaseInstance::windowTitle() const
 {
-	return "MultiMC: " + name();
+    return "MultiMC: " + name();
 }
 
 // FIXME: why is this here? move it to MinecraftInstance!!!
 QStringList BaseInstance::extraArguments() const
 {
-	return Commandline::splitArgs(settings()->get("JvmArgs").toString());
+    return Commandline::splitArgs(settings()->get("JvmArgs").toString());
 }
 
 std::shared_ptr<LaunchTask> BaseInstance::getLaunchTask()
 {
-	return m_launchProcess;
+    return m_launchProcess;
 }
 
 void BaseInstance::setProvider(BaseInstanceProvider* provider)
 {
-	// only once.
-	assert(!m_provider);
-	if(m_provider)
-	{
-		qWarning() << "Provider set more than once for instance" << id();
-	}
-	m_provider = provider;
+    // only once.
+    assert(!m_provider);
+    if(m_provider)
+    {
+        qWarning() << "Provider set more than once for instance" << id();
+    }
+    m_provider = provider;
 }
 
 BaseInstanceProvider* BaseInstance::provider() const
 {
-	return m_provider;
+    return m_provider;
 }
diff --git a/api/logic/BaseInstance.h b/api/logic/BaseInstance.h
index 282bfb70..f3b15a20 100644
--- a/api/logic/BaseInstance.h
+++ b/api/logic/BaseInstance.h
@@ -53,229 +53,229 @@ typedef std::shared_ptr<BaseInstance> InstancePtr;
  */
 class MULTIMC_LOGIC_EXPORT BaseInstance : public QObject, public std::enable_shared_from_this<BaseInstance>
 {
-	Q_OBJECT
+    Q_OBJECT
 protected:
-	/// no-touchy!
-	BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
+    /// no-touchy!
+    BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
 
 public: /* types */
-	enum class Status
-	{
-		Present,
-		Gone // either nuked or invalidated
-	};
+    enum class Status
+    {
+        Present,
+        Gone // either nuked or invalidated
+    };
 
 public:
-	/// virtual destructor to make sure the destruction is COMPLETE
-	virtual ~BaseInstance() {};
+    /// virtual destructor to make sure the destruction is COMPLETE
+    virtual ~BaseInstance() {};
 
-	virtual void init() = 0;
-	virtual void saveNow() = 0;
+    virtual void init() = 0;
+    virtual void saveNow() = 0;
 
-	/// nuke thoroughly - deletes the instance contents, notifies the list/model which is
-	/// responsible of cleaning up the husk
-	void nuke();
+    /// nuke thoroughly - deletes the instance contents, notifies the list/model which is
+    /// responsible of cleaning up the husk
+    void nuke();
 
-	/***
-	 * the instance has been invalidated - it is no longer tracked by MultiMC for some reason,
-	 * but it has not necessarily been deleted.
-	 *
-	 * Happens when the instance folder changes to some other location, or the instance is removed by external means.
-	 */
-	void invalidate();
+    /***
+     * the instance has been invalidated - it is no longer tracked by MultiMC for some reason,
+     * but it has not necessarily been deleted.
+     *
+     * Happens when the instance folder changes to some other location, or the instance is removed by external means.
+     */
+    void invalidate();
 
-	/// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
-	/// be unique.
-	virtual QString id() const;
+    /// The instance's ID. The ID SHALL be determined by MMC internally. The ID IS guaranteed to
+    /// be unique.
+    virtual QString id() const;
 
-	void setRunning(bool running);
-	bool isRunning() const;
-	int64_t totalTimePlayed() const;
-	void resetTimePlayed();
+    void setRunning(bool running);
+    bool isRunning() const;
+    int64_t totalTimePlayed() const;
+    void resetTimePlayed();
 
-	void setProvider(BaseInstanceProvider * provider);
-	BaseInstanceProvider * provider() const;
-
-	/// get the type of this instance
-	QString instanceType() const;
-
-	/// Path to the instance's root directory.
-	QString instanceRoot() const;
-
-	QString name() const;
-	void setName(QString val);
-
-	/// Value used for instance window titles
-	QString windowTitle() const;
-
-	QString iconKey() const;
-	void setIconKey(QString val);
-
-	QString notes() const;
-	void setNotes(QString val);
-
-	QString group() const;
-	void setGroupInitial(QString val);
-	void setGroupPost(QString val);
-
-	QString getPreLaunchCommand();
-	QString getPostExitCommand();
-	QString getWrapperCommand();
-
-	/// guess log level from a line of game log
-	virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level)
-	{
-		return level;
-	};
-
-	virtual QStringList extraArguments() const;
-
-	/// Traits. Normally inside the version, depends on instance implementation.
-	virtual QSet <QString> traits() const = 0;
-
-	/**
-	 * Gets the time that the instance was last launched.
-	 * Stored in milliseconds since epoch.
-	 */
-	qint64 lastLaunch() const;
-	/// Sets the last launched time to 'val' milliseconds since epoch
-	void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch());
-
-	InstancePtr getSharedPtr();
-
-	/*!
-	 * \brief Gets this instance's settings object.
-	 * This settings object stores instance-specific settings.
-	 * \return A pointer to this instance's settings object.
-	 */
-	virtual SettingsObjectPtr settings() const;
-
-	/// returns a valid update task
-	virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0;
-
-	/// returns a valid launcher (task container)
-	virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
-
-	/// returns the current launch task (if any)
-	std::shared_ptr<LaunchTask> getLaunchTask();
-
-	/*!
-	 * Create envrironment variables for running the instance
-	 */
-	virtual QProcessEnvironment createEnvironment() = 0;
-
-	/*!
-	 * Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
-	 */
-	virtual IPathMatcher::Ptr getLogFileMatcher() = 0;
-
-	/*!
-	 * Returns the root folder to use for looking up log files
-	 */
-	virtual QString getLogFileRoot() = 0;
-
-	virtual QString getStatusbarDescription() = 0;
-
-	/// FIXME: this really should be elsewhere...
-	virtual QString instanceConfigFolder() const = 0;
-
-	/// get variables this instance exports
-	virtual QMap<QString, QString> getVariables() const = 0;
-
-	virtual QString typeName() const = 0;
-
-	bool hasVersionBroken() const
-	{
-		return m_hasBrokenVersion;
-	}
-	void setVersionBroken(bool value)
-	{
-		if(m_hasBrokenVersion != value)
-		{
-			m_hasBrokenVersion = value;
-			emit propertiesChanged(this);
-		}
-	}
-
-	bool hasUpdateAvailable() const
-	{
-		return m_hasUpdate;
-	}
-	void setUpdateAvailable(bool value)
-	{
-		if(m_hasUpdate != value)
-		{
-			m_hasUpdate = value;
-			emit propertiesChanged(this);
-		}
-	}
-
-	bool hasCrashed() const
-	{
-		return m_crashed;
-	}
-	void setCrashed(bool value)
-	{
-		if(m_crashed != value)
-		{
-			m_crashed = value;
-			emit propertiesChanged(this);
-		}
-	}
-
-	virtual bool canLaunch() const;
-	virtual bool canEdit() const = 0;
-	virtual bool canExport() const = 0;
-
-	bool reloadSettings();
-
-	/**
-	 * 'print' a verbose desription of the instance into a QStringList
-	 */
-	virtual QStringList verboseDescription(AuthSessionPtr session) = 0;
-
-	Status currentStatus() const;
-
-	int getConsoleMaxLines() const;
-	bool shouldStopOnConsoleOverflow() const;
+    void setProvider(BaseInstanceProvider * provider);
+    BaseInstanceProvider * provider() const;
+
+    /// get the type of this instance
+    QString instanceType() const;
+
+    /// Path to the instance's root directory.
+    QString instanceRoot() const;
+
+    QString name() const;
+    void setName(QString val);
+
+    /// Value used for instance window titles
+    QString windowTitle() const;
+
+    QString iconKey() const;
+    void setIconKey(QString val);
+
+    QString notes() const;
+    void setNotes(QString val);
+
+    QString group() const;
+    void setGroupInitial(QString val);
+    void setGroupPost(QString val);
+
+    QString getPreLaunchCommand();
+    QString getPostExitCommand();
+    QString getWrapperCommand();
+
+    /// guess log level from a line of game log
+    virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level)
+    {
+        return level;
+    };
+
+    virtual QStringList extraArguments() const;
+
+    /// Traits. Normally inside the version, depends on instance implementation.
+    virtual QSet <QString> traits() const = 0;
+
+    /**
+     * Gets the time that the instance was last launched.
+     * Stored in milliseconds since epoch.
+     */
+    qint64 lastLaunch() const;
+    /// Sets the last launched time to 'val' milliseconds since epoch
+    void setLastLaunch(qint64 val = QDateTime::currentMSecsSinceEpoch());
+
+    InstancePtr getSharedPtr();
+
+    /*!
+     * \brief Gets this instance's settings object.
+     * This settings object stores instance-specific settings.
+     * \return A pointer to this instance's settings object.
+     */
+    virtual SettingsObjectPtr settings() const;
+
+    /// returns a valid update task
+    virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) = 0;
+
+    /// returns a valid launcher (task container)
+    virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) = 0;
+
+    /// returns the current launch task (if any)
+    std::shared_ptr<LaunchTask> getLaunchTask();
+
+    /*!
+     * Create envrironment variables for running the instance
+     */
+    virtual QProcessEnvironment createEnvironment() = 0;
+
+    /*!
+     * Returns a matcher that can maps relative paths within the instance to whether they are 'log files'
+     */
+    virtual IPathMatcher::Ptr getLogFileMatcher() = 0;
+
+    /*!
+     * Returns the root folder to use for looking up log files
+     */
+    virtual QString getLogFileRoot() = 0;
+
+    virtual QString getStatusbarDescription() = 0;
+
+    /// FIXME: this really should be elsewhere...
+    virtual QString instanceConfigFolder() const = 0;
+
+    /// get variables this instance exports
+    virtual QMap<QString, QString> getVariables() const = 0;
+
+    virtual QString typeName() const = 0;
+
+    bool hasVersionBroken() const
+    {
+        return m_hasBrokenVersion;
+    }
+    void setVersionBroken(bool value)
+    {
+        if(m_hasBrokenVersion != value)
+        {
+            m_hasBrokenVersion = value;
+            emit propertiesChanged(this);
+        }
+    }
+
+    bool hasUpdateAvailable() const
+    {
+        return m_hasUpdate;
+    }
+    void setUpdateAvailable(bool value)
+    {
+        if(m_hasUpdate != value)
+        {
+            m_hasUpdate = value;
+            emit propertiesChanged(this);
+        }
+    }
+
+    bool hasCrashed() const
+    {
+        return m_crashed;
+    }
+    void setCrashed(bool value)
+    {
+        if(m_crashed != value)
+        {
+            m_crashed = value;
+            emit propertiesChanged(this);
+        }
+    }
+
+    virtual bool canLaunch() const;
+    virtual bool canEdit() const = 0;
+    virtual bool canExport() const = 0;
+
+    bool reloadSettings();
+
+    /**
+     * 'print' a verbose desription of the instance into a QStringList
+     */
+    virtual QStringList verboseDescription(AuthSessionPtr session) = 0;
+
+    Status currentStatus() const;
+
+    int getConsoleMaxLines() const;
+    bool shouldStopOnConsoleOverflow() const;
 
 protected:
-	void changeStatus(Status newStatus);
+    void changeStatus(Status newStatus);
 
 signals:
-	/*!
-	 * \brief Signal emitted when properties relevant to the instance view change
-	 */
-	void propertiesChanged(BaseInstance *inst);
-	/*!
-	 * \brief Signal emitted when groups are affected in any way
-	 */
-	void groupChanged();
+    /*!
+     * \brief Signal emitted when properties relevant to the instance view change
+     */
+    void propertiesChanged(BaseInstance *inst);
+    /*!
+     * \brief Signal emitted when groups are affected in any way
+     */
+    void groupChanged();
 
-	void launchTaskChanged(std::shared_ptr<LaunchTask>);
+    void launchTaskChanged(std::shared_ptr<LaunchTask>);
 
-	void runningStatusChanged(bool running);
+    void runningStatusChanged(bool running);
 
-	void statusChanged(Status from, Status to);
+    void statusChanged(Status from, Status to);
 
 protected slots:
-	void iconUpdated(QString key);
+    void iconUpdated(QString key);
 
 protected: /* data */
-	QString m_rootDir;
-	QString m_group;
-	SettingsObjectPtr m_settings;
-	// InstanceFlags m_flags;
-	bool m_isRunning = false;
-	std::shared_ptr<LaunchTask> m_launchProcess;
-	QDateTime m_timeStarted;
-	BaseInstanceProvider * m_provider = nullptr;
+    QString m_rootDir;
+    QString m_group;
+    SettingsObjectPtr m_settings;
+    // InstanceFlags m_flags;
+    bool m_isRunning = false;
+    std::shared_ptr<LaunchTask> m_launchProcess;
+    QDateTime m_timeStarted;
+    BaseInstanceProvider * m_provider = nullptr;
 
 private: /* data */
-	Status m_status = Status::Present;
-	bool m_crashed = false;
-	bool m_hasUpdate = false;
-	bool m_hasBrokenVersion = false;
+    Status m_status = Status::Present;
+    bool m_crashed = false;
+    bool m_hasUpdate = false;
+    bool m_hasBrokenVersion = false;
 };
 
 Q_DECLARE_METATYPE(std::shared_ptr<BaseInstance>)
diff --git a/api/logic/BaseInstanceProvider.h b/api/logic/BaseInstanceProvider.h
index 34489c5d..1eee0e4f 100644
--- a/api/logic/BaseInstanceProvider.h
+++ b/api/logic/BaseInstanceProvider.h
@@ -12,46 +12,46 @@ using InstanceLocator = std::pair<InstancePtr, int>;
 
 enum class InstCreateError
 {
-	NoCreateError = 0,
-	NoSuchVersion,
-	UnknownCreateError,
-	InstExists,
-	CantCreateDir
+    NoCreateError = 0,
+    NoSuchVersion,
+    UnknownCreateError,
+    InstExists,
+    CantCreateDir
 };
 
 class MULTIMC_LOGIC_EXPORT BaseInstanceProvider : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	BaseInstanceProvider(SettingsObjectPtr settings) : m_globalSettings(settings)
-	{
-		// nil
-	}
+    BaseInstanceProvider(SettingsObjectPtr settings) : m_globalSettings(settings)
+    {
+        // nil
+    }
 public:
-	virtual QList<InstanceId> discoverInstances() = 0;
-	virtual InstancePtr loadInstance(const InstanceId &id) = 0;
-	virtual void loadGroupList() = 0;
-	virtual void saveGroupList() = 0;
-
-	virtual QString getStagedInstancePath()
-	{
-		return QString();
-	}
-	virtual bool commitStagedInstance(const QString & path, const QString& instanceName, const QString & groupName)
-	{
-		return false;
-	}
-	virtual bool destroyStagingPath(const QString & path)
-	{
-		return true;
-	}
+    virtual QList<InstanceId> discoverInstances() = 0;
+    virtual InstancePtr loadInstance(const InstanceId &id) = 0;
+    virtual void loadGroupList() = 0;
+    virtual void saveGroupList() = 0;
+
+    virtual QString getStagedInstancePath()
+    {
+        return QString();
+    }
+    virtual bool commitStagedInstance(const QString & path, const QString& instanceName, const QString & groupName)
+    {
+        return false;
+    }
+    virtual bool destroyStagingPath(const QString & path)
+    {
+        return true;
+    }
 
 signals:
-	// Emit this when the list of provided instances changed
-	void instancesChanged();
-	// Emit when the set of groups your provider supplies changes.
-	void groupsChanged(QSet<QString> groups);
+    // Emit this when the list of provided instances changed
+    void instancesChanged();
+    // Emit when the set of groups your provider supplies changes.
+    void groupsChanged(QSet<QString> groups);
 
 protected:
-	SettingsObjectPtr m_globalSettings;
+    SettingsObjectPtr m_globalSettings;
 };
diff --git a/api/logic/BaseVersion.h b/api/logic/BaseVersion.h
index e49d6277..4f06c3bc 100644
--- a/api/logic/BaseVersion.h
+++ b/api/logic/BaseVersion.h
@@ -25,33 +25,33 @@
 class BaseVersion
 {
 public:
-	virtual ~BaseVersion() {}
-	/*!
-	 * A string used to identify this version in config files.
-	 * This should be unique within the version list or shenanigans will occur.
-	 */
-	virtual QString descriptor() = 0;
-
-	/*!
-	 * The name of this version as it is displayed to the user.
-	 * For example: "1.5.1"
-	 */
-	virtual QString name() = 0;
-
-	/*!
-	 * This should return a string that describes
-	 * the kind of version this is (Stable, Beta, Snapshot, whatever)
-	 */
-	virtual QString typeString() const = 0;
-
-	virtual bool operator<(BaseVersion &a)
-	{
-		return name() < a.name();
-	};
-	virtual bool operator>(BaseVersion &a)
-	{
-		return name() > a.name();
-	};
+    virtual ~BaseVersion() {}
+    /*!
+     * A string used to identify this version in config files.
+     * This should be unique within the version list or shenanigans will occur.
+     */
+    virtual QString descriptor() = 0;
+
+    /*!
+     * The name of this version as it is displayed to the user.
+     * For example: "1.5.1"
+     */
+    virtual QString name() = 0;
+
+    /*!
+     * This should return a string that describes
+     * the kind of version this is (Stable, Beta, Snapshot, whatever)
+     */
+    virtual QString typeString() const = 0;
+
+    virtual bool operator<(BaseVersion &a)
+    {
+        return name() < a.name();
+    };
+    virtual bool operator>(BaseVersion &a)
+    {
+        return name() > a.name();
+    };
 };
 
 typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
diff --git a/api/logic/BaseVersionList.cpp b/api/logic/BaseVersionList.cpp
index 31a635d7..b1f73529 100644
--- a/api/logic/BaseVersionList.cpp
+++ b/api/logic/BaseVersionList.cpp
@@ -22,78 +22,78 @@ BaseVersionList::BaseVersionList(QObject *parent) : QAbstractListModel(parent)
 
 BaseVersionPtr BaseVersionList::findVersion(const QString &descriptor)
 {
-	for (int i = 0; i < count(); i++)
-	{
-		if (at(i)->descriptor() == descriptor)
-			return at(i);
-	}
-	return BaseVersionPtr();
+    for (int i = 0; i < count(); i++)
+    {
+        if (at(i)->descriptor() == descriptor)
+            return at(i);
+    }
+    return BaseVersionPtr();
 }
 
 BaseVersionPtr BaseVersionList::getRecommended() const
 {
-	if (count() <= 0)
-		return BaseVersionPtr();
-	else
-		return at(0);
+    if (count() <= 0)
+        return BaseVersionPtr();
+    else
+        return at(0);
 }
 
 QVariant BaseVersionList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
+    if (!index.isValid())
+        return QVariant();
 
-	if (index.row() > count())
-		return QVariant();
+    if (index.row() > count())
+        return QVariant();
 
-	BaseVersionPtr version = at(index.row());
+    BaseVersionPtr version = at(index.row());
 
-	switch (role)
-	{
-	case VersionPointerRole:
-		return qVariantFromValue(version);
+    switch (role)
+    {
+    case VersionPointerRole:
+        return qVariantFromValue(version);
 
-	case VersionRole:
-		return version->name();
+    case VersionRole:
+        return version->name();
 
-	case VersionIdRole:
-		return version->descriptor();
+    case VersionIdRole:
+        return version->descriptor();
 
-	case TypeRole:
-		return version->typeString();
+    case TypeRole:
+        return version->typeString();
 
-	default:
-		return QVariant();
-	}
+    default:
+        return QVariant();
+    }
 }
 
 BaseVersionList::RoleList BaseVersionList::providesRoles() const
 {
-	return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole};
+    return {VersionPointerRole, VersionRole, VersionIdRole, TypeRole};
 }
 
 int BaseVersionList::rowCount(const QModelIndex &parent) const
 {
-	// Return count
-	return count();
+    // Return count
+    return count();
 }
 
 int BaseVersionList::columnCount(const QModelIndex &parent) const
 {
-	return 1;
+    return 1;
 }
 
 QHash<int, QByteArray> BaseVersionList::roleNames() const
 {
-	QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
-	roles.insert(VersionRole, "version");
-	roles.insert(VersionIdRole, "versionId");
-	roles.insert(ParentVersionRole, "parentGameVersion");
-	roles.insert(RecommendedRole, "recommended");
-	roles.insert(LatestRole, "latest");
-	roles.insert(TypeRole, "type");
-	roles.insert(BranchRole, "branch");
-	roles.insert(PathRole, "path");
-	roles.insert(ArchitectureRole, "architecture");
-	return roles;
+    QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
+    roles.insert(VersionRole, "version");
+    roles.insert(VersionIdRole, "versionId");
+    roles.insert(ParentVersionRole, "parentGameVersion");
+    roles.insert(RecommendedRole, "recommended");
+    roles.insert(LatestRole, "latest");
+    roles.insert(TypeRole, "type");
+    roles.insert(BranchRole, "branch");
+    roles.insert(PathRole, "path");
+    roles.insert(ArchitectureRole, "architecture");
+    return roles;
 }
diff --git a/api/logic/BaseVersionList.h b/api/logic/BaseVersionList.h
index b609e039..a70a414c 100644
--- a/api/logic/BaseVersionList.h
+++ b/api/logic/BaseVersionList.h
@@ -38,85 +38,85 @@
  */
 class MULTIMC_LOGIC_EXPORT BaseVersionList : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum ModelRoles
-	{
-		VersionPointerRole = Qt::UserRole,
-		VersionRole,
-		VersionIdRole,
-		ParentVersionRole,
-		RecommendedRole,
-		LatestRole,
-		TypeRole,
-		BranchRole,
-		PathRole,
-		ArchitectureRole,
-		SortRole
-	};
-	typedef QList<int> RoleList;
+    enum ModelRoles
+    {
+        VersionPointerRole = Qt::UserRole,
+        VersionRole,
+        VersionIdRole,
+        ParentVersionRole,
+        RecommendedRole,
+        LatestRole,
+        TypeRole,
+        BranchRole,
+        PathRole,
+        ArchitectureRole,
+        SortRole
+    };
+    typedef QList<int> RoleList;
 
-	explicit BaseVersionList(QObject *parent = 0);
+    explicit BaseVersionList(QObject *parent = 0);
 
-	/*!
-	 * \brief Gets a task that will reload the version list.
-	 * Simply execute the task to load the list.
-	 * The task returned by this function should reset the model when it's done.
-	 * \return A pointer to a task that reloads the version list.
-	 */
-	virtual shared_qobject_ptr<Task> getLoadTask() = 0;
+    /*!
+     * \brief Gets a task that will reload the version list.
+     * Simply execute the task to load the list.
+     * The task returned by this function should reset the model when it's done.
+     * \return A pointer to a task that reloads the version list.
+     */
+    virtual shared_qobject_ptr<Task> getLoadTask() = 0;
 
-	//! Checks whether or not the list is loaded. If this returns false, the list should be
-	//loaded.
-	virtual bool isLoaded() = 0;
+    //! Checks whether or not the list is loaded. If this returns false, the list should be
+    //loaded.
+    virtual bool isLoaded() = 0;
 
-	//! Gets the version at the given index.
-	virtual const BaseVersionPtr at(int i) const = 0;
+    //! Gets the version at the given index.
+    virtual const BaseVersionPtr at(int i) const = 0;
 
-	//! Returns the number of versions in the list.
-	virtual int count() const = 0;
+    //! Returns the number of versions in the list.
+    virtual int count() const = 0;
 
-	//////// List Model Functions ////////
-	QVariant data(const QModelIndex &index, int role) const override;
-	int rowCount(const QModelIndex &parent) const override;
-	int columnCount(const QModelIndex &parent) const override;
-	QHash<int, QByteArray> roleNames() const override;
+    //////// List Model Functions ////////
+    QVariant data(const QModelIndex &index, int role) const override;
+    int rowCount(const QModelIndex &parent) const override;
+    int columnCount(const QModelIndex &parent) const override;
+    QHash<int, QByteArray> roleNames() const override;
 
-	//! which roles are provided by this version list?
-	virtual RoleList providesRoles() const;
+    //! which roles are provided by this version list?
+    virtual RoleList providesRoles() const;
 
-	/*!
-	 * \brief Finds a version by its descriptor.
-	 * \param descriptor The descriptor of the version to find.
-	 * \return A const pointer to the version with the given descriptor. NULL if
-	 * one doesn't exist.
-	 */
-	virtual BaseVersionPtr findVersion(const QString &descriptor);
+    /*!
+     * \brief Finds a version by its descriptor.
+     * \param descriptor The descriptor of the version to find.
+     * \return A const pointer to the version with the given descriptor. NULL if
+     * one doesn't exist.
+     */
+    virtual BaseVersionPtr findVersion(const QString &descriptor);
 
-	/*!
-	 * \brief Gets the recommended version from this list
-	 * If the list doesn't support recommended versions, this works exactly as getLatestStable
-	 */
-	virtual BaseVersionPtr getRecommended() const;
+    /*!
+     * \brief Gets the recommended version from this list
+     * If the list doesn't support recommended versions, this works exactly as getLatestStable
+     */
+    virtual BaseVersionPtr getRecommended() const;
 
-	/*!
-	 * Sorts the version list.
-	 */
-	virtual void sortVersions() = 0;
+    /*!
+     * Sorts the version list.
+     */
+    virtual void sortVersions() = 0;
 
 protected
 slots:
-	/*!
-	 * Updates this list with the given list of versions.
-	 * This is done by copying each version in the given list and inserting it
-	 * into this one.
-	 * We need to do this so that we can set the parents of the versions are set to this
-	 * version list. This can't be done in the load task, because the versions the load
-	 * task creates are on the load task's thread and Qt won't allow their parents
-	 * to be set to something created on another thread.
-	 * To get around that problem, we invoke this method on the GUI thread, which
-	 * then copies the versions and sets their parents correctly.
-	 * \param versions List of versions whose parents should be set.
-	 */
-	virtual void updateListData(QList<BaseVersionPtr> versions) = 0;
+    /*!
+     * Updates this list with the given list of versions.
+     * This is done by copying each version in the given list and inserting it
+     * into this one.
+     * We need to do this so that we can set the parents of the versions are set to this
+     * version list. This can't be done in the load task, because the versions the load
+     * task creates are on the load task's thread and Qt won't allow their parents
+     * to be set to something created on another thread.
+     * To get around that problem, we invoke this method on the GUI thread, which
+     * then copies the versions and sets their parents correctly.
+     * \param versions List of versions whose parents should be set.
+     */
+    virtual void updateListData(QList<BaseVersionPtr> versions) = 0;
 };
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index 769f112e..4c2445f0 100644
--- a/api/logic/CMakeLists.txt
+++ b/api/logic/CMakeLists.txt
@@ -3,446 +3,446 @@ project(MultiMC_logic)
 include (UnitTest)
 
 set(CORE_SOURCES
-	# LOGIC - Base classes and infrastructure
-	BaseInstaller.h
-	BaseInstaller.cpp
-	BaseVersionList.h
-	BaseVersionList.cpp
-	InstanceList.h
-	InstanceList.cpp
-	InstanceTask.h
-	InstanceTask.cpp
-	LoggedProcess.h
-	LoggedProcess.cpp
-	MessageLevel.cpp
-	MessageLevel.h
-	BaseInstanceProvider.h
-	FolderInstanceProvider.h
-	FolderInstanceProvider.cpp
-	BaseVersion.h
-	BaseInstance.h
-	BaseInstance.cpp
-	NullInstance.h
-	MMCZip.h
-	MMCZip.cpp
-	MMCStrings.h
-	MMCStrings.cpp
-
-	# Basic instance manipulation tasks (derived from InstanceTask)
-	InstanceCreationTask.h
-	InstanceCreationTask.cpp
-	InstanceCopyTask.h
-	InstanceCopyTask.cpp
-	InstanceImportTask.h
-	InstanceImportTask.cpp
-
-	# Use tracking separate from memory management
-	Usable.h
-
-	# Prefix tree where node names are strings between separators
-	SeparatorPrefixTree.h
-
-	# WARNING: globals live here
-	Env.h
-	Env.cpp
-
-	# String filters
-	Filter.h
-	Filter.cpp
-
-	# JSON parsing helpers
-	Json.h
-	Json.cpp
-
-	FileSystem.h
-	FileSystem.cpp
-
-	Exception.h
-
-	# RW lock protected map
-	RWStorage.h
-
-	# A variable that has an implicit default value and keeps track of changes
-	DefaultVariable.h
-
-	# a smart pointer wrapper intended for safer use with Qt signal/slot mechanisms
-	QObjectPtr.h
-
-	# Compression support
-	GZip.h
-	GZip.cpp
-
-	# Command line parameter parsing
-	Commandline.h
-	Commandline.cpp
-
-	# Version number string support
-	Version.h
-	Version.cpp
-
-	# A Recursive file system watcher
-	RecursiveFileSystemWatcher.h
-	RecursiveFileSystemWatcher.cpp
+    # LOGIC - Base classes and infrastructure
+    BaseInstaller.h
+    BaseInstaller.cpp
+    BaseVersionList.h
+    BaseVersionList.cpp
+    InstanceList.h
+    InstanceList.cpp
+    InstanceTask.h
+    InstanceTask.cpp
+    LoggedProcess.h
+    LoggedProcess.cpp
+    MessageLevel.cpp
+    MessageLevel.h
+    BaseInstanceProvider.h
+    FolderInstanceProvider.h
+    FolderInstanceProvider.cpp
+    BaseVersion.h
+    BaseInstance.h
+    BaseInstance.cpp
+    NullInstance.h
+    MMCZip.h
+    MMCZip.cpp
+    MMCStrings.h
+    MMCStrings.cpp
+
+    # Basic instance manipulation tasks (derived from InstanceTask)
+    InstanceCreationTask.h
+    InstanceCreationTask.cpp
+    InstanceCopyTask.h
+    InstanceCopyTask.cpp
+    InstanceImportTask.h
+    InstanceImportTask.cpp
+
+    # Use tracking separate from memory management
+    Usable.h
+
+    # Prefix tree where node names are strings between separators
+    SeparatorPrefixTree.h
+
+    # WARNING: globals live here
+    Env.h
+    Env.cpp
+
+    # String filters
+    Filter.h
+    Filter.cpp
+
+    # JSON parsing helpers
+    Json.h
+    Json.cpp
+
+    FileSystem.h
+    FileSystem.cpp
+
+    Exception.h
+
+    # RW lock protected map
+    RWStorage.h
+
+    # A variable that has an implicit default value and keeps track of changes
+    DefaultVariable.h
+
+    # a smart pointer wrapper intended for safer use with Qt signal/slot mechanisms
+    QObjectPtr.h
+
+    # Compression support
+    GZip.h
+    GZip.cpp
+
+    # Command line parameter parsing
+    Commandline.h
+    Commandline.cpp
+
+    # Version number string support
+    Version.h
+    Version.cpp
+
+    # A Recursive file system watcher
+    RecursiveFileSystemWatcher.h
+    RecursiveFileSystemWatcher.cpp
 )
 
 add_unit_test(FileSystem
-	SOURCES FileSystem_test.cpp
-	LIBS MultiMC_logic
-	DATA testdata
-	)
+    SOURCES FileSystem_test.cpp
+    LIBS MultiMC_logic
+    DATA testdata
+    )
 
 add_unit_test(GZip
-	SOURCES GZip_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES GZip_test.cpp
+    LIBS MultiMC_logic
+    )
 
 set(PATHMATCHER_SOURCES
-	# Path matchers
-	pathmatcher/FSTreeMatcher.h
-	pathmatcher/IPathMatcher.h
-	pathmatcher/MultiMatcher.h
-	pathmatcher/RegexpMatcher.h
+    # Path matchers
+    pathmatcher/FSTreeMatcher.h
+    pathmatcher/IPathMatcher.h
+    pathmatcher/MultiMatcher.h
+    pathmatcher/RegexpMatcher.h
 )
 
 set(NET_SOURCES
-	# network stuffs
-	net/ByteArraySink.h
-	net/ChecksumValidator.h
-	net/Download.cpp
-	net/Download.h
-	net/FileSink.cpp
-	net/FileSink.h
-	net/HttpMetaCache.cpp
-	net/HttpMetaCache.h
-	net/MetaCacheSink.cpp
-	net/MetaCacheSink.h
-	net/NetAction.h
-	net/NetJob.cpp
-	net/NetJob.h
-	net/PasteUpload.cpp
-	net/PasteUpload.h
-	net/Sink.h
-	net/URLConstants.cpp
-	net/URLConstants.h
-	net/Validator.h
+    # network stuffs
+    net/ByteArraySink.h
+    net/ChecksumValidator.h
+    net/Download.cpp
+    net/Download.h
+    net/FileSink.cpp
+    net/FileSink.h
+    net/HttpMetaCache.cpp
+    net/HttpMetaCache.h
+    net/MetaCacheSink.cpp
+    net/MetaCacheSink.h
+    net/NetAction.h
+    net/NetJob.cpp
+    net/NetJob.h
+    net/PasteUpload.cpp
+    net/PasteUpload.h
+    net/Sink.h
+    net/URLConstants.cpp
+    net/URLConstants.h
+    net/Validator.h
 )
 
 # Game launch logic
 set(LAUNCH_SOURCES
-	launch/steps/PostLaunchCommand.cpp
-	launch/steps/PostLaunchCommand.h
-	launch/steps/PreLaunchCommand.cpp
-	launch/steps/PreLaunchCommand.h
-	launch/steps/TextPrint.cpp
-	launch/steps/TextPrint.h
-	launch/steps/Update.cpp
-	launch/steps/Update.h
-	launch/LaunchStep.cpp
-	launch/LaunchStep.h
-	launch/LaunchTask.cpp
-	launch/LaunchTask.h
-	launch/LogModel.cpp
-	launch/LogModel.h
+    launch/steps/PostLaunchCommand.cpp
+    launch/steps/PostLaunchCommand.h
+    launch/steps/PreLaunchCommand.cpp
+    launch/steps/PreLaunchCommand.h
+    launch/steps/TextPrint.cpp
+    launch/steps/TextPrint.h
+    launch/steps/Update.cpp
+    launch/steps/Update.h
+    launch/LaunchStep.cpp
+    launch/LaunchStep.h
+    launch/LaunchTask.cpp
+    launch/LaunchTask.h
+    launch/LogModel.cpp
+    launch/LogModel.h
 )
 
 # Old update system
 set(UPDATE_SOURCES
-	updater/GoUpdate.h
-	updater/GoUpdate.cpp
-	updater/UpdateChecker.h
-	updater/UpdateChecker.cpp
-	updater/DownloadTask.h
-	updater/DownloadTask.cpp
+    updater/GoUpdate.h
+    updater/GoUpdate.cpp
+    updater/UpdateChecker.h
+    updater/UpdateChecker.cpp
+    updater/DownloadTask.h
+    updater/DownloadTask.cpp
 )
 
 add_unit_test(UpdateChecker
-	SOURCES updater/UpdateChecker_test.cpp
-	LIBS MultiMC_logic
-	DATA updater/testdata
-	)
+    SOURCES updater/UpdateChecker_test.cpp
+    LIBS MultiMC_logic
+    DATA updater/testdata
+    )
 
 add_unit_test(DownloadTask
-	SOURCES updater/DownloadTask_test.cpp
-	LIBS MultiMC_logic
-	DATA updater/testdata
-	)
+    SOURCES updater/DownloadTask_test.cpp
+    LIBS MultiMC_logic
+    DATA updater/testdata
+    )
 
 # Rarely used notifications
 set(NOTIFICATIONS_SOURCES
-	# Notifications - short warning messages
-	notifications/NotificationChecker.h
-	notifications/NotificationChecker.cpp
+    # Notifications - short warning messages
+    notifications/NotificationChecker.h
+    notifications/NotificationChecker.cpp
 )
 
 # Backend for the news bar... there's usually no news.
 set(NEWS_SOURCES
-	# News System
-	news/NewsChecker.h
-	news/NewsChecker.cpp
-	news/NewsEntry.h
-	news/NewsEntry.cpp
+    # News System
+    news/NewsChecker.h
+    news/NewsChecker.cpp
+    news/NewsEntry.h
+    news/NewsEntry.cpp
 )
 
 # Icon interface
 set(ICONS_SOURCES
-	# News System
-	icons/IIconList.h
-	icons/IIconList.cpp
+    # News System
+    icons/IIconList.h
+    icons/IIconList.cpp
 )
 
 # Minecraft services status checker
 set(STATUS_SOURCES
-	# Status system
-	status/StatusChecker.h
-	status/StatusChecker.cpp
+    # Status system
+    status/StatusChecker.h
+    status/StatusChecker.cpp
 )
 
 # Support for Minecraft instances and launch
 set(MINECRAFT_SOURCES
-	# Minecraft support
-	minecraft/auth/AuthSession.h
-	minecraft/auth/AuthSession.cpp
-	minecraft/auth/MojangAccountList.h
-	minecraft/auth/MojangAccountList.cpp
-	minecraft/auth/MojangAccount.h
-	minecraft/auth/MojangAccount.cpp
-	minecraft/auth/YggdrasilTask.h
-	minecraft/auth/YggdrasilTask.cpp
-	minecraft/auth/flows/AuthenticateTask.h
-	minecraft/auth/flows/AuthenticateTask.cpp
-	minecraft/auth/flows/RefreshTask.cpp
-	minecraft/auth/flows/RefreshTask.cpp
-	minecraft/auth/flows/ValidateTask.h
-	minecraft/auth/flows/ValidateTask.cpp
-	minecraft/update/AssetUpdateTask.h
-	minecraft/update/AssetUpdateTask.cpp
-	minecraft/update/FMLLibrariesTask.cpp
-	minecraft/update/FMLLibrariesTask.h
-	minecraft/update/FoldersTask.cpp
-	minecraft/update/FoldersTask.h
-	minecraft/update/LibrariesTask.cpp
-	minecraft/update/LibrariesTask.h
-	minecraft/launch/ClaimAccount.cpp
-	minecraft/launch/ClaimAccount.h
-	minecraft/launch/CreateServerResourcePacksFolder.cpp
-	minecraft/launch/CreateServerResourcePacksFolder.h
-	minecraft/launch/ModMinecraftJar.cpp
-	minecraft/launch/ModMinecraftJar.h
-	minecraft/launch/DirectJavaLaunch.cpp
-	minecraft/launch/DirectJavaLaunch.h
-	minecraft/launch/ExtractNatives.cpp
-	minecraft/launch/ExtractNatives.h
-	minecraft/launch/LauncherPartLaunch.cpp
-	minecraft/launch/LauncherPartLaunch.h
-	minecraft/launch/PrintInstanceInfo.cpp
-	minecraft/launch/PrintInstanceInfo.h
-	minecraft/legacy/LegacyModList.h
-	minecraft/legacy/LegacyModList.cpp
-	minecraft/legacy/LegacyInstance.h
-	minecraft/legacy/LegacyInstance.cpp
-	minecraft/legacy/LegacyUpgradeTask.h
-	minecraft/legacy/LegacyUpgradeTask.cpp
-	minecraft/GradleSpecifier.h
-	minecraft/MinecraftInstance.cpp
-	minecraft/MinecraftInstance.h
-	minecraft/LaunchProfile.cpp
-	minecraft/LaunchProfile.h
-	minecraft/Component.cpp
-	minecraft/Component.h
-	minecraft/ComponentList.cpp
-	minecraft/ComponentList.h
-	minecraft/ComponentUpdateTask.cpp
-	minecraft/ComponentUpdateTask.h
-	minecraft/MinecraftLoadAndCheck.h
-	minecraft/MinecraftLoadAndCheck.cpp
-	minecraft/MinecraftUpdate.h
-	minecraft/MinecraftUpdate.cpp
-	minecraft/MojangVersionFormat.cpp
-	minecraft/MojangVersionFormat.h
-	minecraft/Rule.cpp
-	minecraft/Rule.h
-	minecraft/OneSixVersionFormat.cpp
-	minecraft/OneSixVersionFormat.h
-	minecraft/OpSys.cpp
-	minecraft/OpSys.h
-	minecraft/ParseUtils.cpp
-	minecraft/ParseUtils.h
-	minecraft/ProfileUtils.cpp
-	minecraft/ProfileUtils.h
-	minecraft/Library.cpp
-	minecraft/Library.h
-	minecraft/MojangDownloadInfo.h
-	minecraft/VersionFile.cpp
-	minecraft/VersionFile.h
-	minecraft/VersionFilterData.h
-	minecraft/VersionFilterData.cpp
-	minecraft/Mod.h
-	minecraft/Mod.cpp
-	minecraft/ModsModel.h
-	minecraft/ModsModel.cpp
-	minecraft/SimpleModList.h
-	minecraft/SimpleModList.cpp
-	minecraft/World.h
-	minecraft/World.cpp
-	minecraft/WorldList.h
-	minecraft/WorldList.cpp
-
-	# Assets
-	minecraft/AssetsUtils.h
-	minecraft/AssetsUtils.cpp
-
-	# Forge and all things forge related
-	minecraft/forge/ForgeXzDownload.h
-	minecraft/forge/ForgeXzDownload.cpp
-
-	# Skin upload utilities
-	minecraft/SkinUpload.cpp
-	minecraft/SkinUpload.h
-	)
+    # Minecraft support
+    minecraft/auth/AuthSession.h
+    minecraft/auth/AuthSession.cpp
+    minecraft/auth/MojangAccountList.h
+    minecraft/auth/MojangAccountList.cpp
+    minecraft/auth/MojangAccount.h
+    minecraft/auth/MojangAccount.cpp
+    minecraft/auth/YggdrasilTask.h
+    minecraft/auth/YggdrasilTask.cpp
+    minecraft/auth/flows/AuthenticateTask.h
+    minecraft/auth/flows/AuthenticateTask.cpp
+    minecraft/auth/flows/RefreshTask.cpp
+    minecraft/auth/flows/RefreshTask.cpp
+    minecraft/auth/flows/ValidateTask.h
+    minecraft/auth/flows/ValidateTask.cpp
+    minecraft/update/AssetUpdateTask.h
+    minecraft/update/AssetUpdateTask.cpp
+    minecraft/update/FMLLibrariesTask.cpp
+    minecraft/update/FMLLibrariesTask.h
+    minecraft/update/FoldersTask.cpp
+    minecraft/update/FoldersTask.h
+    minecraft/update/LibrariesTask.cpp
+    minecraft/update/LibrariesTask.h
+    minecraft/launch/ClaimAccount.cpp
+    minecraft/launch/ClaimAccount.h
+    minecraft/launch/CreateServerResourcePacksFolder.cpp
+    minecraft/launch/CreateServerResourcePacksFolder.h
+    minecraft/launch/ModMinecraftJar.cpp
+    minecraft/launch/ModMinecraftJar.h
+    minecraft/launch/DirectJavaLaunch.cpp
+    minecraft/launch/DirectJavaLaunch.h
+    minecraft/launch/ExtractNatives.cpp
+    minecraft/launch/ExtractNatives.h
+    minecraft/launch/LauncherPartLaunch.cpp
+    minecraft/launch/LauncherPartLaunch.h
+    minecraft/launch/PrintInstanceInfo.cpp
+    minecraft/launch/PrintInstanceInfo.h
+    minecraft/legacy/LegacyModList.h
+    minecraft/legacy/LegacyModList.cpp
+    minecraft/legacy/LegacyInstance.h
+    minecraft/legacy/LegacyInstance.cpp
+    minecraft/legacy/LegacyUpgradeTask.h
+    minecraft/legacy/LegacyUpgradeTask.cpp
+    minecraft/GradleSpecifier.h
+    minecraft/MinecraftInstance.cpp
+    minecraft/MinecraftInstance.h
+    minecraft/LaunchProfile.cpp
+    minecraft/LaunchProfile.h
+    minecraft/Component.cpp
+    minecraft/Component.h
+    minecraft/ComponentList.cpp
+    minecraft/ComponentList.h
+    minecraft/ComponentUpdateTask.cpp
+    minecraft/ComponentUpdateTask.h
+    minecraft/MinecraftLoadAndCheck.h
+    minecraft/MinecraftLoadAndCheck.cpp
+    minecraft/MinecraftUpdate.h
+    minecraft/MinecraftUpdate.cpp
+    minecraft/MojangVersionFormat.cpp
+    minecraft/MojangVersionFormat.h
+    minecraft/Rule.cpp
+    minecraft/Rule.h
+    minecraft/OneSixVersionFormat.cpp
+    minecraft/OneSixVersionFormat.h
+    minecraft/OpSys.cpp
+    minecraft/OpSys.h
+    minecraft/ParseUtils.cpp
+    minecraft/ParseUtils.h
+    minecraft/ProfileUtils.cpp
+    minecraft/ProfileUtils.h
+    minecraft/Library.cpp
+    minecraft/Library.h
+    minecraft/MojangDownloadInfo.h
+    minecraft/VersionFile.cpp
+    minecraft/VersionFile.h
+    minecraft/VersionFilterData.h
+    minecraft/VersionFilterData.cpp
+    minecraft/Mod.h
+    minecraft/Mod.cpp
+    minecraft/ModsModel.h
+    minecraft/ModsModel.cpp
+    minecraft/SimpleModList.h
+    minecraft/SimpleModList.cpp
+    minecraft/World.h
+    minecraft/World.cpp
+    minecraft/WorldList.h
+    minecraft/WorldList.cpp
+
+    # Assets
+    minecraft/AssetsUtils.h
+    minecraft/AssetsUtils.cpp
+
+    # Forge and all things forge related
+    minecraft/forge/ForgeXzDownload.h
+    minecraft/forge/ForgeXzDownload.cpp
+
+    # Skin upload utilities
+    minecraft/SkinUpload.cpp
+    minecraft/SkinUpload.h
+    )
 
 add_unit_test(GradleSpecifier
-	SOURCES minecraft/GradleSpecifier_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES minecraft/GradleSpecifier_test.cpp
+    LIBS MultiMC_logic
+    )
 
 add_unit_test(MojangVersionFormat
-	SOURCES minecraft/MojangVersionFormat_test.cpp
-	LIBS MultiMC_logic
-	DATA minecraft/testdata
-	)
+    SOURCES minecraft/MojangVersionFormat_test.cpp
+    LIBS MultiMC_logic
+    DATA minecraft/testdata
+    )
 
 add_unit_test(Library
-	SOURCES minecraft/Library_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES minecraft/Library_test.cpp
+    LIBS MultiMC_logic
+    )
 
 # FIXME: shares data with FileSystem test
 add_unit_test(SimpleModList
-	SOURCES minecraft/SimpleModList_test.cpp
-	DATA testdata
-	LIBS MultiMC_logic
-	)
+    SOURCES minecraft/SimpleModList_test.cpp
+    DATA testdata
+    LIBS MultiMC_logic
+    )
 
 add_unit_test(ParseUtils
-	SOURCES minecraft/ParseUtils_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES minecraft/ParseUtils_test.cpp
+    LIBS MultiMC_logic
+    )
 
 # the screenshots feature
 set(SCREENSHOTS_SOURCES
-	screenshots/Screenshot.h
-	screenshots/ImgurUpload.h
-	screenshots/ImgurUpload.cpp
-	screenshots/ImgurAlbumCreation.h
-	screenshots/ImgurAlbumCreation.cpp
+    screenshots/Screenshot.h
+    screenshots/ImgurUpload.h
+    screenshots/ImgurUpload.cpp
+    screenshots/ImgurAlbumCreation.h
+    screenshots/ImgurAlbumCreation.cpp
 )
 
 set(TASKS_SOURCES
-	# Tasks
-	tasks/Task.h
-	tasks/Task.cpp
-	tasks/SequentialTask.h
-	tasks/SequentialTask.cpp
+    # Tasks
+    tasks/Task.h
+    tasks/Task.cpp
+    tasks/SequentialTask.h
+    tasks/SequentialTask.cpp
 )
 
 set(SETTINGS_SOURCES
-	# Settings
-	settings/INIFile.cpp
-	settings/INIFile.h
-	settings/INISettingsObject.cpp
-	settings/INISettingsObject.h
-	settings/OverrideSetting.cpp
-	settings/OverrideSetting.h
-	settings/PassthroughSetting.cpp
-	settings/PassthroughSetting.h
-	settings/Setting.cpp
-	settings/Setting.h
-	settings/SettingsObject.cpp
-	settings/SettingsObject.h
+    # Settings
+    settings/INIFile.cpp
+    settings/INIFile.h
+    settings/INISettingsObject.cpp
+    settings/INISettingsObject.h
+    settings/OverrideSetting.cpp
+    settings/OverrideSetting.h
+    settings/PassthroughSetting.cpp
+    settings/PassthroughSetting.h
+    settings/Setting.cpp
+    settings/Setting.h
+    settings/SettingsObject.cpp
+    settings/SettingsObject.h
 )
 
 add_unit_test(INIFile
-	SOURCES settings/INIFile_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES settings/INIFile_test.cpp
+    LIBS MultiMC_logic
+    )
 
 set(JAVA_SOURCES
-	# Java related code
-	java/launch/CheckJava.cpp
-	java/launch/CheckJava.h
-	java/JavaChecker.h
-	java/JavaChecker.cpp
-	java/JavaCheckerJob.h
-	java/JavaCheckerJob.cpp
-	java/JavaInstall.h
-	java/JavaInstall.cpp
-	java/JavaInstallList.h
-	java/JavaInstallList.cpp
-	java/JavaUtils.h
-	java/JavaUtils.cpp
-	java/JavaVersion.h
-	java/JavaVersion.cpp
+    # Java related code
+    java/launch/CheckJava.cpp
+    java/launch/CheckJava.h
+    java/JavaChecker.h
+    java/JavaChecker.cpp
+    java/JavaCheckerJob.h
+    java/JavaCheckerJob.cpp
+    java/JavaInstall.h
+    java/JavaInstall.cpp
+    java/JavaInstallList.h
+    java/JavaInstallList.cpp
+    java/JavaUtils.h
+    java/JavaUtils.cpp
+    java/JavaVersion.h
+    java/JavaVersion.cpp
 )
 
 add_unit_test(JavaVersion
-	SOURCES java/JavaVersion_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES java/JavaVersion_test.cpp
+    LIBS MultiMC_logic
+    )
 
 set(TRANSLATIONS_SOURCES
-	translations/TranslationsModel.h
-	translations/TranslationsModel.cpp
+    translations/TranslationsModel.h
+    translations/TranslationsModel.cpp
 )
 
 set(TOOLS_SOURCES
-	# Tools
-	tools/BaseExternalTool.cpp
-	tools/BaseExternalTool.h
-	tools/BaseProfiler.cpp
-	tools/BaseProfiler.h
-	tools/JProfiler.cpp
-	tools/JProfiler.h
-	tools/JVisualVM.cpp
-	tools/JVisualVM.h
-	tools/MCEditTool.cpp
-	tools/MCEditTool.h
+    # Tools
+    tools/BaseExternalTool.cpp
+    tools/BaseExternalTool.h
+    tools/BaseProfiler.cpp
+    tools/BaseProfiler.h
+    tools/JProfiler.cpp
+    tools/JProfiler.h
+    tools/JVisualVM.cpp
+    tools/JVisualVM.h
+    tools/MCEditTool.cpp
+    tools/MCEditTool.h
 )
 
 set(META_SOURCES
-	# Metadata sources
-	meta/JsonFormat.cpp
-	meta/JsonFormat.h
-	meta/BaseEntity.cpp
-	meta/BaseEntity.h
-	meta/VersionList.cpp
-	meta/VersionList.h
-	meta/Version.cpp
-	meta/Version.h
-	meta/Index.cpp
-	meta/Index.h
+    # Metadata sources
+    meta/JsonFormat.cpp
+    meta/JsonFormat.h
+    meta/BaseEntity.cpp
+    meta/BaseEntity.h
+    meta/VersionList.cpp
+    meta/VersionList.h
+    meta/Version.cpp
+    meta/Version.h
+    meta/Index.cpp
+    meta/Index.h
 )
 
 set(FTB_SOURCES
-	modplatform/ftb/FtbPackFetchTask.h
-	modplatform/ftb/FtbPackFetchTask.cpp
-	modplatform/ftb/FtbPackInstallTask.h
-	modplatform/ftb/FtbPackInstallTask.cpp
+    modplatform/ftb/FtbPackFetchTask.h
+    modplatform/ftb/FtbPackFetchTask.cpp
+    modplatform/ftb/FtbPackInstallTask.h
+    modplatform/ftb/FtbPackInstallTask.cpp
 
-	modplatform/ftb/PackHelpers.h
+    modplatform/ftb/PackHelpers.h
 )
 
 set(FLAME_SOURCES
-	# Flame
-	modplatform/flame/PackManifest.h
-	modplatform/flame/PackManifest.cpp
-	modplatform/flame/FileResolvingTask.h
-	modplatform/flame/FileResolvingTask.cpp
+    # Flame
+    modplatform/flame/PackManifest.h
+    modplatform/flame/PackManifest.cpp
+    modplatform/flame/FileResolvingTask.h
+    modplatform/flame/FileResolvingTask.cpp
 )
 
 add_unit_test(Index
-	SOURCES meta/Index_test.cpp
-	LIBS MultiMC_logic
-	)
+    SOURCES meta/Index_test.cpp
+    LIBS MultiMC_logic
+    )
 
 ################################ COMPILE ################################
 
@@ -450,25 +450,25 @@ add_unit_test(Index
 find_package(ZLIB REQUIRED)
 
 set(LOGIC_SOURCES
-	${CORE_SOURCES}
-	${PATHMATCHER_SOURCES}
-	${NET_SOURCES}
-	${LAUNCH_SOURCES}
-	${UPDATE_SOURCES}
-	${NOTIFICATIONS_SOURCES}
-	${NEWS_SOURCES}
-	${STATUS_SOURCES}
-	${MINECRAFT_SOURCES}
-	${SCREENSHOTS_SOURCES}
-	${TASKS_SOURCES}
-	${SETTINGS_SOURCES}
-	${JAVA_SOURCES}
-	${TRANSLATIONS_SOURCES}
-	${TOOLS_SOURCES}
-	${META_SOURCES}
-	${ICONS_SOURCES}
-	${FTB_SOURCES}
-	${FLAME_SOURCES}
+    ${CORE_SOURCES}
+    ${PATHMATCHER_SOURCES}
+    ${NET_SOURCES}
+    ${LAUNCH_SOURCES}
+    ${UPDATE_SOURCES}
+    ${NOTIFICATIONS_SOURCES}
+    ${NEWS_SOURCES}
+    ${STATUS_SOURCES}
+    ${MINECRAFT_SOURCES}
+    ${SCREENSHOTS_SOURCES}
+    ${TASKS_SOURCES}
+    ${SETTINGS_SOURCES}
+    ${JAVA_SOURCES}
+    ${TRANSLATIONS_SOURCES}
+    ${TOOLS_SOURCES}
+    ${META_SOURCES}
+    ${ICONS_SOURCES}
+    ${FTB_SOURCES}
+    ${FLAME_SOURCES}
 )
 
 add_library(MultiMC_logic SHARED ${LOGIC_SOURCES})
@@ -485,7 +485,7 @@ target_include_directories(MultiMC_logic PUBLIC "${CMAKE_CURRENT_BINARY_DIR}" "$
 
 # Install it
 install(
-	TARGETS MultiMC_logic
-	RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
-	LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
+    TARGETS MultiMC_logic
+    RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
+    LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
 )
diff --git a/api/logic/Commandline.cpp b/api/logic/Commandline.cpp
index eac9db09..81ae7d0b 100644
--- a/api/logic/Commandline.cpp
+++ b/api/logic/Commandline.cpp
@@ -27,453 +27,453 @@ namespace Commandline
 // commandline splitter
 QStringList splitArgs(QString args)
 {
-	QStringList argv;
-	QString current;
-	bool escape = false;
-	QChar inquotes;
-	for (int i = 0; i < args.length(); i++)
-	{
-		QChar cchar = args.at(i);
-
-		// \ escaped
-		if (escape)
-		{
-			current += cchar;
-			escape = false;
-			// in "quotes"
-		}
-		else if (!inquotes.isNull())
-		{
-			if (cchar == '\\')
-				escape = true;
-			else if (cchar == inquotes)
-				inquotes = 0;
-			else
-				current += cchar;
-			// otherwise
-		}
-		else
-		{
-			if (cchar == ' ')
-			{
-				if (!current.isEmpty())
-				{
-					argv << current;
-					current.clear();
-				}
-			}
-			else if (cchar == '"' || cchar == '\'')
-				inquotes = cchar;
-			else
-				current += cchar;
-		}
-	}
-	if (!current.isEmpty())
-		argv << current;
-	return argv;
+    QStringList argv;
+    QString current;
+    bool escape = false;
+    QChar inquotes;
+    for (int i = 0; i < args.length(); i++)
+    {
+        QChar cchar = args.at(i);
+
+        // \ escaped
+        if (escape)
+        {
+            current += cchar;
+            escape = false;
+            // in "quotes"
+        }
+        else if (!inquotes.isNull())
+        {
+            if (cchar == '\\')
+                escape = true;
+            else if (cchar == inquotes)
+                inquotes = 0;
+            else
+                current += cchar;
+            // otherwise
+        }
+        else
+        {
+            if (cchar == ' ')
+            {
+                if (!current.isEmpty())
+                {
+                    argv << current;
+                    current.clear();
+                }
+            }
+            else if (cchar == '"' || cchar == '\'')
+                inquotes = cchar;
+            else
+                current += cchar;
+        }
+    }
+    if (!current.isEmpty())
+        argv << current;
+    return argv;
 }
 
 Parser::Parser(FlagStyle::Enum flagStyle, ArgumentStyle::Enum argStyle)
 {
-	m_flagStyle = flagStyle;
-	m_argStyle = argStyle;
+    m_flagStyle = flagStyle;
+    m_argStyle = argStyle;
 }
 
 // styles setter/getter
 void Parser::setArgumentStyle(ArgumentStyle::Enum style)
 {
-	m_argStyle = style;
+    m_argStyle = style;
 }
 ArgumentStyle::Enum Parser::argumentStyle()
 {
-	return m_argStyle;
+    return m_argStyle;
 }
 
 void Parser::setFlagStyle(FlagStyle::Enum style)
 {
-	m_flagStyle = style;
+    m_flagStyle = style;
 }
 FlagStyle::Enum Parser::flagStyle()
 {
-	return m_flagStyle;
+    return m_flagStyle;
 }
 
 // setup methods
 void Parser::addSwitch(QString name, bool def)
 {
-	if (m_params.contains(name))
-		throw "Name not unique";
-
-	OptionDef *param = new OptionDef;
-	param->type = otSwitch;
-	param->name = name;
-	param->metavar = QString("<%1>").arg(name);
-	param->def = def;
-
-	m_options[name] = param;
-	m_params[name] = (CommonDef *)param;
-	m_optionList.append(param);
+    if (m_params.contains(name))
+        throw "Name not unique";
+
+    OptionDef *param = new OptionDef;
+    param->type = otSwitch;
+    param->name = name;
+    param->metavar = QString("<%1>").arg(name);
+    param->def = def;
+
+    m_options[name] = param;
+    m_params[name] = (CommonDef *)param;
+    m_optionList.append(param);
 }
 
 void Parser::addOption(QString name, QVariant def)
 {
-	if (m_params.contains(name))
-		throw "Name not unique";
-
-	OptionDef *param = new OptionDef;
-	param->type = otOption;
-	param->name = name;
-	param->metavar = QString("<%1>").arg(name);
-	param->def = def;
-
-	m_options[name] = param;
-	m_params[name] = (CommonDef *)param;
-	m_optionList.append(param);
+    if (m_params.contains(name))
+        throw "Name not unique";
+
+    OptionDef *param = new OptionDef;
+    param->type = otOption;
+    param->name = name;
+    param->metavar = QString("<%1>").arg(name);
+    param->def = def;
+
+    m_options[name] = param;
+    m_params[name] = (CommonDef *)param;
+    m_optionList.append(param);
 }
 
 void Parser::addArgument(QString name, bool required, QVariant def)
 {
-	if (m_params.contains(name))
-		throw "Name not unique";
+    if (m_params.contains(name))
+        throw "Name not unique";
 
-	PositionalDef *param = new PositionalDef;
-	param->name = name;
-	param->def = def;
-	param->required = required;
-	param->metavar = name;
+    PositionalDef *param = new PositionalDef;
+    param->name = name;
+    param->def = def;
+    param->required = required;
+    param->metavar = name;
 
-	m_positionals.append(param);
-	m_params[name] = (CommonDef *)param;
+    m_positionals.append(param);
+    m_params[name] = (CommonDef *)param;
 }
 
 void Parser::addDocumentation(QString name, QString doc, QString metavar)
 {
-	if (!m_params.contains(name))
-		throw "Name does not exist";
+    if (!m_params.contains(name))
+        throw "Name does not exist";
 
-	CommonDef *param = m_params[name];
-	param->doc = doc;
-	if (!metavar.isNull())
-		param->metavar = metavar;
+    CommonDef *param = m_params[name];
+    param->doc = doc;
+    if (!metavar.isNull())
+        param->metavar = metavar;
 }
 
 void Parser::addShortOpt(QString name, QChar flag)
 {
-	if (!m_params.contains(name))
-		throw "Name does not exist";
-	if (!m_options.contains(name))
-		throw "Name is not an Option or Swtich";
-
-	OptionDef *param = m_options[name];
-	m_flags[flag] = param;
-	param->flag = flag;
+    if (!m_params.contains(name))
+        throw "Name does not exist";
+    if (!m_options.contains(name))
+        throw "Name is not an Option or Swtich";
+
+    OptionDef *param = m_options[name];
+    m_flags[flag] = param;
+    param->flag = flag;
 }
 
 // help methods
 QString Parser::compileHelp(QString progName, int helpIndent, bool useFlags)
 {
-	QStringList help;
-	help << compileUsage(progName, useFlags) << "\r\n";
-
-	// positionals
-	if (!m_positionals.isEmpty())
-	{
-		help << "\r\n";
-		help << "Positional arguments:\r\n";
-		QListIterator<PositionalDef *> it2(m_positionals);
-		while (it2.hasNext())
-		{
-			PositionalDef *param = it2.next();
-			help << "  " << param->metavar;
-			help << " " << QString(helpIndent - param->metavar.length() - 1, ' ');
-			help << param->doc << "\r\n";
-		}
-	}
-
-	// Options
-	if (!m_optionList.isEmpty())
-	{
-		help << "\r\n";
-		QString optPrefix, flagPrefix;
-		getPrefix(optPrefix, flagPrefix);
-
-		help << "Options & Switches:\r\n";
-		QListIterator<OptionDef *> it(m_optionList);
-		while (it.hasNext())
-		{
-			OptionDef *option = it.next();
-			help << "  ";
-			int nameLength = optPrefix.length() + option->name.length();
-			if (!option->flag.isNull())
-			{
-				nameLength += 3 + flagPrefix.length();
-				help << flagPrefix << option->flag << ", ";
-			}
-			help << optPrefix << option->name;
-			if (option->type == otOption)
-			{
-				QString arg = QString("%1%2").arg(
-					((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar);
-				nameLength += arg.length();
-				help << arg;
-			}
-			help << " " << QString(helpIndent - nameLength - 1, ' ');
-			help << option->doc << "\r\n";
-		}
-	}
-
-	return help.join("");
+    QStringList help;
+    help << compileUsage(progName, useFlags) << "\r\n";
+
+    // positionals
+    if (!m_positionals.isEmpty())
+    {
+        help << "\r\n";
+        help << "Positional arguments:\r\n";
+        QListIterator<PositionalDef *> it2(m_positionals);
+        while (it2.hasNext())
+        {
+            PositionalDef *param = it2.next();
+            help << "  " << param->metavar;
+            help << " " << QString(helpIndent - param->metavar.length() - 1, ' ');
+            help << param->doc << "\r\n";
+        }
+    }
+
+    // Options
+    if (!m_optionList.isEmpty())
+    {
+        help << "\r\n";
+        QString optPrefix, flagPrefix;
+        getPrefix(optPrefix, flagPrefix);
+
+        help << "Options & Switches:\r\n";
+        QListIterator<OptionDef *> it(m_optionList);
+        while (it.hasNext())
+        {
+            OptionDef *option = it.next();
+            help << "  ";
+            int nameLength = optPrefix.length() + option->name.length();
+            if (!option->flag.isNull())
+            {
+                nameLength += 3 + flagPrefix.length();
+                help << flagPrefix << option->flag << ", ";
+            }
+            help << optPrefix << option->name;
+            if (option->type == otOption)
+            {
+                QString arg = QString("%1%2").arg(
+                    ((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar);
+                nameLength += arg.length();
+                help << arg;
+            }
+            help << " " << QString(helpIndent - nameLength - 1, ' ');
+            help << option->doc << "\r\n";
+        }
+    }
+
+    return help.join("");
 }
 
 QString Parser::compileUsage(QString progName, bool useFlags)
 {
-	QStringList usage;
-	usage << "Usage: " << progName;
-
-	QString optPrefix, flagPrefix;
-	getPrefix(optPrefix, flagPrefix);
-
-	// options
-	QListIterator<OptionDef *> it(m_optionList);
-	while (it.hasNext())
-	{
-		OptionDef *option = it.next();
-		usage << " [";
-		if (!option->flag.isNull() && useFlags)
-			usage << flagPrefix << option->flag;
-		else
-			usage << optPrefix << option->name;
-		if (option->type == otOption)
-			usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar;
-		usage << "]";
-	}
-
-	// arguments
-	QListIterator<PositionalDef *> it2(m_positionals);
-	while (it2.hasNext())
-	{
-		PositionalDef *param = it2.next();
-		usage << " " << (param->required ? "<" : "[");
-		usage << param->metavar;
-		usage << (param->required ? ">" : "]");
-	}
-
-	return usage.join("");
+    QStringList usage;
+    usage << "Usage: " << progName;
+
+    QString optPrefix, flagPrefix;
+    getPrefix(optPrefix, flagPrefix);
+
+    // options
+    QListIterator<OptionDef *> it(m_optionList);
+    while (it.hasNext())
+    {
+        OptionDef *option = it.next();
+        usage << " [";
+        if (!option->flag.isNull() && useFlags)
+            usage << flagPrefix << option->flag;
+        else
+            usage << optPrefix << option->name;
+        if (option->type == otOption)
+            usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar;
+        usage << "]";
+    }
+
+    // arguments
+    QListIterator<PositionalDef *> it2(m_positionals);
+    while (it2.hasNext())
+    {
+        PositionalDef *param = it2.next();
+        usage << " " << (param->required ? "<" : "[");
+        usage << param->metavar;
+        usage << (param->required ? ">" : "]");
+    }
+
+    return usage.join("");
 }
 
 // parsing
 QHash<QString, QVariant> Parser::parse(QStringList argv)
 {
-	QHash<QString, QVariant> map;
+    QHash<QString, QVariant> map;
 
-	QStringListIterator it(argv);
-	QString programName = it.next();
+    QStringListIterator it(argv);
+    QString programName = it.next();
 
-	QString optionPrefix;
-	QString flagPrefix;
-	QListIterator<PositionalDef *> positionals(m_positionals);
-	QStringList expecting;
+    QString optionPrefix;
+    QString flagPrefix;
+    QListIterator<PositionalDef *> positionals(m_positionals);
+    QStringList expecting;
 
-	getPrefix(optionPrefix, flagPrefix);
+    getPrefix(optionPrefix, flagPrefix);
 
-	while (it.hasNext())
-	{
-		QString arg = it.next();
+    while (it.hasNext())
+    {
+        QString arg = it.next();
 
-		if (!expecting.isEmpty())
-		// we were expecting an argument
-		{
-			QString name = expecting.first();
+        if (!expecting.isEmpty())
+        // we were expecting an argument
+        {
+            QString name = expecting.first();
 /*
-			if (map.contains(name))
-				throw ParsingError(
-					QString("Option %2%1 was given multiple times").arg(name, optionPrefix));
+            if (map.contains(name))
+                throw ParsingError(
+                    QString("Option %2%1 was given multiple times").arg(name, optionPrefix));
 */
-			map[name] = QVariant(arg);
-
-			expecting.removeFirst();
-			continue;
-		}
-
-		if (arg.startsWith(optionPrefix))
-		// we have an option
-		{
-			// qDebug("Found option %s", qPrintable(arg));
-
-			QString name = arg.mid(optionPrefix.length());
-			QString equals;
-
-			if ((m_argStyle == ArgumentStyle::Equals ||
-				 m_argStyle == ArgumentStyle::SpaceAndEquals) &&
-				name.contains("="))
-			{
-				int i = name.indexOf("=");
-				equals = name.mid(i + 1);
-				name = name.left(i);
-			}
-
-			if (m_options.contains(name))
-			{
-				/*
-				if (map.contains(name))
-					throw ParsingError(QString("Option %2%1 was given multiple times")
-										   .arg(name, optionPrefix));
+            map[name] = QVariant(arg);
+
+            expecting.removeFirst();
+            continue;
+        }
+
+        if (arg.startsWith(optionPrefix))
+        // we have an option
+        {
+            // qDebug("Found option %s", qPrintable(arg));
+
+            QString name = arg.mid(optionPrefix.length());
+            QString equals;
+
+            if ((m_argStyle == ArgumentStyle::Equals ||
+                 m_argStyle == ArgumentStyle::SpaceAndEquals) &&
+                name.contains("="))
+            {
+                int i = name.indexOf("=");
+                equals = name.mid(i + 1);
+                name = name.left(i);
+            }
+
+            if (m_options.contains(name))
+            {
+                /*
+                if (map.contains(name))
+                    throw ParsingError(QString("Option %2%1 was given multiple times")
+                                           .arg(name, optionPrefix));
 */
-				OptionDef *option = m_options[name];
-				if (option->type == otSwitch)
-					map[name] = true;
-				else // if (option->type == otOption)
-				{
-					if (m_argStyle == ArgumentStyle::Space)
-						expecting.append(name);
-					else if (!equals.isNull())
-						map[name] = equals;
-					else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
-						expecting.append(name);
-					else
-						throw ParsingError(QString("Option %2%1 reqires an argument.")
-											   .arg(name, optionPrefix));
-				}
-
-				continue;
-			}
-
-			throw ParsingError(QString("Unknown Option %2%1").arg(name, optionPrefix));
-		}
-
-		if (arg.startsWith(flagPrefix))
-		// we have (a) flag(s)
-		{
-			// qDebug("Found flags %s", qPrintable(arg));
-
-			QString flags = arg.mid(flagPrefix.length());
-			QString equals;
-
-			if ((m_argStyle == ArgumentStyle::Equals ||
-				 m_argStyle == ArgumentStyle::SpaceAndEquals) &&
-				flags.contains("="))
-			{
-				int i = flags.indexOf("=");
-				equals = flags.mid(i + 1);
-				flags = flags.left(i);
-			}
-
-			for (int i = 0; i < flags.length(); i++)
-			{
-				QChar flag = flags.at(i);
-
-				if (!m_flags.contains(flag))
-					throw ParsingError(QString("Unknown flag %2%1").arg(flag, flagPrefix));
-
-				OptionDef *option = m_flags[flag];
+                OptionDef *option = m_options[name];
+                if (option->type == otSwitch)
+                    map[name] = true;
+                else // if (option->type == otOption)
+                {
+                    if (m_argStyle == ArgumentStyle::Space)
+                        expecting.append(name);
+                    else if (!equals.isNull())
+                        map[name] = equals;
+                    else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
+                        expecting.append(name);
+                    else
+                        throw ParsingError(QString("Option %2%1 reqires an argument.")
+                                               .arg(name, optionPrefix));
+                }
+
+                continue;
+            }
+
+            throw ParsingError(QString("Unknown Option %2%1").arg(name, optionPrefix));
+        }
+
+        if (arg.startsWith(flagPrefix))
+        // we have (a) flag(s)
+        {
+            // qDebug("Found flags %s", qPrintable(arg));
+
+            QString flags = arg.mid(flagPrefix.length());
+            QString equals;
+
+            if ((m_argStyle == ArgumentStyle::Equals ||
+                 m_argStyle == ArgumentStyle::SpaceAndEquals) &&
+                flags.contains("="))
+            {
+                int i = flags.indexOf("=");
+                equals = flags.mid(i + 1);
+                flags = flags.left(i);
+            }
+
+            for (int i = 0; i < flags.length(); i++)
+            {
+                QChar flag = flags.at(i);
+
+                if (!m_flags.contains(flag))
+                    throw ParsingError(QString("Unknown flag %2%1").arg(flag, flagPrefix));
+
+                OptionDef *option = m_flags[flag];
 /*
-				if (map.contains(option->name))
-					throw ParsingError(QString("Option %2%1 was given multiple times")
-										   .arg(option->name, optionPrefix));
+                if (map.contains(option->name))
+                    throw ParsingError(QString("Option %2%1 was given multiple times")
+                                           .arg(option->name, optionPrefix));
 */
-				if (option->type == otSwitch)
-					map[option->name] = true;
-				else // if (option->type == otOption)
-				{
-					if (m_argStyle == ArgumentStyle::Space)
-						expecting.append(option->name);
-					else if (!equals.isNull())
-						if (i == flags.length() - 1)
-							map[option->name] = equals;
-						else
-							throw ParsingError(QString("Flag %4%2 of Argument-requiring Option "
-													   "%1 not last flag in %4%3")
-												   .arg(option->name, flag, flags, flagPrefix));
-					else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
-						expecting.append(option->name);
-					else
-						throw ParsingError(QString("Option %1 reqires an argument. (flag %3%2)")
-											   .arg(option->name, flag, flagPrefix));
-				}
-			}
-
-			continue;
-		}
-
-		// must be a positional argument
-		if (!positionals.hasNext())
-			throw ParsingError(QString("Don't know what to do with '%1'").arg(arg));
-
-		PositionalDef *param = positionals.next();
-
-		map[param->name] = arg;
-	}
-
-	// check if we're missing something
-	if (!expecting.isEmpty())
-		throw ParsingError(QString("Was still expecting arguments for %2%1").arg(
-			expecting.join(QString(", ") + optionPrefix), optionPrefix));
-
-	while (positionals.hasNext())
-	{
-		PositionalDef *param = positionals.next();
-		if (param->required)
-			throw ParsingError(
-				QString("Missing required positional argument '%1'").arg(param->name));
-		else
-			map[param->name] = param->def;
-	}
-
-	// fill out gaps
-	QListIterator<OptionDef *> iter(m_optionList);
-	while (iter.hasNext())
-	{
-		OptionDef *option = iter.next();
-		if (!map.contains(option->name))
-			map[option->name] = option->def;
-	}
-
-	return map;
+                if (option->type == otSwitch)
+                    map[option->name] = true;
+                else // if (option->type == otOption)
+                {
+                    if (m_argStyle == ArgumentStyle::Space)
+                        expecting.append(option->name);
+                    else if (!equals.isNull())
+                        if (i == flags.length() - 1)
+                            map[option->name] = equals;
+                        else
+                            throw ParsingError(QString("Flag %4%2 of Argument-requiring Option "
+                                                       "%1 not last flag in %4%3")
+                                                   .arg(option->name, flag, flags, flagPrefix));
+                    else if (m_argStyle == ArgumentStyle::SpaceAndEquals)
+                        expecting.append(option->name);
+                    else
+                        throw ParsingError(QString("Option %1 reqires an argument. (flag %3%2)")
+                                               .arg(option->name, flag, flagPrefix));
+                }
+            }
+
+            continue;
+        }
+
+        // must be a positional argument
+        if (!positionals.hasNext())
+            throw ParsingError(QString("Don't know what to do with '%1'").arg(arg));
+
+        PositionalDef *param = positionals.next();
+
+        map[param->name] = arg;
+    }
+
+    // check if we're missing something
+    if (!expecting.isEmpty())
+        throw ParsingError(QString("Was still expecting arguments for %2%1").arg(
+            expecting.join(QString(", ") + optionPrefix), optionPrefix));
+
+    while (positionals.hasNext())
+    {
+        PositionalDef *param = positionals.next();
+        if (param->required)
+            throw ParsingError(
+                QString("Missing required positional argument '%1'").arg(param->name));
+        else
+            map[param->name] = param->def;
+    }
+
+    // fill out gaps
+    QListIterator<OptionDef *> iter(m_optionList);
+    while (iter.hasNext())
+    {
+        OptionDef *option = iter.next();
+        if (!map.contains(option->name))
+            map[option->name] = option->def;
+    }
+
+    return map;
 }
 
 // clear defs
 void Parser::clear()
 {
-	m_flags.clear();
-	m_params.clear();
-	m_options.clear();
-
-	QMutableListIterator<OptionDef *> it(m_optionList);
-	while (it.hasNext())
-	{
-		OptionDef *option = it.next();
-		it.remove();
-		delete option;
-	}
-
-	QMutableListIterator<PositionalDef *> it2(m_positionals);
-	while (it2.hasNext())
-	{
-		PositionalDef *arg = it2.next();
-		it2.remove();
-		delete arg;
-	}
+    m_flags.clear();
+    m_params.clear();
+    m_options.clear();
+
+    QMutableListIterator<OptionDef *> it(m_optionList);
+    while (it.hasNext())
+    {
+        OptionDef *option = it.next();
+        it.remove();
+        delete option;
+    }
+
+    QMutableListIterator<PositionalDef *> it2(m_positionals);
+    while (it2.hasNext())
+    {
+        PositionalDef *arg = it2.next();
+        it2.remove();
+        delete arg;
+    }
 }
 
 // Destructor
 Parser::~Parser()
 {
-	clear();
+    clear();
 }
 
 // getPrefix
 void Parser::getPrefix(QString &opt, QString &flag)
 {
-	if (m_flagStyle == FlagStyle::Windows)
-		opt = flag = "/";
-	else if (m_flagStyle == FlagStyle::Unix)
-		opt = flag = "-";
-	// else if (m_flagStyle == FlagStyle::GNU)
-	else
-	{
-		opt = "--";
-		flag = "-";
-	}
+    if (m_flagStyle == FlagStyle::Windows)
+        opt = flag = "/";
+    else if (m_flagStyle == FlagStyle::Unix)
+        opt = flag = "-";
+    // else if (m_flagStyle == FlagStyle::GNU)
+    else
+    {
+        opt = "--";
+        flag = "-";
+    }
 }
 
 // ParsingError
diff --git a/api/logic/Commandline.h b/api/logic/Commandline.h
index c8c8be29..586d644f 100644
--- a/api/logic/Commandline.h
+++ b/api/logic/Commandline.h
@@ -51,13 +51,13 @@ namespace FlagStyle
 {
 enum Enum
 {
-	GNU,	 /**< --option and -o (GNU Style) */
-	Unix,	/**< -option and -o  (Unix Style) */
-	Windows, /**< /option and /o  (Windows Style) */
+    GNU,     /**< --option and -o (GNU Style) */
+    Unix,    /**< -option and -o  (Unix Style) */
+    Windows, /**< /option and /o  (Windows Style) */
 #ifdef Q_OS_WIN32
-	Default = Windows
+    Default = Windows
 #else
-		Default = GNU
+        Default = GNU
 #endif
 };
 }
@@ -69,13 +69,13 @@ namespace ArgumentStyle
 {
 enum Enum
 {
-	Space,		  /**< --option=value */
-	Equals,		 /**< --option value */
-	SpaceAndEquals, /**< --option[= ]value */
+    Space,          /**< --option=value */
+    Equals,         /**< --option value */
+    SpaceAndEquals, /**< --option[= ]value */
 #ifdef Q_OS_WIN32
-	Default = Equals
+    Default = Equals
 #else
-		Default = SpaceAndEquals
+        Default = SpaceAndEquals
 #endif
 };
 }
@@ -86,7 +86,7 @@ enum Enum
 class MULTIMC_LOGIC_EXPORT ParsingError : public std::runtime_error
 {
 public:
-	ParsingError(const QString &what);
+    ParsingError(const QString &what);
 };
 
 /**
@@ -95,158 +95,158 @@ public:
 class MULTIMC_LOGIC_EXPORT Parser
 {
 public:
-	/**
-	 * @brief Parser constructor
-	 * @param flagStyle the FlagStyle to use in this Parser
-	 * @param argStyle the ArgumentStyle to use in this Parser
-	 */
-	Parser(FlagStyle::Enum flagStyle = FlagStyle::Default,
-		   ArgumentStyle::Enum argStyle = ArgumentStyle::Default);
-
-	/**
-	 * @brief set the flag style
-	 * @param style
-	 */
-	void setFlagStyle(FlagStyle::Enum style);
-
-	/**
-	 * @brief get the flag style
-	 * @return
-	 */
-	FlagStyle::Enum flagStyle();
-
-	/**
-	 * @brief set the argument style
-	 * @param style
-	 */
-	void setArgumentStyle(ArgumentStyle::Enum style);
-
-	/**
-	 * @brief get the argument style
-	 * @return
-	 */
-	ArgumentStyle::Enum argumentStyle();
-
-	/**
-	 * @brief define a boolean switch
-	 * @param name the parameter name
-	 * @param def the default value
-	 */
-	void addSwitch(QString name, bool def = false);
-
-	/**
-	 * @brief define an option that takes an additional argument
-	 * @param name the parameter name
-	 * @param def the default value
-	 */
-	void addOption(QString name, QVariant def = QVariant());
-
-	/**
-	 * @brief define a positional argument
-	 * @param name the parameter name
-	 * @param required wether this argument is required
-	 * @param def the default value
-	 */
-	void addArgument(QString name, bool required = true, QVariant def = QVariant());
-
-	/**
-	 * @brief adds a flag to an existing parameter
-	 * @param name the (existing) parameter name
-	 * @param flag the flag character
-	 * @see addSwitch addArgument addOption
-	 * Note: any one parameter can only have one flag
-	 */
-	void addShortOpt(QString name, QChar flag);
-
-	/**
-	 * @brief adds documentation to a Parameter
-	 * @param name the parameter name
-	 * @param metavar a string to be displayed as placeholder for the value
-	 * @param doc a QString containing the documentation
-	 * Note: on positional arguments, metavar replaces the name as displayed.
-	 *       on options , metavar replaces the value placeholder
-	 */
-	void addDocumentation(QString name, QString doc, QString metavar = QString());
-
-	/**
-	 * @brief generate a help message
-	 * @param progName the program name to use in the help message
-	 * @param helpIndent how much the parameter documentation should be indented
-	 * @param flagsInUsage whether we should use flags instead of options in the usage
-	 * @return a help message
-	 */
-	QString compileHelp(QString progName, int helpIndent = 22, bool flagsInUsage = true);
-
-	/**
-	 * @brief generate a short usage message
-	 * @param progName the program name to use in the usage message
-	 * @param useFlags whether we should use flags instead of options
-	 * @return a usage message
-	 */
-	QString compileUsage(QString progName, bool useFlags = true);
-
-	/**
-	 * @brief parse
-	 * @param argv a QStringList containing the program ARGV
-	 * @return a QHash mapping argument names to their values
-	 */
-	QHash<QString, QVariant> parse(QStringList argv);
-
-	/**
-	 * @brief clear all definitions
-	 */
-	void clear();
-
-	~Parser();
+    /**
+     * @brief Parser constructor
+     * @param flagStyle the FlagStyle to use in this Parser
+     * @param argStyle the ArgumentStyle to use in this Parser
+     */
+    Parser(FlagStyle::Enum flagStyle = FlagStyle::Default,
+           ArgumentStyle::Enum argStyle = ArgumentStyle::Default);
+
+    /**
+     * @brief set the flag style
+     * @param style
+     */
+    void setFlagStyle(FlagStyle::Enum style);
+
+    /**
+     * @brief get the flag style
+     * @return
+     */
+    FlagStyle::Enum flagStyle();
+
+    /**
+     * @brief set the argument style
+     * @param style
+     */
+    void setArgumentStyle(ArgumentStyle::Enum style);
+
+    /**
+     * @brief get the argument style
+     * @return
+     */
+    ArgumentStyle::Enum argumentStyle();
+
+    /**
+     * @brief define a boolean switch
+     * @param name the parameter name
+     * @param def the default value
+     */
+    void addSwitch(QString name, bool def = false);
+
+    /**
+     * @brief define an option that takes an additional argument
+     * @param name the parameter name
+     * @param def the default value
+     */
+    void addOption(QString name, QVariant def = QVariant());
+
+    /**
+     * @brief define a positional argument
+     * @param name the parameter name
+     * @param required wether this argument is required
+     * @param def the default value
+     */
+    void addArgument(QString name, bool required = true, QVariant def = QVariant());
+
+    /**
+     * @brief adds a flag to an existing parameter
+     * @param name the (existing) parameter name
+     * @param flag the flag character
+     * @see addSwitch addArgument addOption
+     * Note: any one parameter can only have one flag
+     */
+    void addShortOpt(QString name, QChar flag);
+
+    /**
+     * @brief adds documentation to a Parameter
+     * @param name the parameter name
+     * @param metavar a string to be displayed as placeholder for the value
+     * @param doc a QString containing the documentation
+     * Note: on positional arguments, metavar replaces the name as displayed.
+     *       on options , metavar replaces the value placeholder
+     */
+    void addDocumentation(QString name, QString doc, QString metavar = QString());
+
+    /**
+     * @brief generate a help message
+     * @param progName the program name to use in the help message
+     * @param helpIndent how much the parameter documentation should be indented
+     * @param flagsInUsage whether we should use flags instead of options in the usage
+     * @return a help message
+     */
+    QString compileHelp(QString progName, int helpIndent = 22, bool flagsInUsage = true);
+
+    /**
+     * @brief generate a short usage message
+     * @param progName the program name to use in the usage message
+     * @param useFlags whether we should use flags instead of options
+     * @return a usage message
+     */
+    QString compileUsage(QString progName, bool useFlags = true);
+
+    /**
+     * @brief parse
+     * @param argv a QStringList containing the program ARGV
+     * @return a QHash mapping argument names to their values
+     */
+    QHash<QString, QVariant> parse(QStringList argv);
+
+    /**
+     * @brief clear all definitions
+     */
+    void clear();
+
+    ~Parser();
 
 private:
-	FlagStyle::Enum m_flagStyle;
-	ArgumentStyle::Enum m_argStyle;
-
-	enum OptionType
-	{
-		otSwitch,
-		otOption
-	};
-
-	// Important: the common part MUST BE COMMON ON ALL THREE structs
-	struct CommonDef
-	{
-		QString name;
-		QString doc;
-		QString metavar;
-		QVariant def;
-	};
-
-	struct OptionDef
-	{
-		// common
-		QString name;
-		QString doc;
-		QString metavar;
-		QVariant def;
-		// option
-		OptionType type;
-		QChar flag;
-	};
-
-	struct PositionalDef
-	{
-		// common
-		QString name;
-		QString doc;
-		QString metavar;
-		QVariant def;
-		// positional
-		bool required;
-	};
-
-	QHash<QString, OptionDef *> m_options;
-	QHash<QChar, OptionDef *> m_flags;
-	QHash<QString, CommonDef *> m_params;
-	QList<PositionalDef *> m_positionals;
-	QList<OptionDef *> m_optionList;
-
-	void getPrefix(QString &opt, QString &flag);
+    FlagStyle::Enum m_flagStyle;
+    ArgumentStyle::Enum m_argStyle;
+
+    enum OptionType
+    {
+        otSwitch,
+        otOption
+    };
+
+    // Important: the common part MUST BE COMMON ON ALL THREE structs
+    struct CommonDef
+    {
+        QString name;
+        QString doc;
+        QString metavar;
+        QVariant def;
+    };
+
+    struct OptionDef
+    {
+        // common
+        QString name;
+        QString doc;
+        QString metavar;
+        QVariant def;
+        // option
+        OptionType type;
+        QChar flag;
+    };
+
+    struct PositionalDef
+    {
+        // common
+        QString name;
+        QString doc;
+        QString metavar;
+        QVariant def;
+        // positional
+        bool required;
+    };
+
+    QHash<QString, OptionDef *> m_options;
+    QHash<QChar, OptionDef *> m_flags;
+    QHash<QString, CommonDef *> m_params;
+    QList<PositionalDef *> m_positionals;
+    QList<OptionDef *> m_optionList;
+
+    void getPrefix(QString &opt, QString &flag);
 };
 }
diff --git a/api/logic/DefaultVariable.h b/api/logic/DefaultVariable.h
index 38d7ecc2..5c069bd3 100644
--- a/api/logic/DefaultVariable.h
+++ b/api/logic/DefaultVariable.h
@@ -4,32 +4,32 @@ template <typename T>
 class DefaultVariable
 {
 public:
-	DefaultVariable(const T & value)
-	{
-		defaultValue = value;
-	}
-	DefaultVariable<T> & operator =(const T & value)
-	{
-		currentValue = value;
-		is_default = currentValue == defaultValue;
-		is_explicit = true;
-		return *this;
-	}
-	operator const T &() const
-	{
-		return is_default ? defaultValue : currentValue;
-	}
-	bool isDefault() const
-	{
-		return is_default;
-	}
-	bool isExplicit() const
-	{
-		return is_explicit;
-	}
+    DefaultVariable(const T & value)
+    {
+        defaultValue = value;
+    }
+    DefaultVariable<T> & operator =(const T & value)
+    {
+        currentValue = value;
+        is_default = currentValue == defaultValue;
+        is_explicit = true;
+        return *this;
+    }
+    operator const T &() const
+    {
+        return is_default ? defaultValue : currentValue;
+    }
+    bool isDefault() const
+    {
+        return is_default;
+    }
+    bool isExplicit() const
+    {
+        return is_explicit;
+    }
 private:
-	T currentValue;
-	T defaultValue;
-	bool is_default = true;
-	bool is_explicit = false;
+    T currentValue;
+    T defaultValue;
+    bool is_default = true;
+    bool is_explicit = false;
 };
diff --git a/api/logic/Env.cpp b/api/logic/Env.cpp
index 04a5ab23..73cad2e9 100644
--- a/api/logic/Env.cpp
+++ b/api/logic/Env.cpp
@@ -15,11 +15,11 @@
 
 struct Env::Private
 {
-	QNetworkAccessManager m_qnam;
-	shared_qobject_ptr<HttpMetaCache> m_metacache;
-	std::shared_ptr<IIconList> m_iconlist;
-	shared_qobject_ptr<Meta::Index> m_metadataIndex;
-	QString m_jarsPath;
+    QNetworkAccessManager m_qnam;
+    shared_qobject_ptr<HttpMetaCache> m_metacache;
+    std::shared_ptr<IIconList> m_iconlist;
+    shared_qobject_ptr<Meta::Index> m_metadataIndex;
+    QString m_jarsPath;
 };
 
 static Env * instance;
@@ -30,152 +30,152 @@ static Env * instance;
 
 Env::Env()
 {
-	d = new Private();
+    d = new Private();
 }
 
 Env::~Env()
 {
-	delete d;
+    delete d;
 }
 
 Env& Env::Env::getInstance()
 {
-	if(!instance)
-	{
-		instance = new Env();
-	}
-	return *instance;
+    if(!instance)
+    {
+        instance = new Env();
+    }
+    return *instance;
 }
 
 void Env::dispose()
 {
-	delete instance;
-	instance = nullptr;
+    delete instance;
+    instance = nullptr;
 }
 
 shared_qobject_ptr< HttpMetaCache > Env::metacache()
 {
-	return d->m_metacache;
+    return d->m_metacache;
 }
 
 QNetworkAccessManager& Env::qnam() const
 {
-	return d->m_qnam;
+    return d->m_qnam;
 }
 
 std::shared_ptr<IIconList> Env::icons()
 {
-	return d->m_iconlist;
+    return d->m_iconlist;
 }
 
 void Env::registerIconList(std::shared_ptr<IIconList> iconlist)
 {
-	d->m_iconlist = iconlist;
+    d->m_iconlist = iconlist;
 }
 
 shared_qobject_ptr<Meta::Index> Env::metadataIndex()
 {
-	if (!d->m_metadataIndex)
-	{
-		d->m_metadataIndex.reset(new Meta::Index());
-	}
-	return d->m_metadataIndex;
+    if (!d->m_metadataIndex)
+    {
+        d->m_metadataIndex.reset(new Meta::Index());
+    }
+    return d->m_metadataIndex;
 }
 
 
 void Env::initHttpMetaCache()
 {
-	auto &m_metacache = d->m_metacache;
-	m_metacache.reset(new HttpMetaCache("metacache"));
-	m_metacache->addBase("asset_indexes", QDir("assets/indexes").absolutePath());
-	m_metacache->addBase("asset_objects", QDir("assets/objects").absolutePath());
-	m_metacache->addBase("versions", QDir("versions").absolutePath());
-	m_metacache->addBase("libraries", QDir("libraries").absolutePath());
-	m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
-	m_metacache->addBase("fmllibs", QDir("mods/minecraftforge/libs").absolutePath());
-	m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
-	m_metacache->addBase("general", QDir("cache").absolutePath());
-	m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
-	m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
-	m_metacache->addBase("root", QDir::currentPath());
-	m_metacache->addBase("translations", QDir("translations").absolutePath());
-	m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
-	m_metacache->addBase("meta", QDir("meta").absolutePath());
-	m_metacache->Load();
+    auto &m_metacache = d->m_metacache;
+    m_metacache.reset(new HttpMetaCache("metacache"));
+    m_metacache->addBase("asset_indexes", QDir("assets/indexes").absolutePath());
+    m_metacache->addBase("asset_objects", QDir("assets/objects").absolutePath());
+    m_metacache->addBase("versions", QDir("versions").absolutePath());
+    m_metacache->addBase("libraries", QDir("libraries").absolutePath());
+    m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
+    m_metacache->addBase("fmllibs", QDir("mods/minecraftforge/libs").absolutePath());
+    m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
+    m_metacache->addBase("general", QDir("cache").absolutePath());
+    m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
+    m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
+    m_metacache->addBase("root", QDir::currentPath());
+    m_metacache->addBase("translations", QDir("translations").absolutePath());
+    m_metacache->addBase("icons", QDir("cache/icons").absolutePath());
+    m_metacache->addBase("meta", QDir("meta").absolutePath());
+    m_metacache->Load();
 }
 
 void Env::updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password)
 {
-	// Set the application proxy settings.
-	if (proxyTypeStr == "SOCKS5")
-	{
-		QNetworkProxy::setApplicationProxy(
-			QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password));
-	}
-	else if (proxyTypeStr == "HTTP")
-	{
-		QNetworkProxy::setApplicationProxy(
-			QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password));
-	}
-	else if (proxyTypeStr == "None")
-	{
-		// If we have no proxy set, set no proxy and return.
-		QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy));
-	}
-	else
-	{
-		// If we have "Default" selected, set Qt to use the system proxy settings.
-		QNetworkProxyFactory::setUseSystemConfiguration(true);
-	}
-
-	qDebug() << "Detecting proxy settings...";
-	QNetworkProxy proxy = QNetworkProxy::applicationProxy();
-	d->m_qnam.setProxy(proxy);
-	QString proxyDesc;
-	if (proxy.type() == QNetworkProxy::NoProxy)
-	{
-		qDebug() << "Using no proxy is an option!";
-		return;
-	}
-	switch (proxy.type())
-	{
-	case QNetworkProxy::DefaultProxy:
-		proxyDesc = "Default proxy: ";
-		break;
-	case QNetworkProxy::Socks5Proxy:
-		proxyDesc = "Socks5 proxy: ";
-		break;
-	case QNetworkProxy::HttpProxy:
-		proxyDesc = "HTTP proxy: ";
-		break;
-	case QNetworkProxy::HttpCachingProxy:
-		proxyDesc = "HTTP caching: ";
-		break;
-	case QNetworkProxy::FtpCachingProxy:
-		proxyDesc = "FTP caching: ";
-		break;
-	default:
-		proxyDesc = "DERP proxy: ";
-		break;
-	}
-	proxyDesc += QString("%3@%1:%2 pass %4")
-					 .arg(proxy.hostName())
-					 .arg(proxy.port())
-					 .arg(proxy.user())
-					 .arg(proxy.password());
-	qDebug() << proxyDesc;
+    // Set the application proxy settings.
+    if (proxyTypeStr == "SOCKS5")
+    {
+        QNetworkProxy::setApplicationProxy(
+            QNetworkProxy(QNetworkProxy::Socks5Proxy, addr, port, user, password));
+    }
+    else if (proxyTypeStr == "HTTP")
+    {
+        QNetworkProxy::setApplicationProxy(
+            QNetworkProxy(QNetworkProxy::HttpProxy, addr, port, user, password));
+    }
+    else if (proxyTypeStr == "None")
+    {
+        // If we have no proxy set, set no proxy and return.
+        QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::NoProxy));
+    }
+    else
+    {
+        // If we have "Default" selected, set Qt to use the system proxy settings.
+        QNetworkProxyFactory::setUseSystemConfiguration(true);
+    }
+
+    qDebug() << "Detecting proxy settings...";
+    QNetworkProxy proxy = QNetworkProxy::applicationProxy();
+    d->m_qnam.setProxy(proxy);
+    QString proxyDesc;
+    if (proxy.type() == QNetworkProxy::NoProxy)
+    {
+        qDebug() << "Using no proxy is an option!";
+        return;
+    }
+    switch (proxy.type())
+    {
+    case QNetworkProxy::DefaultProxy:
+        proxyDesc = "Default proxy: ";
+        break;
+    case QNetworkProxy::Socks5Proxy:
+        proxyDesc = "Socks5 proxy: ";
+        break;
+    case QNetworkProxy::HttpProxy:
+        proxyDesc = "HTTP proxy: ";
+        break;
+    case QNetworkProxy::HttpCachingProxy:
+        proxyDesc = "HTTP caching: ";
+        break;
+    case QNetworkProxy::FtpCachingProxy:
+        proxyDesc = "FTP caching: ";
+        break;
+    default:
+        proxyDesc = "DERP proxy: ";
+        break;
+    }
+    proxyDesc += QString("%3@%1:%2 pass %4")
+                     .arg(proxy.hostName())
+                     .arg(proxy.port())
+                     .arg(proxy.user())
+                     .arg(proxy.password());
+    qDebug() << proxyDesc;
 }
 
 QString Env::getJarsPath()
 {
-	if(d->m_jarsPath.isEmpty())
-	{
-		return FS::PathCombine(QCoreApplication::applicationDirPath(), "jars");
-	}
-	return d->m_jarsPath;
+    if(d->m_jarsPath.isEmpty())
+    {
+        return FS::PathCombine(QCoreApplication::applicationDirPath(), "jars");
+    }
+    return d->m_jarsPath;
 }
 
 void Env::setJarsPath(const QString& path)
 {
-	d->m_jarsPath = path;
+    d->m_jarsPath = path;
 }
diff --git a/api/logic/Env.h b/api/logic/Env.h
index 276d762d..4d9ec139 100644
--- a/api/logic/Env.h
+++ b/api/logic/Env.h
@@ -20,40 +20,40 @@ class Index;
 }
 
 #if defined(ENV)
-	#undef ENV
+    #undef ENV
 #endif
 #define ENV (Env::getInstance())
 
 
 class MULTIMC_LOGIC_EXPORT Env
 {
-	friend class MultiMC;
+    friend class MultiMC;
 private:
-	struct Private;
-	Env();
-	~Env();
-	static void dispose();
+    struct Private;
+    Env();
+    ~Env();
+    static void dispose();
 public:
-	static Env& getInstance();
+    static Env& getInstance();
 
-	QNetworkAccessManager &qnam() const;
+    QNetworkAccessManager &qnam() const;
 
-	shared_qobject_ptr<HttpMetaCache> metacache();
+    shared_qobject_ptr<HttpMetaCache> metacache();
 
-	std::shared_ptr<IIconList> icons();
+    std::shared_ptr<IIconList> icons();
 
-	/// init the cache. FIXME: possible future hook point
-	void initHttpMetaCache();
+    /// init the cache. FIXME: possible future hook point
+    void initHttpMetaCache();
 
-	/// Updates the application proxy settings from the settings object.
-	void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
+    /// Updates the application proxy settings from the settings object.
+    void updateProxySettings(QString proxyTypeStr, QString addr, int port, QString user, QString password);
 
-	void registerIconList(std::shared_ptr<IIconList> iconlist);
+    void registerIconList(std::shared_ptr<IIconList> iconlist);
 
-	shared_qobject_ptr<Meta::Index> metadataIndex();
+    shared_qobject_ptr<Meta::Index> metadataIndex();
 
-	QString getJarsPath();
-	void setJarsPath(const QString & path);
+    QString getJarsPath();
+    void setJarsPath(const QString & path);
 protected:
-	Private * d;
+    Private * d;
 };
diff --git a/api/logic/Exception.h b/api/logic/Exception.h
index 30c7aa45..9400b3f8 100644
--- a/api/logic/Exception.h
+++ b/api/logic/Exception.h
@@ -11,24 +11,24 @@
 class MULTIMC_LOGIC_EXPORT Exception : public std::exception
 {
 public:
-	Exception(const QString &message) : std::exception(), m_message(message)
-	{
-		qCritical() << "Exception:" << message;
-	}
-	Exception(const Exception &other)
-		: std::exception(), m_message(other.cause())
-	{
-	}
-	virtual ~Exception() noexcept {}
-	const char *what() const noexcept
-	{
-		return m_message.toLatin1().constData();
-	}
-	QString cause() const
-	{
-		return m_message;
-	}
+    Exception(const QString &message) : std::exception(), m_message(message)
+    {
+        qCritical() << "Exception:" << message;
+    }
+    Exception(const Exception &other)
+        : std::exception(), m_message(other.cause())
+    {
+    }
+    virtual ~Exception() noexcept {}
+    const char *what() const noexcept
+    {
+        return m_message.toLatin1().constData();
+    }
+    QString cause() const
+    {
+        return m_message;
+    }
 
 private:
-	QString m_message;
+    QString m_message;
 };
diff --git a/api/logic/FileSystem.cpp b/api/logic/FileSystem.cpp
index aef35375..1d8b290d 100644
--- a/api/logic/FileSystem.cpp
+++ b/api/logic/FileSystem.cpp
@@ -12,262 +12,262 @@
 #include <QTextStream>
 
 #if defined Q_OS_WIN32
-	#include <windows.h>
-	#include <string>
-	#include <sys/utime.h>
-	#include <winnls.h>
-	#include <shobjidl.h>
-	#include <objbase.h>
-	#include <objidl.h>
-	#include <shlguid.h>
-	#include <shlobj.h>
+    #include <windows.h>
+    #include <string>
+    #include <sys/utime.h>
+    #include <winnls.h>
+    #include <shobjidl.h>
+    #include <objbase.h>
+    #include <objidl.h>
+    #include <shlguid.h>
+    #include <shlobj.h>
 #else
-	#include <utime.h>
+    #include <utime.h>
 #endif
 
 namespace FS {
 
 void ensureExists(const QDir &dir)
 {
-	if (!QDir().mkpath(dir.absolutePath()))
-	{
-		throw FileSystemException("Unable to create folder " + dir.dirName() + " (" +
-									  dir.absolutePath() + ")");
-	}
+    if (!QDir().mkpath(dir.absolutePath()))
+    {
+        throw FileSystemException("Unable to create folder " + dir.dirName() + " (" +
+                                      dir.absolutePath() + ")");
+    }
 }
 
 void write(const QString &filename, const QByteArray &data)
 {
-	ensureExists(QFileInfo(filename).dir());
-	QSaveFile file(filename);
-	if (!file.open(QSaveFile::WriteOnly))
-	{
-		throw FileSystemException("Couldn't open " + filename + " for writing: " +
-								  file.errorString());
-	}
-	if (data.size() != file.write(data))
-	{
-		throw FileSystemException("Error writing data to " + filename + ": " +
-								  file.errorString());
-	}
-	if (!file.commit())
-	{
-		throw FileSystemException("Error while committing data to " + filename + ": " +
-								  file.errorString());
-	}
+    ensureExists(QFileInfo(filename).dir());
+    QSaveFile file(filename);
+    if (!file.open(QSaveFile::WriteOnly))
+    {
+        throw FileSystemException("Couldn't open " + filename + " for writing: " +
+                                  file.errorString());
+    }
+    if (data.size() != file.write(data))
+    {
+        throw FileSystemException("Error writing data to " + filename + ": " +
+                                  file.errorString());
+    }
+    if (!file.commit())
+    {
+        throw FileSystemException("Error while committing data to " + filename + ": " +
+                                  file.errorString());
+    }
 }
 
 QByteArray read(const QString &filename)
 {
-	QFile file(filename);
-	if (!file.open(QFile::ReadOnly))
-	{
-		throw FileSystemException("Unable to open " + filename + " for reading: " +
-								  file.errorString());
-	}
-	const qint64 size = file.size();
-	QByteArray data(int(size), 0);
-	const qint64 ret = file.read(data.data(), size);
-	if (ret == -1 || ret != size)
-	{
-		throw FileSystemException("Error reading data from " + filename + ": " +
-								  file.errorString());
-	}
-	return data;
+    QFile file(filename);
+    if (!file.open(QFile::ReadOnly))
+    {
+        throw FileSystemException("Unable to open " + filename + " for reading: " +
+                                  file.errorString());
+    }
+    const qint64 size = file.size();
+    QByteArray data(int(size), 0);
+    const qint64 ret = file.read(data.data(), size);
+    if (ret == -1 || ret != size)
+    {
+        throw FileSystemException("Error reading data from " + filename + ": " +
+                                  file.errorString());
+    }
+    return data;
 }
 
 bool updateTimestamp(const QString& filename)
 {
 #ifdef Q_OS_WIN32
-	std::wstring filename_utf_16 = filename.toStdWString();
-	return (_wutime64(filename_utf_16.c_str(), nullptr) == 0);
+    std::wstring filename_utf_16 = filename.toStdWString();
+    return (_wutime64(filename_utf_16.c_str(), nullptr) == 0);
 #else
-	QByteArray filenameBA = QFile::encodeName(filename);
-	return (utime(filenameBA.data(), nullptr) == 0);
+    QByteArray filenameBA = QFile::encodeName(filename);
+    return (utime(filenameBA.data(), nullptr) == 0);
 #endif
 }
 
 bool ensureFilePathExists(QString filenamepath)
 {
-	QFileInfo a(filenamepath);
-	QDir dir;
-	QString ensuredPath = a.path();
-	bool success = dir.mkpath(ensuredPath);
-	return success;
+    QFileInfo a(filenamepath);
+    QDir dir;
+    QString ensuredPath = a.path();
+    bool success = dir.mkpath(ensuredPath);
+    return success;
 }
 
 bool ensureFolderPathExists(QString foldernamepath)
 {
-	QFileInfo a(foldernamepath);
-	QDir dir;
-	QString ensuredPath = a.filePath();
-	bool success = dir.mkpath(ensuredPath);
-	return success;
+    QFileInfo a(foldernamepath);
+    QDir dir;
+    QString ensuredPath = a.filePath();
+    bool success = dir.mkpath(ensuredPath);
+    return success;
 }
 
 bool copy::operator()(const QString &offset)
 {
-	//NOTE always deep copy on windows. the alternatives are too messy.
-	#if defined Q_OS_WIN32
-	m_followSymlinks = true;
-	#endif
-
-	auto src = PathCombine(m_src.absolutePath(), offset);
-	auto dst = PathCombine(m_dst.absolutePath(), offset);
-
-	QFileInfo currentSrc(src);
-	if (!currentSrc.exists())
-		return false;
-
-	if(!m_followSymlinks && currentSrc.isSymLink())
-	{
-		qDebug() << "creating symlink" << src << " - " << dst;
-		if (!ensureFilePathExists(dst))
-		{
-			qWarning() << "Cannot create path!";
-			return false;
-		}
-		return QFile::link(currentSrc.symLinkTarget(), dst);
-	}
-	else if(currentSrc.isFile())
-	{
-		qDebug() << "copying file" << src << " - " << dst;
-		if (!ensureFilePathExists(dst))
-		{
-			qWarning() << "Cannot create path!";
-			return false;
-		}
-		return QFile::copy(src, dst);
-	}
-	else if(currentSrc.isDir())
-	{
-		qDebug() << "recursing" << offset;
-		if (!ensureFolderPathExists(dst))
-		{
-			qWarning() << "Cannot create path!";
-			return false;
-		}
-		QDir currentDir(src);
-		for(auto & f : currentDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System))
-		{
-			auto inner_offset = PathCombine(offset, f);
-			// ignore and skip stuff that matches the blacklist.
-			if(m_blacklist && m_blacklist->matches(inner_offset))
-			{
-				continue;
-			}
-			if(!operator()(inner_offset))
-			{
-				qWarning() << "Failed to copy" << inner_offset;
-				return false;
-			}
-		}
-	}
-	else
-	{
-		qCritical() << "Copy ERROR: Unknown filesystem object:" << src;
-		return false;
-	}
-	return true;
+    //NOTE always deep copy on windows. the alternatives are too messy.
+    #if defined Q_OS_WIN32
+    m_followSymlinks = true;
+    #endif
+
+    auto src = PathCombine(m_src.absolutePath(), offset);
+    auto dst = PathCombine(m_dst.absolutePath(), offset);
+
+    QFileInfo currentSrc(src);
+    if (!currentSrc.exists())
+        return false;
+
+    if(!m_followSymlinks && currentSrc.isSymLink())
+    {
+        qDebug() << "creating symlink" << src << " - " << dst;
+        if (!ensureFilePathExists(dst))
+        {
+            qWarning() << "Cannot create path!";
+            return false;
+        }
+        return QFile::link(currentSrc.symLinkTarget(), dst);
+    }
+    else if(currentSrc.isFile())
+    {
+        qDebug() << "copying file" << src << " - " << dst;
+        if (!ensureFilePathExists(dst))
+        {
+            qWarning() << "Cannot create path!";
+            return false;
+        }
+        return QFile::copy(src, dst);
+    }
+    else if(currentSrc.isDir())
+    {
+        qDebug() << "recursing" << offset;
+        if (!ensureFolderPathExists(dst))
+        {
+            qWarning() << "Cannot create path!";
+            return false;
+        }
+        QDir currentDir(src);
+        for(auto & f : currentDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System))
+        {
+            auto inner_offset = PathCombine(offset, f);
+            // ignore and skip stuff that matches the blacklist.
+            if(m_blacklist && m_blacklist->matches(inner_offset))
+            {
+                continue;
+            }
+            if(!operator()(inner_offset))
+            {
+                qWarning() << "Failed to copy" << inner_offset;
+                return false;
+            }
+        }
+    }
+    else
+    {
+        qCritical() << "Copy ERROR: Unknown filesystem object:" << src;
+        return false;
+    }
+    return true;
 }
 
 bool deletePath(QString path)
 {
-	bool OK = true;
-	QDir dir(path);
-
-	if (!dir.exists())
-	{
-		return OK;
-	}
-	auto allEntries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden |
-										QDir::AllDirs | QDir::Files,
-										QDir::DirsFirst);
-
-	for(auto & info: allEntries)
-	{
+    bool OK = true;
+    QDir dir(path);
+
+    if (!dir.exists())
+    {
+        return OK;
+    }
+    auto allEntries = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden |
+                                        QDir::AllDirs | QDir::Files,
+                                        QDir::DirsFirst);
+
+    for(auto & info: allEntries)
+    {
 #if defined Q_OS_WIN32
-		QString nativePath = QDir::toNativeSeparators(info.absoluteFilePath());
-		auto wString = nativePath.toStdWString();
-		DWORD dwAttrs = GetFileAttributesW(wString.c_str());
-		// Windows: check for junctions, reparse points and other nasty things of that sort
-		if(dwAttrs & FILE_ATTRIBUTE_REPARSE_POINT)
-		{
-			if (info.isFile())
-			{
-				OK &= QFile::remove(info.absoluteFilePath());
-			}
-			else if (info.isDir())
-			{
-				OK &= dir.rmdir(info.absoluteFilePath());
-			}
-		}
+        QString nativePath = QDir::toNativeSeparators(info.absoluteFilePath());
+        auto wString = nativePath.toStdWString();
+        DWORD dwAttrs = GetFileAttributesW(wString.c_str());
+        // Windows: check for junctions, reparse points and other nasty things of that sort
+        if(dwAttrs & FILE_ATTRIBUTE_REPARSE_POINT)
+        {
+            if (info.isFile())
+            {
+                OK &= QFile::remove(info.absoluteFilePath());
+            }
+            else if (info.isDir())
+            {
+                OK &= dir.rmdir(info.absoluteFilePath());
+            }
+        }
 #else
-		// We do not trust Qt with reparse points, but do trust it with unix symlinks.
-		if(info.isSymLink())
-		{
-			OK &= QFile::remove(info.absoluteFilePath());
-		}
+        // We do not trust Qt with reparse points, but do trust it with unix symlinks.
+        if(info.isSymLink())
+        {
+            OK &= QFile::remove(info.absoluteFilePath());
+        }
 #endif
-		else if (info.isDir())
-		{
-			OK &= deletePath(info.absoluteFilePath());
-		}
-		else if (info.isFile())
-		{
-			OK &= QFile::remove(info.absoluteFilePath());
-		}
-		else
-		{
-			OK = false;
-			qCritical() << "Delete ERROR: Unknown filesystem object:" << info.absoluteFilePath();
-		}
-	}
-	OK &= dir.rmdir(dir.absolutePath());
-	return OK;
+        else if (info.isDir())
+        {
+            OK &= deletePath(info.absoluteFilePath());
+        }
+        else if (info.isFile())
+        {
+            OK &= QFile::remove(info.absoluteFilePath());
+        }
+        else
+        {
+            OK = false;
+            qCritical() << "Delete ERROR: Unknown filesystem object:" << info.absoluteFilePath();
+        }
+    }
+    OK &= dir.rmdir(dir.absolutePath());
+    return OK;
 }
 
 
 QString PathCombine(const QString & path1, const QString & path2)
 {
-	if(!path1.size())
-		return path2;
-	if(!path2.size())
-		return path1;
+    if(!path1.size())
+        return path2;
+    if(!path2.size())
+        return path1;
     return QDir::cleanPath(path1 + QDir::separator() + path2);
 }
 
 QString PathCombine(const QString & path1, const QString & path2, const QString & path3)
 {
-	return PathCombine(PathCombine(path1, path2), path3);
+    return PathCombine(PathCombine(path1, path2), path3);
 }
 
 QString PathCombine(const QString & path1, const QString & path2, const QString & path3, const QString & path4)
 {
-	return PathCombine(PathCombine(path1, path2, path3), path4);
+    return PathCombine(PathCombine(path1, path2, path3), path4);
 }
 
 QString AbsolutePath(QString path)
 {
-	return QFileInfo(path).absolutePath();
+    return QFileInfo(path).absolutePath();
 }
 
 QString ResolveExecutable(QString path)
 {
-	if (path.isEmpty())
-	{
-		return QString();
-	}
-	if(!path.contains('/'))
-	{
-		path = QStandardPaths::findExecutable(path);
-	}
-	QFileInfo pathInfo(path);
-	if(!pathInfo.exists() || !pathInfo.isExecutable())
-	{
-		return QString();
-	}
-	return pathInfo.absoluteFilePath();
+    if (path.isEmpty())
+    {
+        return QString();
+    }
+    if(!path.contains('/'))
+    {
+        path = QStandardPaths::findExecutable(path);
+    }
+    QFileInfo pathInfo(path);
+    if(!pathInfo.exists() || !pathInfo.isExecutable())
+    {
+        return QString();
+    }
+    return pathInfo.absoluteFilePath();
 }
 
 /**
@@ -278,66 +278,66 @@ QString ResolveExecutable(QString path)
  */
 QString NormalizePath(QString path)
 {
-	QDir a = QDir::currentPath();
-	QString currentAbsolute = a.absolutePath();
-
-	QDir b(path);
-	QString newAbsolute = b.absolutePath();
-
-	if (newAbsolute.startsWith(currentAbsolute))
-	{
-		return a.relativeFilePath(newAbsolute);
-	}
-	else
-	{
-		return newAbsolute;
-	}
+    QDir a = QDir::currentPath();
+    QString currentAbsolute = a.absolutePath();
+
+    QDir b(path);
+    QString newAbsolute = b.absolutePath();
+
+    if (newAbsolute.startsWith(currentAbsolute))
+    {
+        return a.relativeFilePath(newAbsolute);
+    }
+    else
+    {
+        return newAbsolute;
+    }
 }
 
 QString badFilenameChars = "\"\\/?<>:*|!";
 
 QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
 {
-	for (int i = 0; i < string.length(); i++)
-	{
-		if (badFilenameChars.contains(string[i]))
-		{
-			string[i] = replaceWith;
-		}
-	}
-	return string;
+    for (int i = 0; i < string.length(); i++)
+    {
+        if (badFilenameChars.contains(string[i]))
+        {
+            string[i] = replaceWith;
+        }
+    }
+    return string;
 }
 
 QString DirNameFromString(QString string, QString inDir)
 {
-	int num = 0;
-	QString baseName = RemoveInvalidFilenameChars(string, '-');
-	QString dirName;
-	do
-	{
-		if(num == 0)
-		{
-			dirName = baseName;
-		}
-		else
-		{
-			dirName = baseName + QString::number(num);;
-		}
-
-		// If it's over 9000
-		if (num > 9000)
-			return "";
-		num++;
-	} while (QFileInfo(PathCombine(inDir, dirName)).exists());
-	return dirName;
+    int num = 0;
+    QString baseName = RemoveInvalidFilenameChars(string, '-');
+    QString dirName;
+    do
+    {
+        if(num == 0)
+        {
+            dirName = baseName;
+        }
+        else
+        {
+            dirName = baseName + QString::number(num);;
+        }
+
+        // If it's over 9000
+        if (num > 9000)
+            return "";
+        num++;
+    } while (QFileInfo(PathCombine(inDir, dirName)).exists());
+    return dirName;
 }
 
 // Does the folder path contain any '!'? If yes, return true, otherwise false.
 // (This is a problem for Java)
 bool checkProblemticPathJava(QDir folder)
 {
-	QString pathfoldername = folder.absolutePath();
-	return pathfoldername.contains("!", Qt::CaseInsensitive);
+    QString pathfoldername = folder.absolutePath();
+    return pathfoldername.contains("!", Qt::CaseInsensitive);
 }
 
 // Win32 crap
@@ -347,106 +347,106 @@ bool called_coinit = false;
 
 HRESULT CreateLink(LPCSTR linkPath, LPCSTR targetPath, LPCSTR args)
 {
-	HRESULT hres;
-
-	if (!called_coinit)
-	{
-		hres = CoInitialize(NULL);
-		called_coinit = true;
-
-		if (!SUCCEEDED(hres))
-		{
-			qWarning("Failed to initialize COM. Error 0x%08lX", hres);
-			return hres;
-		}
-	}
-
-	IShellLink *link;
-	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
-							(LPVOID *)&link);
-
-	if (SUCCEEDED(hres))
-	{
-		IPersistFile *persistFile;
-
-		link->SetPath(targetPath);
-		link->SetArguments(args);
-
-		hres = link->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile);
-		if (SUCCEEDED(hres))
-		{
-			WCHAR wstr[MAX_PATH];
-
-			MultiByteToWideChar(CP_ACP, 0, linkPath, -1, wstr, MAX_PATH);
-
-			hres = persistFile->Save(wstr, TRUE);
-			persistFile->Release();
-		}
-		link->Release();
-	}
-	return hres;
+    HRESULT hres;
+
+    if (!called_coinit)
+    {
+        hres = CoInitialize(NULL);
+        called_coinit = true;
+
+        if (!SUCCEEDED(hres))
+        {
+            qWarning("Failed to initialize COM. Error 0x%08lX", hres);
+            return hres;
+        }
+    }
+
+    IShellLink *link;
+    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
+                            (LPVOID *)&link);
+
+    if (SUCCEEDED(hres))
+    {
+        IPersistFile *persistFile;
+
+        link->SetPath(targetPath);
+        link->SetArguments(args);
+
+        hres = link->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile);
+        if (SUCCEEDED(hres))
+        {
+            WCHAR wstr[MAX_PATH];
+
+            MultiByteToWideChar(CP_ACP, 0, linkPath, -1, wstr, MAX_PATH);
+
+            hres = persistFile->Save(wstr, TRUE);
+            persistFile->Release();
+        }
+        link->Release();
+    }
+    return hres;
 }
 
 #endif
 
 QString getDesktopDir()
 {
-	return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
+    return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
 }
 
 // Cross-platform Shortcut creation
 bool createShortCut(QString location, QString dest, QStringList args, QString name,
-						  QString icon)
+                          QString icon)
 {
 #if defined Q_OS_LINUX
-	location = PathCombine(location, name + ".desktop");
+    location = PathCombine(location, name + ".desktop");
 
-	QFile f(location);
-	f.open(QIODevice::WriteOnly | QIODevice::Text);
-	QTextStream stream(&f);
+    QFile f(location);
+    f.open(QIODevice::WriteOnly | QIODevice::Text);
+    QTextStream stream(&f);
 
-	QString argstring;
-	if (!args.empty())
-		argstring = " '" + args.join("' '") + "'";
+    QString argstring;
+    if (!args.empty())
+        argstring = " '" + args.join("' '") + "'";
 
-	stream << "[Desktop Entry]"
-		   << "\n";
-	stream << "Type=Application"
-		   << "\n";
-	stream << "TryExec=" << dest.toLocal8Bit() << "\n";
-	stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
-	stream << "Name=" << name.toLocal8Bit() << "\n";
-	stream << "Icon=" << icon.toLocal8Bit() << "\n";
+    stream << "[Desktop Entry]"
+           << "\n";
+    stream << "Type=Application"
+           << "\n";
+    stream << "TryExec=" << dest.toLocal8Bit() << "\n";
+    stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
+    stream << "Name=" << name.toLocal8Bit() << "\n";
+    stream << "Icon=" << icon.toLocal8Bit() << "\n";
 
-	stream.flush();
-	f.close();
+    stream.flush();
+    f.close();
 
-	f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup |
-					 QFileDevice::ExeOther);
+    f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup |
+                     QFileDevice::ExeOther);
 
-	return true;
+    return true;
 #elif defined Q_OS_WIN
-	// TODO: Fix
-	//	QFile file(PathCombine(location, name + ".lnk"));
-	//	WCHAR *file_w;
-	//	WCHAR *dest_w;
-	//	WCHAR *args_w;
-	//	file.fileName().toWCharArray(file_w);
-	//	dest.toWCharArray(dest_w);
-
-	//	QString argStr;
-	//	for (int i = 0; i < args.count(); i++)
-	//	{
-	//		argStr.append(args[i]);
-	//		argStr.append(" ");
-	//	}
-	//	argStr.toWCharArray(args_w);
-
-	//	return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
-	return false;
+    // TODO: Fix
+    //    QFile file(PathCombine(location, name + ".lnk"));
+    //    WCHAR *file_w;
+    //    WCHAR *dest_w;
+    //    WCHAR *args_w;
+    //    file.fileName().toWCharArray(file_w);
+    //    dest.toWCharArray(dest_w);
+
+    //    QString argStr;
+    //    for (int i = 0; i < args.count(); i++)
+    //    {
+    //        argStr.append(args[i]);
+    //        argStr.append(" ");
+    //    }
+    //    argStr.toWCharArray(args_w);
+
+    //    return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
+    return false;
 #else
-	qWarning("Desktop Shortcuts not supported on your platform!");
-	return false;
+    qWarning("Desktop Shortcuts not supported on your platform!");
+    return false;
 #endif
 }
 }
diff --git a/api/logic/FileSystem.h b/api/logic/FileSystem.h
index de8774ff..55ec6a58 100644
--- a/api/logic/FileSystem.h
+++ b/api/logic/FileSystem.h
@@ -15,7 +15,7 @@ namespace FS
 class MULTIMC_LOGIC_EXPORT FileSystemException : public ::Exception
 {
 public:
-	FileSystemException(const QString &message) : Exception(message) {}
+    FileSystemException(const QString &message) : Exception(message) {}
 };
 
 /**
@@ -48,34 +48,34 @@ MULTIMC_LOGIC_EXPORT bool ensureFolderPathExists(QString filenamepath);
 class MULTIMC_LOGIC_EXPORT copy
 {
 public:
-	copy(const QString & src, const QString & dst)
-	{
-		m_src = src;
-		m_dst = dst;
-	}
-	copy & followSymlinks(const bool follow)
-	{
-		m_followSymlinks = follow;
-		return *this;
-	}
-	copy & blacklist(const IPathMatcher * filter)
-	{
-		m_blacklist = filter;
-		return *this;
-	}
-	bool operator()()
-	{
-		return operator()(QString());
-	}
+    copy(const QString & src, const QString & dst)
+    {
+        m_src = src;
+        m_dst = dst;
+    }
+    copy & followSymlinks(const bool follow)
+    {
+        m_followSymlinks = follow;
+        return *this;
+    }
+    copy & blacklist(const IPathMatcher * filter)
+    {
+        m_blacklist = filter;
+        return *this;
+    }
+    bool operator()()
+    {
+        return operator()(QString());
+    }
 
 private:
-	bool operator()(const QString &offset);
+    bool operator()(const QString &offset);
 
 private:
-	bool m_followSymlinks = true;
-	const IPathMatcher * m_blacklist = nullptr;
-	QDir m_src;
-	QDir m_dst;
+    bool m_followSymlinks = true;
+    const IPathMatcher * m_blacklist = nullptr;
+    QDir m_src;
+    QDir m_dst;
 };
 
 /**
diff --git a/api/logic/FileSystem_test.cpp b/api/logic/FileSystem_test.cpp
index d5e1eedb..df653ea1 100644
--- a/api/logic/FileSystem_test.cpp
+++ b/api/logic/FileSystem_test.cpp
@@ -7,155 +7,155 @@
 
 class FileSystemTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 
-	const QString bothSlash = "/foo/";
-	const QString trailingSlash = "foo/";
-	const QString leadingSlash = "/foo";
+    const QString bothSlash = "/foo/";
+    const QString trailingSlash = "foo/";
+    const QString leadingSlash = "/foo";
 
 private
 slots:
-	void test_pathCombine()
-	{
-		QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
-		QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
-		QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
-
-		QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
-		QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
-		QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
-	}
-
-	void test_PathCombine1_data()
-	{
-		QTest::addColumn<QString>("result");
-		QTest::addColumn<QString>("path1");
-		QTest::addColumn<QString>("path2");
-
-		QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc/def" << "ghi/jkl";
-		QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/def/" << "ghi/jkl";
+    void test_pathCombine()
+    {
+        QCOMPARE(QString("/foo/foo"), FS::PathCombine(bothSlash, bothSlash));
+        QCOMPARE(QString("foo/foo"), FS::PathCombine(trailingSlash, trailingSlash));
+        QCOMPARE(QString("/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash));
+
+        QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(bothSlash, bothSlash, bothSlash));
+        QCOMPARE(QString("foo/foo/foo"), FS::PathCombine(trailingSlash, trailingSlash, trailingSlash));
+        QCOMPARE(QString("/foo/foo/foo"), FS::PathCombine(leadingSlash, leadingSlash, leadingSlash));
+    }
+
+    void test_PathCombine1_data()
+    {
+        QTest::addColumn<QString>("result");
+        QTest::addColumn<QString>("path1");
+        QTest::addColumn<QString>("path2");
+
+        QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc/def" << "ghi/jkl";
+        QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/def/" << "ghi/jkl";
 #if defined(Q_OS_WIN)
-		QTest::newRow("win native, from C:") << "C:/abc" << "C:" << "abc";
-		QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def" << "ghi\\jkl";
-		QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def\\" << "ghi\\jkl";
+        QTest::newRow("win native, from C:") << "C:/abc" << "C:" << "abc";
+        QTest::newRow("win native 1") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def" << "ghi\\jkl";
+        QTest::newRow("win native 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\def\\" << "ghi\\jkl";
 #endif
-	}
-
-	void test_PathCombine1()
-	{
-		QFETCH(QString, result);
-		QFETCH(QString, path1);
-		QFETCH(QString, path2);
-
-		QCOMPARE(FS::PathCombine(path1, path2), result);
-	}
-
-	void test_PathCombine2_data()
-	{
-		QTest::addColumn<QString>("result");
-		QTest::addColumn<QString>("path1");
-		QTest::addColumn<QString>("path2");
-		QTest::addColumn<QString>("path3");
-
-		QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc" << "def" << "ghi/jkl";
-		QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/" << "def" << "ghi/jkl";
-		QTest::newRow("qt 3") << "/abc/def/ghi/jkl" << "/abc" << "def/" << "ghi/jkl";
-		QTest::newRow("qt 4") << "/abc/def/ghi/jkl" << "/abc/" << "def/" << "ghi/jkl";
+    }
+
+    void test_PathCombine1()
+    {
+        QFETCH(QString, result);
+        QFETCH(QString, path1);
+        QFETCH(QString, path2);
+
+        QCOMPARE(FS::PathCombine(path1, path2), result);
+    }
+
+    void test_PathCombine2_data()
+    {
+        QTest::addColumn<QString>("result");
+        QTest::addColumn<QString>("path1");
+        QTest::addColumn<QString>("path2");
+        QTest::addColumn<QString>("path3");
+
+        QTest::newRow("qt 1") << "/abc/def/ghi/jkl" << "/abc" << "def" << "ghi/jkl";
+        QTest::newRow("qt 2") << "/abc/def/ghi/jkl" << "/abc/" << "def" << "ghi/jkl";
+        QTest::newRow("qt 3") << "/abc/def/ghi/jkl" << "/abc" << "def/" << "ghi/jkl";
+        QTest::newRow("qt 4") << "/abc/def/ghi/jkl" << "/abc/" << "def/" << "ghi/jkl";
 #if defined(Q_OS_WIN)
-		QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def" << "ghi\\jkl";
-		QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
-		QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def\\" << "ghi\\jkl";
-		QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
+        QTest::newRow("win 1") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def" << "ghi\\jkl";
+        QTest::newRow("win 2") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
+        QTest::newRow("win 3") << "C:/abc/def/ghi/jkl" << "C:\\abc" << "def\\" << "ghi\\jkl";
+        QTest::newRow("win 4") << "C:/abc/def/ghi/jkl" << "C:\\abc\\" << "def" << "ghi\\jkl";
 #endif
-	}
-
-	void test_PathCombine2()
-	{
-		QFETCH(QString, result);
-		QFETCH(QString, path1);
-		QFETCH(QString, path2);
-		QFETCH(QString, path3);
-
-		QCOMPARE(FS::PathCombine(path1, path2, path3), result);
-	}
-
-	void test_copy()
-	{
-		QString folder = QFINDTESTDATA("data/test_folder");
-		auto f = [&folder]()
-		{
-			QTemporaryDir tempDir;
-			tempDir.setAutoRemove(true);
-			qDebug() << "From:" << folder << "To:" << tempDir.path();
-
-			QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
-			qDebug() << tempDir.path();
-			qDebug() << target_dir.path();
-			FS::copy c(folder, target_dir.path());
-			c();
-
-			for(auto entry: target_dir.entryList())
-			{
-				qDebug() << entry;
-			}
-			QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
-			QVERIFY(target_dir.entryList().contains("assets"));
-		};
-
-		// first try variant without trailing /
-		QVERIFY(!folder.endsWith('/'));
-		f();
-
-		// then variant with trailing /
-		folder.append('/');
-		QVERIFY(folder.endsWith('/'));
-		f();
-	}
-
-	void test_getDesktop()
-	{
-		QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
-	}
+    }
+
+    void test_PathCombine2()
+    {
+        QFETCH(QString, result);
+        QFETCH(QString, path1);
+        QFETCH(QString, path2);
+        QFETCH(QString, path3);
+
+        QCOMPARE(FS::PathCombine(path1, path2, path3), result);
+    }
+
+    void test_copy()
+    {
+        QString folder = QFINDTESTDATA("data/test_folder");
+        auto f = [&folder]()
+        {
+            QTemporaryDir tempDir;
+            tempDir.setAutoRemove(true);
+            qDebug() << "From:" << folder << "To:" << tempDir.path();
+
+            QDir target_dir(FS::PathCombine(tempDir.path(), "test_folder"));
+            qDebug() << tempDir.path();
+            qDebug() << target_dir.path();
+            FS::copy c(folder, target_dir.path());
+            c();
+
+            for(auto entry: target_dir.entryList())
+            {
+                qDebug() << entry;
+            }
+            QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+            QVERIFY(target_dir.entryList().contains("assets"));
+        };
+
+        // first try variant without trailing /
+        QVERIFY(!folder.endsWith('/'));
+        f();
+
+        // then variant with trailing /
+        folder.append('/');
+        QVERIFY(folder.endsWith('/'));
+        f();
+    }
+
+    void test_getDesktop()
+    {
+        QCOMPARE(FS::getDesktopDir(), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
+    }
 
 // this is only valid on linux
 // FIXME: implement on windows, OSX, then test.
 #if defined(Q_OS_LINUX)
-	void test_createShortcut_data()
-	{
-		QTest::addColumn<QString>("location");
-		QTest::addColumn<QString>("dest");
-		QTest::addColumn<QStringList>("args");
-		QTest::addColumn<QString>("name");
-		QTest::addColumn<QString>("iconLocation");
-		QTest::addColumn<QByteArray>("result");
-
-		QTest::newRow("unix") << QDir::currentPath()
-							  << "asdfDest"
-							  << (QStringList() << "arg1" << "arg2")
-							  << "asdf"
-							  << QString()
-						 #if defined(Q_OS_LINUX)
-							  << MULTIMC_GET_TEST_FILE("data/FileSystem-test_createShortcut-unix")
-						 #elif defined(Q_OS_WIN)
-							  << QByteArray()
-						 #endif
-								 ;
-	}
-
-	void test_createShortcut()
-	{
-		QFETCH(QString, location);
-		QFETCH(QString, dest);
-		QFETCH(QStringList, args);
-		QFETCH(QString, name);
-		QFETCH(QString, iconLocation);
-		QFETCH(QByteArray, result);
-
-		QVERIFY(FS::createShortCut(location, dest, args, name, iconLocation));
-		QCOMPARE(QString::fromLocal8Bit(TestsInternal::readFile(location + QDir::separator() + name + ".desktop")), QString::fromLocal8Bit(result));
-
-		//QDir().remove(location);
-	}
+    void test_createShortcut_data()
+    {
+        QTest::addColumn<QString>("location");
+        QTest::addColumn<QString>("dest");
+        QTest::addColumn<QStringList>("args");
+        QTest::addColumn<QString>("name");
+        QTest::addColumn<QString>("iconLocation");
+        QTest::addColumn<QByteArray>("result");
+
+        QTest::newRow("unix") << QDir::currentPath()
+                              << "asdfDest"
+                              << (QStringList() << "arg1" << "arg2")
+                              << "asdf"
+                              << QString()
+                         #if defined(Q_OS_LINUX)
+                              << MULTIMC_GET_TEST_FILE("data/FileSystem-test_createShortcut-unix")
+                         #elif defined(Q_OS_WIN)
+                              << QByteArray()
+                         #endif
+                                 ;
+    }
+
+    void test_createShortcut()
+    {
+        QFETCH(QString, location);
+        QFETCH(QString, dest);
+        QFETCH(QStringList, args);
+        QFETCH(QString, name);
+        QFETCH(QString, iconLocation);
+        QFETCH(QByteArray, result);
+
+        QVERIFY(FS::createShortCut(location, dest, args, name, iconLocation));
+        QCOMPARE(QString::fromLocal8Bit(TestsInternal::readFile(location + QDir::separator() + name + ".desktop")), QString::fromLocal8Bit(result));
+
+        //QDir().remove(location);
+    }
 #endif
 };
 
diff --git a/api/logic/Filter.cpp b/api/logic/Filter.cpp
index 7f6667ae..6ec26bcb 100644
--- a/api/logic/Filter.cpp
+++ b/api/logic/Filter.cpp
@@ -6,26 +6,26 @@ ContainsFilter::ContainsFilter(const QString& pattern) : pattern(pattern){}
 ContainsFilter::~ContainsFilter(){}
 bool ContainsFilter::accepts(const QString& value)
 {
-	return value.contains(pattern);
+    return value.contains(pattern);
 }
 
 ExactFilter::ExactFilter(const QString& pattern) : pattern(pattern){}
 ExactFilter::~ExactFilter(){}
 bool ExactFilter::accepts(const QString& value)
 {
-	return value.contains(pattern);
+    return value.contains(pattern);
 }
 
 RegexpFilter::RegexpFilter(const QString& regexp, bool invert)
-	:invert(invert)
+    :invert(invert)
 {
-	pattern.setPattern(regexp);
-	pattern.optimize();
+    pattern.setPattern(regexp);
+    pattern.optimize();
 }
 RegexpFilter::~RegexpFilter(){}
 bool RegexpFilter::accepts(const QString& value)
 {
-	auto match = pattern.match(value);
-	bool matched = match.hasMatch();
-	return invert ? (!matched) : (matched);
+    auto match = pattern.match(value);
+    bool matched = match.hasMatch();
+    return invert ? (!matched) : (matched);
 }
diff --git a/api/logic/Filter.h b/api/logic/Filter.h
index 8de7d8f9..1ba48e48 100644
--- a/api/logic/Filter.h
+++ b/api/logic/Filter.h
@@ -8,37 +8,37 @@
 class MULTIMC_LOGIC_EXPORT Filter
 {
 public:
-	virtual ~Filter();
-	virtual bool accepts(const QString & value) = 0;
+    virtual ~Filter();
+    virtual bool accepts(const QString & value) = 0;
 };
 
 class MULTIMC_LOGIC_EXPORT ContainsFilter: public Filter
 {
 public:
-	ContainsFilter(const QString &pattern);
-	virtual ~ContainsFilter();
-	bool accepts(const QString & value) override;
+    ContainsFilter(const QString &pattern);
+    virtual ~ContainsFilter();
+    bool accepts(const QString & value) override;
 private:
-	QString pattern;
+    QString pattern;
 };
 
 class MULTIMC_LOGIC_EXPORT ExactFilter: public Filter
 {
 public:
-	ExactFilter(const QString &pattern);
-	virtual ~ExactFilter();
-	bool accepts(const QString & value) override;
+    ExactFilter(const QString &pattern);
+    virtual ~ExactFilter();
+    bool accepts(const QString & value) override;
 private:
-	QString pattern;
+    QString pattern;
 };
 
 class MULTIMC_LOGIC_EXPORT RegexpFilter: public Filter
 {
 public:
-	RegexpFilter(const QString &regexp, bool invert);
-	virtual ~RegexpFilter();
-	bool accepts(const QString & value) override;
+    RegexpFilter(const QString &regexp, bool invert);
+    virtual ~RegexpFilter();
+    bool accepts(const QString & value) override;
 private:
-	QRegularExpression pattern;
-	bool invert = false;
+    QRegularExpression pattern;
+    bool invert = false;
 };
diff --git a/api/logic/FolderInstanceProvider.cpp b/api/logic/FolderInstanceProvider.cpp
index cedba408..4f89e5b7 100644
--- a/api/logic/FolderInstanceProvider.cpp
+++ b/api/logic/FolderInstanceProvider.cpp
@@ -18,322 +18,322 @@ const static int GROUP_FILE_FORMAT_VERSION = 1;
 
 struct WatchLock
 {
-	WatchLock(QFileSystemWatcher * watcher, const QString& instDir)
-		: m_watcher(watcher), m_instDir(instDir)
-	{
-		m_watcher->removePath(m_instDir);
-	}
-	~WatchLock()
-	{
-		m_watcher->addPath(m_instDir);
-	}
-	QFileSystemWatcher * m_watcher;
-	QString m_instDir;
+    WatchLock(QFileSystemWatcher * watcher, const QString& instDir)
+        : m_watcher(watcher), m_instDir(instDir)
+    {
+        m_watcher->removePath(m_instDir);
+    }
+    ~WatchLock()
+    {
+        m_watcher->addPath(m_instDir);
+    }
+    QFileSystemWatcher * m_watcher;
+    QString m_instDir;
 };
 
 FolderInstanceProvider::FolderInstanceProvider(SettingsObjectPtr settings, const QString& instDir)
-	: BaseInstanceProvider(settings)
+    : BaseInstanceProvider(settings)
 {
-	// Create aand normalize path
-	if (!QDir::current().exists(instDir))
-	{
-		QDir::current().mkpath(instDir);
-	}
-	// NOTE: canonicalPath requires the path to exist. Do not move this above the creation block!
-	m_instDir = QDir(instDir).canonicalPath();
-	m_watcher = new QFileSystemWatcher(this);
-	connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &FolderInstanceProvider::instanceDirContentsChanged);
-	m_watcher->addPath(m_instDir);
+    // Create aand normalize path
+    if (!QDir::current().exists(instDir))
+    {
+        QDir::current().mkpath(instDir);
+    }
+    // NOTE: canonicalPath requires the path to exist. Do not move this above the creation block!
+    m_instDir = QDir(instDir).canonicalPath();
+    m_watcher = new QFileSystemWatcher(this);
+    connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &FolderInstanceProvider::instanceDirContentsChanged);
+    m_watcher->addPath(m_instDir);
 }
 
 QList< InstanceId > FolderInstanceProvider::discoverInstances()
 {
-	QList<InstanceId> out;
-	QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden, QDirIterator::FollowSymlinks);
-	while (iter.hasNext())
-	{
-		QString subDir = iter.next();
-		QFileInfo dirInfo(subDir);
-		if (!QFileInfo(FS::PathCombine(subDir, "instance.cfg")).exists())
-			continue;
-		// if it is a symlink, ignore it if it goes to the instance folder
-		if(dirInfo.isSymLink())
-		{
-			QFileInfo targetInfo(dirInfo.symLinkTarget());
-			QFileInfo instDirInfo(m_instDir);
-			if(targetInfo.canonicalPath() == instDirInfo.canonicalFilePath())
-			{
-				qDebug() << "Ignoring symlink" << subDir << "that leads into the instances folder";
-				continue;
-			}
-		}
-		auto id = dirInfo.fileName();
-		out.append(id);
-		qDebug() << "Found instance ID" << id;
-	}
-	return out;
+    QList<InstanceId> out;
+    QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable | QDir::Hidden, QDirIterator::FollowSymlinks);
+    while (iter.hasNext())
+    {
+        QString subDir = iter.next();
+        QFileInfo dirInfo(subDir);
+        if (!QFileInfo(FS::PathCombine(subDir, "instance.cfg")).exists())
+            continue;
+        // if it is a symlink, ignore it if it goes to the instance folder
+        if(dirInfo.isSymLink())
+        {
+            QFileInfo targetInfo(dirInfo.symLinkTarget());
+            QFileInfo instDirInfo(m_instDir);
+            if(targetInfo.canonicalPath() == instDirInfo.canonicalFilePath())
+            {
+                qDebug() << "Ignoring symlink" << subDir << "that leads into the instances folder";
+                continue;
+            }
+        }
+        auto id = dirInfo.fileName();
+        out.append(id);
+        qDebug() << "Found instance ID" << id;
+    }
+    return out;
 }
 
 InstancePtr FolderInstanceProvider::loadInstance(const InstanceId& id)
 {
-	if(!m_groupsLoaded)
-	{
-		loadGroupList();
-	}
-
-	auto instanceRoot = FS::PathCombine(m_instDir, id);
-	auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
-	InstancePtr inst;
-
-	instanceSettings->registerSetting("InstanceType", "Legacy");
-
-	QString inst_type = instanceSettings->get("InstanceType").toString();
-
-	if (inst_type == "OneSix" || inst_type == "Nostalgia")
-	{
-		inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
-	}
-	else if (inst_type == "Legacy")
-	{
-		inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot));
-	}
-	else
-	{
-		inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot));
-	}
-	inst->init();
-	inst->setProvider(this);
-	auto iter = groupMap.find(id);
-	if (iter != groupMap.end())
-	{
-		inst->setGroupInitial((*iter));
-	}
-	connect(inst.get(), &BaseInstance::groupChanged, this, &FolderInstanceProvider::groupChanged);
-	qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot();
-	return inst;
+    if(!m_groupsLoaded)
+    {
+        loadGroupList();
+    }
+
+    auto instanceRoot = FS::PathCombine(m_instDir, id);
+    auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(instanceRoot, "instance.cfg"));
+    InstancePtr inst;
+
+    instanceSettings->registerSetting("InstanceType", "Legacy");
+
+    QString inst_type = instanceSettings->get("InstanceType").toString();
+
+    if (inst_type == "OneSix" || inst_type == "Nostalgia")
+    {
+        inst.reset(new MinecraftInstance(m_globalSettings, instanceSettings, instanceRoot));
+    }
+    else if (inst_type == "Legacy")
+    {
+        inst.reset(new LegacyInstance(m_globalSettings, instanceSettings, instanceRoot));
+    }
+    else
+    {
+        inst.reset(new NullInstance(m_globalSettings, instanceSettings, instanceRoot));
+    }
+    inst->init();
+    inst->setProvider(this);
+    auto iter = groupMap.find(id);
+    if (iter != groupMap.end())
+    {
+        inst->setGroupInitial((*iter));
+    }
+    connect(inst.get(), &BaseInstance::groupChanged, this, &FolderInstanceProvider::groupChanged);
+    qDebug() << "Loaded instance " << inst->name() << " from " << inst->instanceRoot();
+    return inst;
 }
 
 void FolderInstanceProvider::saveGroupList()
 {
-	WatchLock foo(m_watcher, m_instDir);
-	QString groupFileName = m_instDir + "/instgroups.json";
-	QMap<QString, QSet<QString>> reverseGroupMap;
-	for (auto iter = groupMap.begin(); iter != groupMap.end(); iter++)
-	{
-		QString id = iter.key();
-		QString group = iter.value();
-		if (group.isEmpty())
-			continue;
-
-		if (!reverseGroupMap.count(group))
-		{
-			QSet<QString> set;
-			set.insert(id);
-			reverseGroupMap[group] = set;
-		}
-		else
-		{
-			QSet<QString> &set = reverseGroupMap[group];
-			set.insert(id);
-		}
-	}
-	QJsonObject toplevel;
-	toplevel.insert("formatVersion", QJsonValue(QString("1")));
-	QJsonObject groupsArr;
-	for (auto iter = reverseGroupMap.begin(); iter != reverseGroupMap.end(); iter++)
-	{
-		auto list = iter.value();
-		auto name = iter.key();
-		QJsonObject groupObj;
-		QJsonArray instanceArr;
-		groupObj.insert("hidden", QJsonValue(QString("false")));
-		for (auto item : list)
-		{
-			instanceArr.append(QJsonValue(item));
-		}
-		groupObj.insert("instances", instanceArr);
-		groupsArr.insert(name, groupObj);
-	}
-	toplevel.insert("groups", groupsArr);
-	QJsonDocument doc(toplevel);
-	try
-	{
-		FS::write(groupFileName, doc.toJson());
-	}
-	catch (const FS::FileSystemException &e)
-	{
-		qCritical() << "Failed to write instance group file :" << e.cause();
-	}
+    WatchLock foo(m_watcher, m_instDir);
+    QString groupFileName = m_instDir + "/instgroups.json";
+    QMap<QString, QSet<QString>> reverseGroupMap;
+    for (auto iter = groupMap.begin(); iter != groupMap.end(); iter++)
+    {
+        QString id = iter.key();
+        QString group = iter.value();
+        if (group.isEmpty())
+            continue;
+
+        if (!reverseGroupMap.count(group))
+        {
+            QSet<QString> set;
+            set.insert(id);
+            reverseGroupMap[group] = set;
+        }
+        else
+        {
+            QSet<QString> &set = reverseGroupMap[group];
+            set.insert(id);
+        }
+    }
+    QJsonObject toplevel;
+    toplevel.insert("formatVersion", QJsonValue(QString("1")));
+    QJsonObject groupsArr;
+    for (auto iter = reverseGroupMap.begin(); iter != reverseGroupMap.end(); iter++)
+    {
+        auto list = iter.value();
+        auto name = iter.key();
+        QJsonObject groupObj;
+        QJsonArray instanceArr;
+        groupObj.insert("hidden", QJsonValue(QString("false")));
+        for (auto item : list)
+        {
+            instanceArr.append(QJsonValue(item));
+        }
+        groupObj.insert("instances", instanceArr);
+        groupsArr.insert(name, groupObj);
+    }
+    toplevel.insert("groups", groupsArr);
+    QJsonDocument doc(toplevel);
+    try
+    {
+        FS::write(groupFileName, doc.toJson());
+    }
+    catch (const FS::FileSystemException &e)
+    {
+        qCritical() << "Failed to write instance group file :" << e.cause();
+    }
 }
 
 void FolderInstanceProvider::loadGroupList()
 {
-	QSet<QString> groupSet;
-
-	QString groupFileName = m_instDir + "/instgroups.json";
-
-	// if there's no group file, fail
-	if (!QFileInfo(groupFileName).exists())
-		return;
-
-	QByteArray jsonData;
-	try
-	{
-		jsonData = FS::read(groupFileName);
-	}
-	catch (const FS::FileSystemException &e)
-	{
-		qCritical() << "Failed to read instance group file :" << e.cause();
-		return;
-	}
-
-	QJsonParseError error;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
-
-	// if the json was bad, fail
-	if (error.error != QJsonParseError::NoError)
-	{
-		qCritical() << QString("Failed to parse instance group file: %1 at offset %2")
-							.arg(error.errorString(), QString::number(error.offset))
-							.toUtf8();
-		return;
-	}
-
-	// if the root of the json wasn't an object, fail
-	if (!jsonDoc.isObject())
-	{
-		qWarning() << "Invalid group file. Root entry should be an object.";
-		return;
-	}
-
-	QJsonObject rootObj = jsonDoc.object();
-
-	// Make sure the format version matches, otherwise fail.
-	if (rootObj.value("formatVersion").toVariant().toInt() != GROUP_FILE_FORMAT_VERSION)
-		return;
-
-	// Get the groups. if it's not an object, fail
-	if (!rootObj.value("groups").isObject())
-	{
-		qWarning() << "Invalid group list JSON: 'groups' should be an object.";
-		return;
-	}
-
-	groupMap.clear();
-
-	// Iterate through all the groups.
-	QJsonObject groupMapping = rootObj.value("groups").toObject();
-	for (QJsonObject::iterator iter = groupMapping.begin(); iter != groupMapping.end(); iter++)
-	{
-		QString groupName = iter.key();
-
-		// If not an object, complain and skip to the next one.
-		if (!iter.value().isObject())
-		{
-			qWarning() << QString("Group '%1' in the group list should "
-								   "be an object.")
-							   .arg(groupName)
-							   .toUtf8();
-			continue;
-		}
-
-		QJsonObject groupObj = iter.value().toObject();
-		if (!groupObj.value("instances").isArray())
-		{
-			qWarning() << QString("Group '%1' in the group list is invalid. "
-								   "It should contain an array "
-								   "called 'instances'.")
-							   .arg(groupName)
-							   .toUtf8();
-			continue;
-		}
-
-		// keep a list/set of groups for choosing
-		groupSet.insert(groupName);
-
-		// Iterate through the list of instances in the group.
-		QJsonArray instancesArray = groupObj.value("instances").toArray();
-
-		for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end();
-			 iter2++)
-		{
-			groupMap[(*iter2).toString()] = groupName;
-		}
-	}
-	m_groupsLoaded = true;
-	emit groupsChanged(groupSet);
+    QSet<QString> groupSet;
+
+    QString groupFileName = m_instDir + "/instgroups.json";
+
+    // if there's no group file, fail
+    if (!QFileInfo(groupFileName).exists())
+        return;
+
+    QByteArray jsonData;
+    try
+    {
+        jsonData = FS::read(groupFileName);
+    }
+    catch (const FS::FileSystemException &e)
+    {
+        qCritical() << "Failed to read instance group file :" << e.cause();
+        return;
+    }
+
+    QJsonParseError error;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
+
+    // if the json was bad, fail
+    if (error.error != QJsonParseError::NoError)
+    {
+        qCritical() << QString("Failed to parse instance group file: %1 at offset %2")
+                            .arg(error.errorString(), QString::number(error.offset))
+                            .toUtf8();
+        return;
+    }
+
+    // if the root of the json wasn't an object, fail
+    if (!jsonDoc.isObject())
+    {
+        qWarning() << "Invalid group file. Root entry should be an object.";
+        return;
+    }
+
+    QJsonObject rootObj = jsonDoc.object();
+
+    // Make sure the format version matches, otherwise fail.
+    if (rootObj.value("formatVersion").toVariant().toInt() != GROUP_FILE_FORMAT_VERSION)
+        return;
+
+    // Get the groups. if it's not an object, fail
+    if (!rootObj.value("groups").isObject())
+    {
+        qWarning() << "Invalid group list JSON: 'groups' should be an object.";
+        return;
+    }
+
+    groupMap.clear();
+
+    // Iterate through all the groups.
+    QJsonObject groupMapping = rootObj.value("groups").toObject();
+    for (QJsonObject::iterator iter = groupMapping.begin(); iter != groupMapping.end(); iter++)
+    {
+        QString groupName = iter.key();
+
+        // If not an object, complain and skip to the next one.
+        if (!iter.value().isObject())
+        {
+            qWarning() << QString("Group '%1' in the group list should "
+                                   "be an object.")
+                               .arg(groupName)
+                               .toUtf8();
+            continue;
+        }
+
+        QJsonObject groupObj = iter.value().toObject();
+        if (!groupObj.value("instances").isArray())
+        {
+            qWarning() << QString("Group '%1' in the group list is invalid. "
+                                   "It should contain an array "
+                                   "called 'instances'.")
+                               .arg(groupName)
+                               .toUtf8();
+            continue;
+        }
+
+        // keep a list/set of groups for choosing
+        groupSet.insert(groupName);
+
+        // Iterate through the list of instances in the group.
+        QJsonArray instancesArray = groupObj.value("instances").toArray();
+
+        for (QJsonArray::iterator iter2 = instancesArray.begin(); iter2 != instancesArray.end();
+             iter2++)
+        {
+            groupMap[(*iter2).toString()] = groupName;
+        }
+    }
+    m_groupsLoaded = true;
+    emit groupsChanged(groupSet);
 }
 
 void FolderInstanceProvider::groupChanged()
 {
-	// save the groups. save all of them.
-	auto instance = (BaseInstance *) QObject::sender();
-	auto id = instance->id();
-	groupMap[id] = instance->group();
-	emit groupsChanged({instance->group()});
-	saveGroupList();
+    // save the groups. save all of them.
+    auto instance = (BaseInstance *) QObject::sender();
+    auto id = instance->id();
+    groupMap[id] = instance->group();
+    emit groupsChanged({instance->group()});
+    saveGroupList();
 }
 
 
 void FolderInstanceProvider::instanceDirContentsChanged(const QString& path)
 {
-	Q_UNUSED(path);
-	emit instancesChanged();
+    Q_UNUSED(path);
+    emit instancesChanged();
 }
 
 void FolderInstanceProvider::on_InstFolderChanged(const Setting &setting, QVariant value)
 {
-	QString newInstDir = QDir(value.toString()).canonicalPath();
-	if(newInstDir != m_instDir)
-	{
-		if(m_groupsLoaded)
-		{
-			saveGroupList();
-		}
-		m_instDir = newInstDir;
-		m_groupsLoaded = false;
-		emit instancesChanged();
-	}
+    QString newInstDir = QDir(value.toString()).canonicalPath();
+    if(newInstDir != m_instDir)
+    {
+        if(m_groupsLoaded)
+        {
+            saveGroupList();
+        }
+        m_instDir = newInstDir;
+        m_groupsLoaded = false;
+        emit instancesChanged();
+    }
 }
 
 template <typename T>
 static void clamp(T& current, T min, T max)
 {
-	if (current < min)
-	{
-		current = min;
-	}
-	else if(current > max)
-	{
-		current = max;
-	}
+    if (current < min)
+    {
+        current = min;
+    }
+    else if(current > max)
+    {
+        current = max;
+    }
 }
 
 // List of numbers from min to max. Next is exponent times bigger than previous.
 class ExponentialSeries
 {
 public:
-	ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2)
-	{
-		m_current = m_min = min;
-		m_max = max;
-		m_exponent = exponent;
-	}
-	void reset()
-	{
-		m_current = m_min;
-	}
-	unsigned operator()()
-	{
-		unsigned retval = m_current;
-		m_current *= m_exponent;
-		clamp(m_current, m_min, m_max);
-		return retval;
-	}
-	unsigned m_current;
-	unsigned m_min;
-	unsigned m_max;
-	unsigned m_exponent;
+    ExponentialSeries(unsigned min, unsigned max, unsigned exponent = 2)
+    {
+        m_current = m_min = min;
+        m_max = max;
+        m_exponent = exponent;
+    }
+    void reset()
+    {
+        m_current = m_min;
+    }
+    unsigned operator()()
+    {
+        unsigned retval = m_current;
+        m_current *= m_exponent;
+        clamp(m_current, m_min, m_max);
+        return retval;
+    }
+    unsigned m_current;
+    unsigned m_min;
+    unsigned m_max;
+    unsigned m_exponent;
 };
 
 /*
@@ -344,121 +344,121 @@ public:
 class FolderInstanceStaging : public Task
 {
 Q_OBJECT
-	const unsigned minBackoff = 1;
-	const unsigned maxBackoff = 16;
+    const unsigned minBackoff = 1;
+    const unsigned maxBackoff = 16;
 public:
-	FolderInstanceStaging (
-		FolderInstanceProvider * parent,
-		Task * child,
-		const QString & stagingPath,
-		const QString& instanceName,
-		const QString& groupName )
-	: backoff(minBackoff, maxBackoff)
-	{
-		m_parent = parent;
-		m_child.reset(child);
-		connect(child, &Task::succeeded, this, &FolderInstanceStaging::childSucceded);
-		connect(child, &Task::failed, this, &FolderInstanceStaging::childFailed);
-		connect(child, &Task::status, this, &FolderInstanceStaging::setStatus);
-		connect(child, &Task::progress, this, &FolderInstanceStaging::setProgress);
-		m_instanceName = instanceName;
-		m_groupName = groupName;
-		m_stagingPath = stagingPath;
-		m_backoffTimer.setSingleShot(true);
-		connect(&m_backoffTimer, &QTimer::timeout, this, &FolderInstanceStaging::childSucceded);
-	}
-
-	virtual ~FolderInstanceStaging() {};
+    FolderInstanceStaging (
+        FolderInstanceProvider * parent,
+        Task * child,
+        const QString & stagingPath,
+        const QString& instanceName,
+        const QString& groupName )
+    : backoff(minBackoff, maxBackoff)
+    {
+        m_parent = parent;
+        m_child.reset(child);
+        connect(child, &Task::succeeded, this, &FolderInstanceStaging::childSucceded);
+        connect(child, &Task::failed, this, &FolderInstanceStaging::childFailed);
+        connect(child, &Task::status, this, &FolderInstanceStaging::setStatus);
+        connect(child, &Task::progress, this, &FolderInstanceStaging::setProgress);
+        m_instanceName = instanceName;
+        m_groupName = groupName;
+        m_stagingPath = stagingPath;
+        m_backoffTimer.setSingleShot(true);
+        connect(&m_backoffTimer, &QTimer::timeout, this, &FolderInstanceStaging::childSucceded);
+    }
+
+    virtual ~FolderInstanceStaging() {};
 
 protected:
-	virtual void executeTask() override
-	{
-		m_child->start();
-	}
-	QStringList warnings() const override
-	{
-		return m_child->warnings();
-	}
+    virtual void executeTask() override
+    {
+        m_child->start();
+    }
+    QStringList warnings() const override
+    {
+        return m_child->warnings();
+    }
 
 private slots:
-	void childSucceded()
-	{
-		unsigned sleepTime = backoff();
-		if(m_parent->commitStagedInstance(m_stagingPath, m_instanceName, m_groupName))
-		{
-			emitSucceeded();
-			return;
-		}
-		// we actually failed, retry?
-		if(sleepTime == maxBackoff)
-		{
-			emitFailed(tr("Failed to commit instance, even after multiple retries. It is being blocked by something."));
-			return;
-		}
-		qDebug() << "Failed to commit instance" << m_instanceName << "Initiating backoff:" << sleepTime;
-		m_backoffTimer.start(sleepTime * 500);
-	}
-	void childFailed(const QString & reason)
-	{
-		m_parent->destroyStagingPath(m_stagingPath);
-		emitFailed(reason);
-	}
+    void childSucceded()
+    {
+        unsigned sleepTime = backoff();
+        if(m_parent->commitStagedInstance(m_stagingPath, m_instanceName, m_groupName))
+        {
+            emitSucceeded();
+            return;
+        }
+        // we actually failed, retry?
+        if(sleepTime == maxBackoff)
+        {
+            emitFailed(tr("Failed to commit instance, even after multiple retries. It is being blocked by something."));
+            return;
+        }
+        qDebug() << "Failed to commit instance" << m_instanceName << "Initiating backoff:" << sleepTime;
+        m_backoffTimer.start(sleepTime * 500);
+    }
+    void childFailed(const QString & reason)
+    {
+        m_parent->destroyStagingPath(m_stagingPath);
+        emitFailed(reason);
+    }
 
 private:
-	ExponentialSeries backoff;
-	QString m_stagingPath;
-	FolderInstanceProvider * m_parent;
-	unique_qobject_ptr<Task> m_child;
-	QString m_instanceName;
-	QString m_groupName;
-	QTimer m_backoffTimer;
+    ExponentialSeries backoff;
+    QString m_stagingPath;
+    FolderInstanceProvider * m_parent;
+    unique_qobject_ptr<Task> m_child;
+    QString m_instanceName;
+    QString m_groupName;
+    QTimer m_backoffTimer;
 };
 
 #include "InstanceTask.h"
 Task * FolderInstanceProvider::wrapInstanceTask(InstanceTask * task)
 {
-	auto stagingPath = getStagedInstancePath();
-	task->setStagingPath(stagingPath);
-	task->setParentSettings(m_globalSettings);
-	return new FolderInstanceStaging(this, task, stagingPath, task->name(), task->group());
+    auto stagingPath = getStagedInstancePath();
+    task->setStagingPath(stagingPath);
+    task->setParentSettings(m_globalSettings);
+    return new FolderInstanceStaging(this, task, stagingPath, task->name(), task->group());
 }
 
 QString FolderInstanceProvider::getStagedInstancePath()
 {
-	QString key = QUuid::createUuid().toString();
-	QString relPath = FS::PathCombine("_MMC_TEMP/" , key);
-	QDir rootPath(m_instDir);
-	auto path = FS::PathCombine(m_instDir, relPath);
-	if(!rootPath.mkpath(relPath))
-	{
-		return QString();
-	}
-	return path;
+    QString key = QUuid::createUuid().toString();
+    QString relPath = FS::PathCombine("_MMC_TEMP/" , key);
+    QDir rootPath(m_instDir);
+    auto path = FS::PathCombine(m_instDir, relPath);
+    if(!rootPath.mkpath(relPath))
+    {
+        return QString();
+    }
+    return path;
 }
 
 bool FolderInstanceProvider::commitStagedInstance(const QString& path, const QString& instanceName, const QString& groupName)
 {
-	QDir dir;
-	QString instID = FS::DirNameFromString(instanceName, m_instDir);
-	{
-		WatchLock lock(m_watcher, m_instDir);
-		QString destination = FS::PathCombine(m_instDir, instID);
-		if(!dir.rename(path, destination))
-		{
-			qWarning() << "Failed to move" << path << "to" << destination;
-			return false;
-		}
-		groupMap[instID] = groupName;
-		emit groupsChanged({groupName});
-		emit instancesChanged();
-	}
-	saveGroupList();
-	return true;
+    QDir dir;
+    QString instID = FS::DirNameFromString(instanceName, m_instDir);
+    {
+        WatchLock lock(m_watcher, m_instDir);
+        QString destination = FS::PathCombine(m_instDir, instID);
+        if(!dir.rename(path, destination))
+        {
+            qWarning() << "Failed to move" << path << "to" << destination;
+            return false;
+        }
+        groupMap[instID] = groupName;
+        emit groupsChanged({groupName});
+        emit instancesChanged();
+    }
+    saveGroupList();
+    return true;
 }
 
 bool FolderInstanceProvider::destroyStagingPath(const QString& keyPath)
 {
-	return FS::deletePath(keyPath);
+    return FS::deletePath(keyPath);
 }
 
 #include "FolderInstanceProvider.moc"
diff --git a/api/logic/FolderInstanceProvider.h b/api/logic/FolderInstanceProvider.h
index e13dcfe9..fc14ba7a 100644
--- a/api/logic/FolderInstanceProvider.h
+++ b/api/logic/FolderInstanceProvider.h
@@ -8,68 +8,68 @@ class InstanceTask;
 
 class MULTIMC_LOGIC_EXPORT FolderInstanceProvider : public BaseInstanceProvider
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	FolderInstanceProvider(SettingsObjectPtr settings, const QString & instDir);
+    FolderInstanceProvider(SettingsObjectPtr settings, const QString & instDir);
 
 public:
-	/// used by InstanceList to @return a list of plausible IDs to probe for
-	QList<InstanceId> discoverInstances() override;
+    /// used by InstanceList to @return a list of plausible IDs to probe for
+    QList<InstanceId> discoverInstances() override;
 
-	/// used by InstanceList to (re)load an instance with the given @id.
-	InstancePtr loadInstance(const InstanceId& id) override;
+    /// used by InstanceList to (re)load an instance with the given @id.
+    InstancePtr loadInstance(const InstanceId& id) override;
 
 
-	/*
-	// create instance in this provider
-	Task * creationTask(BaseVersionPtr version, const QString &instName, const QString &instGroup, const QString &instIcon);
+    /*
+    // create instance in this provider
+    Task * creationTask(BaseVersionPtr version, const QString &instName, const QString &instGroup, const QString &instIcon);
 
-	// copy instance to this provider
-	Task * copyTask(const InstancePtr &oldInstance, const QString& instName, const QString& instGroup, const QString& instIcon, bool copySaves);
+    // copy instance to this provider
+    Task * copyTask(const InstancePtr &oldInstance, const QString& instName, const QString& instGroup, const QString& instIcon, bool copySaves);
 
-	// import zipped instance into this provider
-	Task * zipImportTask(const QUrl sourceUrl, const QString &instName, const QString &instGroup, const QString &instIcon);
+    // import zipped instance into this provider
+    Task * zipImportTask(const QUrl sourceUrl, const QString &instName, const QString &instGroup, const QString &instIcon);
 
-	//create FtbInstance
-	Task * ftbCreationTask(FtbPackDownloader *downloader, const QString &instName, const QString &instGroup, const QString &instIcon);
+    //create FtbInstance
+    Task * ftbCreationTask(FtbPackDownloader *downloader, const QString &instName, const QString &instGroup, const QString &instIcon);
 
-	// migrate an instance to the current format
-	Task * legacyUpgradeTask(const InstancePtr& oldInstance);
+    // migrate an instance to the current format
+    Task * legacyUpgradeTask(const InstancePtr& oldInstance);
 */
 
-	// Wrap an instance creation task in some more task machinery and make it ready to be used
-	Task * wrapInstanceTask(InstanceTask * task);
-
-	/**
-	 * Create a new empty staging area for instance creation and @return a path/key top commit it later.
-	 * Used by instance manipulation tasks.
-	 */
-	QString getStagedInstancePath() override;
-	/**
-	 * Commit the staging area given by @keyPath to the provider - used when creation succeeds.
-	 * Used by instance manipulation tasks.
-	 */
-	bool commitStagedInstance(const QString & keyPath, const QString& instanceName, const QString & groupName) override;
-	/**
-	 * Destroy a previously created staging area given by @keyPath - used when creation fails.
-	 * Used by instance manipulation tasks.
-	 */
-	bool destroyStagingPath(const QString & keyPath) override;
+    // Wrap an instance creation task in some more task machinery and make it ready to be used
+    Task * wrapInstanceTask(InstanceTask * task);
+
+    /**
+     * Create a new empty staging area for instance creation and @return a path/key top commit it later.
+     * Used by instance manipulation tasks.
+     */
+    QString getStagedInstancePath() override;
+    /**
+     * Commit the staging area given by @keyPath to the provider - used when creation succeeds.
+     * Used by instance manipulation tasks.
+     */
+    bool commitStagedInstance(const QString & keyPath, const QString& instanceName, const QString & groupName) override;
+    /**
+     * Destroy a previously created staging area given by @keyPath - used when creation fails.
+     * Used by instance manipulation tasks.
+     */
+    bool destroyStagingPath(const QString & keyPath) override;
 
 public slots:
-	void on_InstFolderChanged(const Setting &setting, QVariant value);
+    void on_InstFolderChanged(const Setting &setting, QVariant value);
 
 private slots:
-	void instanceDirContentsChanged(const QString &path);
-	void groupChanged();
+    void instanceDirContentsChanged(const QString &path);
+    void groupChanged();
 
 private: /* methods */
-	void loadGroupList() override;
-	void saveGroupList() override;
+    void loadGroupList() override;
+    void saveGroupList() override;
 
 private: /* data */
-	QString m_instDir;
-	QFileSystemWatcher * m_watcher;
-	QMap<QString, QString> groupMap;
-	bool m_groupsLoaded = false;
+    QString m_instDir;
+    QFileSystemWatcher * m_watcher;
+    QMap<QString, QString> groupMap;
+    bool m_groupsLoaded = false;
 };
diff --git a/api/logic/GZip.cpp b/api/logic/GZip.cpp
index 38605df6..0368c32d 100644
--- a/api/logic/GZip.cpp
+++ b/api/logic/GZip.cpp
@@ -4,112 +4,112 @@
 
 bool GZip::unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes)
 {
-	if (compressedBytes.size() == 0)
-	{
-		uncompressedBytes = compressedBytes;
-		return true;
-	}
-
-	unsigned uncompLength = compressedBytes.size();
-	uncompressedBytes.clear();
-	uncompressedBytes.resize(uncompLength);
-
-	z_stream strm;
-	memset(&strm, 0, sizeof(strm));
-	strm.next_in = (Bytef *)compressedBytes.data();
-	strm.avail_in = compressedBytes.size();
-
-	bool done = false;
-
-	if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK)
-	{
-		return false;
-	}
-
-	int err = Z_OK;
-
-	while (!done)
-	{
-		// If our output buffer is too small
-		if (strm.total_out >= uncompLength)
-		{
-			uncompressedBytes.resize(uncompLength * 2);
-			uncompLength *= 2;
-		}
-
-		strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out);
-		strm.avail_out = uncompLength - strm.total_out;
-
-		// Inflate another chunk.
-		err = inflate(&strm, Z_SYNC_FLUSH);
-		if (err == Z_STREAM_END)
-			done = true;
-		else if (err != Z_OK)
-		{
-			break;
-		}
-	}
-
-	if (inflateEnd(&strm) != Z_OK || !done)
-	{
-		return false;
-	}
-
-	uncompressedBytes.resize(strm.total_out);
-	return true;
+    if (compressedBytes.size() == 0)
+    {
+        uncompressedBytes = compressedBytes;
+        return true;
+    }
+
+    unsigned uncompLength = compressedBytes.size();
+    uncompressedBytes.clear();
+    uncompressedBytes.resize(uncompLength);
+
+    z_stream strm;
+    memset(&strm, 0, sizeof(strm));
+    strm.next_in = (Bytef *)compressedBytes.data();
+    strm.avail_in = compressedBytes.size();
+
+    bool done = false;
+
+    if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK)
+    {
+        return false;
+    }
+
+    int err = Z_OK;
+
+    while (!done)
+    {
+        // If our output buffer is too small
+        if (strm.total_out >= uncompLength)
+        {
+            uncompressedBytes.resize(uncompLength * 2);
+            uncompLength *= 2;
+        }
+
+        strm.next_out = (Bytef *)(uncompressedBytes.data() + strm.total_out);
+        strm.avail_out = uncompLength - strm.total_out;
+
+        // Inflate another chunk.
+        err = inflate(&strm, Z_SYNC_FLUSH);
+        if (err == Z_STREAM_END)
+            done = true;
+        else if (err != Z_OK)
+        {
+            break;
+        }
+    }
+
+    if (inflateEnd(&strm) != Z_OK || !done)
+    {
+        return false;
+    }
+
+    uncompressedBytes.resize(strm.total_out);
+    return true;
 }
 
 bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
 {
-	if (uncompressedBytes.size() == 0)
-	{
-		compressedBytes = uncompressedBytes;
-		return true;
-	}
-
-	unsigned compLength = std::min(uncompressedBytes.size(), 16);
-	compressedBytes.clear();
-	compressedBytes.resize(compLength);
-
-	z_stream zs;
-	memset(&zs, 0, sizeof(zs));
-
-	if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK)
-	{
-		return false;
-	}
-
-	zs.next_in = (Bytef*)uncompressedBytes.data();
-	zs.avail_in = uncompressedBytes.size();
-
-	int ret;
-	compressedBytes.resize(uncompressedBytes.size());
-
-	unsigned offset = 0;
-	unsigned temp = 0;
-	do
-	{
-		auto remaining = compressedBytes.size() - offset;
-		if(remaining < 1)
-		{
-			compressedBytes.resize(compressedBytes.size() * 2);
-		}
-		zs.next_out = (Bytef *) (compressedBytes.data() + offset);
-		temp = zs.avail_out = compressedBytes.size() - offset;
-		ret = deflate(&zs, Z_FINISH);
-		offset += temp - zs.avail_out;
-	} while (ret == Z_OK);
-
-	compressedBytes.resize(offset);
-
-	if (deflateEnd(&zs) != Z_OK)
-	{
-		return false;
-	}
-
-	if (ret != Z_STREAM_END)
-	{
-		return false;
-	}
-	return true;
+    if (uncompressedBytes.size() == 0)
+    {
+        compressedBytes = uncompressedBytes;
+        return true;
+    }
+
+    unsigned compLength = std::min(uncompressedBytes.size(), 16);
+    compressedBytes.clear();
+    compressedBytes.resize(compLength);
+
+    z_stream zs;
+    memset(&zs, 0, sizeof(zs));
+
+    if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (16 + MAX_WBITS), 8, Z_DEFAULT_STRATEGY) != Z_OK)
+    {
+        return false;
+    }
+
+    zs.next_in = (Bytef*)uncompressedBytes.data();
+    zs.avail_in = uncompressedBytes.size();
+
+    int ret;
+    compressedBytes.resize(uncompressedBytes.size());
+
+    unsigned offset = 0;
+    unsigned temp = 0;
+    do
+    {
+        auto remaining = compressedBytes.size() - offset;
+        if(remaining < 1)
+        {
+            compressedBytes.resize(compressedBytes.size() * 2);
+        }
+        zs.next_out = (Bytef *) (compressedBytes.data() + offset);
+        temp = zs.avail_out = compressedBytes.size() - offset;
+        ret = deflate(&zs, Z_FINISH);
+        offset += temp - zs.avail_out;
+    } while (ret == Z_OK);
+
+    compressedBytes.resize(offset);
+
+    if (deflateEnd(&zs) != Z_OK)
+    {
+        return false;
+    }
+
+    if (ret != Z_STREAM_END)
+    {
+        return false;
+    }
+    return true;
 }
\ No newline at end of file
diff --git a/api/logic/GZip.h b/api/logic/GZip.h
index 6993a222..c7eddbb3 100644
--- a/api/logic/GZip.h
+++ b/api/logic/GZip.h
@@ -6,7 +6,7 @@
 class MULTIMC_LOGIC_EXPORT GZip
 {
 public:
-	static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
-	static bool zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes);
+    static bool unzip(const QByteArray &compressedBytes, QByteArray &uncompressedBytes);
+    static bool zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes);
 };
 
diff --git a/api/logic/GZip_test.cpp b/api/logic/GZip_test.cpp
index f4c9214c..3f4d181c 100644
--- a/api/logic/GZip_test.cpp
+++ b/api/logic/GZip_test.cpp
@@ -6,50 +6,50 @@
 
 void fib(int &prev, int &cur)
 {
-	auto ret = prev + cur;
-	prev = cur;
-	cur = ret;
+    auto ret = prev + cur;
+    prev = cur;
+    cur = ret;
 }
 
 class GZipTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
 
-	void test_Through()
-	{
-		// test up to 10 MB
-		static const int size = 10 * 1024 * 1024;
-		QByteArray random;
-		QByteArray compressed;
-		QByteArray decompressed;
-		std::default_random_engine eng((std::random_device())());
-		std::uniform_int_distribution<uint8_t> idis(0, std::numeric_limits<uint8_t>::max());
-
-		// initialize random buffer
-		for(int i = 0; i < size; i++)
-		{
-			random.append((char)idis(eng));
-		}
-
-		// initialize fibonacci
-		int prev = 1;
-		int cur = 1;
-
-		// test if fibonacci long random buffers pass through GZip
-		do
-		{
-			QByteArray copy = random;
-			copy.resize(cur);
-			compressed.clear();
-			decompressed.clear();
-			QVERIFY(GZip::zip(copy, compressed));
-			QVERIFY(GZip::unzip(compressed, decompressed));
-			QCOMPARE(decompressed, copy);
-			fib(prev, cur);
-		} while (cur < size);
-	}
+    void test_Through()
+    {
+        // test up to 10 MB
+        static const int size = 10 * 1024 * 1024;
+        QByteArray random;
+        QByteArray compressed;
+        QByteArray decompressed;
+        std::default_random_engine eng((std::random_device())());
+        std::uniform_int_distribution<uint8_t> idis(0, std::numeric_limits<uint8_t>::max());
+
+        // initialize random buffer
+        for(int i = 0; i < size; i++)
+        {
+            random.append((char)idis(eng));
+        }
+
+        // initialize fibonacci
+        int prev = 1;
+        int cur = 1;
+
+        // test if fibonacci long random buffers pass through GZip
+        do
+        {
+            QByteArray copy = random;
+            copy.resize(cur);
+            compressed.clear();
+            decompressed.clear();
+            QVERIFY(GZip::zip(copy, compressed));
+            QVERIFY(GZip::unzip(compressed, decompressed));
+            QCOMPARE(decompressed, copy);
+            fib(prev, cur);
+        } while (cur < size);
+    }
 };
 
 QTEST_GUILESS_MAIN(GZipTest)
diff --git a/api/logic/InstanceCopyTask.cpp b/api/logic/InstanceCopyTask.cpp
index 62c22362..cb2deb29 100644
--- a/api/logic/InstanceCopyTask.cpp
+++ b/api/logic/InstanceCopyTask.cpp
@@ -8,50 +8,50 @@
 
 InstanceCopyTask::InstanceCopyTask(InstancePtr origInstance, bool copySaves)
 {
-	m_origInstance = origInstance;
-
-	if(!copySaves)
-	{
-		// FIXME: get this from the original instance type...
-		auto matcherReal = new RegexpMatcher("[.]?minecraft/saves");
-		matcherReal->caseSensitive(false);
-		m_matcher.reset(matcherReal);
-	}
+    m_origInstance = origInstance;
+
+    if(!copySaves)
+    {
+        // FIXME: get this from the original instance type...
+        auto matcherReal = new RegexpMatcher("[.]?minecraft/saves");
+        matcherReal->caseSensitive(false);
+        m_matcher.reset(matcherReal);
+    }
 }
 
 void InstanceCopyTask::executeTask()
 {
-	setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
+    setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
 
-	FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
-	folderCopy.followSymlinks(false).blacklist(m_matcher.get());
+    FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
+    folderCopy.followSymlinks(false).blacklist(m_matcher.get());
 
-	m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
-	connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
-	connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted);
-	m_copyFutureWatcher.setFuture(m_copyFuture);
+    m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
+    connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);
+    connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted);
+    m_copyFutureWatcher.setFuture(m_copyFuture);
 }
 
 void InstanceCopyTask::copyFinished()
 {
-	auto successful = m_copyFuture.result();
-	if(!successful)
-	{
-		emitFailed(tr("Instance folder copy failed."));
-		return;
-	}
-	// FIXME: shouldn't this be able to report errors?
-	auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
-	instanceSettings->registerSetting("InstanceType", "Legacy");
-
-	InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
-	inst->setName(m_instName);
-	inst->setIconKey(m_instIcon);
-	emitSucceeded();
+    auto successful = m_copyFuture.result();
+    if(!successful)
+    {
+        emitFailed(tr("Instance folder copy failed."));
+        return;
+    }
+    // FIXME: shouldn't this be able to report errors?
+    auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
+    instanceSettings->registerSetting("InstanceType", "Legacy");
+
+    InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath));
+    inst->setName(m_instName);
+    inst->setIconKey(m_instIcon);
+    emitSucceeded();
 }
 
 void InstanceCopyTask::copyAborted()
 {
-	emitFailed(tr("Instance folder copy has been aborted."));
-	return;
+    emitFailed(tr("Instance folder copy has been aborted."));
+    return;
 }
diff --git a/api/logic/InstanceCopyTask.h b/api/logic/InstanceCopyTask.h
index a8dc9783..0a338f2f 100644
--- a/api/logic/InstanceCopyTask.h
+++ b/api/logic/InstanceCopyTask.h
@@ -15,19 +15,19 @@ class BaseInstanceProvider;
 
 class MULTIMC_LOGIC_EXPORT InstanceCopyTask : public InstanceTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves);
+    explicit InstanceCopyTask(InstancePtr origInstance, bool copySaves);
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
-	void copyFinished();
-	void copyAborted();
+    //! Entry point for tasks.
+    virtual void executeTask() override;
+    void copyFinished();
+    void copyAborted();
 
 private: /* data */
-	InstancePtr m_origInstance;
-	QFuture<bool> m_copyFuture;
-	QFutureWatcher<bool> m_copyFutureWatcher;
-	std::unique_ptr<IPathMatcher> m_matcher;
+    InstancePtr m_origInstance;
+    QFuture<bool> m_copyFuture;
+    QFutureWatcher<bool> m_copyFutureWatcher;
+    std::unique_ptr<IPathMatcher> m_matcher;
 };
diff --git a/api/logic/InstanceCreationTask.cpp b/api/logic/InstanceCreationTask.cpp
index 6dc2496c..7ac474ec 100644
--- a/api/logic/InstanceCreationTask.cpp
+++ b/api/logic/InstanceCreationTask.cpp
@@ -9,25 +9,25 @@
 
 InstanceCreationTask::InstanceCreationTask(BaseVersionPtr version)
 {
-	m_version = version;
+    m_version = version;
 }
 
 void InstanceCreationTask::executeTask()
 {
-	setStatus(tr("Creating instance from version %1").arg(m_version->name()));
-	{
-		auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
-		instanceSettings->suspendSave();
-		instanceSettings->registerSetting("InstanceType", "Legacy");
-		instanceSettings->set("InstanceType", "OneSix");
-		MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
-		auto components = inst.getComponentList();
-		components->buildingFromScratch();
-		components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
-		inst.setName(m_instName);
-		inst.setIconKey(m_instIcon);
-		inst.init();
-		instanceSettings->resumeSave();
-	}
-	emitSucceeded();
+    setStatus(tr("Creating instance from version %1").arg(m_version->name()));
+    {
+        auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
+        instanceSettings->suspendSave();
+        instanceSettings->registerSetting("InstanceType", "Legacy");
+        instanceSettings->set("InstanceType", "OneSix");
+        MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
+        auto components = inst.getComponentList();
+        components->buildingFromScratch();
+        components->setComponentVersion("net.minecraft", m_version->descriptor(), true);
+        inst.setName(m_instName);
+        inst.setIconKey(m_instIcon);
+        inst.init();
+        instanceSettings->resumeSave();
+    }
+    emitSucceeded();
 }
diff --git a/api/logic/InstanceCreationTask.h b/api/logic/InstanceCreationTask.h
index e06eacbb..154a854f 100644
--- a/api/logic/InstanceCreationTask.h
+++ b/api/logic/InstanceCreationTask.h
@@ -10,14 +10,14 @@
 
 class MULTIMC_LOGIC_EXPORT InstanceCreationTask : public InstanceTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit InstanceCreationTask(BaseVersionPtr version);
+    explicit InstanceCreationTask(BaseVersionPtr version);
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
+    //! Entry point for tasks.
+    virtual void executeTask() override;
 
 private: /* data */
-	BaseVersionPtr m_version;
+    BaseVersionPtr m_version;
 };
diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp
index 45037908..f3e0858d 100644
--- a/api/logic/InstanceImportTask.cpp
+++ b/api/logic/InstanceImportTask.cpp
@@ -18,394 +18,394 @@
 
 InstanceImportTask::InstanceImportTask(const QUrl sourceUrl)
 {
-	m_sourceUrl = sourceUrl;
+    m_sourceUrl = sourceUrl;
 }
 
 void InstanceImportTask::executeTask()
 {
-	InstancePtr newInstance;
+    InstancePtr newInstance;
 
-	if (m_sourceUrl.isLocalFile())
-	{
-		m_archivePath = m_sourceUrl.toLocalFile();
-		processZipPack();
-	}
-	else
-	{
-		setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString()));
-		m_downloadRequired = true;
+    if (m_sourceUrl.isLocalFile())
+    {
+        m_archivePath = m_sourceUrl.toLocalFile();
+        processZipPack();
+    }
+    else
+    {
+        setStatus(tr("Downloading modpack:\n%1").arg(m_sourceUrl.toString()));
+        m_downloadRequired = true;
 
-		const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path();
-		auto entry = ENV.metacache()->resolveEntry("general", path);
-		entry->setStale(true);
-		m_filesNetJob.reset(new NetJob(tr("Modpack download")));
-		m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
-		m_archivePath = entry->getFullPath();
-		auto job = m_filesNetJob.get();
-		connect(job, &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
-		connect(job, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
-		connect(job, &NetJob::failed, this, &InstanceImportTask::downloadFailed);
-		m_filesNetJob->start();
-	}
+        const QString path = m_sourceUrl.host() + '/' + m_sourceUrl.path();
+        auto entry = ENV.metacache()->resolveEntry("general", path);
+        entry->setStale(true);
+        m_filesNetJob.reset(new NetJob(tr("Modpack download")));
+        m_filesNetJob->addNetAction(Net::Download::makeCached(m_sourceUrl, entry));
+        m_archivePath = entry->getFullPath();
+        auto job = m_filesNetJob.get();
+        connect(job, &NetJob::succeeded, this, &InstanceImportTask::downloadSucceeded);
+        connect(job, &NetJob::progress, this, &InstanceImportTask::downloadProgressChanged);
+        connect(job, &NetJob::failed, this, &InstanceImportTask::downloadFailed);
+        m_filesNetJob->start();
+    }
 }
 
 void InstanceImportTask::downloadSucceeded()
 {
-	processZipPack();
-	m_filesNetJob.reset();
+    processZipPack();
+    m_filesNetJob.reset();
 }
 
 void InstanceImportTask::downloadFailed(QString reason)
 {
-	emitFailed(reason);
-	m_filesNetJob.reset();
+    emitFailed(reason);
+    m_filesNetJob.reset();
 }
 
 void InstanceImportTask::downloadProgressChanged(qint64 current, qint64 total)
 {
-	setProgress(current / 2, total);
+    setProgress(current / 2, total);
 }
 
 void InstanceImportTask::processZipPack()
 {
-	setStatus(tr("Extracting modpack"));
-	QDir extractDir(m_stagingPath);
-	qDebug() << "Attempting to create instance from" << m_archivePath;
+    setStatus(tr("Extracting modpack"));
+    QDir extractDir(m_stagingPath);
+    qDebug() << "Attempting to create instance from" << m_archivePath;
 
-	// open the zip and find relevant files in it
-	m_packZip.reset(new QuaZip(m_archivePath));
-	if (!m_packZip->open(QuaZip::mdUnzip))
-	{
-		emitFailed(tr("Unable to open supplied modpack zip file."));
-		return;
-	}
+    // open the zip and find relevant files in it
+    m_packZip.reset(new QuaZip(m_archivePath));
+    if (!m_packZip->open(QuaZip::mdUnzip))
+    {
+        emitFailed(tr("Unable to open supplied modpack zip file."));
+        return;
+    }
 
-	QStringList blacklist = {"instance.cfg", "manifest.json"};
-	QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
-	QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
-	QString root;
-	if(!mmcFound.isNull())
-	{
-		// process as MultiMC instance/pack
-		qDebug() << "MultiMC:" << mmcFound;
-		root = mmcFound;
-		m_modpackType = ModpackType::MultiMC;
-	}
-	else if(!flameFound.isNull())
-	{
-		// process as Flame pack
-		qDebug() << "Flame:" << flameFound;
-		root = flameFound;
-		m_modpackType = ModpackType::Flame;
-	}
+    QStringList blacklist = {"instance.cfg", "manifest.json"};
+    QString mmcFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg");
+    QString flameFound = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
+    QString root;
+    if(!mmcFound.isNull())
+    {
+        // process as MultiMC instance/pack
+        qDebug() << "MultiMC:" << mmcFound;
+        root = mmcFound;
+        m_modpackType = ModpackType::MultiMC;
+    }
+    else if(!flameFound.isNull())
+    {
+        // process as Flame pack
+        qDebug() << "Flame:" << flameFound;
+        root = flameFound;
+        m_modpackType = ModpackType::Flame;
+    }
 
-	if(m_modpackType == ModpackType::Unknown)
-	{
-		emitFailed(tr("Archive does not contain a recognized modpack type."));
-		return;
-	}
+    if(m_modpackType == ModpackType::Unknown)
+    {
+        emitFailed(tr("Archive does not contain a recognized modpack type."));
+        return;
+    }
 
-	// make sure we extract just the pack
-	m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
-	connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
-	connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted);
-	m_extractFutureWatcher.setFuture(m_extractFuture);
+    // make sure we extract just the pack
+    m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), root, extractDir.absolutePath());
+    connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished);
+    connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted);
+    m_extractFutureWatcher.setFuture(m_extractFuture);
 }
 
 void InstanceImportTask::extractFinished()
 {
-	m_packZip.reset();
-	if (m_extractFuture.result().isEmpty())
-	{
-		emitFailed(tr("Failed to extract modpack"));
-		return;
-	}
-	QDir extractDir(m_stagingPath);
+    m_packZip.reset();
+    if (m_extractFuture.result().isEmpty())
+    {
+        emitFailed(tr("Failed to extract modpack"));
+        return;
+    }
+    QDir extractDir(m_stagingPath);
 
-	qDebug() << "Fixing permissions for extracted pack files...";
-	QDirIterator it(extractDir, QDirIterator::Subdirectories);
-	while (it.hasNext())
-	{
-		auto filepath = it.next();
-		QFileInfo file(filepath);
-		auto permissions = QFile::permissions(filepath);
-		auto origPermissions = permissions;
-		if(file.isDir())
-		{
-			// Folder +rwx for current user
-			permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
-		}
-		else
-		{
-			// File +rw for current user
-			permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
-		}
-		if(origPermissions != permissions)
-		{
-			if(!QFile::setPermissions(filepath, permissions))
-			{
-				logWarning(tr("Could not fix permissions for %1").arg(filepath));
-			}
-			else
-			{
-				qDebug() << "Fixed" << filepath;
-			}
-		}
-	}
+    qDebug() << "Fixing permissions for extracted pack files...";
+    QDirIterator it(extractDir, QDirIterator::Subdirectories);
+    while (it.hasNext())
+    {
+        auto filepath = it.next();
+        QFileInfo file(filepath);
+        auto permissions = QFile::permissions(filepath);
+        auto origPermissions = permissions;
+        if(file.isDir())
+        {
+            // Folder +rwx for current user
+            permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
+        }
+        else
+        {
+            // File +rw for current user
+            permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
+        }
+        if(origPermissions != permissions)
+        {
+            if(!QFile::setPermissions(filepath, permissions))
+            {
+                logWarning(tr("Could not fix permissions for %1").arg(filepath));
+            }
+            else
+            {
+                qDebug() << "Fixed" << filepath;
+            }
+        }
+    }
 
-	switch(m_modpackType)
-	{
-		case ModpackType::Flame:
-			processFlame();
-			return;
-		case ModpackType::MultiMC:
-			processMultiMC();
-			return;
-		case ModpackType::Unknown:
-			emitFailed(tr("Archive does not contain a recognized modpack type."));
-			return;
-	}
+    switch(m_modpackType)
+    {
+        case ModpackType::Flame:
+            processFlame();
+            return;
+        case ModpackType::MultiMC:
+            processMultiMC();
+            return;
+        case ModpackType::Unknown:
+            emitFailed(tr("Archive does not contain a recognized modpack type."));
+            return;
+    }
 }
 
 void InstanceImportTask::extractAborted()
 {
-	emitFailed(tr("Instance import has been aborted."));
-	return;
+    emitFailed(tr("Instance import has been aborted."));
+    return;
 }
 
 void InstanceImportTask::processFlame()
 {
-	const static QMap<QString,QString> forgemap = {
-		{"1.2.5", "3.4.9.171"},
-		{"1.4.2", "6.0.1.355"},
-		{"1.4.7", "6.6.2.534"},
-		{"1.5.2", "7.8.1.737"}
-	};
-	Flame::Manifest pack;
-	try
-	{
-		QString configPath = FS::PathCombine(m_stagingPath, "manifest.json");
-		Flame::loadManifest(pack, configPath);
-		QFile::remove(configPath);
-	}
-	catch (const JSONValidationError &e)
-	{
-		emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
-		return;
-	}
-	if(!pack.overrides.isEmpty())
-	{
-		QString overridePath = FS::PathCombine(m_stagingPath, pack.overrides);
-		if (QFile::exists(overridePath))
-		{
-			QString mcPath = FS::PathCombine(m_stagingPath, "minecraft");
-			if (!QFile::rename(overridePath, mcPath))
-			{
-				emitFailed(tr("Could not rename the overrides folder:\n") + pack.overrides);
-				return;
-			}
-		}
-		else
-		{
-			logWarning(tr("The specified overrides folder (%1) is missing. Maybe the modpack was already used before?").arg(pack.overrides));
-		}
-	}
+    const static QMap<QString,QString> forgemap = {
+        {"1.2.5", "3.4.9.171"},
+        {"1.4.2", "6.0.1.355"},
+        {"1.4.7", "6.6.2.534"},
+        {"1.5.2", "7.8.1.737"}
+    };
+    Flame::Manifest pack;
+    try
+    {
+        QString configPath = FS::PathCombine(m_stagingPath, "manifest.json");
+        Flame::loadManifest(pack, configPath);
+        QFile::remove(configPath);
+    }
+    catch (const JSONValidationError &e)
+    {
+        emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
+        return;
+    }
+    if(!pack.overrides.isEmpty())
+    {
+        QString overridePath = FS::PathCombine(m_stagingPath, pack.overrides);
+        if (QFile::exists(overridePath))
+        {
+            QString mcPath = FS::PathCombine(m_stagingPath, "minecraft");
+            if (!QFile::rename(overridePath, mcPath))
+            {
+                emitFailed(tr("Could not rename the overrides folder:\n") + pack.overrides);
+                return;
+            }
+        }
+        else
+        {
+            logWarning(tr("The specified overrides folder (%1) is missing. Maybe the modpack was already used before?").arg(pack.overrides));
+        }
+    }
 
-	QString forgeVersion;
-	for(auto &loader: pack.minecraft.modLoaders)
-	{
-		auto id = loader.id;
-		if(id.startsWith("forge-"))
-		{
-			id.remove("forge-");
-			forgeVersion = id;
-			continue;
-		}
-		logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
-	}
+    QString forgeVersion;
+    for(auto &loader: pack.minecraft.modLoaders)
+    {
+        auto id = loader.id;
+        if(id.startsWith("forge-"))
+        {
+            id.remove("forge-");
+            forgeVersion = id;
+            continue;
+        }
+        logWarning(tr("Unknown mod loader in manifest: %1").arg(id));
+    }
 
-	QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
-	auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
-	instanceSettings->registerSetting("InstanceType", "Legacy");
-	instanceSettings->set("InstanceType", "OneSix");
-	MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
-	auto mcVersion = pack.minecraft.version;
-	// Hack to correct some 'special sauce'...
-	if(mcVersion.endsWith('.'))
-	{
-		mcVersion.remove(QRegExp("[.]+$"));
-		logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
-	}
-	auto components = instance.getComponentList();
-	components->buildingFromScratch();
-	components->setComponentVersion("net.minecraft", mcVersion, true);
-	if(!forgeVersion.isEmpty())
-	{
-		// FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata.
-		if(forgeVersion == "recommended")
-		{
-			if(forgemap.contains(mcVersion))
-			{
-				forgeVersion = forgemap[mcVersion];
-			}
-			else
-			{
-				logWarning(tr("Could not map recommended forge version for Minecraft %1").arg(mcVersion));
-			}
-		}
-		components->setComponentVersion("net.minecraftforge", forgeVersion);
-	}
-	if (m_instIcon != "default")
-	{
-		instance.setIconKey(m_instIcon);
-	}
-	else
-	{
-		if(pack.name.contains("Direwolf20"))
-		{
-			instance.setIconKey("steve");
-		}
-		else if(pack.name.contains("FTB") || pack.name.contains("Feed The Beast"))
-		{
-			instance.setIconKey("ftb_logo");
-		}
-		else
-		{
-			// default to something other than the MultiMC default to distinguish these
-			instance.setIconKey("flame");
-		}
-	}
-	instance.init();
-	QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods");
-	QFileInfo jarmodsInfo(jarmodsPath);
-	if(jarmodsInfo.isDir())
-	{
-		// install all the jar mods
-		qDebug() << "Found jarmods:";
-		QDir jarmodsDir(jarmodsPath);
-		QStringList jarMods;
-		for (auto info: jarmodsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
-		{
-			qDebug() << info.fileName();
-			jarMods.push_back(info.absoluteFilePath());
-		}
-		auto profile = instance.getComponentList();
-		profile->installJarMods(jarMods);
-		// nuke the original files
-		FS::deletePath(jarmodsPath);
-	}
-	instance.setName(m_instName);
-	m_modIdResolver.reset(new Flame::FileResolvingTask(pack));
-	connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
-	{
-		auto results = m_modIdResolver->getResults();
-		m_filesNetJob.reset(new NetJob(tr("Mod download")));
-		for(auto result: results.files)
-		{
-			QString filename = result.fileName;
-			if(!result.required)
-			{
-				filename += ".disabled";
-			}
+    QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
+    auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
+    instanceSettings->registerSetting("InstanceType", "Legacy");
+    instanceSettings->set("InstanceType", "OneSix");
+    MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
+    auto mcVersion = pack.minecraft.version;
+    // Hack to correct some 'special sauce'...
+    if(mcVersion.endsWith('.'))
+    {
+        mcVersion.remove(QRegExp("[.]+$"));
+        logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
+    }
+    auto components = instance.getComponentList();
+    components->buildingFromScratch();
+    components->setComponentVersion("net.minecraft", mcVersion, true);
+    if(!forgeVersion.isEmpty())
+    {
+        // FIXME: dirty, nasty, hack. Proper solution requires dependency resolution and knowledge of the metadata.
+        if(forgeVersion == "recommended")
+        {
+            if(forgemap.contains(mcVersion))
+            {
+                forgeVersion = forgemap[mcVersion];
+            }
+            else
+            {
+                logWarning(tr("Could not map recommended forge version for Minecraft %1").arg(mcVersion));
+            }
+        }
+        components->setComponentVersion("net.minecraftforge", forgeVersion);
+    }
+    if (m_instIcon != "default")
+    {
+        instance.setIconKey(m_instIcon);
+    }
+    else
+    {
+        if(pack.name.contains("Direwolf20"))
+        {
+            instance.setIconKey("steve");
+        }
+        else if(pack.name.contains("FTB") || pack.name.contains("Feed The Beast"))
+        {
+            instance.setIconKey("ftb_logo");
+        }
+        else
+        {
+            // default to something other than the MultiMC default to distinguish these
+            instance.setIconKey("flame");
+        }
+    }
+    instance.init();
+    QString jarmodsPath = FS::PathCombine(m_stagingPath, "minecraft", "jarmods");
+    QFileInfo jarmodsInfo(jarmodsPath);
+    if(jarmodsInfo.isDir())
+    {
+        // install all the jar mods
+        qDebug() << "Found jarmods:";
+        QDir jarmodsDir(jarmodsPath);
+        QStringList jarMods;
+        for (auto info: jarmodsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
+        {
+            qDebug() << info.fileName();
+            jarMods.push_back(info.absoluteFilePath());
+        }
+        auto profile = instance.getComponentList();
+        profile->installJarMods(jarMods);
+        // nuke the original files
+        FS::deletePath(jarmodsPath);
+    }
+    instance.setName(m_instName);
+    m_modIdResolver.reset(new Flame::FileResolvingTask(pack));
+    connect(m_modIdResolver.get(), &Flame::FileResolvingTask::succeeded, [&]()
+    {
+        auto results = m_modIdResolver->getResults();
+        m_filesNetJob.reset(new NetJob(tr("Mod download")));
+        for(auto result: results.files)
+        {
+            QString filename = result.fileName;
+            if(!result.required)
+            {
+                filename += ".disabled";
+            }
 
-			auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
-			auto path = FS::PathCombine(m_stagingPath , relpath);
+            auto relpath = FS::PathCombine("minecraft", result.targetFolder, filename);
+            auto path = FS::PathCombine(m_stagingPath , relpath);
 
-			switch(result.type)
-			{
-				case Flame::File::Type::Folder:
-				{
-					logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
-					// fall-through intentional, we treat these as plain old mods and dump them wherever.
-				}
-				case Flame::File::Type::SingleFile:
-				case Flame::File::Type::Mod:
-				{
-					qDebug() << "Will download" << result.url << "to" << path;
-					auto dl = Net::Download::makeFile(result.url, path);
-					m_filesNetJob->addNetAction(dl);
-					break;
-				}
-				case Flame::File::Type::Modpack:
-					logWarning(tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(relpath));
-					break;
-				case Flame::File::Type::Cmod2:
-				case Flame::File::Type::Ctoc:
-				case Flame::File::Type::Unknown:
-					logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
-					break;
-			}
-		}
-		m_modIdResolver.reset();
-		connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]()
-		{
-			m_filesNetJob.reset();
-			emitSucceeded();
-		}
-		);
-		connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason)
-		{
-			m_filesNetJob.reset();
-			emitFailed(reason);
-		});
-		connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total)
-		{
-			setProgress(current, total);
-		});
-		setStatus(tr("Downloading mods..."));
-		m_filesNetJob->start();
-	}
-	);
-	connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
-	{
-		m_modIdResolver.reset();
-		emitFailed(tr("Unable to resolve mod IDs:\n") + reason);
-	});
-	connect(m_modIdResolver.get(), &Flame::FileResolvingTask::progress, [&](qint64 current, qint64 total)
-	{
-		setProgress(current, total);
-	});
-	connect(m_modIdResolver.get(), &Flame::FileResolvingTask::status, [&](QString status)
-	{
-		setStatus(status);
-	});
-	m_modIdResolver->start();
+            switch(result.type)
+            {
+                case Flame::File::Type::Folder:
+                {
+                    logWarning(tr("This 'Folder' may need extracting: %1").arg(relpath));
+                    // fall-through intentional, we treat these as plain old mods and dump them wherever.
+                }
+                case Flame::File::Type::SingleFile:
+                case Flame::File::Type::Mod:
+                {
+                    qDebug() << "Will download" << result.url << "to" << path;
+                    auto dl = Net::Download::makeFile(result.url, path);
+                    m_filesNetJob->addNetAction(dl);
+                    break;
+                }
+                case Flame::File::Type::Modpack:
+                    logWarning(tr("Nesting modpacks in modpacks is not implemented, nothing was downloaded: %1").arg(relpath));
+                    break;
+                case Flame::File::Type::Cmod2:
+                case Flame::File::Type::Ctoc:
+                case Flame::File::Type::Unknown:
+                    logWarning(tr("Unrecognized/unhandled PackageType for: %1").arg(relpath));
+                    break;
+            }
+        }
+        m_modIdResolver.reset();
+        connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]()
+        {
+            m_filesNetJob.reset();
+            emitSucceeded();
+        }
+        );
+        connect(m_filesNetJob.get(), &NetJob::failed, [&](QString reason)
+        {
+            m_filesNetJob.reset();
+            emitFailed(reason);
+        });
+        connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total)
+        {
+            setProgress(current, total);
+        });
+        setStatus(tr("Downloading mods..."));
+        m_filesNetJob->start();
+    }
+    );
+    connect(m_modIdResolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason)
+    {
+        m_modIdResolver.reset();
+        emitFailed(tr("Unable to resolve mod IDs:\n") + reason);
+    });
+    connect(m_modIdResolver.get(), &Flame::FileResolvingTask::progress, [&](qint64 current, qint64 total)
+    {
+        setProgress(current, total);
+    });
+    connect(m_modIdResolver.get(), &Flame::FileResolvingTask::status, [&](QString status)
+    {
+        setStatus(status);
+    });
+    m_modIdResolver->start();
 }
 
 void InstanceImportTask::processMultiMC()
 {
-	// FIXME: copy from FolderInstanceProvider!!! FIX IT!!!
-	QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
-	auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
-	instanceSettings->registerSetting("InstanceType", "Legacy");
+    // FIXME: copy from FolderInstanceProvider!!! FIX IT!!!
+    QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
+    auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
+    instanceSettings->registerSetting("InstanceType", "Legacy");
 
-	NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
+    NullInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
 
-	// reset time played on import... because packs.
-	instance.resetTimePlayed();
+    // reset time played on import... because packs.
+    instance.resetTimePlayed();
 
-	// set a new nice name
-	instance.setName(m_instName);
+    // set a new nice name
+    instance.setName(m_instName);
 
-	// if the icon was specified by user, use that. otherwise pull icon from the pack
-	if (m_instIcon != "default")
-	{
-		instance.setIconKey(m_instIcon);
-	}
-	else
-	{
-		m_instIcon = instance.iconKey();
-		auto importIconPath = FS::PathCombine(instance.instanceRoot(), m_instIcon + ".png");
-		if (QFile::exists(importIconPath))
-		{
-			// import icon
-			auto iconList = ENV.icons();
-			if (iconList->iconFileExists(m_instIcon))
-			{
-				iconList->deleteIcon(m_instIcon);
-			}
-			iconList->installIcons({importIconPath});
-		}
-	}
-	emitSucceeded();
+    // if the icon was specified by user, use that. otherwise pull icon from the pack
+    if (m_instIcon != "default")
+    {
+        instance.setIconKey(m_instIcon);
+    }
+    else
+    {
+        m_instIcon = instance.iconKey();
+        auto importIconPath = FS::PathCombine(instance.instanceRoot(), m_instIcon + ".png");
+        if (QFile::exists(importIconPath))
+        {
+            // import icon
+            auto iconList = ENV.icons();
+            if (iconList->iconFileExists(m_instIcon))
+            {
+                iconList->deleteIcon(m_instIcon);
+            }
+            iconList->installIcons({importIconPath});
+        }
+    }
+    emitSucceeded();
 }
diff --git a/api/logic/InstanceImportTask.h b/api/logic/InstanceImportTask.h
index 06778dfe..4156aa48 100644
--- a/api/logic/InstanceImportTask.h
+++ b/api/logic/InstanceImportTask.h
@@ -13,43 +13,43 @@ class QuaZip;
 class BaseInstanceProvider;
 namespace Flame
 {
-	class FileResolvingTask;
+    class FileResolvingTask;
 }
 
 class MULTIMC_LOGIC_EXPORT InstanceImportTask : public InstanceTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit InstanceImportTask(const QUrl sourceUrl);
+    explicit InstanceImportTask(const QUrl sourceUrl);
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
+    //! Entry point for tasks.
+    virtual void executeTask() override;
 
 private:
-	void processZipPack();
-	void processMultiMC();
-	void processFlame();
+    void processZipPack();
+    void processMultiMC();
+    void processFlame();
 
 private slots:
-	void downloadSucceeded();
-	void downloadFailed(QString reason);
-	void downloadProgressChanged(qint64 current, qint64 total);
-	void extractFinished();
-	void extractAborted();
+    void downloadSucceeded();
+    void downloadFailed(QString reason);
+    void downloadProgressChanged(qint64 current, qint64 total);
+    void extractFinished();
+    void extractAborted();
 
 private: /* data */
-	NetJobPtr m_filesNetJob;
-	shared_qobject_ptr<Flame::FileResolvingTask> m_modIdResolver;
-	QUrl m_sourceUrl;
-	QString m_archivePath;
-	bool m_downloadRequired = false;
-	std::unique_ptr<QuaZip> m_packZip;
-	QFuture<QStringList> m_extractFuture;
-	QFutureWatcher<QStringList> m_extractFutureWatcher;
-	enum class ModpackType{
-		Unknown,
-		MultiMC,
-		Flame
-	} m_modpackType = ModpackType::Unknown;
+    NetJobPtr m_filesNetJob;
+    shared_qobject_ptr<Flame::FileResolvingTask> m_modIdResolver;
+    QUrl m_sourceUrl;
+    QString m_archivePath;
+    bool m_downloadRequired = false;
+    std::unique_ptr<QuaZip> m_packZip;
+    QFuture<QStringList> m_extractFuture;
+    QFutureWatcher<QStringList> m_extractFutureWatcher;
+    enum class ModpackType{
+        Unknown,
+        MultiMC,
+        Flame
+    } m_modpackType = ModpackType::Unknown;
 };
diff --git a/api/logic/InstanceList.cpp b/api/logic/InstanceList.cpp
index 75b523e4..c7a22b08 100644
--- a/api/logic/InstanceList.cpp
+++ b/api/logic/InstanceList.cpp
@@ -27,9 +27,9 @@
 #include "FolderInstanceProvider.h"
 
 InstanceList::InstanceList(QObject *parent)
-	: QAbstractListModel(parent)
+    : QAbstractListModel(parent)
 {
-	resumeWatch();
+    resumeWatch();
 }
 
 InstanceList::~InstanceList()
@@ -38,310 +38,310 @@ InstanceList::~InstanceList()
 
 int InstanceList::rowCount(const QModelIndex &parent) const
 {
-	Q_UNUSED(parent);
-	return m_instances.count();
+    Q_UNUSED(parent);
+    return m_instances.count();
 }
 
 QModelIndex InstanceList::index(int row, int column, const QModelIndex &parent) const
 {
-	Q_UNUSED(parent);
-	if (row < 0 || row >= m_instances.size())
-		return QModelIndex();
-	return createIndex(row, column, (void *)m_instances.at(row).get());
+    Q_UNUSED(parent);
+    if (row < 0 || row >= m_instances.size())
+        return QModelIndex();
+    return createIndex(row, column, (void *)m_instances.at(row).get());
 }
 
 QVariant InstanceList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-	{
-		return QVariant();
-	}
-	BaseInstance *pdata = static_cast<BaseInstance *>(index.internalPointer());
-	switch (role)
-	{
-	case InstancePointerRole:
-	{
-		QVariant v = qVariantFromValue((void *)pdata);
-		return v;
-	}
-	case InstanceIDRole:
+    if (!index.isValid())
+    {
+        return QVariant();
+    }
+    BaseInstance *pdata = static_cast<BaseInstance *>(index.internalPointer());
+    switch (role)
+    {
+    case InstancePointerRole:
+    {
+        QVariant v = qVariantFromValue((void *)pdata);
+        return v;
+    }
+    case InstanceIDRole:
     {
         return pdata->id();
     }
-	case Qt::DisplayRole:
-	{
-		return pdata->name();
-	}
-	case Qt::ToolTipRole:
-	{
-		return pdata->instanceRoot();
-	}
-	case Qt::DecorationRole:
-	{
-		return pdata->iconKey();
-	}
-	// HACK: see GroupView.h in gui!
-	case GroupRole:
-	{
-		return pdata->group();
-	}
-	default:
-		break;
-	}
-	return QVariant();
+    case Qt::DisplayRole:
+    {
+        return pdata->name();
+    }
+    case Qt::ToolTipRole:
+    {
+        return pdata->instanceRoot();
+    }
+    case Qt::DecorationRole:
+    {
+        return pdata->iconKey();
+    }
+    // HACK: see GroupView.h in gui!
+    case GroupRole:
+    {
+        return pdata->group();
+    }
+    default:
+        break;
+    }
+    return QVariant();
 }
 
 Qt::ItemFlags InstanceList::flags(const QModelIndex &index) const
 {
-	Qt::ItemFlags f;
-	if (index.isValid())
-	{
-		f |= (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
-	}
-	return f;
+    Qt::ItemFlags f;
+    if (index.isValid())
+    {
+        f |= (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+    }
+    return f;
 }
 
 QStringList InstanceList::getGroups()
 {
-	return m_groups.toList();
+    return m_groups.toList();
 }
 
 void InstanceList::deleteGroup(const QString& name)
 {
-	for(auto & instance: m_instances)
-	{
-		auto instGroupName = instance->group();
-		if(instGroupName == name)
-		{
-			instance->setGroupPost(QString());
-		}
-	}
+    for(auto & instance: m_instances)
+    {
+        auto instGroupName = instance->group();
+        if(instGroupName == name)
+        {
+            instance->setGroupPost(QString());
+        }
+    }
 }
 
 static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr> &list)
 {
-	QMap<InstanceId, InstanceLocator> out;
-	int i = 0;
-	for(auto & item: list)
-	{
-		auto id = item->id();
-		if(out.contains(id))
-		{
-			qWarning() << "Duplicate ID" << id << "in instance list";
-		}
-		out[id] = std::make_pair(item, i);
-		i++;
-	}
-	return out;
+    QMap<InstanceId, InstanceLocator> out;
+    int i = 0;
+    for(auto & item: list)
+    {
+        auto id = item->id();
+        if(out.contains(id))
+        {
+            qWarning() << "Duplicate ID" << id << "in instance list";
+        }
+        out[id] = std::make_pair(item, i);
+        i++;
+    }
+    return out;
 }
 
 InstanceList::InstListError InstanceList::loadList(bool complete)
 {
-	auto existingIds = getIdMapping(m_instances);
+    auto existingIds = getIdMapping(m_instances);
 
-	QList<InstancePtr> newList;
+    QList<InstancePtr> newList;
 
-	auto processIds = [&](BaseInstanceProvider * provider, QList<InstanceId> ids)
-	{
-		for(auto & id: ids)
-		{
-			if(existingIds.contains(id))
-			{
-				auto instPair = existingIds[id];
-				/*
-				auto & instPtr = instPair.first;
-				auto & instIdx = instPair.second;
-				*/
-				existingIds.remove(id);
-				qDebug() << "Should keep and soft-reload" << id;
-			}
-			else
-			{
-				InstancePtr instPtr = provider->loadInstance(id);
-				if(instPtr)
-				{
-					newList.append(instPtr);
-				}
-			}
-		}
-	};
-	if(complete)
-	{
-		for(auto & item: m_providers)
-		{
-			processIds(item.get(), item->discoverInstances());
-		}
-	}
-	else
-	{
-		for (auto & item: m_updatedProviders)
-		{
-			processIds(item, item->discoverInstances());
-		}
-	}
+    auto processIds = [&](BaseInstanceProvider * provider, QList<InstanceId> ids)
+    {
+        for(auto & id: ids)
+        {
+            if(existingIds.contains(id))
+            {
+                auto instPair = existingIds[id];
+                /*
+                auto & instPtr = instPair.first;
+                auto & instIdx = instPair.second;
+                */
+                existingIds.remove(id);
+                qDebug() << "Should keep and soft-reload" << id;
+            }
+            else
+            {
+                InstancePtr instPtr = provider->loadInstance(id);
+                if(instPtr)
+                {
+                    newList.append(instPtr);
+                }
+            }
+        }
+    };
+    if(complete)
+    {
+        for(auto & item: m_providers)
+        {
+            processIds(item.get(), item->discoverInstances());
+        }
+    }
+    else
+    {
+        for (auto & item: m_updatedProviders)
+        {
+            processIds(item, item->discoverInstances());
+        }
+    }
 
-	// TODO: looks like a general algorithm with a few specifics inserted. Do something about it.
-	if(!existingIds.isEmpty())
-	{
-		// get the list of removed instances and sort it by their original index, from last to first
-		auto deadList = existingIds.values();
-		auto orderSortPredicate = [](const InstanceLocator & a, const InstanceLocator & b) -> bool
-		{
-			return a.second > b.second;
-		};
-		std::sort(deadList.begin(), deadList.end(), orderSortPredicate);
-		// remove the contiguous ranges of rows
-		int front_bookmark = -1;
-		int back_bookmark = -1;
-		int currentItem = -1;
-		auto removeNow = [&]()
-		{
-			beginRemoveRows(QModelIndex(), front_bookmark, back_bookmark);
-			m_instances.erase(m_instances.begin() + front_bookmark, m_instances.begin() + back_bookmark + 1);
-			endRemoveRows();
-			front_bookmark = -1;
-			back_bookmark = currentItem;
-		};
-		for(auto & removedItem: deadList)
-		{
-			auto instPtr = removedItem.first;
-			if(!complete && !m_updatedProviders.contains(instPtr->provider()))
-			{
-				continue;
-			}
-			instPtr->invalidate();
-			currentItem = removedItem.second;
-			if(back_bookmark == -1)
-			{
-				// no bookmark yet
-				back_bookmark = currentItem;
-			}
-			else if(currentItem == front_bookmark - 1)
-			{
-				// part of contiguous sequence, continue
-			}
-			else
-			{
-				// seam between previous and current item
-				removeNow();
-			}
-			front_bookmark = currentItem;
-		}
-		if(back_bookmark != -1)
-		{
-			removeNow();
-		}
-	}
-	if(newList.size())
-	{
-		add(newList);
-	}
-	m_updatedProviders.clear();
-	return NoError;
+    // TODO: looks like a general algorithm with a few specifics inserted. Do something about it.
+    if(!existingIds.isEmpty())
+    {
+        // get the list of removed instances and sort it by their original index, from last to first
+        auto deadList = existingIds.values();
+        auto orderSortPredicate = [](const InstanceLocator & a, const InstanceLocator & b) -> bool
+        {
+            return a.second > b.second;
+        };
+        std::sort(deadList.begin(), deadList.end(), orderSortPredicate);
+        // remove the contiguous ranges of rows
+        int front_bookmark = -1;
+        int back_bookmark = -1;
+        int currentItem = -1;
+        auto removeNow = [&]()
+        {
+            beginRemoveRows(QModelIndex(), front_bookmark, back_bookmark);
+            m_instances.erase(m_instances.begin() + front_bookmark, m_instances.begin() + back_bookmark + 1);
+            endRemoveRows();
+            front_bookmark = -1;
+            back_bookmark = currentItem;
+        };
+        for(auto & removedItem: deadList)
+        {
+            auto instPtr = removedItem.first;
+            if(!complete && !m_updatedProviders.contains(instPtr->provider()))
+            {
+                continue;
+            }
+            instPtr->invalidate();
+            currentItem = removedItem.second;
+            if(back_bookmark == -1)
+            {
+                // no bookmark yet
+                back_bookmark = currentItem;
+            }
+            else if(currentItem == front_bookmark - 1)
+            {
+                // part of contiguous sequence, continue
+            }
+            else
+            {
+                // seam between previous and current item
+                removeNow();
+            }
+            front_bookmark = currentItem;
+        }
+        if(back_bookmark != -1)
+        {
+            removeNow();
+        }
+    }
+    if(newList.size())
+    {
+        add(newList);
+    }
+    m_updatedProviders.clear();
+    return NoError;
 }
 
 void InstanceList::saveNow()
 {
-	for(auto & item: m_instances)
-	{
-		item->saveNow();
-	}
+    for(auto & item: m_instances)
+    {
+        item->saveNow();
+    }
 }
 
 void InstanceList::add(const QList<InstancePtr> &t)
 {
-	beginInsertRows(QModelIndex(), m_instances.count(), m_instances.count() + t.size() - 1);
-	m_instances.append(t);
-	for(auto & ptr : t)
-	{
-		connect(ptr.get(), &BaseInstance::propertiesChanged, this, &InstanceList::propertiesChanged);
-	}
-	endInsertRows();
+    beginInsertRows(QModelIndex(), m_instances.count(), m_instances.count() + t.size() - 1);
+    m_instances.append(t);
+    for(auto & ptr : t)
+    {
+        connect(ptr.get(), &BaseInstance::propertiesChanged, this, &InstanceList::propertiesChanged);
+    }
+    endInsertRows();
 }
 
 void InstanceList::resumeWatch()
 {
-	if(m_watchLevel > 0)
-	{
-		qWarning() << "Bad suspend level resume in instance list";
-		return;
-	}
-	m_watchLevel++;
-	if(m_watchLevel > 0 && !m_updatedProviders.isEmpty())
-	{
-		loadList();
-	}
+    if(m_watchLevel > 0)
+    {
+        qWarning() << "Bad suspend level resume in instance list";
+        return;
+    }
+    m_watchLevel++;
+    if(m_watchLevel > 0 && !m_updatedProviders.isEmpty())
+    {
+        loadList();
+    }
 }
 
 void InstanceList::suspendWatch()
 {
-	m_watchLevel --;
+    m_watchLevel --;
 }
 
 void InstanceList::providerUpdated()
 {
-	auto provider = dynamic_cast<BaseInstanceProvider *>(QObject::sender());
-	if(!provider)
-	{
-		qWarning() << "InstanceList::providerUpdated triggered by a non-provider";
-		return;
-	}
-	m_updatedProviders.insert(provider);
-	if(m_watchLevel == 1)
-	{
-		loadList();
-	}
+    auto provider = dynamic_cast<BaseInstanceProvider *>(QObject::sender());
+    if(!provider)
+    {
+        qWarning() << "InstanceList::providerUpdated triggered by a non-provider";
+        return;
+    }
+    m_updatedProviders.insert(provider);
+    if(m_watchLevel == 1)
+    {
+        loadList();
+    }
 }
 
 void InstanceList::groupsPublished(QSet<QString> newGroups)
 {
-	m_groups.unite(newGroups);
+    m_groups.unite(newGroups);
 }
 
 void InstanceList::addInstanceProvider(BaseInstanceProvider* provider)
 {
-	connect(provider, &BaseInstanceProvider::instancesChanged, this, &InstanceList::providerUpdated);
-	connect(provider, &BaseInstanceProvider::groupsChanged, this, &InstanceList::groupsPublished);
-	m_providers.append(provider);
+    connect(provider, &BaseInstanceProvider::instancesChanged, this, &InstanceList::providerUpdated);
+    connect(provider, &BaseInstanceProvider::groupsChanged, this, &InstanceList::groupsPublished);
+    m_providers.append(provider);
 }
 
 InstancePtr InstanceList::getInstanceById(QString instId) const
 {
-	if(instId.isEmpty())
-		return InstancePtr();
-	for(auto & inst: m_instances)
-	{
-		if (inst->id() == instId)
-		{
-			return inst;
-		}
-	}
-	return InstancePtr();
+    if(instId.isEmpty())
+        return InstancePtr();
+    for(auto & inst: m_instances)
+    {
+        if (inst->id() == instId)
+        {
+            return inst;
+        }
+    }
+    return InstancePtr();
 }
 
 QModelIndex InstanceList::getInstanceIndexById(const QString &id) const
 {
-	return index(getInstIndex(getInstanceById(id).get()));
+    return index(getInstIndex(getInstanceById(id).get()));
 }
 
 int InstanceList::getInstIndex(BaseInstance *inst) const
 {
-	int count = m_instances.count();
-	for (int i = 0; i < count; i++)
-	{
-		if (inst == m_instances[i].get())
-		{
-			return i;
-		}
-	}
-	return -1;
+    int count = m_instances.count();
+    for (int i = 0; i < count; i++)
+    {
+        if (inst == m_instances[i].get())
+        {
+            return i;
+        }
+    }
+    return -1;
 }
 
 void InstanceList::propertiesChanged(BaseInstance *inst)
 {
-	int i = getInstIndex(inst);
-	if (i != -1)
-	{
-		emit dataChanged(index(i), index(i));
-	}
+    int i = getInstIndex(inst);
+    if (i != -1)
+    {
+        emit dataChanged(index(i), index(i));
+    }
 }
diff --git a/api/logic/InstanceList.h b/api/logic/InstanceList.h
index bb879c83..7fe5ea34 100644
--- a/api/logic/InstanceList.h
+++ b/api/logic/InstanceList.h
@@ -31,75 +31,75 @@ class BaseInstance;
 
 class MULTIMC_LOGIC_EXPORT InstanceList : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	explicit InstanceList(QObject *parent = 0);
-	virtual ~InstanceList();
+    explicit InstanceList(QObject *parent = 0);
+    virtual ~InstanceList();
 
 public:
-	QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
-	int rowCount(const QModelIndex &parent = QModelIndex()) const;
-	QVariant data(const QModelIndex &index, int role) const;
-	Qt::ItemFlags flags(const QModelIndex &index) const;
-
-	enum AdditionalRoles
-	{
-		GroupRole = Qt::UserRole,
-		InstancePointerRole = 0x34B1CB48, ///< Return pointer to real instance
-		InstanceIDRole = 0x34B1CB49 ///< Return id if the instance
-	};
-	/*!
-	 * \brief Error codes returned by functions in the InstanceList class.
-	 * NoError Indicates that no error occurred.
-	 * UnknownError indicates that an unspecified error occurred.
-	 */
-	enum InstListError
-	{
-		NoError = 0,
-		UnknownError
-	};
-
-	InstancePtr at(int i) const
-	{
-		return m_instances.at(i);
-	}
-
-	int count() const
-	{
-		return m_instances.count();
-	}
-
-	InstListError loadList(bool complete = false);
-	void saveNow();
-
-	/// Add an instance provider. Takes ownership of it. Should only be done before the first load.
-	void addInstanceProvider(BaseInstanceProvider * provider);
-
-	InstancePtr getInstanceById(QString id) const;
-	QModelIndex getInstanceIndexById(const QString &id) const;
-	QStringList getGroups();
-
-	void deleteGroup(const QString & name);
+    QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role) const;
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    enum AdditionalRoles
+    {
+        GroupRole = Qt::UserRole,
+        InstancePointerRole = 0x34B1CB48, ///< Return pointer to real instance
+        InstanceIDRole = 0x34B1CB49 ///< Return id if the instance
+    };
+    /*!
+     * \brief Error codes returned by functions in the InstanceList class.
+     * NoError Indicates that no error occurred.
+     * UnknownError indicates that an unspecified error occurred.
+     */
+    enum InstListError
+    {
+        NoError = 0,
+        UnknownError
+    };
+
+    InstancePtr at(int i) const
+    {
+        return m_instances.at(i);
+    }
+
+    int count() const
+    {
+        return m_instances.count();
+    }
+
+    InstListError loadList(bool complete = false);
+    void saveNow();
+
+    /// Add an instance provider. Takes ownership of it. Should only be done before the first load.
+    void addInstanceProvider(BaseInstanceProvider * provider);
+
+    InstancePtr getInstanceById(QString id) const;
+    QModelIndex getInstanceIndexById(const QString &id) const;
+    QStringList getGroups();
+
+    void deleteGroup(const QString & name);
 
 signals:
-	void dataIsInvalid();
+    void dataIsInvalid();
 
 private slots:
-	void propertiesChanged(BaseInstance *inst);
-	void groupsPublished(QSet<QString>);
-	void providerUpdated();
+    void propertiesChanged(BaseInstance *inst);
+    void groupsPublished(QSet<QString>);
+    void providerUpdated();
 
 private:
-	int getInstIndex(BaseInstance *inst) const;
-	void suspendWatch();
-	void resumeWatch();
-	void add(const QList<InstancePtr> &list);
+    int getInstIndex(BaseInstance *inst) const;
+    void suspendWatch();
+    void resumeWatch();
+    void add(const QList<InstancePtr> &list);
 
 protected:
-	int m_watchLevel = 0;
-	QSet<BaseInstanceProvider *> m_updatedProviders;
-	QList<InstancePtr> m_instances;
-	QSet<QString> m_groups;
-	QVector<shared_qobject_ptr<BaseInstanceProvider>> m_providers;
+    int m_watchLevel = 0;
+    QSet<BaseInstanceProvider *> m_updatedProviders;
+    QList<InstancePtr> m_instances;
+    QSet<QString> m_groups;
+    QVector<shared_qobject_ptr<BaseInstanceProvider>> m_providers;
 };
diff --git a/api/logic/InstanceTask.h b/api/logic/InstanceTask.h
index 8fc98eb7..5face5fc 100644
--- a/api/logic/InstanceTask.h
+++ b/api/logic/InstanceTask.h
@@ -8,48 +8,48 @@ class BaseInstanceProvider;
 
 class MULTIMC_LOGIC_EXPORT InstanceTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit InstanceTask();
-	virtual ~InstanceTask();
-
-	void setParentSettings(SettingsObjectPtr settings)
-	{
-		m_globalSettings = settings;
-	}
-
-	void setStagingPath(const QString &stagingPath)
-	{
-		m_stagingPath = stagingPath;
-	}
-
-	void setName(const QString &name)
-	{
-		m_instName = name;
-	}
-	QString name() const
-	{
-		return m_instName;
-	}
-
-	void setIcon(const QString &icon)
-	{
-		m_instIcon = icon;
-	}
-
-	void setGroup(const QString &group)
-	{
-		m_instGroup = group;
-	}
-	QString group() const
-	{
-		return m_instGroup;
-	}
+    explicit InstanceTask();
+    virtual ~InstanceTask();
+
+    void setParentSettings(SettingsObjectPtr settings)
+    {
+        m_globalSettings = settings;
+    }
+
+    void setStagingPath(const QString &stagingPath)
+    {
+        m_stagingPath = stagingPath;
+    }
+
+    void setName(const QString &name)
+    {
+        m_instName = name;
+    }
+    QString name() const
+    {
+        return m_instName;
+    }
+
+    void setIcon(const QString &icon)
+    {
+        m_instIcon = icon;
+    }
+
+    void setGroup(const QString &group)
+    {
+        m_instGroup = group;
+    }
+    QString group() const
+    {
+        return m_instGroup;
+    }
 
 protected: /* data */
-	SettingsObjectPtr m_globalSettings;
-	QString m_instName;
-	QString m_instIcon;
-	QString m_instGroup;
-	QString m_stagingPath;
+    SettingsObjectPtr m_globalSettings;
+    QString m_instName;
+    QString m_instIcon;
+    QString m_instGroup;
+    QString m_stagingPath;
 };
diff --git a/api/logic/Json.cpp b/api/logic/Json.cpp
index f2cbc8a3..37ada1aa 100644
--- a/api/logic/Json.cpp
+++ b/api/logic/Json.cpp
@@ -11,262 +11,262 @@ namespace Json
 {
 void write(const QJsonDocument &doc, const QString &filename)
 {
-	FS::write(filename, doc.toJson());
+    FS::write(filename, doc.toJson());
 }
 void write(const QJsonObject &object, const QString &filename)
 {
-	write(QJsonDocument(object), filename);
+    write(QJsonDocument(object), filename);
 }
 void write(const QJsonArray &array, const QString &filename)
 {
-	write(QJsonDocument(array), filename);
+    write(QJsonDocument(array), filename);
 }
 
 QByteArray toBinary(const QJsonObject &obj)
 {
-	return QJsonDocument(obj).toBinaryData();
+    return QJsonDocument(obj).toBinaryData();
 }
 QByteArray toBinary(const QJsonArray &array)
 {
-	return QJsonDocument(array).toBinaryData();
+    return QJsonDocument(array).toBinaryData();
 }
 QByteArray toText(const QJsonObject &obj)
 {
-	return QJsonDocument(obj).toJson(QJsonDocument::Compact);
+    return QJsonDocument(obj).toJson(QJsonDocument::Compact);
 }
 QByteArray toText(const QJsonArray &array)
 {
-	return QJsonDocument(array).toJson(QJsonDocument::Compact);
+    return QJsonDocument(array).toJson(QJsonDocument::Compact);
 }
 
 static bool isBinaryJson(const QByteArray &data)
 {
-	decltype(QJsonDocument::BinaryFormatTag) tag = QJsonDocument::BinaryFormatTag;
-	return memcmp(data.constData(), &tag, sizeof(QJsonDocument::BinaryFormatTag)) == 0;
+    decltype(QJsonDocument::BinaryFormatTag) tag = QJsonDocument::BinaryFormatTag;
+    return memcmp(data.constData(), &tag, sizeof(QJsonDocument::BinaryFormatTag)) == 0;
 }
 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;
-	}
-	else
-	{
-		QJsonParseError error;
-		QJsonDocument doc = QJsonDocument::fromJson(data, &error);
-		if (error.error != QJsonParseError::NoError)
-		{
-			throw JsonException(what + ": Error parsing JSON: " + error.errorString());
-		}
-		return doc;
-	}
+    if (isBinaryJson(data))
+    {
+        QJsonDocument doc = QJsonDocument::fromBinaryData(data);
+        if (doc.isNull())
+        {
+            throw JsonException(what + ": Invalid JSON (binary JSON detected)");
+        }
+        return doc;
+    }
+    else
+    {
+        QJsonParseError error;
+        QJsonDocument doc = QJsonDocument::fromJson(data, &error);
+        if (error.error != QJsonParseError::NoError)
+        {
+            throw JsonException(what + ": Error parsing JSON: " + error.errorString());
+        }
+        return doc;
+    }
 }
 QJsonDocument requireDocument(const QString &filename, const QString &what)
 {
-	return requireDocument(FS::read(filename), what);
+    return requireDocument(FS::read(filename), what);
 }
 QJsonObject requireObject(const QJsonDocument &doc, const QString &what)
 {
-	if (!doc.isObject())
-	{
-		throw JsonException(what + " is not an object");
-	}
-	return doc.object();
+    if (!doc.isObject())
+    {
+        throw JsonException(what + " is not an object");
+    }
+    return doc.object();
 }
 QJsonArray requireArray(const QJsonDocument &doc, const QString &what)
 {
-	if (!doc.isArray())
-	{
-		throw JsonException(what + " is not an array");
-	}
-	return doc.array();
+    if (!doc.isArray())
+    {
+        throw JsonException(what + " is not an array");
+    }
+    return doc.array();
 }
 
 void writeString(QJsonObject &to, const QString &key, const QString &value)
 {
-	if (!value.isEmpty())
-	{
-		to.insert(key, value);
-	}
+    if (!value.isEmpty())
+    {
+        to.insert(key, value);
+    }
 }
 
 void writeStringList(QJsonObject &to, const QString &key, const QStringList &values)
 {
-	if (!values.isEmpty())
-	{
-		QJsonArray array;
-		for(auto value: values)
-		{
-			array.append(value);
-		}
-		to.insert(key, array);
-	}
+    if (!values.isEmpty())
+    {
+        QJsonArray array;
+        for(auto value: values)
+        {
+            array.append(value);
+        }
+        to.insert(key, array);
+    }
 }
 
 template<>
 QJsonValue toJson<QUrl>(const QUrl &url)
 {
-	return QJsonValue(url.toString(QUrl::FullyEncoded));
+    return QJsonValue(url.toString(QUrl::FullyEncoded));
 }
 template<>
 QJsonValue toJson<QByteArray>(const QByteArray &data)
 {
-	return QJsonValue(QString::fromLatin1(data.toHex()));
+    return QJsonValue(QString::fromLatin1(data.toHex()));
 }
 template<>
 QJsonValue toJson<QDateTime>(const QDateTime &datetime)
 {
-	return QJsonValue(datetime.toString(Qt::ISODate));
+    return QJsonValue(datetime.toString(Qt::ISODate));
 }
 template<>
 QJsonValue toJson<QDir>(const QDir &dir)
 {
-	return QDir::current().relativeFilePath(dir.absolutePath());
+    return QDir::current().relativeFilePath(dir.absolutePath());
 }
 template<>
 QJsonValue toJson<QUuid>(const QUuid &uuid)
 {
-	return uuid.toString();
+    return uuid.toString();
 }
 template<>
 QJsonValue toJson<QVariant>(const QVariant &variant)
 {
-	return QJsonValue::fromVariant(variant);
+    return QJsonValue::fromVariant(variant);
 }
 
 
 template<> QByteArray requireIsType<QByteArray>(const QJsonValue &value, const QString &what)
 {
-	const QString string = ensureIsType<QString>(value, what);
-	// ensure that the string can be safely cast to Latin1
-	if (string != QString::fromLatin1(string.toLatin1()))
-	{
-		throw JsonException(what + " is not encodable as Latin1");
-	}
-	return QByteArray::fromHex(string.toLatin1());
+    const QString string = ensureIsType<QString>(value, what);
+    // ensure that the string can be safely cast to Latin1
+    if (string != QString::fromLatin1(string.toLatin1()))
+    {
+        throw JsonException(what + " is not encodable as Latin1");
+    }
+    return QByteArray::fromHex(string.toLatin1());
 }
 
 template<> QJsonArray requireIsType<QJsonArray>(const QJsonValue &value, const QString &what)
 {
-	if (!value.isArray())
-	{
-		throw JsonException(what + " is not an array");
-	}
-	return value.toArray();
+    if (!value.isArray())
+    {
+        throw JsonException(what + " is not an array");
+    }
+    return value.toArray();
 }
 
 
 template<> QString requireIsType<QString>(const QJsonValue &value, const QString &what)
 {
-	if (!value.isString())
-	{
-		throw JsonException(what + " is not a string");
-	}
-	return value.toString();
+    if (!value.isString())
+    {
+        throw JsonException(what + " is not a string");
+    }
+    return value.toString();
 }
 
 template<> bool requireIsType<bool>(const QJsonValue &value, const QString &what)
 {
-	if (!value.isBool())
-	{
-		throw JsonException(what + " is not a bool");
-	}
-	return value.toBool();
+    if (!value.isBool())
+    {
+        throw JsonException(what + " is not a bool");
+    }
+    return value.toBool();
 }
 
 template<> double requireIsType<double>(const QJsonValue &value, const QString &what)
 {
-	if (!value.isDouble())
-	{
-		throw JsonException(what + " is not a double");
-	}
-	return value.toDouble();
+    if (!value.isDouble())
+    {
+        throw JsonException(what + " is not a double");
+    }
+    return value.toDouble();
 }
 
 template<> int requireIsType<int>(const QJsonValue &value, const QString &what)
 {
-	const double doubl = requireIsType<double>(value, what);
-	if (fmod(doubl, 1) != 0)
-	{
-		throw JsonException(what + " is not an integer");
-	}
-	return int(doubl);
+    const double doubl = requireIsType<double>(value, what);
+    if (fmod(doubl, 1) != 0)
+    {
+        throw JsonException(what + " is not an integer");
+    }
+    return int(doubl);
 }
 
 template<> QDateTime requireIsType<QDateTime>(const QJsonValue &value, const QString &what)
 {
-	const QString string = requireIsType<QString>(value, what);
-	const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate);
-	if (!datetime.isValid())
-	{
-		throw JsonException(what + " is not a ISO formatted date/time value");
-	}
-	return datetime;
+    const QString string = requireIsType<QString>(value, what);
+    const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate);
+    if (!datetime.isValid())
+    {
+        throw JsonException(what + " is not a ISO formatted date/time value");
+    }
+    return datetime;
 }
 
 template<> QUrl requireIsType<QUrl>(const QJsonValue &value, const QString &what)
 {
-	const QString string = ensureIsType<QString>(value, what);
-	if (string.isEmpty())
-	{
-		return QUrl();
-	}
-	const QUrl url = QUrl(string, QUrl::StrictMode);
-	if (!url.isValid())
-	{
-		throw JsonException(what + " is not a correctly formatted URL");
-	}
-	return url;
+    const QString string = ensureIsType<QString>(value, what);
+    if (string.isEmpty())
+    {
+        return QUrl();
+    }
+    const QUrl url = QUrl(string, QUrl::StrictMode);
+    if (!url.isValid())
+    {
+        throw JsonException(what + " is not a correctly formatted URL");
+    }
+    return url;
 }
 
 template<> QDir requireIsType<QDir>(const QJsonValue &value, const QString &what)
 {
-	const QString string = requireIsType<QString>(value, what);
-	// FIXME: does not handle invalid characters!
-	return QDir::current().absoluteFilePath(string);
+    const QString string = requireIsType<QString>(value, what);
+    // FIXME: does not handle invalid characters!
+    return QDir::current().absoluteFilePath(string);
 }
 
 template<> QUuid requireIsType<QUuid>(const QJsonValue &value, const QString &what)
 {
-	const QString string = requireIsType<QString>(value, what);
-	const QUuid uuid = QUuid(string);
-	if (uuid.toString() != string) // converts back => valid
-	{
-		throw JsonException(what + " is not a valid UUID");
-	}
-	return uuid;
+    const QString string = requireIsType<QString>(value, what);
+    const QUuid uuid = QUuid(string);
+    if (uuid.toString() != string) // converts back => valid
+    {
+        throw JsonException(what + " is not a valid UUID");
+    }
+    return uuid;
 }
 
 template<> QJsonObject requireIsType<QJsonObject>(const QJsonValue &value, const QString &what)
 {
-	if (!value.isObject())
-	{
-		throw JsonException(what + " is not an object");
-	}
-	return value.toObject();
+    if (!value.isObject())
+    {
+        throw JsonException(what + " is not an object");
+    }
+    return value.toObject();
 }
 
 template<> QVariant requireIsType<QVariant>(const QJsonValue &value, const QString &what)
 {
-	if (value.isNull() || value.isUndefined())
-	{
-		throw JsonException(what + " is null or undefined");
-	}
-	return value.toVariant();
+    if (value.isNull() || value.isUndefined())
+    {
+        throw JsonException(what + " is null or undefined");
+    }
+    return value.toVariant();
 }
 
 template<> QJsonValue requireIsType<QJsonValue>(const QJsonValue &value, const QString &what)
 {
-	if (value.isNull() || value.isUndefined())
-	{
-		throw JsonException(what + " is null or undefined");
-	}
-	return value;
+    if (value.isNull() || value.isUndefined())
+    {
+        throw JsonException(what + " is null or undefined");
+    }
+    return value;
 }
 
 }
diff --git a/api/logic/Json.h b/api/logic/Json.h
index a84d204a..34ff6fe2 100644
--- a/api/logic/Json.h
+++ b/api/logic/Json.h
@@ -19,7 +19,7 @@ namespace Json
 class MULTIMC_LOGIC_EXPORT JsonException : public ::Exception
 {
 public:
-	JsonException(const QString &message) : Exception(message) {}
+    JsonException(const QString &message) : Exception(message) {}
 };
 
 /// @throw FileSystemException
@@ -51,7 +51,7 @@ void writeStringList(QJsonObject & to, const QString &key, const QStringList &va
 template<typename T>
 QJsonValue toJson(const T &t)
 {
-	return QJsonValue(t);
+    return QJsonValue(t);
 }
 template<>
 QJsonValue toJson<QUrl>(const QUrl &url);
@@ -69,12 +69,12 @@ QJsonValue toJson<QVariant>(const QVariant &variant);
 template<typename T>
 QJsonArray toJsonArray(const QList<T> &container)
 {
-	QJsonArray array;
-	for (const T item : container)
-	{
-		array.append(toJson<T>(item));
-	}
-	return array;
+    QJsonArray array;
+    for (const T item : container)
+    {
+        array.append(toJson<T>(item));
+    }
+    return array;
 }
 
 ////////////////// READING ////////////////////
@@ -115,119 +115,119 @@ template<> MULTIMC_LOGIC_EXPORT QUrl requireIsType<QUrl>(const QJsonValue &value
 template <typename T>
 T ensureIsType(const QJsonValue &value, const T default_ = T(), const QString &what = "Value")
 {
-	if (value.isUndefined() || value.isNull())
-	{
-		return default_;
-	}
-	try
-	{
-		return requireIsType<T>(value, what);
-	}
-	catch (const JsonException &)
-	{
-		return default_;
-	}
+    if (value.isUndefined() || value.isNull())
+    {
+        return default_;
+    }
+    try
+    {
+        return requireIsType<T>(value, what);
+    }
+    catch (const JsonException &)
+    {
+        return default_;
+    }
 }
 
 /// @throw JsonException
 template <typename T>
 T requireIsType(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__")
 {
-	const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
-	if (!parent.contains(key))
-	{
-		throw JsonException(localWhat + "s parent does not contain " + localWhat);
-	}
-	return requireIsType<T>(parent.value(key), localWhat);
+    const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
+    if (!parent.contains(key))
+    {
+        throw JsonException(localWhat + "s parent does not contain " + localWhat);
+    }
+    return requireIsType<T>(parent.value(key), localWhat);
 }
 
 template <typename T>
 T ensureIsType(const QJsonObject &parent, const QString &key, const T default_ = T(), const QString &what = "__placeholder__")
 {
-	const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
-	if (!parent.contains(key))
-	{
-		return default_;
-	}
-	return ensureIsType<T>(parent.value(key), default_, localWhat);
+    const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
+    if (!parent.contains(key))
+    {
+        return default_;
+    }
+    return ensureIsType<T>(parent.value(key), default_, localWhat);
 }
 
 template <typename T>
 QVector<T> requireIsArrayOf(const QJsonDocument &doc)
 {
-	const QJsonArray array = requireArray(doc);
-	QVector<T> out;
-	for (const QJsonValue val : array)
-	{
-		out.append(requireIsType<T>(val, "Document"));
-	}
-	return out;
+    const QJsonArray array = requireArray(doc);
+    QVector<T> out;
+    for (const QJsonValue val : array)
+    {
+        out.append(requireIsType<T>(val, "Document"));
+    }
+    return out;
 }
 
 template <typename T>
 QVector<T> ensureIsArrayOf(const QJsonValue &value, const QString &what = "Value")
 {
-	const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what);
-	QVector<T> out;
-	for (const QJsonValue val : array)
-	{
-		out.append(requireIsType<T>(val, what));
-	}
-	return out;
+    const QJsonArray array = ensureIsType<QJsonArray>(value, QJsonArray(), what);
+    QVector<T> out;
+    for (const QJsonValue val : array)
+    {
+        out.append(requireIsType<T>(val, what));
+    }
+    return out;
 }
 
 template <typename T>
 QVector<T> ensureIsArrayOf(const QJsonValue &value, const QVector<T> default_, const QString &what = "Value")
 {
-	if (value.isUndefined())
-	{
-		return default_;
-	}
-	return ensureIsArrayOf<T>(value, what);
+    if (value.isUndefined())
+    {
+        return default_;
+    }
+    return ensureIsArrayOf<T>(value, what);
 }
 
 /// @throw JsonException
 template <typename T>
 QVector<T> requireIsArrayOf(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__")
 {
-	const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
-	if (!parent.contains(key))
-	{
-		throw JsonException(localWhat + "s parent does not contain " + localWhat);
-	}
-	return ensureIsArrayOf<T>(parent.value(key), localWhat);
+    const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
+    if (!parent.contains(key))
+    {
+        throw JsonException(localWhat + "s parent does not contain " + localWhat);
+    }
+    return ensureIsArrayOf<T>(parent.value(key), localWhat);
 }
 
 template <typename T>
 QVector<T> ensureIsArrayOf(const QJsonObject &parent, const QString &key,
-						 const QVector<T> &default_ = QVector<T>(), const QString &what = "__placeholder__")
+                         const QVector<T> &default_ = QVector<T>(), const QString &what = "__placeholder__")
 {
-	const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
-	if (!parent.contains(key))
-	{
-		return default_;
-	}
-	return ensureIsArrayOf<T>(parent.value(key), default_, localWhat);
+    const QString localWhat = QString(what).replace("__placeholder__", '\'' + key + '\'');
+    if (!parent.contains(key))
+    {
+        return default_;
+    }
+    return ensureIsArrayOf<T>(parent.value(key), default_, localWhat);
 }
 
 // this macro part could be replaced by variadic functions that just pass on their arguments, but that wouldn't work well with IDE helpers
 #define JSON_HELPERFUNCTIONS(NAME, TYPE) \
-	inline TYPE require##NAME(const QJsonValue &value, const QString &what = "Value") \
-	{ \
-		return requireIsType<TYPE>(value, what); \
-	} \
-	inline TYPE ensure##NAME(const QJsonValue &value, const TYPE default_ = TYPE(), const QString &what = "Value") \
-	{ \
-		return ensureIsType<TYPE>(value, default_, what); \
-	} \
-	inline TYPE require##NAME(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__") \
-	{ \
-		return requireIsType<TYPE>(parent, key, what); \
-	} \
-	inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_ = TYPE(), const QString &what = "__placeholder") \
-	{ \
-		return ensureIsType<TYPE>(parent, key, default_, what); \
-	}
+    inline TYPE require##NAME(const QJsonValue &value, const QString &what = "Value") \
+    { \
+        return requireIsType<TYPE>(value, what); \
+    } \
+    inline TYPE ensure##NAME(const QJsonValue &value, const TYPE default_ = TYPE(), const QString &what = "Value") \
+    { \
+        return ensureIsType<TYPE>(value, default_, what); \
+    } \
+    inline TYPE require##NAME(const QJsonObject &parent, const QString &key, const QString &what = "__placeholder__") \
+    { \
+        return requireIsType<TYPE>(parent, key, what); \
+    } \
+    inline TYPE ensure##NAME(const QJsonObject &parent, const QString &key, const TYPE default_ = TYPE(), const QString &what = "__placeholder") \
+    { \
+        return ensureIsType<TYPE>(parent, key, default_, what); \
+    }
 
 JSON_HELPERFUNCTIONS(Array, QJsonArray)
 JSON_HELPERFUNCTIONS(Object, QJsonObject)
diff --git a/api/logic/LoggedProcess.cpp b/api/logic/LoggedProcess.cpp
index f89b4acc..822c0f04 100644
--- a/api/logic/LoggedProcess.cpp
+++ b/api/logic/LoggedProcess.cpp
@@ -4,157 +4,157 @@
 
 LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent)
 {
-	// QProcess has a strange interface... let's map a lot of those into a few.
-	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, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange);
+    // QProcess has a strange interface... let's map a lot of those into a few.
+    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, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange);
 }
 
 LoggedProcess::~LoggedProcess()
 {
-	if(m_is_detachable)
-	{
-		setProcessState(QProcess::NotRunning);
-	}
+    if(m_is_detachable)
+    {
+        setProcessState(QProcess::NotRunning);
+    }
 }
 
 QStringList reprocess(const QByteArray & data, QString & leftover)
 {
-	QString str = leftover + QString::fromLocal8Bit(data);
+    QString str = leftover + QString::fromLocal8Bit(data);
 
-	str.remove('\r');
-	QStringList lines = str.split("\n");
-	leftover = lines.takeLast();
-	return lines;
+    str.remove('\r');
+    QStringList lines = str.split("\n");
+    leftover = lines.takeLast();
+    return lines;
 }
 
 void LoggedProcess::on_stdErr()
 {
-	auto lines = reprocess(readAllStandardError(), m_err_leftover);
-	emit log(lines, MessageLevel::StdErr);
+    auto lines = reprocess(readAllStandardError(), m_err_leftover);
+    emit log(lines, MessageLevel::StdErr);
 }
 
 void LoggedProcess::on_stdOut()
 {
-	auto lines = reprocess(readAllStandardOutput(), m_out_leftover);
-	emit log(lines, MessageLevel::StdOut);
+    auto lines = reprocess(readAllStandardOutput(), m_out_leftover);
+    emit log(lines, MessageLevel::StdOut);
 }
 
 void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status)
 {
-	// save the exit code
-	m_exit_code = exit_code;
-
-	// Flush console window
-	if (!m_err_leftover.isEmpty())
-	{
-		emit log({m_err_leftover}, MessageLevel::StdErr);
-		m_err_leftover.clear();
-	}
-	if (!m_out_leftover.isEmpty())
-	{
-		emit log({m_err_leftover}, MessageLevel::StdOut);
-		m_out_leftover.clear();
-	}
-
-	// based on state, send signals
-	if (!m_is_aborting)
-	{
-		if (status == QProcess::NormalExit)
-		{
-			//: Message displayed on instance exit
-			emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::MultiMC);
-			changeState(LoggedProcess::Finished);
-		}
-		else
-		{
-			//: Message displayed on instance crashed
-			if(exit_code == -1)
-				emit log({tr("Process crashed.")}, MessageLevel::MultiMC);
-			else
-				emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::MultiMC);
-			changeState(LoggedProcess::Crashed);
-		}
-	}
-	else
-	{
-		//: Message displayed after the instance exits due to kill request
-		emit log({tr("Process was killed by user.")}, MessageLevel::Error);
-		changeState(LoggedProcess::Aborted);
-	}
+    // save the exit code
+    m_exit_code = exit_code;
+
+    // Flush console window
+    if (!m_err_leftover.isEmpty())
+    {
+        emit log({m_err_leftover}, MessageLevel::StdErr);
+        m_err_leftover.clear();
+    }
+    if (!m_out_leftover.isEmpty())
+    {
+        emit log({m_err_leftover}, MessageLevel::StdOut);
+        m_out_leftover.clear();
+    }
+
+    // based on state, send signals
+    if (!m_is_aborting)
+    {
+        if (status == QProcess::NormalExit)
+        {
+            //: Message displayed on instance exit
+            emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::MultiMC);
+            changeState(LoggedProcess::Finished);
+        }
+        else
+        {
+            //: Message displayed on instance crashed
+            if(exit_code == -1)
+                emit log({tr("Process crashed.")}, MessageLevel::MultiMC);
+            else
+                emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::MultiMC);
+            changeState(LoggedProcess::Crashed);
+        }
+    }
+    else
+    {
+        //: Message displayed after the instance exits due to kill request
+        emit log({tr("Process was killed by user.")}, MessageLevel::Error);
+        changeState(LoggedProcess::Aborted);
+    }
 }
 
 void LoggedProcess::on_error(QProcess::ProcessError error)
 {
-	switch(error)
-	{
-		case QProcess::FailedToStart:
-		{
-			emit log({tr("The process failed to start.")}, MessageLevel::Fatal);
-			changeState(LoggedProcess::FailedToStart);
-			break;
-		}
-		// we'll just ignore those... never needed them
-		case QProcess::Crashed:
-		case QProcess::ReadError:
-		case QProcess::Timedout:
-		case QProcess::UnknownError:
-		case QProcess::WriteError:
-			break;
-	}
+    switch(error)
+    {
+        case QProcess::FailedToStart:
+        {
+            emit log({tr("The process failed to start.")}, MessageLevel::Fatal);
+            changeState(LoggedProcess::FailedToStart);
+            break;
+        }
+        // we'll just ignore those... never needed them
+        case QProcess::Crashed:
+        case QProcess::ReadError:
+        case QProcess::Timedout:
+        case QProcess::UnknownError:
+        case QProcess::WriteError:
+            break;
+    }
 }
 
 void LoggedProcess::kill()
 {
-	m_is_aborting = true;
-	QProcess::kill();
+    m_is_aborting = true;
+    QProcess::kill();
 }
 
 int LoggedProcess::exitCode() const
 {
-	return m_exit_code;
+    return m_exit_code;
 }
 
 void LoggedProcess::changeState(LoggedProcess::State state)
 {
-	if(state == m_state)
-		return;
-	m_state = state;
-	emit stateChanged(m_state);
+    if(state == m_state)
+        return;
+    m_state = state;
+    emit stateChanged(m_state);
 }
 
 LoggedProcess::State LoggedProcess::state() const
 {
-	return m_state;
+    return m_state;
 }
 
 void LoggedProcess::on_stateChange(QProcess::ProcessState state)
 {
-	switch(state)
-	{
-		case QProcess::NotRunning:
-			break; // let's not - there are too many that handle this already.
-		case QProcess::Starting:
-		{
-			if(m_state != LoggedProcess::NotRunning)
-			{
-				qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Starting;
-			}
-			changeState(LoggedProcess::Starting);
-			return;
-		}
-		case QProcess::Running:
-		{
-			if(m_state != LoggedProcess::Starting)
-			{
-				qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Running;
-			}
-			changeState(LoggedProcess::Running);
-			return;
-		}
-	}
+    switch(state)
+    {
+        case QProcess::NotRunning:
+            break; // let's not - there are too many that handle this already.
+        case QProcess::Starting:
+        {
+            if(m_state != LoggedProcess::NotRunning)
+            {
+                qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Starting;
+            }
+            changeState(LoggedProcess::Starting);
+            return;
+        }
+        case QProcess::Running:
+        {
+            if(m_state != LoggedProcess::Starting)
+            {
+                qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Running;
+            }
+            changeState(LoggedProcess::Running);
+            return;
+        }
+    }
 }
 
 #if defined Q_OS_WIN32
@@ -172,5 +172,5 @@ qint64 LoggedProcess::processId() const
 
 void LoggedProcess::setDetachable(bool detachable)
 {
-	m_is_detachable = detachable;
+    m_is_detachable = detachable;
 }
diff --git a/api/logic/LoggedProcess.h b/api/logic/LoggedProcess.h
index 6a80365f..2cbc28bc 100644
--- a/api/logic/LoggedProcess.h
+++ b/api/logic/LoggedProcess.h
@@ -27,54 +27,54 @@ class MULTIMC_LOGIC_EXPORT LoggedProcess : public QProcess
 {
 Q_OBJECT
 public:
-	enum State
-	{
-		NotRunning,
-		Starting,
-		FailedToStart,
-		Running,
-		Finished,
-		Crashed,
-		Aborted
-	};
+    enum State
+    {
+        NotRunning,
+        Starting,
+        FailedToStart,
+        Running,
+        Finished,
+        Crashed,
+        Aborted
+    };
 
 public:
-	explicit LoggedProcess(QObject* parent = 0);
-	virtual ~LoggedProcess();
+    explicit LoggedProcess(QObject* parent = 0);
+    virtual ~LoggedProcess();
 
-	State state() const;
-	int exitCode() const;
-	qint64 processId() const;
+    State state() const;
+    int exitCode() const;
+    qint64 processId() const;
 
-	void setDetachable(bool detachable);
+    void setDetachable(bool detachable);
 
 signals:
-	void log(QStringList lines, MessageLevel::Enum level);
-	void stateChanged(LoggedProcess::State state);
+    void log(QStringList lines, MessageLevel::Enum level);
+    void stateChanged(LoggedProcess::State state);
 
 public slots:
-	/**
-	 * @brief kill the process - equivalent to kill -9
-	 */
-	void kill();
+    /**
+     * @brief kill the process - equivalent to kill -9
+     */
+    void kill();
 
 
 private slots:
-	void on_stdErr();
-	void on_stdOut();
-	void on_exit(int exit_code, QProcess::ExitStatus status);
-	void on_error(QProcess::ProcessError error);
-	void on_stateChange(QProcess::ProcessState);
+    void on_stdErr();
+    void on_stdOut();
+    void on_exit(int exit_code, QProcess::ExitStatus status);
+    void on_error(QProcess::ProcessError error);
+    void on_stateChange(QProcess::ProcessState);
 
 private:
-	void changeState(LoggedProcess::State state);
+    void changeState(LoggedProcess::State state);
 
 private:
-	QString m_err_leftover;
-	QString m_out_leftover;
-	bool m_killed = false;
-	State m_state = NotRunning;
-	int m_exit_code = 0;
-	bool m_is_aborting = false;
-	bool m_is_detachable = false;
+    QString m_err_leftover;
+    QString m_out_leftover;
+    bool m_killed = false;
+    State m_state = NotRunning;
+    int m_exit_code = 0;
+    bool m_is_aborting = false;
+    bool m_is_detachable = false;
 };
diff --git a/api/logic/MMCStrings.cpp b/api/logic/MMCStrings.cpp
index c50d596e..dc91c8d6 100644
--- a/api/logic/MMCStrings.cpp
+++ b/api/logic/MMCStrings.cpp
@@ -3,74 +3,74 @@
 /// TAKEN FROM Qt, because it doesn't expose it intelligently
 static inline QChar getNextChar(const QString &s, int location)
 {
-	return (location < s.length()) ? s.at(location) : QChar();
+    return (location < s.length()) ? s.at(location) : QChar();
 }
 
 /// TAKEN FROM Qt, because it doesn't expose it intelligently
 int Strings::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
 {
-	for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2)
-	{
-		// skip spaces, tabs and 0's
-		QChar c1 = getNextChar(s1, l1);
-		while (c1.isSpace())
-			c1 = getNextChar(s1, ++l1);
-		QChar c2 = getNextChar(s2, l2);
-		while (c2.isSpace())
-			c2 = getNextChar(s2, ++l2);
+    for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2)
+    {
+        // skip spaces, tabs and 0's
+        QChar c1 = getNextChar(s1, l1);
+        while (c1.isSpace())
+            c1 = getNextChar(s1, ++l1);
+        QChar c2 = getNextChar(s2, l2);
+        while (c2.isSpace())
+            c2 = getNextChar(s2, ++l2);
 
-		if (c1.isDigit() && c2.isDigit())
-		{
-			while (c1.digitValue() == 0)
-				c1 = getNextChar(s1, ++l1);
-			while (c2.digitValue() == 0)
-				c2 = getNextChar(s2, ++l2);
+        if (c1.isDigit() && c2.isDigit())
+        {
+            while (c1.digitValue() == 0)
+                c1 = getNextChar(s1, ++l1);
+            while (c2.digitValue() == 0)
+                c2 = getNextChar(s2, ++l2);
 
-			int lookAheadLocation1 = l1;
-			int lookAheadLocation2 = l2;
-			int currentReturnValue = 0;
-			// find the last digit, setting currentReturnValue as we go if it isn't equal
-			for (QChar lookAhead1 = c1, lookAhead2 = c2;
-				 (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
-				 lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
-					   lookAhead2 = getNextChar(s2, ++lookAheadLocation2))
-			{
-				bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
-				bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
-				if (!is1ADigit && !is2ADigit)
-					break;
-				if (!is1ADigit)
-					return -1;
-				if (!is2ADigit)
-					return 1;
-				if (currentReturnValue == 0)
-				{
-					if (lookAhead1 < lookAhead2)
-					{
-						currentReturnValue = -1;
-					}
-					else if (lookAhead1 > lookAhead2)
-					{
-						currentReturnValue = 1;
-					}
-				}
-			}
-			if (currentReturnValue != 0)
-				return currentReturnValue;
-		}
-		if (cs == Qt::CaseInsensitive)
-		{
-			if (!c1.isLower())
-				c1 = c1.toLower();
-			if (!c2.isLower())
-				c2 = c2.toLower();
-		}
-		int r = QString::localeAwareCompare(c1, c2);
-		if (r < 0)
-			return -1;
-		if (r > 0)
-			return 1;
-	}
-	// The two strings are the same (02 == 2) so fall back to the normal sort
-	return QString::compare(s1, s2, cs);
+            int lookAheadLocation1 = l1;
+            int lookAheadLocation2 = l2;
+            int currentReturnValue = 0;
+            // find the last digit, setting currentReturnValue as we go if it isn't equal
+            for (QChar lookAhead1 = c1, lookAhead2 = c2;
+                 (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
+                 lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
+                       lookAhead2 = getNextChar(s2, ++lookAheadLocation2))
+            {
+                bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
+                bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
+                if (!is1ADigit && !is2ADigit)
+                    break;
+                if (!is1ADigit)
+                    return -1;
+                if (!is2ADigit)
+                    return 1;
+                if (currentReturnValue == 0)
+                {
+                    if (lookAhead1 < lookAhead2)
+                    {
+                        currentReturnValue = -1;
+                    }
+                    else if (lookAhead1 > lookAhead2)
+                    {
+                        currentReturnValue = 1;
+                    }
+                }
+            }
+            if (currentReturnValue != 0)
+                return currentReturnValue;
+        }
+        if (cs == Qt::CaseInsensitive)
+        {
+            if (!c1.isLower())
+                c1 = c1.toLower();
+            if (!c2.isLower())
+                c2 = c2.toLower();
+        }
+        int r = QString::localeAwareCompare(c1, c2);
+        if (r < 0)
+            return -1;
+        if (r > 0)
+            return 1;
+    }
+    // The two strings are the same (02 == 2) so fall back to the normal sort
+    return QString::compare(s1, s2, cs);
 }
diff --git a/api/logic/MMCStrings.h b/api/logic/MMCStrings.h
index 5606b909..493ba3d2 100644
--- a/api/logic/MMCStrings.h
+++ b/api/logic/MMCStrings.h
@@ -6,5 +6,5 @@
 
 namespace Strings
 {
-	int MULTIMC_LOGIC_EXPORT naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
+    int MULTIMC_LOGIC_EXPORT naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
 }
diff --git a/api/logic/MMCZip.cpp b/api/logic/MMCZip.cpp
index 1e7ad51d..21a55493 100644
--- a/api/logic/MMCZip.cpp
+++ b/api/logic/MMCZip.cpp
@@ -25,231 +25,231 @@
 // ours
 bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, const JlCompress::FilterFunction filter)
 {
-	QuaZip modZip(from.filePath());
-	modZip.open(QuaZip::mdUnzip);
-
-	QuaZipFile fileInsideMod(&modZip);
-	QuaZipFile zipOutFile(into);
-	for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
-	{
-		QString filename = modZip.getCurrentFileName();
-		if (filter && !filter(filename))
-		{
-			qDebug() << "Skipping file " << filename << " from "
-						<< from.fileName() << " - filtered";
-			continue;
-		}
-		if (contained.contains(filename))
-		{
-			qDebug() << "Skipping already contained file " << filename << " from "
-						<< from.fileName();
-			continue;
-		}
-		contained.insert(filename);
-
-		if (!fileInsideMod.open(QIODevice::ReadOnly))
-		{
-			qCritical() << "Failed to open " << filename << " from " << from.fileName();
-			return false;
-		}
-
-		QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
-
-		if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
-		{
-			qCritical() << "Failed to open " << filename << " in the jar";
-			fileInsideMod.close();
-			return false;
-		}
-		if (!JlCompress::copyData(fileInsideMod, zipOutFile))
-		{
-			zipOutFile.close();
-			fileInsideMod.close();
-			qCritical() << "Failed to copy data of " << filename << " into the jar";
-			return false;
-		}
-		zipOutFile.close();
-		fileInsideMod.close();
-	}
-	return true;
+    QuaZip modZip(from.filePath());
+    modZip.open(QuaZip::mdUnzip);
+
+    QuaZipFile fileInsideMod(&modZip);
+    QuaZipFile zipOutFile(into);
+    for (bool more = modZip.goToFirstFile(); more; more = modZip.goToNextFile())
+    {
+        QString filename = modZip.getCurrentFileName();
+        if (filter && !filter(filename))
+        {
+            qDebug() << "Skipping file " << filename << " from "
+                        << from.fileName() << " - filtered";
+            continue;
+        }
+        if (contained.contains(filename))
+        {
+            qDebug() << "Skipping already contained file " << filename << " from "
+                        << from.fileName();
+            continue;
+        }
+        contained.insert(filename);
+
+        if (!fileInsideMod.open(QIODevice::ReadOnly))
+        {
+            qCritical() << "Failed to open " << filename << " from " << from.fileName();
+            return false;
+        }
+
+        QuaZipNewInfo info_out(fileInsideMod.getActualFileName());
+
+        if (!zipOutFile.open(QIODevice::WriteOnly, info_out))
+        {
+            qCritical() << "Failed to open " << filename << " in the jar";
+            fileInsideMod.close();
+            return false;
+        }
+        if (!JlCompress::copyData(fileInsideMod, zipOutFile))
+        {
+            zipOutFile.close();
+            fileInsideMod.close();
+            qCritical() << "Failed to copy data of " << filename << " into the jar";
+            return false;
+        }
+        zipOutFile.close();
+        fileInsideMod.close();
+    }
+    return true;
 }
 
 // ours
 bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods)
 {
-	QuaZip zipOut(targetJarPath);
-	if (!zipOut.open(QuaZip::mdCreate))
-	{
-		QFile::remove(targetJarPath);
-		qCritical() << "Failed to open the minecraft.jar for modding";
-		return false;
-	}
-	// Files already added to the jar.
-	// These files will be skipped.
-	QSet<QString> addedFiles;
-
-	// Modify the jar
-	QListIterator<Mod> i(mods);
+    QuaZip zipOut(targetJarPath);
+    if (!zipOut.open(QuaZip::mdCreate))
+    {
+        QFile::remove(targetJarPath);
+        qCritical() << "Failed to open the minecraft.jar for modding";
+        return false;
+    }
+    // Files already added to the jar.
+    // These files will be skipped.
+    QSet<QString> addedFiles;
+
+    // Modify the jar
+    QListIterator<Mod> i(mods);
     i.toBack();
     while (i.hasPrevious())
-	{
-		const Mod &mod = i.previous();
-		// do not merge disabled mods.
-		if (!mod.enabled())
-			continue;
-		if (mod.type() == Mod::MOD_ZIPFILE)
-		{
-			if (!mergeZipFiles(&zipOut, mod.filename(), addedFiles))
-			{
-				zipOut.close();
-				QFile::remove(targetJarPath);
-				qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
-				return false;
-			}
-		}
-		else if (mod.type() == Mod::MOD_SINGLEFILE)
-		{
-			// FIXME: buggy - does not work with addedFiles
-			auto filename = mod.filename();
-			if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName()))
-			{
-				zipOut.close();
-				QFile::remove(targetJarPath);
-				qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
-				return false;
-			}
-			addedFiles.insert(filename.fileName());
-		}
-		else if (mod.type() == Mod::MOD_FOLDER)
-		{
-			// FIXME: buggy - does not work with addedFiles
-			auto filename = mod.filename();
-			QString what_to_zip = filename.absoluteFilePath();
-			QDir dir(what_to_zip);
-			dir.cdUp();
-			QString parent_dir = dir.absolutePath();
-			if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, addedFiles))
-			{
-				zipOut.close();
-				QFile::remove(targetJarPath);
-				qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
-				return false;
-			}
-			qDebug() << "Adding folder " << filename.fileName() << " from "
-						<< filename.absoluteFilePath();
-		}
-		else
-		{
-			// Make sure we do not continue launching when something is missing or undefined...
-			zipOut.close();
-			QFile::remove(targetJarPath);
-			qCritical() << "Failed to add unknown mod type" << mod.filename().fileName() << "to the jar.";
-			return false;
-		}
-	}
-
-	if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key){return !key.contains("META-INF");}))
-	{
-		zipOut.close();
-		QFile::remove(targetJarPath);
-		qCritical() << "Failed to insert minecraft.jar contents.";
-		return false;
-	}
-
-	// Recompress the jar
-	zipOut.close();
-	if (zipOut.getZipError() != 0)
-	{
-		QFile::remove(targetJarPath);
-		qCritical() << "Failed to finalize minecraft.jar!";
-		return false;
-	}
-	return true;
+    {
+        const Mod &mod = i.previous();
+        // do not merge disabled mods.
+        if (!mod.enabled())
+            continue;
+        if (mod.type() == Mod::MOD_ZIPFILE)
+        {
+            if (!mergeZipFiles(&zipOut, mod.filename(), addedFiles))
+            {
+                zipOut.close();
+                QFile::remove(targetJarPath);
+                qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+                return false;
+            }
+        }
+        else if (mod.type() == Mod::MOD_SINGLEFILE)
+        {
+            // FIXME: buggy - does not work with addedFiles
+            auto filename = mod.filename();
+            if (!JlCompress::compressFile(&zipOut, filename.absoluteFilePath(), filename.fileName()))
+            {
+                zipOut.close();
+                QFile::remove(targetJarPath);
+                qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+                return false;
+            }
+            addedFiles.insert(filename.fileName());
+        }
+        else if (mod.type() == Mod::MOD_FOLDER)
+        {
+            // FIXME: buggy - does not work with addedFiles
+            auto filename = mod.filename();
+            QString what_to_zip = filename.absoluteFilePath();
+            QDir dir(what_to_zip);
+            dir.cdUp();
+            QString parent_dir = dir.absolutePath();
+            if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, addedFiles))
+            {
+                zipOut.close();
+                QFile::remove(targetJarPath);
+                qCritical() << "Failed to add" << mod.filename().fileName() << "to the jar.";
+                return false;
+            }
+            qDebug() << "Adding folder " << filename.fileName() << " from "
+                        << filename.absoluteFilePath();
+        }
+        else
+        {
+            // Make sure we do not continue launching when something is missing or undefined...
+            zipOut.close();
+            QFile::remove(targetJarPath);
+            qCritical() << "Failed to add unknown mod type" << mod.filename().fileName() << "to the jar.";
+            return false;
+        }
+    }
+
+    if (!mergeZipFiles(&zipOut, QFileInfo(sourceJarPath), addedFiles, [](const QString key){return !key.contains("META-INF");}))
+    {
+        zipOut.close();
+        QFile::remove(targetJarPath);
+        qCritical() << "Failed to insert minecraft.jar contents.";
+        return false;
+    }
+
+    // Recompress the jar
+    zipOut.close();
+    if (zipOut.getZipError() != 0)
+    {
+        QFile::remove(targetJarPath);
+        qCritical() << "Failed to finalize minecraft.jar!";
+        return false;
+    }
+    return true;
 }
 
 // ours
 QString MMCZip::findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root)
 {
-	QuaZipDir rootDir(zip, root);
-	for(auto fileName: rootDir.entryList(QDir::Files))
-	{
-		if(fileName == what)
-			return root;
-	}
-	for(auto fileName: rootDir.entryList(QDir::Dirs))
-	{
-		QString result = findFolderOfFileInZip(zip, what, root + fileName);
-		if(!result.isEmpty())
-		{
-			return result;
-		}
-	}
-	return QString();
+    QuaZipDir rootDir(zip, root);
+    for(auto fileName: rootDir.entryList(QDir::Files))
+    {
+        if(fileName == what)
+            return root;
+    }
+    for(auto fileName: rootDir.entryList(QDir::Dirs))
+    {
+        QString result = findFolderOfFileInZip(zip, what, root + fileName);
+        if(!result.isEmpty())
+        {
+            return result;
+        }
+    }
+    return QString();
 }
 
 // ours
 bool MMCZip::findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root)
 {
-	QuaZipDir rootDir(zip, root);
-	for(auto fileName: rootDir.entryList(QDir::Files))
-	{
-		if(fileName == what)
-		{
-			result.append(root);
-			return true;
-		}
-	}
-	for(auto fileName: rootDir.entryList(QDir::Dirs))
-	{
-		findFilesInZip(zip, what, result, root + fileName);
-	}
-	return !result.isEmpty();
+    QuaZipDir rootDir(zip, root);
+    for(auto fileName: rootDir.entryList(QDir::Files))
+    {
+        if(fileName == what)
+        {
+            result.append(root);
+            return true;
+        }
+    }
+    for(auto fileName: rootDir.entryList(QDir::Dirs))
+    {
+        findFilesInZip(zip, what, result, root + fileName);
+    }
+    return !result.isEmpty();
 }
 
 
 // ours
 QStringList MMCZip::extractSubDir(QuaZip *zip, const QString & subdir, const QString &target)
 {
-	QDir directory(target);
-	QStringList extracted;
-	qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
-	if (!zip->goToFirstFile())
-	{
-		qWarning() << "Failed to seek to first file in zip";
-		return QStringList();
-	}
-	do
-	{
-		QString name = zip->getCurrentFileName();
-		if(!name.startsWith(subdir))
-		{
-			continue;
-		}
-		name.remove(0, subdir.size());
-		QString absFilePath = directory.absoluteFilePath(name);
-		if(name.isEmpty())
-		{
-			absFilePath += "/";
-		}
-		if (!JlCompress::extractFile(zip, "", absFilePath))
-		{
-			qWarning() << "Failed to extract file" << name << "to" << absFilePath;
-			JlCompress::removeFile(extracted);
-			return QStringList();
-		}
-		extracted.append(absFilePath);
-		qDebug() << "Extracted file" << name;
-	} while (zip->goToNextFile());
-	return extracted;
+    QDir directory(target);
+    QStringList extracted;
+    qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
+    if (!zip->goToFirstFile())
+    {
+        qWarning() << "Failed to seek to first file in zip";
+        return QStringList();
+    }
+    do
+    {
+        QString name = zip->getCurrentFileName();
+        if(!name.startsWith(subdir))
+        {
+            continue;
+        }
+        name.remove(0, subdir.size());
+        QString absFilePath = directory.absoluteFilePath(name);
+        if(name.isEmpty())
+        {
+            absFilePath += "/";
+        }
+        if (!JlCompress::extractFile(zip, "", absFilePath))
+        {
+            qWarning() << "Failed to extract file" << name << "to" << absFilePath;
+            JlCompress::removeFile(extracted);
+            return QStringList();
+        }
+        extracted.append(absFilePath);
+        qDebug() << "Extracted file" << name;
+    } while (zip->goToNextFile());
+    return extracted;
 }
 
 // ours
 QStringList MMCZip::extractDir(QString fileCompressed, QString dir)
 {
-	QuaZip zip(fileCompressed);
-	if (!zip.open(QuaZip::mdUnzip))
-	{
-		return {};
-	}
-	return MMCZip::extractSubDir(&zip, "", dir);
+    QuaZip zip(fileCompressed);
+    if (!zip.open(QuaZip::mdUnzip))
+    {
+        return {};
+    }
+    return MMCZip::extractSubDir(&zip, "", dir);
 }
diff --git a/api/logic/MMCZip.h b/api/logic/MMCZip.h
index 68094b2c..4eb86361 100644
--- a/api/logic/MMCZip.h
+++ b/api/logic/MMCZip.h
@@ -28,44 +28,44 @@
 namespace MMCZip
 {
 
-	/**
-	 * Merge two zip files, using a filter function
-	 */
-	bool MULTIMC_LOGIC_EXPORT mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
-											const JlCompress::FilterFunction filter = nullptr);
+    /**
+     * Merge two zip files, using a filter function
+     */
+    bool MULTIMC_LOGIC_EXPORT mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
+                                            const JlCompress::FilterFunction filter = nullptr);
 
-	/**
-	 * take a source jar, add mods to it, resulting in target jar
-	 */
-	bool MULTIMC_LOGIC_EXPORT createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods);
+    /**
+     * take a source jar, add mods to it, resulting in target jar
+     */
+    bool MULTIMC_LOGIC_EXPORT createModdedJar(QString sourceJarPath, QString targetJarPath, const QList<Mod>& mods);
 
-	/**
-	 * Find a single file in archive by file name (not path)
-	 *
-	 * \return the path prefix where the file is
-	 */
-	QString MULTIMC_LOGIC_EXPORT findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString(""));
+    /**
+     * Find a single file in archive by file name (not path)
+     *
+     * \return the path prefix where the file is
+     */
+    QString MULTIMC_LOGIC_EXPORT findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString(""));
 
-	/**
-	 * Find a multiple files of the same name in archive by file name
-	 * If a file is found in a path, no deeper paths are searched
-	 *
-	 * \return true if anything was found
-	 */
-	bool MULTIMC_LOGIC_EXPORT findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root = QString());
+    /**
+     * Find a multiple files of the same name in archive by file name
+     * If a file is found in a path, no deeper paths are searched
+     *
+     * \return true if anything was found
+     */
+    bool MULTIMC_LOGIC_EXPORT findFilesInZip(QuaZip * zip, const QString & what, QStringList & result, const QString &root = QString());
 
-	/**
-	 * Extract a subdirectory from an archive
-	 */
-	QStringList MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
+    /**
+     * Extract a subdirectory from an archive
+     */
+    QStringList MULTIMC_LOGIC_EXPORT extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
 
-	/**
-	 * Extract a whole archive.
-	 *
-	 * \param fileCompressed The name of the archive.
-	 * \param dir The directory to extract to, the current directory if left empty.
-	 * \return The list of the full paths of the files extracted, empty on failure.
-	 */
-	QStringList MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
+    /**
+     * Extract a whole archive.
+     *
+     * \param fileCompressed The name of the archive.
+     * \param dir The directory to extract to, the current directory if left empty.
+     * \return The list of the full paths of the files extracted, empty on failure.
+     */
+    QStringList MULTIMC_LOGIC_EXPORT extractDir(QString fileCompressed, QString dir);
 
 }
diff --git a/api/logic/MessageLevel.cpp b/api/logic/MessageLevel.cpp
index a5191290..0a2cd23d 100644
--- a/api/logic/MessageLevel.cpp
+++ b/api/logic/MessageLevel.cpp
@@ -2,35 +2,35 @@
 
 MessageLevel::Enum MessageLevel::getLevel(const QString& levelName)
 {
-	if (levelName == "MultiMC")
-		return MessageLevel::MultiMC;
-	else if (levelName == "Debug")
-		return MessageLevel::Debug;
-	else if (levelName == "Info")
-		return MessageLevel::Info;
-	else if (levelName == "Message")
-		return MessageLevel::Message;
-	else if (levelName == "Warning")
-		return MessageLevel::Warning;
-	else if (levelName == "Error")
-		return MessageLevel::Error;
-	else if (levelName == "Fatal")
-		return MessageLevel::Fatal;
-	// Skip PrePost, it's not exposed to !![]!
-	// Also skip StdErr and StdOut
-	else
-		return MessageLevel::Unknown;
+    if (levelName == "MultiMC")
+        return MessageLevel::MultiMC;
+    else if (levelName == "Debug")
+        return MessageLevel::Debug;
+    else if (levelName == "Info")
+        return MessageLevel::Info;
+    else if (levelName == "Message")
+        return MessageLevel::Message;
+    else if (levelName == "Warning")
+        return MessageLevel::Warning;
+    else if (levelName == "Error")
+        return MessageLevel::Error;
+    else if (levelName == "Fatal")
+        return MessageLevel::Fatal;
+    // Skip PrePost, it's not exposed to !![]!
+    // Also skip StdErr and StdOut
+    else
+        return MessageLevel::Unknown;
 }
 
 MessageLevel::Enum MessageLevel::fromLine(QString &line)
 {
-	// Level prefix
-	int endmark = line.indexOf("]!");
-	if (line.startsWith("!![") && endmark != -1)
-	{
-		auto level = MessageLevel::getLevel(line.left(endmark).mid(3));
-		line = line.mid(endmark + 2);
-		return level;
-	}
-	return MessageLevel::Unknown;
+    // Level prefix
+    int endmark = line.indexOf("]!");
+    if (line.startsWith("!![") && endmark != -1)
+    {
+        auto level = MessageLevel::getLevel(line.left(endmark).mid(3));
+        line = line.mid(endmark + 2);
+        return level;
+    }
+    return MessageLevel::Unknown;
 }
diff --git a/api/logic/MessageLevel.h b/api/logic/MessageLevel.h
index 0128148d..f19048e3 100644
--- a/api/logic/MessageLevel.h
+++ b/api/logic/MessageLevel.h
@@ -10,16 +10,16 @@ namespace MessageLevel
 {
 enum Enum
 {
-	Unknown, /**< No idea what this is or where it came from */
-	StdOut,  /**< Undetermined stderr messages */
-	StdErr,  /**< Undetermined stdout messages */
-	MultiMC, /**< MultiMC Messages */
-	Debug,   /**< Debug Messages */
-	Info,    /**< Info Messages */
-	Message, /**< Standard Messages */
-	Warning, /**< Warnings */
-	Error,   /**< Errors */
-	Fatal,   /**< Fatal Errors */
+    Unknown, /**< No idea what this is or where it came from */
+    StdOut,  /**< Undetermined stderr messages */
+    StdErr,  /**< Undetermined stdout messages */
+    MultiMC, /**< MultiMC Messages */
+    Debug,   /**< Debug Messages */
+    Info,    /**< Info Messages */
+    Message, /**< Standard Messages */
+    Warning, /**< Warnings */
+    Error,   /**< Errors */
+    Fatal,   /**< Fatal Errors */
 };
 MessageLevel::Enum getLevel(const QString &levelName);
 
diff --git a/api/logic/NullInstance.h b/api/logic/NullInstance.h
index 64965277..861a2f57 100644
--- a/api/logic/NullInstance.h
+++ b/api/logic/NullInstance.h
@@ -4,74 +4,74 @@
 class NullInstance: public BaseInstance
 {
 public:
-	NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir)
-	:BaseInstance(globalSettings, settings, rootDir)
-	{
-		setVersionBroken(true);
-	}
-	virtual ~NullInstance() {};
-	virtual void init() override
-	{
-	}
-	virtual void saveNow() override
-	{
-	}
-	virtual QString getStatusbarDescription() override
-	{
-		return tr("Unknown instance type");
-	};
-	virtual QSet< QString > traits() const override
-	{
-		return {};
-	};
-	virtual QString instanceConfigFolder() const override
-	{
-		return instanceRoot();
-	};
-	virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr) override
-	{
-		return nullptr;
-	}
-	virtual shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override
-	{
-		return nullptr;
-	}
-	virtual QProcessEnvironment createEnvironment() override
-	{
-		return QProcessEnvironment();
-	}
-	virtual QMap<QString, QString> getVariables() const override
-	{
-		return QMap<QString, QString>();
-	}
-	virtual IPathMatcher::Ptr getLogFileMatcher() override
-	{
-		return nullptr;
-	}
-	virtual QString getLogFileRoot() override
-	{
-		return instanceRoot();
-	}
-	virtual QString typeName() const override
-	{
-		return "Null";
-	}
-	bool canExport() const override
-	{
-		return false;
-	}
-	bool canEdit() const override
-	{
-		return false;
-	}
-	bool canLaunch() const override
-	{
-		return false;
-	}
-	QStringList verboseDescription(AuthSessionPtr session) override
-	{
-		QStringList out;
-		out << "Null instance - placeholder.";
-		return out;
-	}
+    NullInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString& rootDir)
+    :BaseInstance(globalSettings, settings, rootDir)
+    {
+        setVersionBroken(true);
+    }
+    virtual ~NullInstance() {};
+    virtual void init() override
+    {
+    }
+    virtual void saveNow() override
+    {
+    }
+    virtual QString getStatusbarDescription() override
+    {
+        return tr("Unknown instance type");
+    };
+    virtual QSet< QString > traits() const override
+    {
+        return {};
+    };
+    virtual QString instanceConfigFolder() const override
+    {
+        return instanceRoot();
+    };
+    virtual std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr) override
+    {
+        return nullptr;
+    }
+    virtual shared_qobject_ptr< Task > createUpdateTask(Net::Mode mode) override
+    {
+        return nullptr;
+    }
+    virtual QProcessEnvironment createEnvironment() override
+    {
+        return QProcessEnvironment();
+    }
+    virtual QMap<QString, QString> getVariables() const override
+    {
+        return QMap<QString, QString>();
+    }
+    virtual IPathMatcher::Ptr getLogFileMatcher() override
+    {
+        return nullptr;
+    }
+    virtual QString getLogFileRoot() override
+    {
+        return instanceRoot();
+    }
+    virtual QString typeName() const override
+    {
+        return "Null";
+    }
+    bool canExport() const override
+    {
+        return false;
+    }
+    bool canEdit() const override
+    {
+        return false;
+    }
+    bool canLaunch() const override
+    {
+        return false;
+    }
+    QStringList verboseDescription(AuthSessionPtr session) override
+    {
+        QStringList out;
+        out << "Null instance - placeholder.";
+        return out;
+    }
 };
diff --git a/api/logic/ProblemProvider.h b/api/logic/ProblemProvider.h
index 978710f0..33c9d364 100644
--- a/api/logic/ProblemProvider.h
+++ b/api/logic/ProblemProvider.h
@@ -4,46 +4,46 @@
 
 enum class ProblemSeverity
 {
-	None,
-	Warning,
-	Error
+    None,
+    Warning,
+    Error
 };
 
 struct PatchProblem
 {
-	ProblemSeverity m_severity;
-	QString m_description;
+    ProblemSeverity m_severity;
+    QString m_description;
 };
 
 class MULTIMC_LOGIC_EXPORT ProblemProvider
 {
 public:
-	virtual ~ProblemProvider() {};
-	virtual const QList<PatchProblem> getProblems() const = 0;
-	virtual ProblemSeverity getProblemSeverity() const = 0;
+    virtual ~ProblemProvider() {};
+    virtual const QList<PatchProblem> getProblems() const = 0;
+    virtual ProblemSeverity getProblemSeverity() const = 0;
 };
 
 class MULTIMC_LOGIC_EXPORT ProblemContainer : public ProblemProvider
 {
 public:
-	const QList<PatchProblem> getProblems() const override
-	{
-		return m_problems;
-	}
-	ProblemSeverity getProblemSeverity() const override
-	{
-		return m_problemSeverity;
-	}
-	virtual void addProblem(ProblemSeverity severity, const QString &description)
-	{
-		if(severity > m_problemSeverity)
-		{
-			m_problemSeverity = severity;
-		}
-		m_problems.append({severity, description});
-	}
+    const QList<PatchProblem> getProblems() const override
+    {
+        return m_problems;
+    }
+    ProblemSeverity getProblemSeverity() const override
+    {
+        return m_problemSeverity;
+    }
+    virtual void addProblem(ProblemSeverity severity, const QString &description)
+    {
+        if(severity > m_problemSeverity)
+        {
+            m_problemSeverity = severity;
+        }
+        m_problems.append({severity, description});
+    }
 
 private:
-	QList<PatchProblem> m_problems;
-	ProblemSeverity m_problemSeverity = ProblemSeverity::None;
+    QList<PatchProblem> m_problems;
+    ProblemSeverity m_problemSeverity = ProblemSeverity::None;
 };
diff --git a/api/logic/QObjectPtr.h b/api/logic/QObjectPtr.h
index 4a42f728..0ff51136 100644
--- a/api/logic/QObjectPtr.h
+++ b/api/logic/QObjectPtr.h
@@ -8,10 +8,10 @@ namespace details
 {
 struct DeleteQObjectLater
 {
-	void operator()(QObject *obj) const
-	{
-		obj->deleteLater();
-	}
+    void operator()(QObject *obj) const
+    {
+        obj->deleteLater();
+    }
 };
 }
 /**
@@ -28,56 +28,56 @@ template <typename T>
 class shared_qobject_ptr
 {
 public:
-	shared_qobject_ptr(){}
-	shared_qobject_ptr(T * wrap)
-	{
-		reset(wrap);
-	}
-	shared_qobject_ptr(const shared_qobject_ptr<T>& other)
-	{
-		m_ptr = other.m_ptr;
-	}
-	template<typename Derived>
-	shared_qobject_ptr(const shared_qobject_ptr<Derived> &other)
-	{
-		m_ptr = other.unwrap();
-	}
+    shared_qobject_ptr(){}
+    shared_qobject_ptr(T * wrap)
+    {
+        reset(wrap);
+    }
+    shared_qobject_ptr(const shared_qobject_ptr<T>& other)
+    {
+        m_ptr = other.m_ptr;
+    }
+    template<typename Derived>
+    shared_qobject_ptr(const shared_qobject_ptr<Derived> &other)
+    {
+        m_ptr = other.unwrap();
+    }
 
 public:
-	void reset(T * wrap)
-	{
-		using namespace std::placeholders;
-		m_ptr.reset(wrap, std::bind(&QObject::deleteLater, _1));
-	}
-	void reset(const shared_qobject_ptr<T> &other)
-	{
-		m_ptr = other.m_ptr;
-	}
-	void reset()
-	{
-		m_ptr.reset();
-	}
-	T * get() const
-	{
-		return m_ptr.get();
-	}
-	T * operator->() const
-	{
-		return m_ptr.get();
-	}
-	T & operator*() const
-	{
-		return *m_ptr.get();
-	}
-	operator bool() const
-	{
-		return m_ptr.get() != nullptr;
-	}
-	const std::shared_ptr <T> unwrap() const
-	{
-		return m_ptr;
-	}
+    void reset(T * wrap)
+    {
+        using namespace std::placeholders;
+        m_ptr.reset(wrap, std::bind(&QObject::deleteLater, _1));
+    }
+    void reset(const shared_qobject_ptr<T> &other)
+    {
+        m_ptr = other.m_ptr;
+    }
+    void reset()
+    {
+        m_ptr.reset();
+    }
+    T * get() const
+    {
+        return m_ptr.get();
+    }
+    T * operator->() const
+    {
+        return m_ptr.get();
+    }
+    T & operator*() const
+    {
+        return *m_ptr.get();
+    }
+    operator bool() const
+    {
+        return m_ptr.get() != nullptr;
+    }
+    const std::shared_ptr <T> unwrap() const
+    {
+        return m_ptr;
+    }
 
 private:
-	std::shared_ptr <T> m_ptr;
+    std::shared_ptr <T> m_ptr;
 };
diff --git a/api/logic/RWStorage.h b/api/logic/RWStorage.h
index 4afbd96c..5d792367 100644
--- a/api/logic/RWStorage.h
+++ b/api/logic/RWStorage.h
@@ -5,59 +5,59 @@ template <typename K, typename V>
 class RWStorage
 {
 public:
-	void add(K key, V value)
-	{
-		QWriteLocker l(&lock);
-		cache[key] = value;
-		stale_entries.remove(key);
-	}
-	V get(K key)
-	{
-		QReadLocker l(&lock);
-		if(cache.contains(key))
-		{
-			return cache[key];
-		}
-		else return V();
-	}
-	bool get(K key, V& value)
-	{
-		QReadLocker l(&lock);
-		if(cache.contains(key))
-		{
-			value = cache[key];
-			return true;
-		}
-		else return false;
-	}
-	bool has(K key)
-	{
-		QReadLocker l(&lock);
-		return cache.contains(key);
-	}
-	bool stale(K key)
-	{
-		QReadLocker l(&lock);
-		if(!cache.contains(key))
-			return true;
-		return stale_entries.contains(key);
-	}
-	void setStale(K key)
-	{
-		QWriteLocker l(&lock);
-		if(cache.contains(key))
-		{
-			stale_entries.insert(key);
-		}
-	}
-	void clear()
-	{
-		QWriteLocker l(&lock);
-		cache.clear();
-		stale_entries.clear();
-	}
+    void add(K key, V value)
+    {
+        QWriteLocker l(&lock);
+        cache[key] = value;
+        stale_entries.remove(key);
+    }
+    V get(K key)
+    {
+        QReadLocker l(&lock);
+        if(cache.contains(key))
+        {
+            return cache[key];
+        }
+        else return V();
+    }
+    bool get(K key, V& value)
+    {
+        QReadLocker l(&lock);
+        if(cache.contains(key))
+        {
+            value = cache[key];
+            return true;
+        }
+        else return false;
+    }
+    bool has(K key)
+    {
+        QReadLocker l(&lock);
+        return cache.contains(key);
+    }
+    bool stale(K key)
+    {
+        QReadLocker l(&lock);
+        if(!cache.contains(key))
+            return true;
+        return stale_entries.contains(key);
+    }
+    void setStale(K key)
+    {
+        QWriteLocker l(&lock);
+        if(cache.contains(key))
+        {
+            stale_entries.insert(key);
+        }
+    }
+    void clear()
+    {
+        QWriteLocker l(&lock);
+        cache.clear();
+        stale_entries.clear();
+    }
 private:
-	QReadWriteLock lock;
-	QMap<K, V> cache;
-	QSet<K> stale_entries;
+    QReadWriteLock lock;
+    QMap<K, V> cache;
+    QSet<K> stale_entries;
 };
diff --git a/api/logic/RecursiveFileSystemWatcher.cpp b/api/logic/RecursiveFileSystemWatcher.cpp
index 59c3f0f0..b7417cdf 100644
--- a/api/logic/RecursiveFileSystemWatcher.cpp
+++ b/api/logic/RecursiveFileSystemWatcher.cpp
@@ -4,108 +4,108 @@
 #include <QDebug>
 
 RecursiveFileSystemWatcher::RecursiveFileSystemWatcher(QObject *parent)
-	: QObject(parent), m_watcher(new QFileSystemWatcher(this))
+    : QObject(parent), m_watcher(new QFileSystemWatcher(this))
 {
-	connect(m_watcher, &QFileSystemWatcher::fileChanged, this,
-			&RecursiveFileSystemWatcher::fileChange);
-	connect(m_watcher, &QFileSystemWatcher::directoryChanged, this,
-			&RecursiveFileSystemWatcher::directoryChange);
+    connect(m_watcher, &QFileSystemWatcher::fileChanged, this,
+            &RecursiveFileSystemWatcher::fileChange);
+    connect(m_watcher, &QFileSystemWatcher::directoryChanged, this,
+            &RecursiveFileSystemWatcher::directoryChange);
 }
 
 void RecursiveFileSystemWatcher::setRootDir(const QDir &root)
 {
-	bool wasEnabled = m_isEnabled;
-	disable();
-	m_root = root;
-	setFiles(scanRecursive(m_root));
-	if (wasEnabled)
-	{
-		enable();
-	}
+    bool wasEnabled = m_isEnabled;
+    disable();
+    m_root = root;
+    setFiles(scanRecursive(m_root));
+    if (wasEnabled)
+    {
+        enable();
+    }
 }
 void RecursiveFileSystemWatcher::setWatchFiles(const bool watchFiles)
 {
-	bool wasEnabled = m_isEnabled;
-	disable();
-	m_watchFiles = watchFiles;
-	if (wasEnabled)
-	{
-		enable();
-	}
+    bool wasEnabled = m_isEnabled;
+    disable();
+    m_watchFiles = watchFiles;
+    if (wasEnabled)
+    {
+        enable();
+    }
 }
 
 void RecursiveFileSystemWatcher::enable()
 {
-	if (m_isEnabled)
-	{
-		return;
-	}
-	Q_ASSERT(m_root != QDir::root());
-	addFilesToWatcherRecursive(m_root);
-	m_isEnabled = true;
+    if (m_isEnabled)
+    {
+        return;
+    }
+    Q_ASSERT(m_root != QDir::root());
+    addFilesToWatcherRecursive(m_root);
+    m_isEnabled = true;
 }
 void RecursiveFileSystemWatcher::disable()
 {
-	if (!m_isEnabled)
-	{
-		return;
-	}
-	m_isEnabled = false;
-	m_watcher->removePaths(m_watcher->files());
-	m_watcher->removePaths(m_watcher->directories());
+    if (!m_isEnabled)
+    {
+        return;
+    }
+    m_isEnabled = false;
+    m_watcher->removePaths(m_watcher->files());
+    m_watcher->removePaths(m_watcher->directories());
 }
 
 void RecursiveFileSystemWatcher::setFiles(const QStringList &files)
 {
-	if (files != m_files)
-	{
-		m_files = files;
-		emit filesChanged();
-	}
+    if (files != m_files)
+    {
+        m_files = files;
+        emit filesChanged();
+    }
 }
 
 void RecursiveFileSystemWatcher::addFilesToWatcherRecursive(const QDir &dir)
 {
-	m_watcher->addPath(dir.absolutePath());
-	for (const QString &directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
-	{
-		addFilesToWatcherRecursive(dir.absoluteFilePath(directory));
-	}
-	if (m_watchFiles)
-	{
-		for (const QFileInfo &info : dir.entryInfoList(QDir::Files))
-		{
-			m_watcher->addPath(info.absoluteFilePath());
-		}
-	}
+    m_watcher->addPath(dir.absolutePath());
+    for (const QString &directory : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
+    {
+        addFilesToWatcherRecursive(dir.absoluteFilePath(directory));
+    }
+    if (m_watchFiles)
+    {
+        for (const QFileInfo &info : dir.entryInfoList(QDir::Files))
+        {
+            m_watcher->addPath(info.absoluteFilePath());
+        }
+    }
 }
 QStringList RecursiveFileSystemWatcher::scanRecursive(const QDir &directory)
 {
-	QStringList ret;
-	if(!m_matcher)
-	{
-		return {};
-	}
-	for (const QString &dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden))
-	{
-		ret.append(scanRecursive(directory.absoluteFilePath(dir)));
-	}
-	for (const QString &file : directory.entryList(QDir::Files | QDir::Hidden))
-	{
-		auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file));
-		if (m_matcher->matches(relPath))
-		{
-			ret.append(relPath);
-		}
-	}
-	return ret;
+    QStringList ret;
+    if(!m_matcher)
+    {
+        return {};
+    }
+    for (const QString &dir : directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden))
+    {
+        ret.append(scanRecursive(directory.absoluteFilePath(dir)));
+    }
+    for (const QString &file : directory.entryList(QDir::Files | QDir::Hidden))
+    {
+        auto relPath = m_root.relativeFilePath(directory.absoluteFilePath(file));
+        if (m_matcher->matches(relPath))
+        {
+            ret.append(relPath);
+        }
+    }
+    return ret;
 }
 
 void RecursiveFileSystemWatcher::fileChange(const QString &path)
 {
-	emit fileChanged(path);
+    emit fileChanged(path);
 }
 void RecursiveFileSystemWatcher::directoryChange(const QString &path)
 {
-	setFiles(scanRecursive(m_root));
+    setFiles(scanRecursive(m_root));
 }
diff --git a/api/logic/RecursiveFileSystemWatcher.h b/api/logic/RecursiveFileSystemWatcher.h
index 07bce0b9..c9c39f49 100644
--- a/api/logic/RecursiveFileSystemWatcher.h
+++ b/api/logic/RecursiveFileSystemWatcher.h
@@ -8,56 +8,56 @@
 
 class MULTIMC_LOGIC_EXPORT RecursiveFileSystemWatcher : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	RecursiveFileSystemWatcher(QObject *parent);
-
-	void setRootDir(const QDir &root);
-	QDir rootDir() const
-	{
-		return m_root;
-	}
-
-	// WARNING: setting this to true may be bad for performance
-	void setWatchFiles(const bool watchFiles);
-	bool watchFiles() const
-	{
-		return m_watchFiles;
-	}
-
-	void setMatcher(IPathMatcher::Ptr matcher)
-	{
-		m_matcher = matcher;
-	}
-
-	QStringList files() const
-	{
-		return m_files;
-	}
+    RecursiveFileSystemWatcher(QObject *parent);
+
+    void setRootDir(const QDir &root);
+    QDir rootDir() const
+    {
+        return m_root;
+    }
+
+    // WARNING: setting this to true may be bad for performance
+    void setWatchFiles(const bool watchFiles);
+    bool watchFiles() const
+    {
+        return m_watchFiles;
+    }
+
+    void setMatcher(IPathMatcher::Ptr matcher)
+    {
+        m_matcher = matcher;
+    }
+
+    QStringList files() const
+    {
+        return m_files;
+    }
 
 signals:
-	void filesChanged();
-	void fileChanged(const QString &path);
+    void filesChanged();
+    void fileChanged(const QString &path);
 
 public slots:
-	void enable();
-	void disable();
+    void enable();
+    void disable();
 
 private:
-	QDir m_root;
-	bool m_watchFiles = false;
-	bool m_isEnabled = false;
-	IPathMatcher::Ptr m_matcher;
+    QDir m_root;
+    bool m_watchFiles = false;
+    bool m_isEnabled = false;
+    IPathMatcher::Ptr m_matcher;
 
-	QFileSystemWatcher *m_watcher;
+    QFileSystemWatcher *m_watcher;
 
-	QStringList m_files;
-	void setFiles(const QStringList &files);
+    QStringList m_files;
+    void setFiles(const QStringList &files);
 
-	void addFilesToWatcherRecursive(const QDir &dir);
-	QStringList scanRecursive(const QDir &dir);
+    void addFilesToWatcherRecursive(const QDir &dir);
+    QStringList scanRecursive(const QDir &dir);
 
 private slots:
-	void fileChange(const QString &path);
-	void directoryChange(const QString &path);
+    void fileChange(const QString &path);
+    void directoryChange(const QString &path);
 };
diff --git a/api/logic/SeparatorPrefixTree.h b/api/logic/SeparatorPrefixTree.h
index fd149af0..7a841cb7 100644
--- a/api/logic/SeparatorPrefixTree.h
+++ b/api/logic/SeparatorPrefixTree.h
@@ -7,292 +7,292 @@ template <char Tseparator>
 class SeparatorPrefixTree
 {
 public:
-	SeparatorPrefixTree(QStringList paths)
-	{
-		insert(paths);
-	}
+    SeparatorPrefixTree(QStringList paths)
+    {
+        insert(paths);
+    }
 
-	SeparatorPrefixTree(bool contained = false)
-	{
-		m_contained = contained;
-	}
+    SeparatorPrefixTree(bool contained = false)
+    {
+        m_contained = contained;
+    }
 
-	void insert(QStringList paths)
-	{
-		for(auto &path: paths)
-		{
-			insert(path);
-		}
-	}
+    void insert(QStringList paths)
+    {
+        for(auto &path: paths)
+        {
+            insert(path);
+        }
+    }
 
-	/// insert an exact path into the tree
-	SeparatorPrefixTree & insert(QString path)
-	{
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			children[path] = SeparatorPrefixTree(true);
-			return children[path];
-		}
-		else
-		{
-			auto prefix = path.left(sepIndex);
-			if(!children.contains(prefix))
-			{
-				children[prefix] = SeparatorPrefixTree(false);
-			}
-			return children[prefix].insert(path.mid(sepIndex + 1));
-		}
-	}
+    /// insert an exact path into the tree
+    SeparatorPrefixTree & insert(QString path)
+    {
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            children[path] = SeparatorPrefixTree(true);
+            return children[path];
+        }
+        else
+        {
+            auto prefix = path.left(sepIndex);
+            if(!children.contains(prefix))
+            {
+                children[prefix] = SeparatorPrefixTree(false);
+            }
+            return children[prefix].insert(path.mid(sepIndex + 1));
+        }
+    }
 
-	/// is the path fully contained in the tree?
-	bool contains(QString path) const
-	{
-		auto node = find(path);
-		return node != nullptr;
-	}
+    /// is the path fully contained in the tree?
+    bool contains(QString path) const
+    {
+        auto node = find(path);
+        return node != nullptr;
+    }
 
-	/// does the tree cover a path? That means the prefix of the path is contained in the tree
-	bool covers(QString path) const
-	{
-		// if we found some valid node, it's good enough. the tree covers the path
-		if(m_contained)
-		{
-			return true;
-		}
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			auto found = children.find(path);
-			if(found == children.end())
-			{
-				return false;
-			}
-			return (*found).covers(QString());
-		}
-		else
-		{
-			auto prefix = path.left(sepIndex);
-			auto found = children.find(prefix);
-			if(found == children.end())
-			{
-				return false;
-			}
-			return (*found).covers(path.mid(sepIndex + 1));
-		}
-	}
+    /// does the tree cover a path? That means the prefix of the path is contained in the tree
+    bool covers(QString path) const
+    {
+        // if we found some valid node, it's good enough. the tree covers the path
+        if(m_contained)
+        {
+            return true;
+        }
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            auto found = children.find(path);
+            if(found == children.end())
+            {
+                return false;
+            }
+            return (*found).covers(QString());
+        }
+        else
+        {
+            auto prefix = path.left(sepIndex);
+            auto found = children.find(prefix);
+            if(found == children.end())
+            {
+                return false;
+            }
+            return (*found).covers(path.mid(sepIndex + 1));
+        }
+    }
 
-	/// return the contained path that covers the path specified
-	QString cover(QString path) const
-	{
-		// if we found some valid node, it's good enough. the tree covers the path
-		if(m_contained)
-		{
-			return QString("");
-		}
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			auto found = children.find(path);
-			if(found == children.end())
-			{
-				return QString();
-			}
-			auto nested = (*found).cover(QString());
-			if(nested.isNull())
-			{
-				return nested;
-			}
-			if(nested.isEmpty())
-				return path;
-			return path + Tseparator + nested;
-		}
-		else
-		{
-			auto prefix = path.left(sepIndex);
-			auto found = children.find(prefix);
-			if(found == children.end())
-			{
-				return QString();
-			}
-			auto nested = (*found).cover(path.mid(sepIndex + 1));
-			if(nested.isNull())
-			{
-				return nested;
-			}
-			if(nested.isEmpty())
-				return prefix;
-			return prefix + Tseparator + nested;
-		}
-	}
+    /// return the contained path that covers the path specified
+    QString cover(QString path) const
+    {
+        // if we found some valid node, it's good enough. the tree covers the path
+        if(m_contained)
+        {
+            return QString("");
+        }
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            auto found = children.find(path);
+            if(found == children.end())
+            {
+                return QString();
+            }
+            auto nested = (*found).cover(QString());
+            if(nested.isNull())
+            {
+                return nested;
+            }
+            if(nested.isEmpty())
+                return path;
+            return path + Tseparator + nested;
+        }
+        else
+        {
+            auto prefix = path.left(sepIndex);
+            auto found = children.find(prefix);
+            if(found == children.end())
+            {
+                return QString();
+            }
+            auto nested = (*found).cover(path.mid(sepIndex + 1));
+            if(nested.isNull())
+            {
+                return nested;
+            }
+            if(nested.isEmpty())
+                return prefix;
+            return prefix + Tseparator + nested;
+        }
+    }
 
-	/// Does the path-specified node exist in the tree? It does not have to be contained.
-	bool exists(QString path) const
-	{
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			auto found = children.find(path);
-			if(found == children.end())
-			{
-				return false;
-			}
-			return true;
-		}
-		else
-		{
-			auto prefix = path.left(sepIndex);
-			auto found = children.find(prefix);
-			if(found == children.end())
-			{
-				return false;
-			}
-			return (*found).exists(path.mid(sepIndex + 1));
-		}
-	}
+    /// Does the path-specified node exist in the tree? It does not have to be contained.
+    bool exists(QString path) const
+    {
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            auto found = children.find(path);
+            if(found == children.end())
+            {
+                return false;
+            }
+            return true;
+        }
+        else
+        {
+            auto prefix = path.left(sepIndex);
+            auto found = children.find(prefix);
+            if(found == children.end())
+            {
+                return false;
+            }
+            return (*found).exists(path.mid(sepIndex + 1));
+        }
+    }
 
-	/// find a node in the tree by name
-	const SeparatorPrefixTree * find(QString path) const
-	{
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			auto found = children.find(path);
-			if(found == children.end())
-			{
-				return nullptr;
-			}
-			return &(*found);
-		}
-		else
-		{
-			auto prefix = path.left(sepIndex);
-			auto found = children.find(prefix);
-			if(found == children.end())
-			{
-				return nullptr;
-			}
-			return (*found).find(path.mid(sepIndex + 1));
-		}
-	}
+    /// find a node in the tree by name
+    const SeparatorPrefixTree * find(QString path) const
+    {
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            auto found = children.find(path);
+            if(found == children.end())
+            {
+                return nullptr;
+            }
+            return &(*found);
+        }
+        else
+        {
+            auto prefix = path.left(sepIndex);
+            auto found = children.find(prefix);
+            if(found == children.end())
+            {
+                return nullptr;
+            }
+            return (*found).find(path.mid(sepIndex + 1));
+        }
+    }
 
-	/// is this a leaf node?
-	bool leaf() const
-	{
-		return children.isEmpty();
-	}
+    /// is this a leaf node?
+    bool leaf() const
+    {
+        return children.isEmpty();
+    }
 
-	/// is this node actually contained in the tree, or is it purely structural?
-	bool contained() const
-	{
-		return m_contained;
-	}
+    /// is this node actually contained in the tree, or is it purely structural?
+    bool contained() const
+    {
+        return m_contained;
+    }
 
-	/// Remove a path from the tree
-	bool remove(QString path)
-	{
-		return removeInternal(path) != Failed;
-	}
+    /// Remove a path from the tree
+    bool remove(QString path)
+    {
+        return removeInternal(path) != Failed;
+    }
 
-	/// Clear all children of this node tree node
-	void clear()
-	{
-		children.clear();
-	}
+    /// Clear all children of this node tree node
+    void clear()
+    {
+        children.clear();
+    }
 
-	QStringList toStringList() const
-	{
-		QStringList collected;
-		// collecting these is more expensive.
-		auto iter = children.begin();
-		while(iter != children.end())
-		{
-			QStringList list = iter.value().toStringList();
-			for(int i = 0; i < list.size(); i++)
-			{
-				list[i] = iter.key() + Tseparator + list[i];
-			}
-			collected.append(list);
-			if((*iter).m_contained)
-			{
-				collected.append(iter.key());
-			}
-			iter++;
-		}
-		return collected;
-	}
+    QStringList toStringList() const
+    {
+        QStringList collected;
+        // collecting these is more expensive.
+        auto iter = children.begin();
+        while(iter != children.end())
+        {
+            QStringList list = iter.value().toStringList();
+            for(int i = 0; i < list.size(); i++)
+            {
+                list[i] = iter.key() + Tseparator + list[i];
+            }
+            collected.append(list);
+            if((*iter).m_contained)
+            {
+                collected.append(iter.key());
+            }
+            iter++;
+        }
+        return collected;
+    }
 private:
-	enum Removal
-	{
-		Failed,
-		Succeeded,
-		HasChildren
-	};
-	Removal removeInternal(QString path = QString())
-	{
-		if(path.isEmpty())
-		{
-			if(!m_contained)
-			{
-				// remove all children - we are removing a prefix
-				clear();
-				return Succeeded;
-			}
-			m_contained = false;
-			if(children.size())
-			{
-				return HasChildren;
-			}
-			return Succeeded;
-		}
-		Removal remStatus = Failed;
-		QString childToRemove;
-		auto sepIndex = path.indexOf(Tseparator);
-		if(sepIndex == -1)
-		{
-			childToRemove = path;
-			auto found = children.find(childToRemove);
-			if(found == children.end())
-			{
-				return Failed;
-			}
-			remStatus = (*found).removeInternal();
-		}
-		else
-		{
-			childToRemove = path.left(sepIndex);
-			auto found = children.find(childToRemove);
-			if(found == children.end())
-			{
-				return Failed;
-			}
-			remStatus = (*found).removeInternal(path.mid(sepIndex + 1));
-		}
-		switch (remStatus)
-		{
-			case Failed:
-			case HasChildren:
-			{
-				return remStatus;
-			}
-			case Succeeded:
-			{
-				children.remove(childToRemove);
-				if(m_contained)
-				{
-					return HasChildren;
-				}
-				if(children.size())
-				{
-					return HasChildren;
-				}
-				return Succeeded;
-			}
-		}
-		return Failed;
-	}
+    enum Removal
+    {
+        Failed,
+        Succeeded,
+        HasChildren
+    };
+    Removal removeInternal(QString path = QString())
+    {
+        if(path.isEmpty())
+        {
+            if(!m_contained)
+            {
+                // remove all children - we are removing a prefix
+                clear();
+                return Succeeded;
+            }
+            m_contained = false;
+            if(children.size())
+            {
+                return HasChildren;
+            }
+            return Succeeded;
+        }
+        Removal remStatus = Failed;
+        QString childToRemove;
+        auto sepIndex = path.indexOf(Tseparator);
+        if(sepIndex == -1)
+        {
+            childToRemove = path;
+            auto found = children.find(childToRemove);
+            if(found == children.end())
+            {
+                return Failed;
+            }
+            remStatus = (*found).removeInternal();
+        }
+        else
+        {
+            childToRemove = path.left(sepIndex);
+            auto found = children.find(childToRemove);
+            if(found == children.end())
+            {
+                return Failed;
+            }
+            remStatus = (*found).removeInternal(path.mid(sepIndex + 1));
+        }
+        switch (remStatus)
+        {
+            case Failed:
+            case HasChildren:
+            {
+                return remStatus;
+            }
+            case Succeeded:
+            {
+                children.remove(childToRemove);
+                if(m_contained)
+                {
+                    return HasChildren;
+                }
+                if(children.size())
+                {
+                    return HasChildren;
+                }
+                return Succeeded;
+            }
+        }
+        return Failed;
+    }
 
 private:
-	QMap<QString,SeparatorPrefixTree<Tseparator>> children;
-	bool m_contained = false;
+    QMap<QString,SeparatorPrefixTree<Tseparator>> children;
+    bool m_contained = false;
 };
diff --git a/api/logic/Usable.h b/api/logic/Usable.h
index 1168be4d..83dd083d 100644
--- a/api/logic/Usable.h
+++ b/api/logic/Usable.h
@@ -12,27 +12,27 @@ class Usable;
  */
 class Usable
 {
-	friend class UseLock;
+    friend class UseLock;
 public:
-	std::size_t useCount()
-	{
-		return m_useCount;
-	}
-	bool isInUse()
-	{
-		return m_useCount > 0;
-	}
+    std::size_t useCount()
+    {
+        return m_useCount;
+    }
+    bool isInUse()
+    {
+        return m_useCount > 0;
+    }
 protected:
-	virtual void decrementUses()
-	{
-		m_useCount--;
-	}
-	virtual void incrementUses()
-	{
-		m_useCount++;
-	}
+    virtual void decrementUses()
+    {
+        m_useCount--;
+    }
+    virtual void incrementUses()
+    {
+        m_useCount++;
+    }
 private:
-	std::size_t m_useCount = 0;
+    std::size_t m_useCount = 0;
 };
 
 /**
@@ -43,16 +43,16 @@ private:
 class UseLock
 {
 public:
-	UseLock(std::shared_ptr<Usable> usable)
-		: m_usable(usable)
-	{
-		// this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate.
-		m_usable->incrementUses();
-	}
-	~UseLock()
-	{
-		m_usable->decrementUses();
-	}
+    UseLock(std::shared_ptr<Usable> usable)
+        : m_usable(usable)
+    {
+        // this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate.
+        m_usable->incrementUses();
+    }
+    ~UseLock()
+    {
+        m_usable->decrementUses();
+    }
 private:
-	std::shared_ptr<Usable> m_usable;
+    std::shared_ptr<Usable> m_usable;
 };
diff --git a/api/logic/Version.cpp b/api/logic/Version.cpp
index 2c83374f..42eac669 100644
--- a/api/logic/Version.cpp
+++ b/api/logic/Version.cpp
@@ -7,79 +7,79 @@
 
 Version::Version(const QString &str) : m_string(str)
 {
-	parse();
+    parse();
 }
 
 bool Version::operator<(const Version &other) const
 {
-	const int size = qMax(m_sections.size(), other.m_sections.size());
-	for (int i = 0; i < size; ++i)
-	{
-		const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
-		const Section sec2 =
-			(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
-		if (sec1 != sec2)
-		{
-			return sec1 < sec2;
-		}
-	}
+    const int size = qMax(m_sections.size(), other.m_sections.size());
+    for (int i = 0; i < size; ++i)
+    {
+        const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
+        const Section sec2 =
+            (i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
+        if (sec1 != sec2)
+        {
+            return sec1 < sec2;
+        }
+    }
 
-	return false;
+    return false;
 }
 bool Version::operator<=(const Version &other) const
 {
-	return *this < other || *this == other;
+    return *this < other || *this == other;
 }
 bool Version::operator>(const Version &other) const
 {
-	const int size = qMax(m_sections.size(), other.m_sections.size());
-	for (int i = 0; i < size; ++i)
-	{
-		const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
-		const Section sec2 =
-			(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
-		if (sec1 != sec2)
-		{
-			return sec1 > sec2;
-		}
-	}
+    const int size = qMax(m_sections.size(), other.m_sections.size());
+    for (int i = 0; i < size; ++i)
+    {
+        const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
+        const Section sec2 =
+            (i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
+        if (sec1 != sec2)
+        {
+            return sec1 > sec2;
+        }
+    }
 
-	return false;
+    return false;
 }
 bool Version::operator>=(const Version &other) const
 {
-	return *this > other || *this == other;
+    return *this > other || *this == other;
 }
 bool Version::operator==(const Version &other) const
 {
-	const int size = qMax(m_sections.size(), other.m_sections.size());
-	for (int i = 0; i < size; ++i)
-	{
-		const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
-		const Section sec2 =
-			(i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
-		if (sec1 != sec2)
-		{
-			return false;
-		}
-	}
+    const int size = qMax(m_sections.size(), other.m_sections.size());
+    for (int i = 0; i < size; ++i)
+    {
+        const Section sec1 = (i >= m_sections.size()) ? Section("0") : m_sections.at(i);
+        const Section sec2 =
+            (i >= other.m_sections.size()) ? Section("0") : other.m_sections.at(i);
+        if (sec1 != sec2)
+        {
+            return false;
+        }
+    }
 
-	return true;
+    return true;
 }
 bool Version::operator!=(const Version &other) const
 {
-	return !operator==(other);
+    return !operator==(other);
 }
 
 void Version::parse()
 {
-	m_sections.clear();
+    m_sections.clear();
 
-	// FIXME: this is bad. versions can contain a lot more separators...
-	QStringList parts = m_string.split('.');
+    // FIXME: this is bad. versions can contain a lot more separators...
+    QStringList parts = m_string.split('.');
 
-	for (const auto part : parts)
-	{
-		m_sections.append(Section(part));
-	}
+    for (const auto part : parts)
+    {
+        m_sections.append(Section(part));
+    }
 }
diff --git a/api/logic/Version.h b/api/logic/Version.h
index 7aa2ebe8..c5d93081 100644
--- a/api/logic/Version.h
+++ b/api/logic/Version.h
@@ -10,98 +10,98 @@ class QUrl;
 class MULTIMC_LOGIC_EXPORT Version
 {
 public:
-	Version(const QString &str);
-	Version() {}
+    Version(const QString &str);
+    Version() {}
 
-	bool operator<(const Version &other) const;
-	bool operator<=(const Version &other) const;
-	bool operator>(const Version &other) const;
-	bool operator>=(const Version &other) const;
-	bool operator==(const Version &other) const;
-	bool operator!=(const Version &other) const;
+    bool operator<(const Version &other) const;
+    bool operator<=(const Version &other) const;
+    bool operator>(const Version &other) const;
+    bool operator>=(const Version &other) const;
+    bool operator==(const Version &other) const;
+    bool operator!=(const Version &other) const;
 
-	QString toString() const
-	{
-		return m_string;
-	}
+    QString toString() const
+    {
+        return m_string;
+    }
 
 private:
-	QString m_string;
-	struct Section
-	{
-		explicit Section(const QString &fullString)
-		{
-			m_fullString = fullString;
-			int cutoff = m_fullString.size();
-			for(int i = 0; i < m_fullString.size(); i++)
-			{
-				if(!m_fullString[i].isDigit())
-				{
-					cutoff = i;
-					break;
-				}
-			}
-			auto numPart = m_fullString.leftRef(cutoff);
-			if(numPart.size())
-			{
-				numValid = true;
-				m_numPart = numPart.toInt();
-			}
-			auto stringPart = m_fullString.midRef(cutoff);
-			if(stringPart.size())
-			{
-				m_stringPart = stringPart.toString();
-			}
-		}
-		explicit Section() {}
-		bool numValid = false;
-		int m_numPart = 0;
-		QString m_stringPart;
-		QString m_fullString;
+    QString m_string;
+    struct Section
+    {
+        explicit Section(const QString &fullString)
+        {
+            m_fullString = fullString;
+            int cutoff = m_fullString.size();
+            for(int i = 0; i < m_fullString.size(); i++)
+            {
+                if(!m_fullString[i].isDigit())
+                {
+                    cutoff = i;
+                    break;
+                }
+            }
+            auto numPart = m_fullString.leftRef(cutoff);
+            if(numPart.size())
+            {
+                numValid = true;
+                m_numPart = numPart.toInt();
+            }
+            auto stringPart = m_fullString.midRef(cutoff);
+            if(stringPart.size())
+            {
+                m_stringPart = stringPart.toString();
+            }
+        }
+        explicit Section() {}
+        bool numValid = false;
+        int m_numPart = 0;
+        QString m_stringPart;
+        QString m_fullString;
 
-		inline bool operator!=(const Section &other) const
-		{
-			if(numValid && other.numValid)
-			{
-				return m_numPart != other.m_numPart || m_stringPart != other.m_stringPart;
-			}
-			else
-			{
-				return m_fullString != other.m_fullString;
-			}
-		}
-		inline bool operator<(const Section &other) const
-		{
-			if(numValid && other.numValid)
-			{
-				if(m_numPart < other.m_numPart)
-					return true;
-				if(m_numPart == other.m_numPart && m_stringPart < other.m_stringPart)
-					return true;
-				return false;
-			}
-			else
-			{
-				return m_fullString < other.m_fullString;
-			}
-		}
-		inline bool operator>(const Section &other) const
-		{
-			if(numValid && other.numValid)
-			{
-				if(m_numPart > other.m_numPart)
-					return true;
-				if(m_numPart == other.m_numPart && m_stringPart > other.m_stringPart)
-					return true;
-				return false;
-			}
-			else
-			{
-				return m_fullString > other.m_fullString;
-			}
-		}
-	};
-	QList<Section> m_sections;
+        inline bool operator!=(const Section &other) const
+        {
+            if(numValid && other.numValid)
+            {
+                return m_numPart != other.m_numPart || m_stringPart != other.m_stringPart;
+            }
+            else
+            {
+                return m_fullString != other.m_fullString;
+            }
+        }
+        inline bool operator<(const Section &other) const
+        {
+            if(numValid && other.numValid)
+            {
+                if(m_numPart < other.m_numPart)
+                    return true;
+                if(m_numPart == other.m_numPart && m_stringPart < other.m_stringPart)
+                    return true;
+                return false;
+            }
+            else
+            {
+                return m_fullString < other.m_fullString;
+            }
+        }
+        inline bool operator>(const Section &other) const
+        {
+            if(numValid && other.numValid)
+            {
+                if(m_numPart > other.m_numPart)
+                    return true;
+                if(m_numPart == other.m_numPart && m_stringPart > other.m_stringPart)
+                    return true;
+                return false;
+            }
+            else
+            {
+                return m_fullString > other.m_fullString;
+            }
+        }
+    };
+    QList<Section> m_sections;
 
-	void parse();
+    void parse();
 };
diff --git a/api/logic/Version_test.cpp b/api/logic/Version_test.cpp
index b8e05768..bfbec12d 100644
--- a/api/logic/Version_test.cpp
+++ b/api/logic/Version_test.cpp
@@ -20,64 +20,64 @@
 
 class ModUtilsTest : public QObject
 {
-	Q_OBJECT
-	void setupVersions()
-	{
-		QTest::addColumn<QString>("first");
-		QTest::addColumn<QString>("second");
-		QTest::addColumn<bool>("lessThan");
-		QTest::addColumn<bool>("equal");
+    Q_OBJECT
+    void setupVersions()
+    {
+        QTest::addColumn<QString>("first");
+        QTest::addColumn<QString>("second");
+        QTest::addColumn<bool>("lessThan");
+        QTest::addColumn<bool>("equal");
 
-		QTest::newRow("equal, explicit") << "1.2.0" << "1.2.0" << false << true;
-		QTest::newRow("equal, implicit 1") << "1.2" << "1.2.0" << false << true;
-		QTest::newRow("equal, implicit 2") << "1.2.0" << "1.2" << false << true;
-		QTest::newRow("equal, two-digit") << "1.42" << "1.42" << false << true;
+        QTest::newRow("equal, explicit") << "1.2.0" << "1.2.0" << false << true;
+        QTest::newRow("equal, implicit 1") << "1.2" << "1.2.0" << false << true;
+        QTest::newRow("equal, implicit 2") << "1.2.0" << "1.2" << false << true;
+        QTest::newRow("equal, two-digit") << "1.42" << "1.42" << false << true;
 
-		QTest::newRow("lessThan, explicit 1") << "1.2.0" << "1.2.1" << true << false;
-		QTest::newRow("lessThan, explicit 2") << "1.2.0" << "1.3.0" << true << false;
-		QTest::newRow("lessThan, explicit 3") << "1.2.0" << "2.2.0" << true << false;
-		QTest::newRow("lessThan, implicit 1") << "1.2" << "1.2.1" << true << false;
-		QTest::newRow("lessThan, implicit 2") << "1.2" << "1.3.0" << true << false;
-		QTest::newRow("lessThan, implicit 3") << "1.2" << "2.2.0" << true << false;
-		QTest::newRow("lessThan, two-digit") << "1.41" << "1.42" << true << false;
+        QTest::newRow("lessThan, explicit 1") << "1.2.0" << "1.2.1" << true << false;
+        QTest::newRow("lessThan, explicit 2") << "1.2.0" << "1.3.0" << true << false;
+        QTest::newRow("lessThan, explicit 3") << "1.2.0" << "2.2.0" << true << false;
+        QTest::newRow("lessThan, implicit 1") << "1.2" << "1.2.1" << true << false;
+        QTest::newRow("lessThan, implicit 2") << "1.2" << "1.3.0" << true << false;
+        QTest::newRow("lessThan, implicit 3") << "1.2" << "2.2.0" << true << false;
+        QTest::newRow("lessThan, two-digit") << "1.41" << "1.42" << true << false;
 
-		QTest::newRow("greaterThan, explicit 1") << "1.2.1" << "1.2.0" << false << false;
-		QTest::newRow("greaterThan, explicit 2") << "1.3.0" << "1.2.0" << false << false;
-		QTest::newRow("greaterThan, explicit 3") << "2.2.0" << "1.2.0" << false << false;
-		QTest::newRow("greaterThan, implicit 1") << "1.2.1" << "1.2" << false << false;
-		QTest::newRow("greaterThan, implicit 2") << "1.3.0" << "1.2" << false << false;
-		QTest::newRow("greaterThan, implicit 3") << "2.2.0" << "1.2" << false << false;
-		QTest::newRow("greaterThan, two-digit") << "1.42" << "1.41" << false << false;
-	}
+        QTest::newRow("greaterThan, explicit 1") << "1.2.1" << "1.2.0" << false << false;
+        QTest::newRow("greaterThan, explicit 2") << "1.3.0" << "1.2.0" << false << false;
+        QTest::newRow("greaterThan, explicit 3") << "2.2.0" << "1.2.0" << false << false;
+        QTest::newRow("greaterThan, implicit 1") << "1.2.1" << "1.2" << false << false;
+        QTest::newRow("greaterThan, implicit 2") << "1.3.0" << "1.2" << false << false;
+        QTest::newRow("greaterThan, implicit 3") << "2.2.0" << "1.2" << false << false;
+        QTest::newRow("greaterThan, two-digit") << "1.42" << "1.41" << false << false;
+    }
 
 private slots:
-	void initTestCase()
-	{
+    void initTestCase()
+    {
 
-	}
-	void cleanupTestCase()
-	{
+    }
+    void cleanupTestCase()
+    {
 
-	}
+    }
 
-	void test_versionCompare_data()
-	{
-		setupVersions();
-	}
-	void test_versionCompare()
-	{
-		QFETCH(QString, first);
-		QFETCH(QString, second);
-		QFETCH(bool, lessThan);
-		QFETCH(bool, equal);
+    void test_versionCompare_data()
+    {
+        setupVersions();
+    }
+    void test_versionCompare()
+    {
+        QFETCH(QString, first);
+        QFETCH(QString, second);
+        QFETCH(bool, lessThan);
+        QFETCH(bool, equal);
 
-		const auto v1 = Version(first);
-		const auto v2 = Version(second);
+        const auto v1 = Version(first);
+        const auto v2 = Version(second);
 
-		QCOMPARE(v1 < v2, lessThan);
-		QCOMPARE(v1 > v2, !lessThan && !equal);
-		QCOMPARE(v1 == v2, equal);
-	}
+        QCOMPARE(v1 < v2, lessThan);
+        QCOMPARE(v1 > v2, !lessThan && !equal);
+        QCOMPARE(v1 == v2, equal);
+    }
 };
 
 QTEST_GUILESS_MAIN(ModUtilsTest)
diff --git a/api/logic/icons/IIconList.h b/api/logic/icons/IIconList.h
index e6c16d50..9a3fe022 100644
--- a/api/logic/icons/IIconList.h
+++ b/api/logic/icons/IIconList.h
@@ -6,21 +6,21 @@
 
 enum IconType : unsigned
 {
-	Builtin,
-	Transient,
-	FileBased,
-	ICONS_TOTAL,
-	ToBeDeleted
+    Builtin,
+    Transient,
+    FileBased,
+    ICONS_TOTAL,
+    ToBeDeleted
 };
 
 class MULTIMC_LOGIC_EXPORT IIconList
 {
 public:
-	virtual ~IIconList();
-	virtual bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type) = 0;
-	virtual bool deleteIcon(const QString &key) = 0;
-	virtual void saveIcon(const QString &key, const QString &path, const char * format) const = 0;
-	virtual bool iconFileExists(const QString &key) const = 0;
-	virtual void installIcons(const QStringList &iconFiles) = 0;
-	virtual void installIcon(const QString &file, const QString &name) = 0;
+    virtual ~IIconList();
+    virtual bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type) = 0;
+    virtual bool deleteIcon(const QString &key) = 0;
+    virtual void saveIcon(const QString &key, const QString &path, const char * format) const = 0;
+    virtual bool iconFileExists(const QString &key) const = 0;
+    virtual void installIcons(const QStringList &iconFiles) = 0;
+    virtual void installIcon(const QString &file, const QString &name) = 0;
 };
diff --git a/api/logic/java/JavaChecker.cpp b/api/logic/java/JavaChecker.cpp
index f0b71e48..9ba3933f 100644
--- a/api/logic/java/JavaChecker.cpp
+++ b/api/logic/java/JavaChecker.cpp
@@ -16,149 +16,149 @@ JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
 
 void JavaChecker::performCheck()
 {
-	QString checkerJar = FS::PathCombine(ENV.getJarsPath(), "JavaCheck.jar");
-
-	QStringList args;
-
-	process.reset(new QProcess());
-	if(m_args.size())
-	{
-		auto extraArgs = Commandline::splitArgs(m_args);
-		args.append(extraArgs);
-	}
-	if(m_minMem != 0)
-	{
-		args << QString("-Xms%1m").arg(m_minMem);
-	}
-	if(m_maxMem != 0)
-	{
-		args << QString("-Xmx%1m").arg(m_maxMem);
-	}
-	if(m_permGen != 64)
-	{
-		args << QString("-XX:PermSize=%1m").arg(m_permGen);
-	}
-
-	args.append({"-jar", checkerJar});
-	process->setArguments(args);
-	process->setProgram(m_path);
-	process->setProcessChannelMode(QProcess::SeparateChannels);
-	process->setProcessEnvironment(CleanEnviroment());
-	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(readyReadStandardOutput()), this, SLOT(stdoutReady()));
-	connect(process.get(), SIGNAL(readyReadStandardError()), this, SLOT(stderrReady()));
-	connect(&killTimer, SIGNAL(timeout()), SLOT(timeout()));
-	killTimer.setSingleShot(true);
-	killTimer.start(15000);
-	process->start();
+    QString checkerJar = FS::PathCombine(ENV.getJarsPath(), "JavaCheck.jar");
+
+    QStringList args;
+
+    process.reset(new QProcess());
+    if(m_args.size())
+    {
+        auto extraArgs = Commandline::splitArgs(m_args);
+        args.append(extraArgs);
+    }
+    if(m_minMem != 0)
+    {
+        args << QString("-Xms%1m").arg(m_minMem);
+    }
+    if(m_maxMem != 0)
+    {
+        args << QString("-Xmx%1m").arg(m_maxMem);
+    }
+    if(m_permGen != 64)
+    {
+        args << QString("-XX:PermSize=%1m").arg(m_permGen);
+    }
+
+    args.append({"-jar", checkerJar});
+    process->setArguments(args);
+    process->setProgram(m_path);
+    process->setProcessChannelMode(QProcess::SeparateChannels);
+    process->setProcessEnvironment(CleanEnviroment());
+    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(readyReadStandardOutput()), this, SLOT(stdoutReady()));
+    connect(process.get(), SIGNAL(readyReadStandardError()), this, SLOT(stderrReady()));
+    connect(&killTimer, SIGNAL(timeout()), SLOT(timeout()));
+    killTimer.setSingleShot(true);
+    killTimer.start(15000);
+    process->start();
 }
 
 void JavaChecker::stdoutReady()
 {
-	QByteArray data = process->readAllStandardOutput();
-	QString added = QString::fromLocal8Bit(data);
-	added.remove('\r');
-	m_stdout += added;
+    QByteArray data = process->readAllStandardOutput();
+    QString added = QString::fromLocal8Bit(data);
+    added.remove('\r');
+    m_stdout += added;
 }
 
 void JavaChecker::stderrReady()
 {
-	QByteArray data = process->readAllStandardError();
-	QString added = QString::fromLocal8Bit(data);
-	added.remove('\r');
-	m_stderr += added;
+    QByteArray data = process->readAllStandardError();
+    QString added = QString::fromLocal8Bit(data);
+    added.remove('\r');
+    m_stderr += added;
 }
 
 void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
 {
-	killTimer.stop();
-	QProcessPtr _process;
-	_process.swap(process);
-
-	JavaCheckResult result;
-	{
-		result.path = m_path;
-		result.id = m_id;
-	}
-	result.errorLog = m_stderr;
-	result.outLog = m_stdout;
-	qDebug() << "STDOUT" << m_stdout;
-	qWarning() << "STDERR" << m_stderr;
-	qDebug() << "Java checker finished with status " << status << " exit code " << exitcode;
-
-	if (status == QProcess::CrashExit || exitcode == 1)
-	{
-		result.validity = JavaCheckResult::Validity::Errored;
-		emit checkFinished(result);
-		return;
-	}
-
-	bool success = true;
-
-	QMap<QString, QString> results;
-	QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts);
-	for(QString line : lines)
-	{
-		line = line.trimmed();
-
-		auto parts = line.split('=', QString::SkipEmptyParts);
-		if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
-		{
-			success = false;
-		}
-		else
-		{
-			results.insert(parts[0], parts[1]);
-		}
-	}
-
-	if(!results.contains("os.arch") || !results.contains("java.version") || !success)
-	{
-		result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
-		emit checkFinished(result);
-		return;
-	}
-
-	auto os_arch = results["os.arch"];
-	auto java_version = results["java.version"];
-	bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
-
-
-	result.validity = JavaCheckResult::Validity::Valid;
-	result.is_64bit = is_64;
-	result.mojangPlatform = is_64 ? "64" : "32";
-	result.realPlatform = os_arch;
-	result.javaVersion = java_version;
-	qDebug() << "Java checker succeeded.";
-	emit checkFinished(result);
+    killTimer.stop();
+    QProcessPtr _process;
+    _process.swap(process);
+
+    JavaCheckResult result;
+    {
+        result.path = m_path;
+        result.id = m_id;
+    }
+    result.errorLog = m_stderr;
+    result.outLog = m_stdout;
+    qDebug() << "STDOUT" << m_stdout;
+    qWarning() << "STDERR" << m_stderr;
+    qDebug() << "Java checker finished with status " << status << " exit code " << exitcode;
+
+    if (status == QProcess::CrashExit || exitcode == 1)
+    {
+        result.validity = JavaCheckResult::Validity::Errored;
+        emit checkFinished(result);
+        return;
+    }
+
+    bool success = true;
+
+    QMap<QString, QString> results;
+    QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts);
+    for(QString line : lines)
+    {
+        line = line.trimmed();
+
+        auto parts = line.split('=', QString::SkipEmptyParts);
+        if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
+        {
+            success = false;
+        }
+        else
+        {
+            results.insert(parts[0], parts[1]);
+        }
+    }
+
+    if(!results.contains("os.arch") || !results.contains("java.version") || !success)
+    {
+        result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
+        emit checkFinished(result);
+        return;
+    }
+
+    auto os_arch = results["os.arch"];
+    auto java_version = results["java.version"];
+    bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
+
+
+    result.validity = JavaCheckResult::Validity::Valid;
+    result.is_64bit = is_64;
+    result.mojangPlatform = is_64 ? "64" : "32";
+    result.realPlatform = os_arch;
+    result.javaVersion = java_version;
+    qDebug() << "Java checker succeeded.";
+    emit checkFinished(result);
 }
 
 void JavaChecker::error(QProcess::ProcessError err)
 {
-	if(err == QProcess::FailedToStart)
-	{
-		killTimer.stop();
-		qDebug() << "Java checker has failed to start.";
-		JavaCheckResult result;
-		{
-			result.path = m_path;
-			result.id = m_id;
-		}
-
-		emit checkFinished(result);
-		return;
-	}
+    if(err == QProcess::FailedToStart)
+    {
+        killTimer.stop();
+        qDebug() << "Java checker has failed to start.";
+        JavaCheckResult result;
+        {
+            result.path = m_path;
+            result.id = m_id;
+        }
+
+        emit checkFinished(result);
+        return;
+    }
 }
 
 void JavaChecker::timeout()
 {
-	// NO MERCY. NO ABUSE.
-	if(process)
-	{
-		qDebug() << "Java checker has been killed by timeout.";
-		process->kill();
-	}
+    // NO MERCY. NO ABUSE.
+    if(process)
+    {
+        qDebug() << "Java checker has been killed by timeout.";
+        process->kill();
+    }
 }
diff --git a/api/logic/java/JavaChecker.h b/api/logic/java/JavaChecker.h
index c6bd697c..d5d4b0de 100644
--- a/api/logic/java/JavaChecker.h
+++ b/api/logic/java/JavaChecker.h
@@ -11,50 +11,50 @@ class JavaChecker;
 
 struct MULTIMC_LOGIC_EXPORT JavaCheckResult
 {
-	QString path;
-	QString mojangPlatform;
-	QString realPlatform;
-	JavaVersion javaVersion;
-	QString outLog;
-	QString errorLog;
-	bool is_64bit = false;
-	int id;
-	enum class Validity
-	{
-		Errored,
-		ReturnedInvalidData,
-		Valid
-	} validity = Validity::Errored;
+    QString path;
+    QString mojangPlatform;
+    QString realPlatform;
+    JavaVersion javaVersion;
+    QString outLog;
+    QString errorLog;
+    bool is_64bit = false;
+    int id;
+    enum class Validity
+    {
+        Errored,
+        ReturnedInvalidData,
+        Valid
+    } validity = Validity::Errored;
 };
 
 typedef std::shared_ptr<QProcess> QProcessPtr;
 typedef std::shared_ptr<JavaChecker> JavaCheckerPtr;
 class MULTIMC_LOGIC_EXPORT JavaChecker : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit JavaChecker(QObject *parent = 0);
-	void performCheck();
+    explicit JavaChecker(QObject *parent = 0);
+    void performCheck();
 
-	QString m_path;
-	QString m_args;
-	int m_id = 0;
-	int m_minMem = 0;
-	int m_maxMem = 0;
-	int m_permGen = 64;
+    QString m_path;
+    QString m_args;
+    int m_id = 0;
+    int m_minMem = 0;
+    int m_maxMem = 0;
+    int m_permGen = 64;
 
 signals:
-	void checkFinished(JavaCheckResult result);
+    void checkFinished(JavaCheckResult result);
 private:
-	QProcessPtr process;
-	QTimer killTimer;
-	QString m_stdout;
-	QString m_stderr;
+    QProcessPtr process;
+    QTimer killTimer;
+    QString m_stdout;
+    QString m_stderr;
 public
 slots:
-	void timeout();
-	void finished(int exitcode, QProcess::ExitStatus);
-	void error(QProcess::ProcessError);
-	void stdoutReady();
-	void stderrReady();
+    void timeout();
+    void finished(int exitcode, QProcess::ExitStatus);
+    void error(QProcess::ProcessError);
+    void stdoutReady();
+    void stderrReady();
 };
diff --git a/api/logic/java/JavaCheckerJob.cpp b/api/logic/java/JavaCheckerJob.cpp
index fabb5aaa..a26846f2 100644
--- a/api/logic/java/JavaCheckerJob.cpp
+++ b/api/logic/java/JavaCheckerJob.cpp
@@ -19,26 +19,26 @@
 
 void JavaCheckerJob::partFinished(JavaCheckResult result)
 {
-	num_finished++;
-	qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/"
-				<< javacheckers.size();
-	setProgress(num_finished, javacheckers.size());
+    num_finished++;
+    qDebug() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/"
+                << javacheckers.size();
+    setProgress(num_finished, javacheckers.size());
 
-	javaresults.replace(result.id, result);
+    javaresults.replace(result.id, result);
 
-	if (num_finished == javacheckers.size())
-	{
-		emitSucceeded();
-	}
+    if (num_finished == javacheckers.size())
+    {
+        emitSucceeded();
+    }
 }
 
 void JavaCheckerJob::executeTask()
 {
-	qDebug() << m_job_name.toLocal8Bit() << " started.";
-	for (auto iter : javacheckers)
-	{
-		javaresults.append(JavaCheckResult());
-		connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
-		iter->performCheck();
-	}
+    qDebug() << m_job_name.toLocal8Bit() << " started.";
+    for (auto iter : javacheckers)
+    {
+        javaresults.append(JavaCheckResult());
+        connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
+        iter->performCheck();
+    }
 }
diff --git a/api/logic/java/JavaCheckerJob.h b/api/logic/java/JavaCheckerJob.h
index 64ac58a1..e52970c1 100644
--- a/api/logic/java/JavaCheckerJob.h
+++ b/api/logic/java/JavaCheckerJob.h
@@ -25,37 +25,37 @@ typedef std::shared_ptr<JavaCheckerJob> JavaCheckerJobPtr;
 // FIXME: this just seems horribly redundant
 class JavaCheckerJob : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name) {};
-	virtual ~JavaCheckerJob() {};
-
-	bool addJavaCheckerAction(JavaCheckerPtr base)
-	{
-		javacheckers.append(base);
-		// if this is already running, the action needs to be started right away!
-		if (isRunning())
-		{
-			setProgress(num_finished, javacheckers.size());
-			connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished);
-			base->performCheck();
-		}
-		return true;
-	}
-	QList<JavaCheckResult> getResults()
-	{
-		return javaresults;
-	}
+    explicit JavaCheckerJob(QString job_name) : Task(), m_job_name(job_name) {};
+    virtual ~JavaCheckerJob() {};
+
+    bool addJavaCheckerAction(JavaCheckerPtr base)
+    {
+        javacheckers.append(base);
+        // if this is already running, the action needs to be started right away!
+        if (isRunning())
+        {
+            setProgress(num_finished, javacheckers.size());
+            connect(base.get(), &JavaChecker::checkFinished, this, &JavaCheckerJob::partFinished);
+            base->performCheck();
+        }
+        return true;
+    }
+    QList<JavaCheckResult> getResults()
+    {
+        return javaresults;
+    }
 
 private slots:
-	void partFinished(JavaCheckResult result);
+    void partFinished(JavaCheckResult result);
 
 protected:
-	virtual void executeTask() override;
+    virtual void executeTask() override;
 
 private:
-	QString m_job_name;
-	QList<JavaCheckerPtr> javacheckers;
-	QList<JavaCheckResult> javaresults;
-	int num_finished = 0;
+    QString m_job_name;
+    QList<JavaCheckerPtr> javacheckers;
+    QList<JavaCheckResult> javaresults;
+    int num_finished = 0;
 };
diff --git a/api/logic/java/JavaInstall.cpp b/api/logic/java/JavaInstall.cpp
index bb262b6e..5bcf7bcb 100644
--- a/api/logic/java/JavaInstall.cpp
+++ b/api/logic/java/JavaInstall.cpp
@@ -3,26 +3,26 @@
 
 bool JavaInstall::operator<(const JavaInstall &rhs)
 {
-	auto archCompare = Strings::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
-	if(archCompare != 0)
-		return archCompare < 0;
-	if(id < rhs.id)
-	{
-		return true;
-	}
-	if(id > rhs.id)
-	{
-		return false;
-	}
-	return Strings::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
+    auto archCompare = Strings::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive);
+    if(archCompare != 0)
+        return archCompare < 0;
+    if(id < rhs.id)
+    {
+        return true;
+    }
+    if(id > rhs.id)
+    {
+        return false;
+    }
+    return Strings::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0;
 }
 
 bool JavaInstall::operator==(const JavaInstall &rhs)
 {
-	return arch == rhs.arch && id == rhs.id && path == rhs.path;
+    return arch == rhs.arch && id == rhs.id && path == rhs.path;
 }
 
 bool JavaInstall::operator>(const JavaInstall &rhs)
 {
-	return (!operator<(rhs)) && (!operator==(rhs));
+    return (!operator<(rhs)) && (!operator==(rhs));
 }
diff --git a/api/logic/java/JavaInstall.h b/api/logic/java/JavaInstall.h
index 882c7386..64be40d1 100644
--- a/api/logic/java/JavaInstall.h
+++ b/api/logic/java/JavaInstall.h
@@ -5,34 +5,34 @@
 
 struct JavaInstall : public BaseVersion
 {
-	JavaInstall(){}
-	JavaInstall(QString id, QString arch, QString path)
-	: id(id), arch(arch), path(path)
-	{
-	}
-	virtual QString descriptor()
-	{
-		return id.toString();
-	}
+    JavaInstall(){}
+    JavaInstall(QString id, QString arch, QString path)
+    : id(id), arch(arch), path(path)
+    {
+    }
+    virtual QString descriptor()
+    {
+        return id.toString();
+    }
 
-	virtual QString name()
-	{
-		return id.toString();
-	}
+    virtual QString name()
+    {
+        return id.toString();
+    }
 
-	virtual QString typeString() const
-	{
-		return arch;
-	}
+    virtual QString typeString() const
+    {
+        return arch;
+    }
 
-	bool operator<(const JavaInstall & rhs);
-	bool operator==(const JavaInstall & rhs);
-	bool operator>(const JavaInstall & rhs);
+    bool operator<(const JavaInstall & rhs);
+    bool operator==(const JavaInstall & rhs);
+    bool operator>(const JavaInstall & rhs);
 
-	JavaVersion id;
-	QString arch;
-	QString path;
-	bool recommended = false;
+    JavaVersion id;
+    QString arch;
+    QString path;
+    bool recommended = false;
 };
 
 typedef std::shared_ptr<JavaInstall> JavaInstallPtr;
diff --git a/api/logic/java/JavaInstallList.cpp b/api/logic/java/JavaInstallList.cpp
index 9d2e2f8b..605d4c0c 100644
--- a/api/logic/java/JavaInstallList.cpp
+++ b/api/logic/java/JavaInstallList.cpp
@@ -31,111 +31,111 @@ JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent)
 
 shared_qobject_ptr<Task> JavaInstallList::getLoadTask()
 {
-	load();
-	return getCurrentTask();
+    load();
+    return getCurrentTask();
 }
 
 shared_qobject_ptr<Task> JavaInstallList::getCurrentTask()
 {
-	if(m_status == Status::InProgress)
-	{
-		return m_loadTask;
-	}
-	return nullptr;
+    if(m_status == Status::InProgress)
+    {
+        return m_loadTask;
+    }
+    return nullptr;
 }
 
 void JavaInstallList::load()
 {
-	if(m_status != Status::InProgress)
-	{
-		m_status = Status::InProgress;
-		m_loadTask = new JavaListLoadTask(this);
-		m_loadTask->start();
-	}
+    if(m_status != Status::InProgress)
+    {
+        m_status = Status::InProgress;
+        m_loadTask = new JavaListLoadTask(this);
+        m_loadTask->start();
+    }
 }
 
 const BaseVersionPtr JavaInstallList::at(int i) const
 {
-	return m_vlist.at(i);
+    return m_vlist.at(i);
 }
 
 bool JavaInstallList::isLoaded()
 {
-	return m_status == JavaInstallList::Status::Done;
+    return m_status == JavaInstallList::Status::Done;
 }
 
 int JavaInstallList::count() const
 {
-	return m_vlist.count();
+    return m_vlist.count();
 }
 
 QVariant JavaInstallList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	if (index.row() > count())
-		return QVariant();
-
-	auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]);
-	switch (role)
-	{
-		case VersionPointerRole:
-			return qVariantFromValue(m_vlist[index.row()]);
-		case VersionIdRole:
-			return version->descriptor();
-		case VersionRole:
-			return version->id.toString();
-		case RecommendedRole:
-			return version->recommended;
-		case PathRole:
-			return version->path;
-		case ArchitectureRole:
-			return version->arch;
-		default:
-			return QVariant();
-	}
+    if (!index.isValid())
+        return QVariant();
+
+    if (index.row() > count())
+        return QVariant();
+
+    auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]);
+    switch (role)
+    {
+        case VersionPointerRole:
+            return qVariantFromValue(m_vlist[index.row()]);
+        case VersionIdRole:
+            return version->descriptor();
+        case VersionRole:
+            return version->id.toString();
+        case RecommendedRole:
+            return version->recommended;
+        case PathRole:
+            return version->path;
+        case ArchitectureRole:
+            return version->arch;
+        default:
+            return QVariant();
+    }
 }
 
 BaseVersionList::RoleList JavaInstallList::providesRoles() const
 {
-	return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole};
+    return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole};
 }
 
 
 void JavaInstallList::updateListData(QList<BaseVersionPtr> versions)
 {
-	beginResetModel();
-	m_vlist = versions;
-	sortVersions();
-	if(m_vlist.size())
-	{
-		auto best = std::dynamic_pointer_cast<JavaInstall>(m_vlist[0]);
-		best->recommended = true;
-	}
-	endResetModel();
-	m_status = Status::Done;
-	m_loadTask.reset();
+    beginResetModel();
+    m_vlist = versions;
+    sortVersions();
+    if(m_vlist.size())
+    {
+        auto best = std::dynamic_pointer_cast<JavaInstall>(m_vlist[0]);
+        best->recommended = true;
+    }
+    endResetModel();
+    m_status = Status::Done;
+    m_loadTask.reset();
 }
 
 bool sortJavas(BaseVersionPtr left, BaseVersionPtr right)
 {
-	auto rleft = std::dynamic_pointer_cast<JavaInstall>(left);
-	auto rright = std::dynamic_pointer_cast<JavaInstall>(right);
-	return (*rleft) > (*rright);
+    auto rleft = std::dynamic_pointer_cast<JavaInstall>(left);
+    auto rright = std::dynamic_pointer_cast<JavaInstall>(right);
+    return (*rleft) > (*rright);
 }
 
 void JavaInstallList::sortVersions()
 {
-	beginResetModel();
-	std::sort(m_vlist.begin(), m_vlist.end(), sortJavas);
-	endResetModel();
+    beginResetModel();
+    std::sort(m_vlist.begin(), m_vlist.end(), sortJavas);
+    endResetModel();
 }
 
 JavaListLoadTask::JavaListLoadTask(JavaInstallList *vlist) : Task()
 {
-	m_list = vlist;
-	m_currentRecommended = NULL;
+    m_list = vlist;
+    m_currentRecommended = NULL;
 }
 
 JavaListLoadTask::~JavaListLoadTask()
@@ -144,65 +144,65 @@ JavaListLoadTask::~JavaListLoadTask()
 
 void JavaListLoadTask::executeTask()
 {
-	setStatus(tr("Detecting Java installations..."));
+    setStatus(tr("Detecting Java installations..."));
 
-	JavaUtils ju;
-	QList<QString> candidate_paths = ju.FindJavaPaths();
+    JavaUtils ju;
+    QList<QString> candidate_paths = ju.FindJavaPaths();
 
-	m_job = std::shared_ptr<JavaCheckerJob>(new JavaCheckerJob("Java detection"));
-	connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
-	connect(m_job.get(), &Task::progress, this, &Task::setProgress);
+    m_job = std::shared_ptr<JavaCheckerJob>(new JavaCheckerJob("Java detection"));
+    connect(m_job.get(), &Task::finished, this, &JavaListLoadTask::javaCheckerFinished);
+    connect(m_job.get(), &Task::progress, this, &Task::setProgress);
 
-	qDebug() << "Probing the following Java paths: ";
-	int id = 0;
-	for(QString candidate : candidate_paths)
-	{
-		qDebug() << " " << candidate;
+    qDebug() << "Probing the following Java paths: ";
+    int id = 0;
+    for(QString candidate : candidate_paths)
+    {
+        qDebug() << " " << candidate;
 
-		auto candidate_checker = new JavaChecker();
-		candidate_checker->m_path = candidate;
-		candidate_checker->m_id = id;
-		m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
+        auto candidate_checker = new JavaChecker();
+        candidate_checker->m_path = candidate;
+        candidate_checker->m_id = id;
+        m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
 
-		id++;
-	}
+        id++;
+    }
 
-	m_job->start();
+    m_job->start();
 }
 
 void JavaListLoadTask::javaCheckerFinished()
 {
-	QList<JavaInstallPtr> candidates;
-	auto results = m_job->getResults();
-
-	qDebug() << "Found the following valid Java installations:";
-	for(JavaCheckResult result : results)
-	{
-		if(result.validity == JavaCheckResult::Validity::Valid)
-		{
-			JavaInstallPtr javaVersion(new JavaInstall());
-
-			javaVersion->id = result.javaVersion;
-			javaVersion->arch = result.mojangPlatform;
-			javaVersion->path = result.path;
-			candidates.append(javaVersion);
-
-			qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path;
-		}
-	}
-
-	QList<BaseVersionPtr> javas_bvp;
-	for (auto java : candidates)
-	{
-		//qDebug() << java->id << java->arch << " at " << java->path;
-		BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
-
-		if (bp_java)
-		{
-			javas_bvp.append(java);
-		}
-	}
-
-	m_list->updateListData(javas_bvp);
-	emitSucceeded();
+    QList<JavaInstallPtr> candidates;
+    auto results = m_job->getResults();
+
+    qDebug() << "Found the following valid Java installations:";
+    for(JavaCheckResult result : results)
+    {
+        if(result.validity == JavaCheckResult::Validity::Valid)
+        {
+            JavaInstallPtr javaVersion(new JavaInstall());
+
+            javaVersion->id = result.javaVersion;
+            javaVersion->arch = result.mojangPlatform;
+            javaVersion->path = result.path;
+            candidates.append(javaVersion);
+
+            qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path;
+        }
+    }
+
+    QList<BaseVersionPtr> javas_bvp;
+    for (auto java : candidates)
+    {
+        //qDebug() << java->id << java->arch << " at " << java->path;
+        BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
+
+        if (bp_java)
+        {
+            javas_bvp.append(java);
+        }
+    }
+
+    m_list->updateListData(javas_bvp);
+    emitSucceeded();
 }
diff --git a/api/logic/java/JavaInstallList.h b/api/logic/java/JavaInstallList.h
index 9ec12f87..7e72b5ef 100644
--- a/api/logic/java/JavaInstallList.h
+++ b/api/logic/java/JavaInstallList.h
@@ -30,52 +30,52 @@ class JavaListLoadTask;
 
 class MULTIMC_LOGIC_EXPORT JavaInstallList : public BaseVersionList
 {
-	Q_OBJECT
-	enum class Status
-	{
-		NotDone,
-		InProgress,
-		Done
-	};
+    Q_OBJECT
+    enum class Status
+    {
+        NotDone,
+        InProgress,
+        Done
+    };
 public:
-	explicit JavaInstallList(QObject *parent = 0);
+    explicit JavaInstallList(QObject *parent = 0);
 
-	shared_qobject_ptr<Task> getLoadTask() override;
-	bool isLoaded() override;
-	const BaseVersionPtr at(int i) const override;
-	int count() const override;
-	void sortVersions() override;
+    shared_qobject_ptr<Task> getLoadTask() override;
+    bool isLoaded() override;
+    const BaseVersionPtr at(int i) const override;
+    int count() const override;
+    void sortVersions() override;
 
-	QVariant data(const QModelIndex &index, int role) const override;
-	RoleList providesRoles() const override;
+    QVariant data(const QModelIndex &index, int role) const override;
+    RoleList providesRoles() const override;
 
 public slots:
-	void updateListData(QList<BaseVersionPtr> versions) override;
+    void updateListData(QList<BaseVersionPtr> versions) override;
 
 protected:
-	void load();
-	shared_qobject_ptr<Task> getCurrentTask();
+    void load();
+    shared_qobject_ptr<Task> getCurrentTask();
 
 protected:
-	Status m_status = Status::NotDone;
-	shared_qobject_ptr<JavaListLoadTask> m_loadTask;
-	QList<BaseVersionPtr> m_vlist;
+    Status m_status = Status::NotDone;
+    shared_qobject_ptr<JavaListLoadTask> m_loadTask;
+    QList<BaseVersionPtr> m_vlist;
 };
 
 class JavaListLoadTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	explicit JavaListLoadTask(JavaInstallList *vlist);
-	virtual ~JavaListLoadTask();
+    explicit JavaListLoadTask(JavaInstallList *vlist);
+    virtual ~JavaListLoadTask();
 
-	void executeTask() override;
+    void executeTask() override;
 public slots:
-	void javaCheckerFinished();
+    void javaCheckerFinished();
 
 protected:
-	std::shared_ptr<JavaCheckerJob> m_job;
-	JavaInstallList *m_list;
-	JavaInstall *m_currentRecommended;
+    std::shared_ptr<JavaCheckerJob> m_job;
+    JavaInstallList *m_list;
+    JavaInstall *m_currentRecommended;
 };
diff --git a/api/logic/java/JavaUtils.cpp b/api/logic/java/JavaUtils.cpp
index 798c80e8..9f7fdcb0 100644
--- a/api/logic/java/JavaUtils.cpp
+++ b/api/logic/java/JavaUtils.cpp
@@ -34,312 +34,312 @@ JavaUtils::JavaUtils()
 #ifdef Q_OS_LINUX
 static QString processLD_LIBRARY_PATH(const QString & LD_LIBRARY_PATH)
 {
-	QDir mmcBin(QCoreApplication::applicationDirPath());
-	auto items = LD_LIBRARY_PATH.split(':');
-	QStringList final;
-	for(auto & item: items)
-	{
-		QDir test(item);
-		if(test == mmcBin)
-		{
-			qDebug() << "Env:LD_LIBRARY_PATH ignoring path" << item;
-			continue;
-		}
-		final.append(item);
-	}
-	return final.join(':');
+    QDir mmcBin(QCoreApplication::applicationDirPath());
+    auto items = LD_LIBRARY_PATH.split(':');
+    QStringList final;
+    for(auto & item: items)
+    {
+        QDir test(item);
+        if(test == mmcBin)
+        {
+            qDebug() << "Env:LD_LIBRARY_PATH ignoring path" << item;
+            continue;
+        }
+        final.append(item);
+    }
+    return final.join(':');
 }
 #endif
 
 QProcessEnvironment CleanEnviroment()
 {
-	// prepare the process environment
-	QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment();
-	QProcessEnvironment env;
-
-	QStringList ignored =
-	{
-		"JAVA_ARGS",
-		"CLASSPATH",
-		"CONFIGPATH",
-		"JAVA_HOME",
-		"JRE_HOME",
-		"_JAVA_OPTIONS",
-		"JAVA_OPTIONS",
-		"JAVA_TOOL_OPTIONS"
-	};
-	for(auto key: rawenv.keys())
-	{
-		auto value = rawenv.value(key);
-		// filter out dangerous java crap
-		if(ignored.contains(key))
-		{
-			qDebug() << "Env: ignoring" << key << value;
-			continue;
-		}
-		// filter MultiMC-related things
-		if(key.startsWith("QT_"))
-		{
-			qDebug() << "Env: ignoring" << key << value;
-			continue;
-		}
+    // prepare the process environment
+    QProcessEnvironment rawenv = QProcessEnvironment::systemEnvironment();
+    QProcessEnvironment env;
+
+    QStringList ignored =
+    {
+        "JAVA_ARGS",
+        "CLASSPATH",
+        "CONFIGPATH",
+        "JAVA_HOME",
+        "JRE_HOME",
+        "_JAVA_OPTIONS",
+        "JAVA_OPTIONS",
+        "JAVA_TOOL_OPTIONS"
+    };
+    for(auto key: rawenv.keys())
+    {
+        auto value = rawenv.value(key);
+        // filter out dangerous java crap
+        if(ignored.contains(key))
+        {
+            qDebug() << "Env: ignoring" << key << value;
+            continue;
+        }
+        // filter MultiMC-related things
+        if(key.startsWith("QT_"))
+        {
+            qDebug() << "Env: ignoring" << key << value;
+            continue;
+        }
 #ifdef Q_OS_LINUX
-		// Do not pass LD_* variables to java. They were intended for MultiMC
-		if(key.startsWith("LD_"))
-		{
-			qDebug() << "Env: ignoring" << key << value;
-			continue;
-		}
-		// Strip IBus
-		// IBus is a Linux IME framework. For some reason, it breaks MC?
-		if (key == "XMODIFIERS" && value.contains(IBUS))
-		{
-			QString save = value;
-			value.replace(IBUS, "");
-			qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value;
-		}
-		if(key == "GAME_PRELOAD")
-		{
-			env.insert("LD_PRELOAD", value);
-			continue;
-		}
-		if(key == "GAME_LIBRARY_PATH")
-		{
-			env.insert("LD_LIBRARY_PATH", processLD_LIBRARY_PATH(value));
-			continue;
-		}
+        // Do not pass LD_* variables to java. They were intended for MultiMC
+        if(key.startsWith("LD_"))
+        {
+            qDebug() << "Env: ignoring" << key << value;
+            continue;
+        }
+        // Strip IBus
+        // IBus is a Linux IME framework. For some reason, it breaks MC?
+        if (key == "XMODIFIERS" && value.contains(IBUS))
+        {
+            QString save = value;
+            value.replace(IBUS, "");
+            qDebug() << "Env: stripped" << IBUS << "from" << save << ":" << value;
+        }
+        if(key == "GAME_PRELOAD")
+        {
+            env.insert("LD_PRELOAD", value);
+            continue;
+        }
+        if(key == "GAME_LIBRARY_PATH")
+        {
+            env.insert("LD_LIBRARY_PATH", processLD_LIBRARY_PATH(value));
+            continue;
+        }
 #endif
-		// qDebug() << "Env: " << key << value;
-		env.insert(key, value);
-	}
+        // qDebug() << "Env: " << key << value;
+        env.insert(key, value);
+    }
 #ifdef Q_OS_LINUX
-	// HACK: Workaround for QTBUG42500
-	if(!env.contains("LD_LIBRARY_PATH"))
-	{
-		env.insert("LD_LIBRARY_PATH", "");
-	}
+    // HACK: Workaround for QTBUG42500
+    if(!env.contains("LD_LIBRARY_PATH"))
+    {
+        env.insert("LD_LIBRARY_PATH", "");
+    }
 #endif
 
-	return env;
+    return env;
 }
 
 JavaInstallPtr JavaUtils::MakeJavaPtr(QString path, QString id, QString arch)
 {
-	JavaInstallPtr javaVersion(new JavaInstall());
+    JavaInstallPtr javaVersion(new JavaInstall());
 
-	javaVersion->id = id;
-	javaVersion->arch = arch;
-	javaVersion->path = path;
+    javaVersion->id = id;
+    javaVersion->arch = arch;
+    javaVersion->path = path;
 
-	return javaVersion;
+    return javaVersion;
 }
 
 JavaInstallPtr JavaUtils::GetDefaultJava()
 {
-	JavaInstallPtr javaVersion(new JavaInstall());
+    JavaInstallPtr javaVersion(new JavaInstall());
 
-	javaVersion->id = "java";
-	javaVersion->arch = "unknown";
+    javaVersion->id = "java";
+    javaVersion->arch = "unknown";
 #if defined(Q_OS_WIN32)
-	javaVersion->path = "javaw";
+    javaVersion->path = "javaw";
 #else
-	javaVersion->path = "java";
+    javaVersion->path = "java";
 #endif
 
-	return javaVersion;
+    return javaVersion;
 }
 
 #if defined(Q_OS_WIN32)
 QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName)
 {
-	QList<JavaInstallPtr> javas;
-
-	QString archType = "unknown";
-	if (keyType == KEY_WOW64_64KEY)
-		archType = "64";
-	else if (keyType == KEY_WOW64_32KEY)
-		archType = "32";
-
-	HKEY jreKey;
-	if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName.toStdString().c_str(), 0,
-					  KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS)
-	{
-		// Read the current type version from the registry.
-		// This will be used to find any key that contains the JavaHome value.
-		char *value = new char[0];
-		DWORD valueSz = 0;
-		if (RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz) ==
-			ERROR_MORE_DATA)
-		{
-			value = new char[valueSz];
-			RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz);
-		}
-
-		QString recommended = value;
-
-		TCHAR subKeyName[255];
-		DWORD subKeyNameSize, numSubKeys, retCode;
-
-		// Get the number of subkeys
-		RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL,
-						NULL, NULL);
-
-		// Iterate until RegEnumKeyEx fails
-		if (numSubKeys > 0)
-		{
-			for (DWORD i = 0; i < numSubKeys; i++)
-			{
-				subKeyNameSize = 255;
-				retCode = RegEnumKeyEx(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL,
-									   NULL);
-				if (retCode == ERROR_SUCCESS)
-				{
-					// Now open the registry key for the version that we just got.
-					QString newKeyName = keyName + "\\" + subKeyName;
-
-					HKEY newKey;
-					if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0,
-									 KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS)
-					{
-						// Read the JavaHome value to find where Java is installed.
-						value = new char[0];
-						valueSz = 0;
-						if (RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
-											&valueSz) == ERROR_MORE_DATA)
-						{
-							value = new char[valueSz];
-							RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
-											&valueSz);
-
-							// Now, we construct the version object and add it to the list.
-							JavaInstallPtr javaVersion(new JavaInstall());
-
-							javaVersion->id = subKeyName;
-							javaVersion->arch = archType;
-							javaVersion->path =
-								QDir(FS::PathCombine(value, "bin")).absoluteFilePath("javaw.exe");
-							javas.append(javaVersion);
-						}
-
-						RegCloseKey(newKey);
-					}
-				}
-			}
-		}
-
-		RegCloseKey(jreKey);
-	}
-
-	return javas;
+    QList<JavaInstallPtr> javas;
+
+    QString archType = "unknown";
+    if (keyType == KEY_WOW64_64KEY)
+        archType = "64";
+    else if (keyType == KEY_WOW64_32KEY)
+        archType = "32";
+
+    HKEY jreKey;
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName.toStdString().c_str(), 0,
+                      KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS)
+    {
+        // Read the current type version from the registry.
+        // This will be used to find any key that contains the JavaHome value.
+        char *value = new char[0];
+        DWORD valueSz = 0;
+        if (RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz) ==
+            ERROR_MORE_DATA)
+        {
+            value = new char[valueSz];
+            RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE *)value, &valueSz);
+        }
+
+        QString recommended = value;
+
+        TCHAR subKeyName[255];
+        DWORD subKeyNameSize, numSubKeys, retCode;
+
+        // Get the number of subkeys
+        RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL,
+                        NULL, NULL);
+
+        // Iterate until RegEnumKeyEx fails
+        if (numSubKeys > 0)
+        {
+            for (DWORD i = 0; i < numSubKeys; i++)
+            {
+                subKeyNameSize = 255;
+                retCode = RegEnumKeyEx(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL,
+                                       NULL);
+                if (retCode == ERROR_SUCCESS)
+                {
+                    // Now open the registry key for the version that we just got.
+                    QString newKeyName = keyName + "\\" + subKeyName;
+
+                    HKEY newKey;
+                    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0,
+                                     KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS)
+                    {
+                        // Read the JavaHome value to find where Java is installed.
+                        value = new char[0];
+                        valueSz = 0;
+                        if (RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
+                                            &valueSz) == ERROR_MORE_DATA)
+                        {
+                            value = new char[valueSz];
+                            RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE *)value,
+                                            &valueSz);
+
+                            // Now, we construct the version object and add it to the list.
+                            JavaInstallPtr javaVersion(new JavaInstall());
+
+                            javaVersion->id = subKeyName;
+                            javaVersion->arch = archType;
+                            javaVersion->path =
+                                QDir(FS::PathCombine(value, "bin")).absoluteFilePath("javaw.exe");
+                            javas.append(javaVersion);
+                        }
+
+                        RegCloseKey(newKey);
+                    }
+                }
+            }
+        }
+
+        RegCloseKey(jreKey);
+    }
+
+    return javas;
 }
 
 QList<QString> JavaUtils::FindJavaPaths()
 {
-	QList<JavaInstallPtr> java_candidates;
-
-	QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey(
-		KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
-	QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey(
-		KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
-	QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey(
-		KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
-	QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey(
-		KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
-
-	java_candidates.append(JRE64s);
-	java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre8/bin/javaw.exe"));
-	java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre7/bin/javaw.exe"));
-	java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre6/bin/javaw.exe"));
-	java_candidates.append(JDK64s);
-	java_candidates.append(JRE32s);
-	java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre8/bin/javaw.exe"));
-	java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre7/bin/javaw.exe"));
-	java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre6/bin/javaw.exe"));
-	java_candidates.append(JDK32s);
-	java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
-
-	QList<QString> candidates;
-	for(JavaInstallPtr java_candidate : java_candidates)
-	{
-		if(!candidates.contains(java_candidate->path))
-		{
-			candidates.append(java_candidate->path);
-		}
-	}
-
-	return candidates;
+    QList<JavaInstallPtr> java_candidates;
+
+    QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey(
+        KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
+    QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey(
+        KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
+    QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey(
+        KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
+    QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey(
+        KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
+
+    java_candidates.append(JRE64s);
+    java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre8/bin/javaw.exe"));
+    java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre7/bin/javaw.exe"));
+    java_candidates.append(MakeJavaPtr("C:/Program Files/Java/jre6/bin/javaw.exe"));
+    java_candidates.append(JDK64s);
+    java_candidates.append(JRE32s);
+    java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre8/bin/javaw.exe"));
+    java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre7/bin/javaw.exe"));
+    java_candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre6/bin/javaw.exe"));
+    java_candidates.append(JDK32s);
+    java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path));
+
+    QList<QString> candidates;
+    for(JavaInstallPtr java_candidate : java_candidates)
+    {
+        if(!candidates.contains(java_candidate->path))
+        {
+            candidates.append(java_candidate->path);
+        }
+    }
+
+    return candidates;
 }
 
 #elif defined(Q_OS_MAC)
 QList<QString> JavaUtils::FindJavaPaths()
 {
-	QList<QString> javas;
-	javas.append(this->GetDefaultJava()->path);
-	javas.append("/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/bin/java");
-	javas.append("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java");
-	javas.append("/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java");
-	QDir libraryJVMDir("/Library/Java/JavaVirtualMachines/");
-	QStringList libraryJVMJavas = libraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
-	foreach (const QString &java, libraryJVMJavas) {
-		javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
-		javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/jre/bin/java");
-	}
-	QDir systemLibraryJVMDir("/System/Library/Java/JavaVirtualMachines/");
-	QStringList systemLibraryJVMJavas = systemLibraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
-	foreach (const QString &java, systemLibraryJVMJavas) {
-		javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
-		javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
-	}
-	return javas;
+    QList<QString> javas;
+    javas.append(this->GetDefaultJava()->path);
+    javas.append("/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/bin/java");
+    javas.append("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java");
+    javas.append("/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java");
+    QDir libraryJVMDir("/Library/Java/JavaVirtualMachines/");
+    QStringList libraryJVMJavas = libraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+    foreach (const QString &java, libraryJVMJavas) {
+        javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
+        javas.append(libraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/jre/bin/java");
+    }
+    QDir systemLibraryJVMDir("/System/Library/Java/JavaVirtualMachines/");
+    QStringList systemLibraryJVMJavas = systemLibraryJVMDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+    foreach (const QString &java, systemLibraryJVMJavas) {
+        javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Home/bin/java");
+        javas.append(systemLibraryJVMDir.absolutePath() + "/" + java + "/Contents/Commands/java");
+    }
+    return javas;
 }
 
 #elif defined(Q_OS_LINUX)
 QList<QString> JavaUtils::FindJavaPaths()
 {
-	qDebug() << "Linux Java detection incomplete - defaulting to \"java\"";
-
-	QList<QString> javas;
-	javas.append(this->GetDefaultJava()->path);
-	auto scanJavaDir = [&](const QString & dirPath)
-	{
-		QDir dir(dirPath);
-		if(!dir.exists())
-			return;
-		auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
-		for(auto & entry: entries)
-		{
-
-			QString prefix;
-			if(entry.isAbsolute())
-			{
-				prefix = entry.absoluteFilePath();
-			}
-			else
-			{
-				prefix = entry.filePath();
-			}
-
-			javas.append(FS::PathCombine(prefix, "jre/bin/java"));
-			javas.append(FS::PathCombine(prefix, "bin/java"));
-		}
-	};
-	// oracle RPMs
-	scanJavaDir("/usr/java");
-	// general locations used by distro packaging
-	scanJavaDir("/usr/lib/jvm");
-	scanJavaDir("/usr/lib32/jvm");
-	// javas stored in MultiMC's folder
-	scanJavaDir("java");
-	return javas;
+    qDebug() << "Linux Java detection incomplete - defaulting to \"java\"";
+
+    QList<QString> javas;
+    javas.append(this->GetDefaultJava()->path);
+    auto scanJavaDir = [&](const QString & dirPath)
+    {
+        QDir dir(dirPath);
+        if(!dir.exists())
+            return;
+        auto entries = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
+        for(auto & entry: entries)
+        {
+
+            QString prefix;
+            if(entry.isAbsolute())
+            {
+                prefix = entry.absoluteFilePath();
+            }
+            else
+            {
+                prefix = entry.filePath();
+            }
+
+            javas.append(FS::PathCombine(prefix, "jre/bin/java"));
+            javas.append(FS::PathCombine(prefix, "bin/java"));
+        }
+    };
+    // oracle RPMs
+    scanJavaDir("/usr/java");
+    // general locations used by distro packaging
+    scanJavaDir("/usr/lib/jvm");
+    scanJavaDir("/usr/lib32/jvm");
+    // javas stored in MultiMC's folder
+    scanJavaDir("java");
+    return javas;
 }
 #else
 QList<QString> JavaUtils::FindJavaPaths()
 {
-	qDebug() << "Unknown operating system build - defaulting to \"java\"";
+    qDebug() << "Unknown operating system build - defaulting to \"java\"";
 
-	QList<QString> javas;
-	javas.append(this->GetDefaultJava()->path);
+    QList<QString> javas;
+    javas.append(this->GetDefaultJava()->path);
 
-	return javas;
+    return javas;
 }
 #endif
diff --git a/api/logic/java/JavaUtils.h b/api/logic/java/JavaUtils.h
index b43e93cf..40745ad6 100644
--- a/api/logic/java/JavaUtils.h
+++ b/api/logic/java/JavaUtils.h
@@ -30,15 +30,15 @@ QProcessEnvironment CleanEnviroment();
 
 class MULTIMC_LOGIC_EXPORT JavaUtils : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	JavaUtils();
+    JavaUtils();
 
-	JavaInstallPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown");
-	QList<QString> FindJavaPaths();
-	JavaInstallPtr GetDefaultJava();
+    JavaInstallPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown");
+    QList<QString> FindJavaPaths();
+    JavaInstallPtr GetDefaultJava();
 
 #ifdef Q_OS_WIN
-	QList<JavaInstallPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName);
+    QList<JavaInstallPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName);
 #endif
 };
diff --git a/api/logic/java/JavaVersion.cpp b/api/logic/java/JavaVersion.cpp
index 27050da3..179ccd8d 100644
--- a/api/logic/java/JavaVersion.cpp
+++ b/api/logic/java/JavaVersion.cpp
@@ -6,116 +6,116 @@
 
 JavaVersion & JavaVersion::operator=(const QString & javaVersionString)
 {
-	m_string = javaVersionString;
+    m_string = javaVersionString;
 
-	auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int
-	{
-		auto str = match.captured(what);
-		if(str.isEmpty())
-		{
-			return 0;
-		}
-		return str.toInt();
-	};
+    auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int
+    {
+        auto str = match.captured(what);
+        if(str.isEmpty())
+        {
+            return 0;
+        }
+        return str.toInt();
+    };
 
-	QRegularExpression pattern;
-	if(javaVersionString.startsWith("1."))
-	{
-		pattern = QRegularExpression ("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?");
-	}
-	else
-	{
-		pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?");
-	}
+    QRegularExpression pattern;
+    if(javaVersionString.startsWith("1."))
+    {
+        pattern = QRegularExpression ("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?");
+    }
+    else
+    {
+        pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?");
+    }
 
-	auto match = pattern.match(m_string);
-	m_parseable = match.hasMatch();
-	m_major = getCapturedInteger(match, "major");
-	m_minor = getCapturedInteger(match, "minor");
-	m_security = getCapturedInteger(match, "security");
-	m_prerelease = match.captured("prerelease");
-	return *this;
+    auto match = pattern.match(m_string);
+    m_parseable = match.hasMatch();
+    m_major = getCapturedInteger(match, "major");
+    m_minor = getCapturedInteger(match, "minor");
+    m_security = getCapturedInteger(match, "security");
+    m_prerelease = match.captured("prerelease");
+    return *this;
 }
 
 JavaVersion::JavaVersion(const QString &rhs)
 {
-	operator=(rhs);
+    operator=(rhs);
 }
 
 QString JavaVersion::toString()
 {
-	return m_string;
+    return m_string;
 }
 
 bool JavaVersion::requiresPermGen()
 {
-	if(m_parseable)
-	{
-		return m_major < 8;
-	}
-	return true;
+    if(m_parseable)
+    {
+        return m_major < 8;
+    }
+    return true;
 }
 
 bool JavaVersion::operator<(const JavaVersion &rhs)
 {
-	if(m_parseable && rhs.m_parseable)
-	{
-		auto major = m_major;
-		auto rmajor = rhs.m_major;
+    if(m_parseable && rhs.m_parseable)
+    {
+        auto major = m_major;
+        auto rmajor = rhs.m_major;
 
-		// HACK: discourage using java 9
-		if(major > 8)
-			major = -major;
-		if(rmajor > 8)
-			rmajor = -rmajor;
+        // HACK: discourage using java 9
+        if(major > 8)
+            major = -major;
+        if(rmajor > 8)
+            rmajor = -rmajor;
 
-		if(major < rmajor)
-			return true;
-		if(major > rmajor)
-			return false;
-		if(m_minor < rhs.m_minor)
-			return true;
-		if(m_minor > rhs.m_minor)
-			return false;
-		if(m_security < rhs.m_security)
-			return true;
-		if(m_security > rhs.m_security)
-			return false;
+        if(major < rmajor)
+            return true;
+        if(major > rmajor)
+            return false;
+        if(m_minor < rhs.m_minor)
+            return true;
+        if(m_minor > rhs.m_minor)
+            return false;
+        if(m_security < rhs.m_security)
+            return true;
+        if(m_security > rhs.m_security)
+            return false;
 
-		// everything else being equal, consider prerelease status
-		bool thisPre = !m_prerelease.isEmpty();
-		bool rhsPre = !rhs.m_prerelease.isEmpty();
-		if(thisPre && !rhsPre)
-		{
-			// this is a prerelease and the other one isn't -> lesser
-			return true;
-		}
-		else if(!thisPre && rhsPre)
-		{
-			// this isn't a prerelease and the other one is -> greater
-			return false;
-		}
-		else if(thisPre && rhsPre)
-		{
-			// both are prereleases - use natural compare...
-			return Strings::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
-		}
-		// neither is prerelease, so they are the same -> this cannot be less than rhs
-		return false;
-	}
-	else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
+        // everything else being equal, consider prerelease status
+        bool thisPre = !m_prerelease.isEmpty();
+        bool rhsPre = !rhs.m_prerelease.isEmpty();
+        if(thisPre && !rhsPre)
+        {
+            // this is a prerelease and the other one isn't -> lesser
+            return true;
+        }
+        else if(!thisPre && rhsPre)
+        {
+            // this isn't a prerelease and the other one is -> greater
+            return false;
+        }
+        else if(thisPre && rhsPre)
+        {
+            // both are prereleases - use natural compare...
+            return Strings::naturalCompare(m_prerelease, rhs.m_prerelease, Qt::CaseSensitive) < 0;
+        }
+        // neither is prerelease, so they are the same -> this cannot be less than rhs
+        return false;
+    }
+    else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
 }
 
 bool JavaVersion::operator==(const JavaVersion &rhs)
 {
-	if(m_parseable && rhs.m_parseable)
-	{
-		return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease;
-	}
-	return m_string == rhs.m_string;
+    if(m_parseable && rhs.m_parseable)
+    {
+        return m_major == rhs.m_major && m_minor == rhs.m_minor && m_security == rhs.m_security && m_prerelease == rhs.m_prerelease;
+    }
+    return m_string == rhs.m_string;
 }
 
 bool JavaVersion::operator>(const JavaVersion &rhs)
 {
-	return (!operator<(rhs)) && (!operator==(rhs));
+    return (!operator<(rhs)) && (!operator==(rhs));
 }
diff --git a/api/logic/java/JavaVersion.h b/api/logic/java/JavaVersion.h
index de13998c..8589c21a 100644
--- a/api/logic/java/JavaVersion.h
+++ b/api/logic/java/JavaVersion.h
@@ -5,46 +5,46 @@
 
 // NOTE: apparently the GNU C library pollutes the global namespace with these... undef them.
 #ifdef major
-	#undef major
+    #undef major
 #endif
 #ifdef minor
-	#undef minor
+    #undef minor
 #endif
 
 class MULTIMC_LOGIC_EXPORT JavaVersion
 {
-	friend class JavaVersionTest;
+    friend class JavaVersionTest;
 public:
-	JavaVersion() {};
-	JavaVersion(const QString & rhs);
-
-	JavaVersion & operator=(const QString & rhs);
-
-	bool operator<(const JavaVersion & rhs);
-	bool operator==(const JavaVersion & rhs);
-	bool operator>(const JavaVersion & rhs);
-
-	bool requiresPermGen();
-
-	QString toString();
-
-	int major()
-	{
-		return m_major;
-	}
-	int minor()
-	{
-		return m_minor;
-	}
-	int security()
-	{
-		return m_security;
-	}
+    JavaVersion() {};
+    JavaVersion(const QString & rhs);
+
+    JavaVersion & operator=(const QString & rhs);
+
+    bool operator<(const JavaVersion & rhs);
+    bool operator==(const JavaVersion & rhs);
+    bool operator>(const JavaVersion & rhs);
+
+    bool requiresPermGen();
+
+    QString toString();
+
+    int major()
+    {
+        return m_major;
+    }
+    int minor()
+    {
+        return m_minor;
+    }
+    int security()
+    {
+        return m_security;
+    }
 private:
-	QString m_string;
-	int m_major = 0;
-	int m_minor = 0;
-	int m_security = 0;
-	bool m_parseable = false;
-	QString m_prerelease;
+    QString m_string;
+    int m_major = 0;
+    int m_minor = 0;
+    int m_security = 0;
+    bool m_parseable = false;
+    QString m_prerelease;
 };
diff --git a/api/logic/java/JavaVersion_test.cpp b/api/logic/java/JavaVersion_test.cpp
index e719ffc8..10ae13a7 100644
--- a/api/logic/java/JavaVersion_test.cpp
+++ b/api/logic/java/JavaVersion_test.cpp
@@ -5,110 +5,110 @@
 
 class JavaVersionTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void test_Parse_data()
-	{
-		QTest::addColumn<QString>("string");
-		QTest::addColumn<int>("major");
-		QTest::addColumn<int>("minor");
-		QTest::addColumn<int>("security");
-		QTest::addColumn<QString>("prerelease");
+    void test_Parse_data()
+    {
+        QTest::addColumn<QString>("string");
+        QTest::addColumn<int>("major");
+        QTest::addColumn<int>("minor");
+        QTest::addColumn<int>("security");
+        QTest::addColumn<QString>("prerelease");
 
-		QTest::newRow("old format") << "1.6.0_33" << 6 << 0 << 33 << QString();
-		QTest::newRow("old format prerelease") << "1.9.0_1-ea" << 9 << 0 << 1 << "ea";
+        QTest::newRow("old format") << "1.6.0_33" << 6 << 0 << 33 << QString();
+        QTest::newRow("old format prerelease") << "1.9.0_1-ea" << 9 << 0 << 1 << "ea";
 
-		QTest::newRow("new format major") << "9" << 9 << 0 << 0 << QString();
-		QTest::newRow("new format minor") << "9.1" << 9 << 1 << 0 << QString();
-		QTest::newRow("new format security") << "9.0.1" << 9 << 0 << 1 << QString();
-		QTest::newRow("new format prerelease") << "9-ea" << 9 << 0 << 0 << "ea";
-		QTest::newRow("new format long prerelease") << "9.0.1-ea" << 9 << 0 << 1 << "ea";
-	}
-	void test_Parse()
-	{
-		QFETCH(QString, string);
-		QFETCH(int, major);
-		QFETCH(int, minor);
-		QFETCH(int, security);
-		QFETCH(QString, prerelease);
+        QTest::newRow("new format major") << "9" << 9 << 0 << 0 << QString();
+        QTest::newRow("new format minor") << "9.1" << 9 << 1 << 0 << QString();
+        QTest::newRow("new format security") << "9.0.1" << 9 << 0 << 1 << QString();
+        QTest::newRow("new format prerelease") << "9-ea" << 9 << 0 << 0 << "ea";
+        QTest::newRow("new format long prerelease") << "9.0.1-ea" << 9 << 0 << 1 << "ea";
+    }
+    void test_Parse()
+    {
+        QFETCH(QString, string);
+        QFETCH(int, major);
+        QFETCH(int, minor);
+        QFETCH(int, security);
+        QFETCH(QString, prerelease);
 
-		JavaVersion test(string);
-		QCOMPARE(test.m_string, string);
-		QCOMPARE(test.toString(), string);
-		QCOMPARE(test.m_major, major);
-		QCOMPARE(test.m_minor, minor);
-		QCOMPARE(test.m_security, security);
-		QCOMPARE(test.m_prerelease, prerelease);
-	}
+        JavaVersion test(string);
+        QCOMPARE(test.m_string, string);
+        QCOMPARE(test.toString(), string);
+        QCOMPARE(test.m_major, major);
+        QCOMPARE(test.m_minor, minor);
+        QCOMPARE(test.m_security, security);
+        QCOMPARE(test.m_prerelease, prerelease);
+    }
 
-	void test_Sort_data()
-	{
-		QTest::addColumn<QString>("lhs");
-		QTest::addColumn<QString>("rhs");
-		QTest::addColumn<bool>("smaller");
-		QTest::addColumn<bool>("equal");
-		QTest::addColumn<bool>("bigger");
+    void test_Sort_data()
+    {
+        QTest::addColumn<QString>("lhs");
+        QTest::addColumn<QString>("rhs");
+        QTest::addColumn<bool>("smaller");
+        QTest::addColumn<bool>("equal");
+        QTest::addColumn<bool>("bigger");
 
-		// old format and new format equivalence
-		QTest::newRow("1.6.0_33 == 6.0.33") << "1.6.0_33" << "6.0.33" << false << true << false;
-		// old format major version
-		QTest::newRow("1.5.0_33 < 1.6.0_33") << "1.5.0_33" << "1.6.0_33" << true << false << false;
-		// new format - first release vs first security patch
-		QTest::newRow("9 < 9.0.1") << "9" << "9.0.1" << true << false << false;
-		QTest::newRow("9.0.1 > 9") << "9.0.1" << "9" << false << false << true;
-		// new format - first minor vs first release/security patch
-		QTest::newRow("9.1 > 9.0.1") << "9.1" << "9.0.1" << false << false << true;
-		QTest::newRow("9.0.1 < 9.1") << "9.0.1" << "9.1" << true << false << false;
-		QTest::newRow("9.1 > 9") << "9.1" << "9" << false << false << true;
-		QTest::newRow("9 > 9.1") << "9" << "9.1" << true << false << false;
-		// new format - omitted numbers
-		QTest::newRow("9 == 9.0") << "9" << "9.0" << false << true << false;
-		QTest::newRow("9 == 9.0.0") << "9" << "9.0.0" << false << true << false;
-		QTest::newRow("9.0 == 9.0.0") << "9.0" << "9.0.0" << false << true << false;
-		// early access and prereleases compared to final release
-		QTest::newRow("9-ea < 9") << "9-ea" << "9" << true << false << false;
-		QTest::newRow("9 < 9.0.1-ea") << "9" << "9.0.1-ea" << true << false << false;
-		QTest::newRow("9.0.1-ea > 9") << "9.0.1-ea" << "9" << false << false << true;
-		// prerelease difference only testing
-		QTest::newRow("9-1 == 9-1") << "9-1" << "9-1" << false << true << false;
-		QTest::newRow("9-1 < 9-2") << "9-1" << "9-2" << true << false << false;
-		QTest::newRow("9-5 < 9-20") << "9-5" << "9-20" << true << false << false;
-		QTest::newRow("9-rc1 < 9-rc2") << "9-rc1" << "9-rc2" << true << false << false;
-		QTest::newRow("9-rc5 < 9-rc20") << "9-rc5" << "9-rc20" << true << false << false;
-		QTest::newRow("9-rc < 9-rc2") << "9-rc" << "9-rc2" << true << false << false;
-		QTest::newRow("9-ea < 9-rc") << "9-ea" << "9-rc" << true << false << false;
-	}
-	void test_Sort()
-	{
-		QFETCH(QString, lhs);
-		QFETCH(QString, rhs);
-		QFETCH(bool, smaller);
-		QFETCH(bool, equal);
-		QFETCH(bool, bigger);
-		JavaVersion lver(lhs);
-		JavaVersion rver(rhs);
-		QCOMPARE(lver < rver, smaller);
-		QCOMPARE(lver == rver, equal);
-		QCOMPARE(lver > rver, bigger);
-	}
-	void test_PermGen_data()
-	{
-		QTest::addColumn<QString>("version");
-		QTest::addColumn<bool>("needs_permgen");
-		QTest::newRow("1.6.0_33") << "1.6.0_33" << true;
-		QTest::newRow("1.7.0_60") << "1.7.0_60" << true;
-		QTest::newRow("1.8.0_22") << "1.8.0_22" << false;
-		QTest::newRow("9-ea") << "9-ea" << false;
-		QTest::newRow("9.2.4") << "9.2.4" << false;
-	}
-	void test_PermGen()
-	{
-		QFETCH(QString, version);
-		QFETCH(bool, needs_permgen);
-		JavaVersion v(version);
-		QCOMPARE(needs_permgen, v.requiresPermGen());
-	}
+        // old format and new format equivalence
+        QTest::newRow("1.6.0_33 == 6.0.33") << "1.6.0_33" << "6.0.33" << false << true << false;
+        // old format major version
+        QTest::newRow("1.5.0_33 < 1.6.0_33") << "1.5.0_33" << "1.6.0_33" << true << false << false;
+        // new format - first release vs first security patch
+        QTest::newRow("9 < 9.0.1") << "9" << "9.0.1" << true << false << false;
+        QTest::newRow("9.0.1 > 9") << "9.0.1" << "9" << false << false << true;
+        // new format - first minor vs first release/security patch
+        QTest::newRow("9.1 > 9.0.1") << "9.1" << "9.0.1" << false << false << true;
+        QTest::newRow("9.0.1 < 9.1") << "9.0.1" << "9.1" << true << false << false;
+        QTest::newRow("9.1 > 9") << "9.1" << "9" << false << false << true;
+        QTest::newRow("9 > 9.1") << "9" << "9.1" << true << false << false;
+        // new format - omitted numbers
+        QTest::newRow("9 == 9.0") << "9" << "9.0" << false << true << false;
+        QTest::newRow("9 == 9.0.0") << "9" << "9.0.0" << false << true << false;
+        QTest::newRow("9.0 == 9.0.0") << "9.0" << "9.0.0" << false << true << false;
+        // early access and prereleases compared to final release
+        QTest::newRow("9-ea < 9") << "9-ea" << "9" << true << false << false;
+        QTest::newRow("9 < 9.0.1-ea") << "9" << "9.0.1-ea" << true << false << false;
+        QTest::newRow("9.0.1-ea > 9") << "9.0.1-ea" << "9" << false << false << true;
+        // prerelease difference only testing
+        QTest::newRow("9-1 == 9-1") << "9-1" << "9-1" << false << true << false;
+        QTest::newRow("9-1 < 9-2") << "9-1" << "9-2" << true << false << false;
+        QTest::newRow("9-5 < 9-20") << "9-5" << "9-20" << true << false << false;
+        QTest::newRow("9-rc1 < 9-rc2") << "9-rc1" << "9-rc2" << true << false << false;
+        QTest::newRow("9-rc5 < 9-rc20") << "9-rc5" << "9-rc20" << true << false << false;
+        QTest::newRow("9-rc < 9-rc2") << "9-rc" << "9-rc2" << true << false << false;
+        QTest::newRow("9-ea < 9-rc") << "9-ea" << "9-rc" << true << false << false;
+    }
+    void test_Sort()
+    {
+        QFETCH(QString, lhs);
+        QFETCH(QString, rhs);
+        QFETCH(bool, smaller);
+        QFETCH(bool, equal);
+        QFETCH(bool, bigger);
+        JavaVersion lver(lhs);
+        JavaVersion rver(rhs);
+        QCOMPARE(lver < rver, smaller);
+        QCOMPARE(lver == rver, equal);
+        QCOMPARE(lver > rver, bigger);
+    }
+    void test_PermGen_data()
+    {
+        QTest::addColumn<QString>("version");
+        QTest::addColumn<bool>("needs_permgen");
+        QTest::newRow("1.6.0_33") << "1.6.0_33" << true;
+        QTest::newRow("1.7.0_60") << "1.7.0_60" << true;
+        QTest::newRow("1.8.0_22") << "1.8.0_22" << false;
+        QTest::newRow("9-ea") << "9-ea" << false;
+        QTest::newRow("9.2.4") << "9.2.4" << false;
+    }
+    void test_PermGen()
+    {
+        QFETCH(QString, version);
+        QFETCH(bool, needs_permgen);
+        JavaVersion v(version);
+        QCOMPARE(needs_permgen, v.requiresPermGen());
+    }
 };
 
 QTEST_GUILESS_MAIN(JavaVersionTest)
diff --git a/api/logic/java/launch/CheckJava.cpp b/api/logic/java/launch/CheckJava.cpp
index 24f26682..4ea40084 100644
--- a/api/logic/java/launch/CheckJava.cpp
+++ b/api/logic/java/launch/CheckJava.cpp
@@ -22,115 +22,115 @@
 
 void CheckJava::executeTask()
 {
-	auto instance = m_parent->instance();
-	auto settings = instance->settings();
-	m_javaPath = FS::ResolveExecutable(settings->get("JavaPath").toString());
-	bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool();
+    auto instance = m_parent->instance();
+    auto settings = instance->settings();
+    m_javaPath = FS::ResolveExecutable(settings->get("JavaPath").toString());
+    bool perInstance = settings->get("OverrideJava").toBool() || settings->get("OverrideJavaLocation").toBool();
 
-	auto realJavaPath = QStandardPaths::findExecutable(m_javaPath);
-	if (realJavaPath.isEmpty())
-	{
-		if (perInstance)
-		{
-			emit logLine(
-				tr("The java binary \"%1\" couldn't be found. Please fix the java path "
-				   "override in the instance's settings or disable it.").arg(m_javaPath),
-				MessageLevel::Warning);
-		}
-		else
-		{
-			emit logLine(tr("The java binary \"%1\" couldn't be found. Please set up java in "
-							"the settings.").arg(m_javaPath),
-						 MessageLevel::Warning);
-		}
-		emitFailed(tr("Java path is not valid."));
-		return;
-	}
-	else
-	{
-		emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::MultiMC);
-	}
+    auto realJavaPath = QStandardPaths::findExecutable(m_javaPath);
+    if (realJavaPath.isEmpty())
+    {
+        if (perInstance)
+        {
+            emit logLine(
+                tr("The java binary \"%1\" couldn't be found. Please fix the java path "
+                   "override in the instance's settings or disable it.").arg(m_javaPath),
+                MessageLevel::Warning);
+        }
+        else
+        {
+            emit logLine(tr("The java binary \"%1\" couldn't be found. Please set up java in "
+                            "the settings.").arg(m_javaPath),
+                         MessageLevel::Warning);
+        }
+        emitFailed(tr("Java path is not valid."));
+        return;
+    }
+    else
+    {
+        emit logLine("Java path is:\n" + m_javaPath + "\n\n", MessageLevel::MultiMC);
+    }
 
-	QFileInfo javaInfo(realJavaPath);
-	qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch();
-	auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
-	auto storedArchitecture = settings->get("JavaArchitecture").toString();
-	auto storedVersion = settings->get("JavaVersion").toString();
-	m_javaUnixTime = javaUnixTime;
-	// if timestamps are not the same, or something is missing, check!
-	if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0)
-	{
-		m_JavaChecker = std::make_shared<JavaChecker>();
-		emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
-		connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
-		m_JavaChecker->m_path = realJavaPath;
-		m_JavaChecker->performCheck();
-		return;
-	}
-	else
-	{
-		auto verString = instance->settings()->get("JavaVersion").toString();
-		auto archString = instance->settings()->get("JavaArchitecture").toString();
-		printJavaInfo(verString, archString);
-	}
-	emitSucceeded();
+    QFileInfo javaInfo(realJavaPath);
+    qlonglong javaUnixTime = javaInfo.lastModified().toMSecsSinceEpoch();
+    auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
+    auto storedArchitecture = settings->get("JavaArchitecture").toString();
+    auto storedVersion = settings->get("JavaVersion").toString();
+    m_javaUnixTime = javaUnixTime;
+    // if timestamps are not the same, or something is missing, check!
+    if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0)
+    {
+        m_JavaChecker = std::make_shared<JavaChecker>();
+        emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
+        connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
+        m_JavaChecker->m_path = realJavaPath;
+        m_JavaChecker->performCheck();
+        return;
+    }
+    else
+    {
+        auto verString = instance->settings()->get("JavaVersion").toString();
+        auto archString = instance->settings()->get("JavaArchitecture").toString();
+        printJavaInfo(verString, archString);
+    }
+    emitSucceeded();
 }
 
 void CheckJava::checkJavaFinished(JavaCheckResult result)
 {
-	switch (result.validity)
-	{
-		case JavaCheckResult::Validity::Errored:
-		{
-			// Error message displayed if java can't start
-			emit logLine(tr("Could not start java:"), MessageLevel::Error);
-			emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
-			emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
-			printSystemInfo(false, false);
-			emitFailed(tr("Could not start java!"));
-			return;
-		}
-		case JavaCheckResult::Validity::ReturnedInvalidData:
-		{
-			emit logLine(tr("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
-			emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
-			emit logLine("\nMinecraft might not start properly.", MessageLevel::MultiMC);
-			printSystemInfo(false, false);
-			emitSucceeded();
-			return;
-		}
-		case JavaCheckResult::Validity::Valid:
-		{
-			auto instance = m_parent->instance();
-			printJavaInfo(result.javaVersion.toString(), result.mojangPlatform);
-			instance->settings()->set("JavaVersion", result.javaVersion.toString());
-			instance->settings()->set("JavaArchitecture", result.mojangPlatform);
-			instance->settings()->set("JavaTimestamp", m_javaUnixTime);
-			emitSucceeded();
-			return;
-		}
-	}
+    switch (result.validity)
+    {
+        case JavaCheckResult::Validity::Errored:
+        {
+            // Error message displayed if java can't start
+            emit logLine(tr("Could not start java:"), MessageLevel::Error);
+            emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
+            emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
+            printSystemInfo(false, false);
+            emitFailed(tr("Could not start java!"));
+            return;
+        }
+        case JavaCheckResult::Validity::ReturnedInvalidData:
+        {
+            emit logLine(tr("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
+            emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
+            emit logLine("\nMinecraft might not start properly.", MessageLevel::MultiMC);
+            printSystemInfo(false, false);
+            emitSucceeded();
+            return;
+        }
+        case JavaCheckResult::Validity::Valid:
+        {
+            auto instance = m_parent->instance();
+            printJavaInfo(result.javaVersion.toString(), result.mojangPlatform);
+            instance->settings()->set("JavaVersion", result.javaVersion.toString());
+            instance->settings()->set("JavaArchitecture", result.mojangPlatform);
+            instance->settings()->set("JavaTimestamp", m_javaUnixTime);
+            emitSucceeded();
+            return;
+        }
+    }
 }
 
 void CheckJava::printJavaInfo(const QString& version, const QString& architecture)
 {
-	emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
-	printSystemInfo(true, architecture == "64");
+    emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
+    printSystemInfo(true, architecture == "64");
 }
 
 void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
 {
-	auto cpu64 = Sys::isCPU64bit();
-	auto system64 = Sys::isSystem64bit();
-	if(cpu64 != system64)
-	{
-		emit logLine(tr("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
-	}
-	if(javaIsKnown)
-	{
-		if(javaIs64bit != system64)
-		{
-			emit logLine(tr("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
-		}
-	}
+    auto cpu64 = Sys::isCPU64bit();
+    auto system64 = Sys::isSystem64bit();
+    if(cpu64 != system64)
+    {
+        emit logLine(tr("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
+    }
+    if(javaIsKnown)
+    {
+        if(javaIs64bit != system64)
+        {
+            emit logLine(tr("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
+        }
+    }
 }
diff --git a/api/logic/java/launch/CheckJava.h b/api/logic/java/launch/CheckJava.h
index 82508cd4..be247a1b 100644
--- a/api/logic/java/launch/CheckJava.h
+++ b/api/logic/java/launch/CheckJava.h
@@ -21,25 +21,25 @@
 
 class CheckJava: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit CheckJava(LaunchTask *parent) :LaunchStep(parent){};
-	virtual ~CheckJava() {};
+    explicit CheckJava(LaunchTask *parent) :LaunchStep(parent){};
+    virtual ~CheckJava() {};
 
-	virtual void executeTask();
-	virtual bool canAbort() const
-	{
-		return false;
-	}
+    virtual void executeTask();
+    virtual bool canAbort() const
+    {
+        return false;
+    }
 private slots:
-	void checkJavaFinished(JavaCheckResult result);
+    void checkJavaFinished(JavaCheckResult result);
 
 private:
-	void printJavaInfo(const QString & version, const QString & architecture);
-	void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
+    void printJavaInfo(const QString & version, const QString & architecture);
+    void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
 
 private:
-	QString m_javaPath;
-	qlonglong m_javaUnixTime;
-	JavaCheckerPtr m_JavaChecker;
+    QString m_javaPath;
+    qlonglong m_javaUnixTime;
+    JavaCheckerPtr m_JavaChecker;
 };
diff --git a/api/logic/launch/LaunchStep.cpp b/api/logic/launch/LaunchStep.cpp
index 01f72a0a..e2327712 100644
--- a/api/logic/launch/LaunchStep.cpp
+++ b/api/logic/launch/LaunchStep.cpp
@@ -18,10 +18,10 @@
 
 void LaunchStep::bind(LaunchTask *parent)
 {
-	m_parent = parent;
-	connect(this, &LaunchStep::readyForLaunch, parent, &LaunchTask::onReadyForLaunch);
-	connect(this, &LaunchStep::logLine, parent, &LaunchTask::onLogLine);
-	connect(this, &LaunchStep::logLines, parent, &LaunchTask::onLogLines);
-	connect(this, &LaunchStep::finished, parent, &LaunchTask::onStepFinished);
-	connect(this, &LaunchStep::progressReportingRequest, parent, &LaunchTask::onProgressReportingRequested);
+    m_parent = parent;
+    connect(this, &LaunchStep::readyForLaunch, parent, &LaunchTask::onReadyForLaunch);
+    connect(this, &LaunchStep::logLine, parent, &LaunchTask::onLogLine);
+    connect(this, &LaunchStep::logLines, parent, &LaunchTask::onLogLines);
+    connect(this, &LaunchStep::finished, parent, &LaunchTask::onStepFinished);
+    connect(this, &LaunchStep::progressReportingRequest, parent, &LaunchTask::onProgressReportingRequested);
 }
diff --git a/api/logic/launch/LaunchStep.h b/api/logic/launch/LaunchStep.h
index 80778e34..0abe456a 100644
--- a/api/logic/launch/LaunchStep.h
+++ b/api/logic/launch/LaunchStep.h
@@ -23,28 +23,28 @@
 class LaunchTask;
 class LaunchStep: public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public: /* methods */
-	explicit LaunchStep(LaunchTask *parent):Task(nullptr), m_parent(parent)
-	{
-		bind(parent);
-	};
-	virtual ~LaunchStep() {};
+    explicit LaunchStep(LaunchTask *parent):Task(nullptr), m_parent(parent)
+    {
+        bind(parent);
+    };
+    virtual ~LaunchStep() {};
 
 protected: /* methods */
-	virtual void bind(LaunchTask *parent);
+    virtual void bind(LaunchTask *parent);
 
 signals:
-	void logLines(QStringList lines, MessageLevel::Enum level);
-	void logLine(QString line, MessageLevel::Enum level);
-	void readyForLaunch();
-	void progressReportingRequest();
+    void logLines(QStringList lines, MessageLevel::Enum level);
+    void logLine(QString line, MessageLevel::Enum level);
+    void readyForLaunch();
+    void progressReportingRequest();
 
 public slots:
-	virtual void proceed() {};
-	// called in the opposite order than the Task launch(), used to clean up or otherwise undo things after the launch ends
-	virtual void finalize() {};
+    virtual void proceed() {};
+    // called in the opposite order than the Task launch(), used to clean up or otherwise undo things after the launch ends
+    virtual void finalize() {};
 
 protected: /* data */
-	LaunchTask *m_parent;
+    LaunchTask *m_parent;
 };
\ No newline at end of file
diff --git a/api/logic/launch/LaunchTask.cpp b/api/logic/launch/LaunchTask.cpp
index 99c16721..c00fa32a 100644
--- a/api/logic/launch/LaunchTask.cpp
+++ b/api/logic/launch/LaunchTask.cpp
@@ -30,14 +30,14 @@
 
 void LaunchTask::init()
 {
-	m_instance->setRunning(true);
+    m_instance->setRunning(true);
 }
 
 std::shared_ptr<LaunchTask> LaunchTask::create(InstancePtr inst)
 {
-	std::shared_ptr<LaunchTask> proc(new LaunchTask(inst));
-	proc->init();
-	return proc;
+    std::shared_ptr<LaunchTask> proc(new LaunchTask(inst));
+    proc->init();
+    return proc;
 }
 
 LaunchTask::LaunchTask(InstancePtr instance): m_instance(instance)
@@ -46,235 +46,235 @@ LaunchTask::LaunchTask(InstancePtr instance): m_instance(instance)
 
 void LaunchTask::appendStep(std::shared_ptr<LaunchStep> step)
 {
-	m_steps.append(step);
+    m_steps.append(step);
 }
 
 void LaunchTask::prependStep(std::shared_ptr<LaunchStep> step)
 {
-	m_steps.prepend(step);
+    m_steps.prepend(step);
 }
 
 void LaunchTask::executeTask()
 {
-	m_instance->setCrashed(false);
-	if(!m_steps.size())
-	{
-		state = LaunchTask::Finished;
-		emitSucceeded();
-	}
-	state = LaunchTask::Running;
-	onStepFinished();
+    m_instance->setCrashed(false);
+    if(!m_steps.size())
+    {
+        state = LaunchTask::Finished;
+        emitSucceeded();
+    }
+    state = LaunchTask::Running;
+    onStepFinished();
 }
 
 void LaunchTask::onReadyForLaunch()
 {
-	state = LaunchTask::Waiting;
-	emit readyForLaunch();
+    state = LaunchTask::Waiting;
+    emit readyForLaunch();
 }
 
 void LaunchTask::onStepFinished()
 {
-	// initial -> just start the first step
-	if(currentStep == -1)
-	{
-		currentStep ++;
-		m_steps[currentStep]->start();
-		return;
-	}
+    // initial -> just start the first step
+    if(currentStep == -1)
+    {
+        currentStep ++;
+        m_steps[currentStep]->start();
+        return;
+    }
 
-	auto step = m_steps[currentStep];
-	if(step->wasSuccessful())
-	{
-		// end?
-		if(currentStep == m_steps.size() - 1)
-		{
-			finalizeSteps(true, QString());
-		}
-		else
-		{
-			currentStep ++;
-			step = m_steps[currentStep];
-			step->start();
-		}
-	}
-	else
-	{
-		finalizeSteps(false, step->failReason());
-	}
+    auto step = m_steps[currentStep];
+    if(step->wasSuccessful())
+    {
+        // end?
+        if(currentStep == m_steps.size() - 1)
+        {
+            finalizeSteps(true, QString());
+        }
+        else
+        {
+            currentStep ++;
+            step = m_steps[currentStep];
+            step->start();
+        }
+    }
+    else
+    {
+        finalizeSteps(false, step->failReason());
+    }
 }
 
 void LaunchTask::finalizeSteps(bool successful, const QString& error)
 {
-	for(auto step = currentStep; step >= 0; step--)
-	{
-		m_steps[step]->finalize();
-	}
-	if(successful)
-	{
-		emitSucceeded();
-	}
-	else
-	{
-		emitFailed(error);
-	}
+    for(auto step = currentStep; step >= 0; step--)
+    {
+        m_steps[step]->finalize();
+    }
+    if(successful)
+    {
+        emitSucceeded();
+    }
+    else
+    {
+        emitFailed(error);
+    }
 }
 
 void LaunchTask::onProgressReportingRequested()
 {
-	state = LaunchTask::Waiting;
-	emit requestProgress(m_steps[currentStep].get());
+    state = LaunchTask::Waiting;
+    emit requestProgress(m_steps[currentStep].get());
 }
 
 void LaunchTask::setCensorFilter(QMap<QString, QString> filter)
 {
-	m_censorFilter = filter;
+    m_censorFilter = filter;
 }
 
 QString LaunchTask::censorPrivateInfo(QString in)
 {
-	auto iter = m_censorFilter.begin();
-	while (iter != m_censorFilter.end())
-	{
-		in.replace(iter.key(), iter.value());
-		iter++;
-	}
-	return in;
+    auto iter = m_censorFilter.begin();
+    while (iter != m_censorFilter.end())
+    {
+        in.replace(iter.key(), iter.value());
+        iter++;
+    }
+    return in;
 }
 
 void LaunchTask::proceed()
 {
-	if(state != LaunchTask::Waiting)
-	{
-		return;
-	}
-	m_steps[currentStep]->proceed();
+    if(state != LaunchTask::Waiting)
+    {
+        return;
+    }
+    m_steps[currentStep]->proceed();
 }
 
 bool LaunchTask::canAbort() const
 {
-	switch(state)
-	{
-		case LaunchTask::Aborted:
-		case LaunchTask::Failed:
-		case LaunchTask::Finished:
-			return false;
-		case LaunchTask::NotStarted:
-			return true;
-		case LaunchTask::Running:
-		case LaunchTask::Waiting:
-		{
-			auto step = m_steps[currentStep];
-			return step->canAbort();
-		}
-	}
-	return false;
+    switch(state)
+    {
+        case LaunchTask::Aborted:
+        case LaunchTask::Failed:
+        case LaunchTask::Finished:
+            return false;
+        case LaunchTask::NotStarted:
+            return true;
+        case LaunchTask::Running:
+        case LaunchTask::Waiting:
+        {
+            auto step = m_steps[currentStep];
+            return step->canAbort();
+        }
+    }
+    return false;
 }
 
 bool LaunchTask::abort()
 {
-	switch(state)
-	{
-		case LaunchTask::Aborted:
-		case LaunchTask::Failed:
-		case LaunchTask::Finished:
-			return true;
-		case LaunchTask::NotStarted:
-		{
-			state = LaunchTask::Aborted;
-			emitFailed("Aborted");
-			return true;
-		}
-		case LaunchTask::Running:
-		case LaunchTask::Waiting:
-		{
-			auto step = m_steps[currentStep];
-			if(!step->canAbort())
-			{
-				return false;
-			}
-			if(step->abort())
-			{
-				state = LaunchTask::Aborted;
-				return true;
-			}
-		}
-		default:
-			break;
-	}
-	return false;
+    switch(state)
+    {
+        case LaunchTask::Aborted:
+        case LaunchTask::Failed:
+        case LaunchTask::Finished:
+            return true;
+        case LaunchTask::NotStarted:
+        {
+            state = LaunchTask::Aborted;
+            emitFailed("Aborted");
+            return true;
+        }
+        case LaunchTask::Running:
+        case LaunchTask::Waiting:
+        {
+            auto step = m_steps[currentStep];
+            if(!step->canAbort())
+            {
+                return false;
+            }
+            if(step->abort())
+            {
+                state = LaunchTask::Aborted;
+                return true;
+            }
+        }
+        default:
+            break;
+    }
+    return false;
 }
 
 shared_qobject_ptr<LogModel> LaunchTask::getLogModel()
 {
-	if(!m_logModel)
-	{
-		m_logModel.reset(new LogModel());
-		m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
-		m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
-		// FIXME: should this really be here?
-		m_logModel->setOverflowMessage(tr("MultiMC stopped watching the game log because the log length surpassed %1 lines.\n"
-			"You may have to fix your mods because the game is still logging to files and"
-			" likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines()));
-	}
-	return m_logModel;
+    if(!m_logModel)
+    {
+        m_logModel.reset(new LogModel());
+        m_logModel->setMaxLines(m_instance->getConsoleMaxLines());
+        m_logModel->setStopOnOverflow(m_instance->shouldStopOnConsoleOverflow());
+        // FIXME: should this really be here?
+        m_logModel->setOverflowMessage(tr("MultiMC stopped watching the game log because the log length surpassed %1 lines.\n"
+            "You may have to fix your mods because the game is still logging to files and"
+            " likely wasting harddrive space at an alarming rate!").arg(m_logModel->getMaxLines()));
+    }
+    return m_logModel;
 }
 
 void LaunchTask::onLogLines(const QStringList &lines, MessageLevel::Enum defaultLevel)
 {
-	for (auto & line: lines)
-	{
-		onLogLine(line, defaultLevel);
-	}
+    for (auto & line: lines)
+    {
+        onLogLine(line, defaultLevel);
+    }
 }
 
 void LaunchTask::onLogLine(QString line, MessageLevel::Enum level)
 {
-	// if the launcher part set a log level, use it
-	auto innerLevel = MessageLevel::fromLine(line);
-	if(innerLevel != MessageLevel::Unknown)
-	{
-		level = innerLevel;
-	}
+    // if the launcher part set a log level, use it
+    auto innerLevel = MessageLevel::fromLine(line);
+    if(innerLevel != MessageLevel::Unknown)
+    {
+        level = innerLevel;
+    }
 
-	// If the level is still undetermined, guess level
-	if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown)
-	{
-		level = m_instance->guessLevel(line, level);
-	}
+    // If the level is still undetermined, guess level
+    if (level == MessageLevel::StdErr || level == MessageLevel::StdOut || level == MessageLevel::Unknown)
+    {
+        level = m_instance->guessLevel(line, level);
+    }
 
-	// censor private user info
-	line = censorPrivateInfo(line);
+    // censor private user info
+    line = censorPrivateInfo(line);
 
-	auto &model = *getLogModel();
-	model.append(level, line);
+    auto &model = *getLogModel();
+    model.append(level, line);
 }
 
 void LaunchTask::emitSucceeded()
 {
-	m_instance->setRunning(false);
-	Task::emitSucceeded();
+    m_instance->setRunning(false);
+    Task::emitSucceeded();
 }
 
 void LaunchTask::emitFailed(QString reason)
 {
-	m_instance->setRunning(false);
-	m_instance->setCrashed(true);
-	Task::emitFailed(reason);
+    m_instance->setRunning(false);
+    m_instance->setCrashed(true);
+    Task::emitFailed(reason);
 }
 
 QString LaunchTask::substituteVariables(const QString &cmd) const
 {
-	QString out = cmd;
-	auto variables = m_instance->getVariables();
-	for (auto it = variables.begin(); it != variables.end(); ++it)
-	{
-		out.replace("$" + it.key(), it.value());
-	}
-	auto env = QProcessEnvironment::systemEnvironment();
-	for (auto var : env.keys())
-	{
-		out.replace("$" + var, env.value(var));
-	}
-	return out;
+    QString out = cmd;
+    auto variables = m_instance->getVariables();
+    for (auto it = variables.begin(); it != variables.end(); ++it)
+    {
+        out.replace("$" + it.key(), it.value());
+    }
+    auto env = QProcessEnvironment::systemEnvironment();
+    for (auto var : env.keys())
+    {
+        out.replace("$" + var, env.value(var));
+    }
+    return out;
 }
 
diff --git a/api/logic/launch/LaunchTask.h b/api/logic/launch/LaunchTask.h
index 746d6d19..f5e226b5 100644
--- a/api/logic/launch/LaunchTask.h
+++ b/api/logic/launch/LaunchTask.h
@@ -6,7 +6,7 @@
  * 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
+ *     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,
@@ -28,98 +28,98 @@
 
 class MULTIMC_LOGIC_EXPORT LaunchTask: public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 protected:
-	explicit LaunchTask(InstancePtr instance);
-	void init();
+    explicit LaunchTask(InstancePtr instance);
+    void init();
 
 public:
-	enum State
-	{
-		NotStarted,
-		Running,
-		Waiting,
-		Failed,
-		Aborted,
-		Finished
-	};
+    enum State
+    {
+        NotStarted,
+        Running,
+        Waiting,
+        Failed,
+        Aborted,
+        Finished
+    };
 
 public: /* methods */
-	static std::shared_ptr<LaunchTask> create(InstancePtr inst);
-	virtual ~LaunchTask() {};
+    static std::shared_ptr<LaunchTask> create(InstancePtr inst);
+    virtual ~LaunchTask() {};
 
-	void appendStep(std::shared_ptr<LaunchStep> step);
-	void prependStep(std::shared_ptr<LaunchStep> step);
-	void setCensorFilter(QMap<QString, QString> filter);
+    void appendStep(std::shared_ptr<LaunchStep> step);
+    void prependStep(std::shared_ptr<LaunchStep> step);
+    void setCensorFilter(QMap<QString, QString> filter);
 
-	InstancePtr instance()
-	{
-		return m_instance;
-	}
+    InstancePtr instance()
+    {
+        return m_instance;
+    }
 
-	void setPid(qint64 pid)
-	{
-		m_pid = pid;
-	}
+    void setPid(qint64 pid)
+    {
+        m_pid = pid;
+    }
 
-	qint64 pid()
-	{
-		return m_pid;
-	}
+    qint64 pid()
+    {
+        return m_pid;
+    }
 
-	/**
-	 * @brief prepare the process for launch (for multi-stage launch)
-	 */
-	virtual void executeTask() override;
+    /**
+     * @brief prepare the process for launch (for multi-stage launch)
+     */
+    virtual void executeTask() override;
 
-	/**
-	 * @brief launch the armed instance
-	 */
-	void proceed();
+    /**
+     * @brief launch the armed instance
+     */
+    void proceed();
 
-	/**
-	 * @brief abort launch
-	 */
-	bool abort() override;
+    /**
+     * @brief abort launch
+     */
+    bool abort() override;
 
-	bool canAbort() const override;
+    bool canAbort() const override;
 
-	shared_qobject_ptr<LogModel> getLogModel();
+    shared_qobject_ptr<LogModel> getLogModel();
 
 public:
-	QString substituteVariables(const QString &cmd) const;
-	QString censorPrivateInfo(QString in);
+    QString substituteVariables(const QString &cmd) const;
+    QString censorPrivateInfo(QString in);
 
 protected: /* methods */
-	virtual void emitFailed(QString reason) override;
-	virtual void emitSucceeded() override;
+    virtual void emitFailed(QString reason) override;
+    virtual void emitSucceeded() override;
 
 signals:
-	/**
-	 * @brief emitted when the launch preparations are done
-	 */
-	void readyForLaunch();
+    /**
+     * @brief emitted when the launch preparations are done
+     */
+    void readyForLaunch();
 
-	void requestProgress(Task *task);
+    void requestProgress(Task *task);
 
-	void requestLogging();
+    void requestLogging();
 
 public slots:
-	void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
-	void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
-	void onReadyForLaunch();
-	void onStepFinished();
-	void onProgressReportingRequested();
+    void onLogLines(const QStringList& lines, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
+    void onLogLine(QString line, MessageLevel::Enum defaultLevel = MessageLevel::MultiMC);
+    void onReadyForLaunch();
+    void onStepFinished();
+    void onProgressReportingRequested();
 
 private: /*methods */
-	void finalizeSteps(bool successful, const QString & error);
+    void finalizeSteps(bool successful, const QString & error);
 
 protected: /* data */
-	InstancePtr m_instance;
-	shared_qobject_ptr<LogModel> m_logModel;
-	QList <std::shared_ptr<LaunchStep>> m_steps;
-	QMap<QString, QString> m_censorFilter;
-	int currentStep = -1;
-	State state = NotStarted;
-	qint64 m_pid = -1;
+    InstancePtr m_instance;
+    shared_qobject_ptr<LogModel> m_logModel;
+    QList <std::shared_ptr<LaunchStep>> m_steps;
+    QMap<QString, QString> m_censorFilter;
+    int currentStep = -1;
+    State state = NotStarted;
+    qint64 m_pid = -1;
 };
diff --git a/api/logic/launch/LogModel.cpp b/api/logic/launch/LogModel.cpp
index 72b076e9..92f9487a 100644
--- a/api/logic/launch/LogModel.cpp
+++ b/api/logic/launch/LogModel.cpp
@@ -2,166 +2,166 @@
 
 LogModel::LogModel(QObject *parent):QAbstractListModel(parent)
 {
-	m_content.resize(m_maxLines);
+    m_content.resize(m_maxLines);
 }
 
 int LogModel::rowCount(const QModelIndex &parent) const
 {
-	if (parent.isValid())
-		return 0;
+    if (parent.isValid())
+        return 0;
 
-	return m_numLines;
+    return m_numLines;
 }
 
 QVariant LogModel::data(const QModelIndex &index, int role) const
 {
-	if (index.row() < 0 || index.row() >= m_numLines)
-		return QVariant();
-
-	auto row = index.row();
-	auto realRow = (row + m_firstLine) % m_maxLines;
-	if (role == Qt::DisplayRole || role == Qt::EditRole)
-	{
-		return m_content[realRow].line;
-	}
-	if(role == LevelRole)
-	{
-		return m_content[realRow].level;
-	}
-
-	return QVariant();
+    if (index.row() < 0 || index.row() >= m_numLines)
+        return QVariant();
+
+    auto row = index.row();
+    auto realRow = (row + m_firstLine) % m_maxLines;
+    if (role == Qt::DisplayRole || role == Qt::EditRole)
+    {
+        return m_content[realRow].line;
+    }
+    if(role == LevelRole)
+    {
+        return m_content[realRow].level;
+    }
+
+    return QVariant();
 }
 
 void LogModel::append(MessageLevel::Enum level, QString line)
 {
-	if(m_suspended)
-	{
-		return;
-	}
-	int lineNum = (m_firstLine + m_numLines) % m_maxLines;
-	// overflow
-	if(m_numLines == m_maxLines)
-	{
-		if(m_stopOnOverflow)
-		{
-			// nothing more to do, the buffer is full
-			return;
-		}
-		beginRemoveRows(QModelIndex(), 0, 0);
-		m_firstLine = (m_firstLine + 1) % m_maxLines;
-		m_numLines --;
-		endRemoveRows();
-	}
-	else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow)
-	{
-		level = MessageLevel::Fatal;
-		line = m_overflowMessage;
-	}
-	beginInsertRows(QModelIndex(), m_numLines, m_numLines);
-	m_numLines ++;
-	m_content[lineNum].level = level;
-	m_content[lineNum].line = line;
-	endInsertRows();
+    if(m_suspended)
+    {
+        return;
+    }
+    int lineNum = (m_firstLine + m_numLines) % m_maxLines;
+    // overflow
+    if(m_numLines == m_maxLines)
+    {
+        if(m_stopOnOverflow)
+        {
+            // nothing more to do, the buffer is full
+            return;
+        }
+        beginRemoveRows(QModelIndex(), 0, 0);
+        m_firstLine = (m_firstLine + 1) % m_maxLines;
+        m_numLines --;
+        endRemoveRows();
+    }
+    else if (m_numLines == m_maxLines - 1 && m_stopOnOverflow)
+    {
+        level = MessageLevel::Fatal;
+        line = m_overflowMessage;
+    }
+    beginInsertRows(QModelIndex(), m_numLines, m_numLines);
+    m_numLines ++;
+    m_content[lineNum].level = level;
+    m_content[lineNum].line = line;
+    endInsertRows();
 }
 
 void LogModel::suspend(bool suspend)
 {
-	m_suspended = suspend;
+    m_suspended = suspend;
 }
 
 bool LogModel::suspended()
 {
-	return m_suspended;
+    return m_suspended;
 }
 
 void LogModel::clear()
 {
-	beginResetModel();
-	m_firstLine = 0;
-	m_numLines = 0;
-	endResetModel();
+    beginResetModel();
+    m_firstLine = 0;
+    m_numLines = 0;
+    endResetModel();
 }
 
 QString LogModel::toPlainText()
 {
-	QString out;
-	out.reserve(m_numLines * 80);
-	for(int i = 0; i < m_numLines; i++)
-	{
-		QString & line = m_content[(m_firstLine + i) % m_maxLines].line;
-		out.append(line + '\n');
-	}
-	out.squeeze();
-	return out;
+    QString out;
+    out.reserve(m_numLines * 80);
+    for(int i = 0; i < m_numLines; i++)
+    {
+        QString & line = m_content[(m_firstLine + i) % m_maxLines].line;
+        out.append(line + '\n');
+    }
+    out.squeeze();
+    return out;
 }
 
 void LogModel::setMaxLines(int maxLines)
 {
-	// no-op
-	if(maxLines == m_maxLines)
-	{
-		return;
-	}
-	// if it all still fits in the buffer, just resize it
-	if(m_firstLine + m_numLines < m_maxLines)
-	{
-		m_maxLines = maxLines;
-		m_content.resize(maxLines);
-		return;
-	}
-	// otherwise, we need to reorganize the data because it crosses the wrap boundary
-	QVector<entry> newContent;
-	newContent.resize(maxLines);
-	if(m_numLines <= maxLines)
-	{
-		// if it all fits in the new buffer, just copy it over
-		for(int i = 0; i < m_numLines; i++)
-		{
-			newContent[i] = m_content[(m_firstLine + i) % m_maxLines];
-		}
-		m_content.swap(newContent);
-	}
-	else
-	{
-		// if it doesn't fit, part of the data needs to be thrown away (the oldest log messages)
-		int lead = m_numLines - maxLines;
-		beginRemoveRows(QModelIndex(), 0, lead - 1);
-		for(int i = 0; i < maxLines; i++)
-		{
-			newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines];
-		}
-		m_numLines = m_maxLines;
-		m_content.swap(newContent);
-		endRemoveRows();
-	}
-	m_firstLine = 0;
-	m_maxLines = maxLines;
+    // no-op
+    if(maxLines == m_maxLines)
+    {
+        return;
+    }
+    // if it all still fits in the buffer, just resize it
+    if(m_firstLine + m_numLines < m_maxLines)
+    {
+        m_maxLines = maxLines;
+        m_content.resize(maxLines);
+        return;
+    }
+    // otherwise, we need to reorganize the data because it crosses the wrap boundary
+    QVector<entry> newContent;
+    newContent.resize(maxLines);
+    if(m_numLines <= maxLines)
+    {
+        // if it all fits in the new buffer, just copy it over
+        for(int i = 0; i < m_numLines; i++)
+        {
+            newContent[i] = m_content[(m_firstLine + i) % m_maxLines];
+        }
+        m_content.swap(newContent);
+    }
+    else
+    {
+        // if it doesn't fit, part of the data needs to be thrown away (the oldest log messages)
+        int lead = m_numLines - maxLines;
+        beginRemoveRows(QModelIndex(), 0, lead - 1);
+        for(int i = 0; i < maxLines; i++)
+        {
+            newContent[i] = m_content[(m_firstLine + lead + i) % m_maxLines];
+        }
+        m_numLines = m_maxLines;
+        m_content.swap(newContent);
+        endRemoveRows();
+    }
+    m_firstLine = 0;
+    m_maxLines = maxLines;
 }
 
 int LogModel::getMaxLines()
 {
-	return m_maxLines;
+    return m_maxLines;
 }
 
 void LogModel::setStopOnOverflow(bool stop)
 {
-	m_stopOnOverflow = stop;
+    m_stopOnOverflow = stop;
 }
 
 void LogModel::setOverflowMessage(const QString& overflowMessage)
 {
-	m_overflowMessage = overflowMessage;
+    m_overflowMessage = overflowMessage;
 }
 
 void LogModel::setLineWrap(bool state)
 {
-	if(m_lineWrap != state)
-	{
-		m_lineWrap = state;
-	}
+    if(m_lineWrap != state)
+    {
+        m_lineWrap = state;
+    }
 }
 
 bool LogModel::wrapLines() const
 {
-	return m_lineWrap;
+    return m_lineWrap;
 }
diff --git a/api/logic/launch/LogModel.h b/api/logic/launch/LogModel.h
index e6deac89..bccceaef 100644
--- a/api/logic/launch/LogModel.h
+++ b/api/logic/launch/LogModel.h
@@ -8,53 +8,53 @@
 
 class MULTIMC_LOGIC_EXPORT LogModel : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit LogModel(QObject *parent = 0);
+    explicit LogModel(QObject *parent = 0);
 
-	int rowCount(const QModelIndex &parent = QModelIndex()) const;
-	QVariant data(const QModelIndex &index, int role) const;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role) const;
 
-	void append(MessageLevel::Enum, QString line);
-	void clear();
+    void append(MessageLevel::Enum, QString line);
+    void clear();
 
-	void suspend(bool suspend);
-	bool suspended();
+    void suspend(bool suspend);
+    bool suspended();
 
-	QString toPlainText();
+    QString toPlainText();
 
-	int getMaxLines();
-	void setMaxLines(int maxLines);
-	void setStopOnOverflow(bool stop);
-	void setOverflowMessage(const QString & overflowMessage);
+    int getMaxLines();
+    void setMaxLines(int maxLines);
+    void setStopOnOverflow(bool stop);
+    void setOverflowMessage(const QString & overflowMessage);
 
-	void setLineWrap(bool state);
-	bool wrapLines() const;
+    void setLineWrap(bool state);
+    bool wrapLines() const;
 
-	enum Roles
-	{
-		LevelRole = Qt::UserRole
-	};
+    enum Roles
+    {
+        LevelRole = Qt::UserRole
+    };
 
 private /* types */:
-	struct entry
-	{
-		MessageLevel::Enum level;
-		QString line;
-	};
+    struct entry
+    {
+        MessageLevel::Enum level;
+        QString line;
+    };
 
 private: /* data */
-	QVector <entry> m_content;
-	int m_maxLines = 1000;
-	// first line in the circular buffer
-	int m_firstLine = 0;
-	// number of lines occupied in the circular buffer
-	int m_numLines = 0;
-	bool m_stopOnOverflow = false;
-	QString m_overflowMessage = "OVERFLOW";
-	bool m_suspended = false;
-	bool m_lineWrap = true;
+    QVector <entry> m_content;
+    int m_maxLines = 1000;
+    // first line in the circular buffer
+    int m_firstLine = 0;
+    // number of lines occupied in the circular buffer
+    int m_numLines = 0;
+    bool m_stopOnOverflow = false;
+    QString m_overflowMessage = "OVERFLOW";
+    bool m_suspended = false;
+    bool m_lineWrap = true;
 
 private:
-	Q_DISABLE_COPY(LogModel)
+    Q_DISABLE_COPY(LogModel)
 };
diff --git a/api/logic/launch/steps/PostLaunchCommand.cpp b/api/logic/launch/steps/PostLaunchCommand.cpp
index bc3b3ffe..3730f71c 100644
--- a/api/logic/launch/steps/PostLaunchCommand.cpp
+++ b/api/logic/launch/steps/PostLaunchCommand.cpp
@@ -18,67 +18,67 @@
 
 PostLaunchCommand::PostLaunchCommand(LaunchTask *parent) : LaunchStep(parent)
 {
-	auto instance = m_parent->instance();
-	m_command = instance->getPostExitCommand();
-	m_process.setProcessEnvironment(instance->createEnvironment());
-	connect(&m_process, &LoggedProcess::log, this, &PostLaunchCommand::logLines);
-	connect(&m_process, &LoggedProcess::stateChanged, this, &PostLaunchCommand::on_state);
+    auto instance = m_parent->instance();
+    m_command = instance->getPostExitCommand();
+    m_process.setProcessEnvironment(instance->createEnvironment());
+    connect(&m_process, &LoggedProcess::log, this, &PostLaunchCommand::logLines);
+    connect(&m_process, &LoggedProcess::stateChanged, this, &PostLaunchCommand::on_state);
 }
 
 void PostLaunchCommand::executeTask()
 {
-	QString postlaunch_cmd = m_parent->substituteVariables(m_command);
-	emit logLine(tr("Running Post-Launch command: %1").arg(postlaunch_cmd), MessageLevel::MultiMC);
-	m_process.start(postlaunch_cmd);
+    QString postlaunch_cmd = m_parent->substituteVariables(m_command);
+    emit logLine(tr("Running Post-Launch command: %1").arg(postlaunch_cmd), MessageLevel::MultiMC);
+    m_process.start(postlaunch_cmd);
 }
 
 void PostLaunchCommand::on_state(LoggedProcess::State state)
 {
-	auto getError = [&]()
-	{
-		return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode());
-	};
-	switch(state)
-	{
-		case LoggedProcess::Aborted:
-		case LoggedProcess::Crashed:
-		case LoggedProcess::FailedToStart:
-		{
-			auto error = getError();
-			emit logLine(error, MessageLevel::Fatal);
-			emitFailed(error);
-			return;
-		}
-		case LoggedProcess::Finished:
-		{
-			if(m_process.exitCode() != 0)
-			{
-				auto error = getError();
-				emit logLine(error, MessageLevel::Fatal);
-				emitFailed(error);
-			}
-			else
-			{
-				emit logLine(tr("Post-Launch command ran successfully.\n\n"), MessageLevel::MultiMC);
-				emitSucceeded();
-			}
-		}
-		default:
-			break;
-	}
+    auto getError = [&]()
+    {
+        return tr("Post-Launch command failed with code %1.\n\n").arg(m_process.exitCode());
+    };
+    switch(state)
+    {
+        case LoggedProcess::Aborted:
+        case LoggedProcess::Crashed:
+        case LoggedProcess::FailedToStart:
+        {
+            auto error = getError();
+            emit logLine(error, MessageLevel::Fatal);
+            emitFailed(error);
+            return;
+        }
+        case LoggedProcess::Finished:
+        {
+            if(m_process.exitCode() != 0)
+            {
+                auto error = getError();
+                emit logLine(error, MessageLevel::Fatal);
+                emitFailed(error);
+            }
+            else
+            {
+                emit logLine(tr("Post-Launch command ran successfully.\n\n"), MessageLevel::MultiMC);
+                emitSucceeded();
+            }
+        }
+        default:
+            break;
+    }
 }
 
 void PostLaunchCommand::setWorkingDirectory(const QString &wd)
 {
-	m_process.setWorkingDirectory(wd);
+    m_process.setWorkingDirectory(wd);
 }
 
 bool PostLaunchCommand::abort()
 {
-	auto state = m_process.state();
-	if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
-	{
-		m_process.kill();
-	}
-	return true;
+    auto state = m_process.state();
+    if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
+    {
+        m_process.kill();
+    }
+    return true;
 }
diff --git a/api/logic/launch/steps/PostLaunchCommand.h b/api/logic/launch/steps/PostLaunchCommand.h
index 88681cbc..efba62d9 100644
--- a/api/logic/launch/steps/PostLaunchCommand.h
+++ b/api/logic/launch/steps/PostLaunchCommand.h
@@ -20,22 +20,22 @@
 
 class PostLaunchCommand: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit PostLaunchCommand(LaunchTask *parent);
-	virtual ~PostLaunchCommand() {};
+    explicit PostLaunchCommand(LaunchTask *parent);
+    virtual ~PostLaunchCommand() {};
 
-	virtual void executeTask();
-	virtual bool abort();
-	virtual bool canAbort() const
-	{
-		return true;
-	}
-	void setWorkingDirectory(const QString &wd);
+    virtual void executeTask();
+    virtual bool abort();
+    virtual bool canAbort() const
+    {
+        return true;
+    }
+    void setWorkingDirectory(const QString &wd);
 private slots:
-	void on_state(LoggedProcess::State state);
+    void on_state(LoggedProcess::State state);
 
 private:
-	LoggedProcess m_process;
-	QString m_command;
+    LoggedProcess m_process;
+    QString m_command;
 };
diff --git a/api/logic/launch/steps/PreLaunchCommand.cpp b/api/logic/launch/steps/PreLaunchCommand.cpp
index 7c37d5cb..c5e1e373 100644
--- a/api/logic/launch/steps/PreLaunchCommand.cpp
+++ b/api/logic/launch/steps/PreLaunchCommand.cpp
@@ -18,68 +18,68 @@
 
 PreLaunchCommand::PreLaunchCommand(LaunchTask *parent) : LaunchStep(parent)
 {
-	auto instance = m_parent->instance();
-	m_command = instance->getPreLaunchCommand();
-	m_process.setProcessEnvironment(instance->createEnvironment());
-	connect(&m_process, &LoggedProcess::log, this, &PreLaunchCommand::logLines);
-	connect(&m_process, &LoggedProcess::stateChanged, this, &PreLaunchCommand::on_state);
+    auto instance = m_parent->instance();
+    m_command = instance->getPreLaunchCommand();
+    m_process.setProcessEnvironment(instance->createEnvironment());
+    connect(&m_process, &LoggedProcess::log, this, &PreLaunchCommand::logLines);
+    connect(&m_process, &LoggedProcess::stateChanged, this, &PreLaunchCommand::on_state);
 }
 
 void PreLaunchCommand::executeTask()
 {
-	//FIXME: where to put this?
-	QString prelaunch_cmd = m_parent->substituteVariables(m_command);
-	emit logLine(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd), MessageLevel::MultiMC);
-	m_process.start(prelaunch_cmd);
+    //FIXME: where to put this?
+    QString prelaunch_cmd = m_parent->substituteVariables(m_command);
+    emit logLine(tr("Running Pre-Launch command: %1").arg(prelaunch_cmd), MessageLevel::MultiMC);
+    m_process.start(prelaunch_cmd);
 }
 
 void PreLaunchCommand::on_state(LoggedProcess::State state)
 {
-	auto getError = [&]()
-	{
-		return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode());
-	};
-	switch(state)
-	{
-		case LoggedProcess::Aborted:
-		case LoggedProcess::Crashed:
-		case LoggedProcess::FailedToStart:
-		{
-			auto error = getError();
-			emit logLine(error, MessageLevel::Fatal);
-			emitFailed(error);
-			return;
-		}
-		case LoggedProcess::Finished:
-		{
-			if(m_process.exitCode() != 0)
-			{
-				auto error = getError();
-				emit logLine(error, MessageLevel::Fatal);
-				emitFailed(error);
-			}
-			else
-			{
-				emit logLine(tr("Pre-Launch command ran successfully.\n\n"), MessageLevel::MultiMC);
-				emitSucceeded();
-			}
-		}
-		default:
-			break;
-	}
+    auto getError = [&]()
+    {
+        return tr("Pre-Launch command failed with code %1.\n\n").arg(m_process.exitCode());
+    };
+    switch(state)
+    {
+        case LoggedProcess::Aborted:
+        case LoggedProcess::Crashed:
+        case LoggedProcess::FailedToStart:
+        {
+            auto error = getError();
+            emit logLine(error, MessageLevel::Fatal);
+            emitFailed(error);
+            return;
+        }
+        case LoggedProcess::Finished:
+        {
+            if(m_process.exitCode() != 0)
+            {
+                auto error = getError();
+                emit logLine(error, MessageLevel::Fatal);
+                emitFailed(error);
+            }
+            else
+            {
+                emit logLine(tr("Pre-Launch command ran successfully.\n\n"), MessageLevel::MultiMC);
+                emitSucceeded();
+            }
+        }
+        default:
+            break;
+    }
 }
 
 void PreLaunchCommand::setWorkingDirectory(const QString &wd)
 {
-	m_process.setWorkingDirectory(wd);
+    m_process.setWorkingDirectory(wd);
 }
 
 bool PreLaunchCommand::abort()
 {
-	auto state = m_process.state();
-	if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
-	{
-		m_process.kill();
-	}
-	return true;
+    auto state = m_process.state();
+    if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
+    {
+        m_process.kill();
+    }
+    return true;
 }
diff --git a/api/logic/launch/steps/PreLaunchCommand.h b/api/logic/launch/steps/PreLaunchCommand.h
index 5c955923..861e5be7 100644
--- a/api/logic/launch/steps/PreLaunchCommand.h
+++ b/api/logic/launch/steps/PreLaunchCommand.h
@@ -20,22 +20,22 @@
 
 class PreLaunchCommand: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit PreLaunchCommand(LaunchTask *parent);
-	virtual ~PreLaunchCommand() {};
+    explicit PreLaunchCommand(LaunchTask *parent);
+    virtual ~PreLaunchCommand() {};
 
-	virtual void executeTask();
-	virtual bool abort();
-	virtual bool canAbort() const
-	{
-		return true;
-	}
-	void setWorkingDirectory(const QString &wd);
+    virtual void executeTask();
+    virtual bool abort();
+    virtual bool canAbort() const
+    {
+        return true;
+    }
+    void setWorkingDirectory(const QString &wd);
 private slots:
-	void on_state(LoggedProcess::State state);
+    void on_state(LoggedProcess::State state);
 
 private:
-	LoggedProcess m_process;
-	QString m_command;
+    LoggedProcess m_process;
+    QString m_command;
 };
diff --git a/api/logic/launch/steps/TextPrint.cpp b/api/logic/launch/steps/TextPrint.cpp
index f307b1fd..0c1f320c 100644
--- a/api/logic/launch/steps/TextPrint.cpp
+++ b/api/logic/launch/steps/TextPrint.cpp
@@ -2,28 +2,28 @@
 
 TextPrint::TextPrint(LaunchTask * parent, const QStringList &lines, MessageLevel::Enum level) : LaunchStep(parent)
 {
-	m_lines = lines;
-	m_level = level;
+    m_lines = lines;
+    m_level = level;
 }
 TextPrint::TextPrint(LaunchTask *parent, const QString &line, MessageLevel::Enum level) : LaunchStep(parent)
 {
-	m_lines.append(line);
-	m_level = level;
+    m_lines.append(line);
+    m_level = level;
 }
 
 void TextPrint::executeTask()
 {
-	emit logLines(m_lines, m_level);
-	emitSucceeded();
+    emit logLines(m_lines, m_level);
+    emitSucceeded();
 }
 
 bool TextPrint::canAbort() const
 {
-	return true;
+    return true;
 }
 
 bool TextPrint::abort()
 {
-	emitFailed("Aborted.");
-	return true;
+    emitFailed("Aborted.");
+    return true;
 }
diff --git a/api/logic/launch/steps/TextPrint.h b/api/logic/launch/steps/TextPrint.h
index 3e3e06cb..48b8cf6f 100644
--- a/api/logic/launch/steps/TextPrint.h
+++ b/api/logic/launch/steps/TextPrint.h
@@ -27,17 +27,17 @@
 
 class MULTIMC_LOGIC_EXPORT TextPrint: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit TextPrint(LaunchTask *parent, const QStringList &lines, MessageLevel::Enum level);
-	explicit TextPrint(LaunchTask *parent, const QString &line, MessageLevel::Enum level);
-	virtual ~TextPrint(){};
+    explicit TextPrint(LaunchTask *parent, const QStringList &lines, MessageLevel::Enum level);
+    explicit TextPrint(LaunchTask *parent, const QString &line, MessageLevel::Enum level);
+    virtual ~TextPrint(){};
 
-	virtual void executeTask();
-	virtual bool canAbort() const;
-	virtual bool abort();
+    virtual void executeTask();
+    virtual bool canAbort() const;
+    virtual bool abort();
 
 private:
-	QStringList m_lines;
-	MessageLevel::Enum m_level;
+    QStringList m_lines;
+    MessageLevel::Enum m_level;
 };
diff --git a/api/logic/launch/steps/Update.cpp b/api/logic/launch/steps/Update.cpp
index d057febb..65f24391 100644
--- a/api/logic/launch/steps/Update.cpp
+++ b/api/logic/launch/steps/Update.cpp
@@ -18,63 +18,63 @@
 
 void Update::executeTask()
 {
-	if(m_aborted)
-	{
-		emitFailed(tr("Task aborted."));
-		return;
-	}
-	m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode));
-	if(m_updateTask)
-	{
-		connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished()));
-		connect(m_updateTask.get(), &Task::progress, this, &Task::setProgress);
-		connect(m_updateTask.get(), &Task::status, this, &Task::setStatus);
-		emit progressReportingRequest();
-		return;
-	}
-	emitSucceeded();
+    if(m_aborted)
+    {
+        emitFailed(tr("Task aborted."));
+        return;
+    }
+    m_updateTask.reset(m_parent->instance()->createUpdateTask(m_mode));
+    if(m_updateTask)
+    {
+        connect(m_updateTask.get(), SIGNAL(finished()), this, SLOT(updateFinished()));
+        connect(m_updateTask.get(), &Task::progress, this, &Task::setProgress);
+        connect(m_updateTask.get(), &Task::status, this, &Task::setStatus);
+        emit progressReportingRequest();
+        return;
+    }
+    emitSucceeded();
 }
 
 void Update::proceed()
 {
-	m_updateTask->start();
+    m_updateTask->start();
 }
 
 void Update::updateFinished()
 {
-	if(m_updateTask->wasSuccessful())
-	{
-		m_updateTask.reset();
-		emitSucceeded();
-	}
-	else
-	{
-		QString reason = tr("Instance update failed because: %1.\n\n").arg(m_updateTask->failReason());
-		m_updateTask.reset();
-		emit logLine(reason, MessageLevel::Fatal);
-		emitFailed(reason);
-	}
+    if(m_updateTask->wasSuccessful())
+    {
+        m_updateTask.reset();
+        emitSucceeded();
+    }
+    else
+    {
+        QString reason = tr("Instance update failed because: %1.\n\n").arg(m_updateTask->failReason());
+        m_updateTask.reset();
+        emit logLine(reason, MessageLevel::Fatal);
+        emitFailed(reason);
+    }
 }
 
 bool Update::canAbort() const
 {
-	if(m_updateTask)
-	{
-		return m_updateTask->canAbort();
-	}
-	return true;
+    if(m_updateTask)
+    {
+        return m_updateTask->canAbort();
+    }
+    return true;
 }
 
 
 bool Update::abort()
 {
-	m_aborted = true;
-	if(m_updateTask)
-	{
-		if(m_updateTask->canAbort())
-		{
-			return m_updateTask->abort();
-		}
-	}
-	return true;
+    m_aborted = true;
+    if(m_updateTask)
+    {
+        if(m_updateTask->canAbort())
+        {
+            return m_updateTask->abort();
+        }
+    }
+    return true;
 }
diff --git a/api/logic/launch/steps/Update.h b/api/logic/launch/steps/Update.h
index 7a14011a..baa0b80e 100644
--- a/api/logic/launch/steps/Update.h
+++ b/api/logic/launch/steps/Update.h
@@ -24,22 +24,22 @@
 // FIXME: stupid. should be defined by the instance type? or even completely abstracted away...
 class Update: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit Update(LaunchTask *parent, Net::Mode mode):LaunchStep(parent), m_mode(mode) {};
-	virtual ~Update() {};
+    explicit Update(LaunchTask *parent, Net::Mode mode):LaunchStep(parent), m_mode(mode) {};
+    virtual ~Update() {};
 
-	void executeTask() override;
-	bool canAbort() const override;
-	void proceed() override;
+    void executeTask() override;
+    bool canAbort() const override;
+    void proceed() override;
 public slots:
-	bool abort() override;
+    bool abort() override;
 
 private slots:
-	void updateFinished();
+    void updateFinished();
 
 private:
-	shared_qobject_ptr<Task> m_updateTask;
-	bool m_aborted = false;
-	Net::Mode m_mode = Net::Mode::Offline;
+    shared_qobject_ptr<Task> m_updateTask;
+    bool m_aborted = false;
+    Net::Mode m_mode = Net::Mode::Offline;
 };
diff --git a/api/logic/meta/BaseEntity.cpp b/api/logic/meta/BaseEntity.cpp
index 342f676c..9ea712fa 100644
--- a/api/logic/meta/BaseEntity.cpp
+++ b/api/logic/meta/BaseEntity.cpp
@@ -27,45 +27,45 @@
 class ParsingValidator : public Net::Validator
 {
 public: /* con/des */
-	ParsingValidator(Meta::BaseEntity *entity) : m_entity(entity)
-	{
-	};
-	virtual ~ParsingValidator()
-	{
-	};
+    ParsingValidator(Meta::BaseEntity *entity) : m_entity(entity)
+    {
+    };
+    virtual ~ParsingValidator()
+    {
+    };
 
 public: /* methods */
-	bool init(QNetworkRequest &) override
-	{
-		return true;
-	}
-	bool write(QByteArray & data) override
-	{
-		this->data.append(data);
-		return true;
-	}
-	bool abort() override
-	{
-		return true;
-	}
-	bool validate(QNetworkReply &) override
-	{
-		auto fname = m_entity->localFilename();
-		try
-		{
-			m_entity->parse(Json::requireObject(Json::requireDocument(data, fname), fname));
-			return true;
-		}
-		catch (const Exception &e)
-		{
-			qWarning() << "Unable to parse response:" << e.cause();
-			return false;
-		}
-	}
+    bool init(QNetworkRequest &) override
+    {
+        return true;
+    }
+    bool write(QByteArray & data) override
+    {
+        this->data.append(data);
+        return true;
+    }
+    bool abort() override
+    {
+        return true;
+    }
+    bool validate(QNetworkReply &) override
+    {
+        auto fname = m_entity->localFilename();
+        try
+        {
+            m_entity->parse(Json::requireObject(Json::requireDocument(data, fname), fname));
+            return true;
+        }
+        catch (const Exception &e)
+        {
+            qWarning() << "Unable to parse response:" << e.cause();
+            return false;
+        }
+    }
 
 private: /* data */
-	QByteArray data;
-	Meta::BaseEntity *m_entity;
+    QByteArray data;
+    Meta::BaseEntity *m_entity;
 };
 
 Meta::BaseEntity::~BaseEntity()
@@ -74,89 +74,89 @@ Meta::BaseEntity::~BaseEntity()
 
 QUrl Meta::BaseEntity::url() const
 {
-	return QUrl("https://v1.meta.multimc.org").resolved(localFilename());
+    return QUrl("https://v1.meta.multimc.org").resolved(localFilename());
 }
 
 bool Meta::BaseEntity::loadLocalFile()
 {
-	const QString fname = QDir("meta").absoluteFilePath(localFilename());
-	if (!QFile::exists(fname))
-	{
-		return false;
-	}
-	// TODO: check if the file has the expected checksum
-	try
-	{
-		parse(Json::requireObject(Json::requireDocument(fname, fname), fname));
-		return true;
-	}
-	catch (const Exception &e)
-	{
-		qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause());
-		// just make sure it's gone and we never consider it again.
-		QFile::remove(fname);
-		return false;
-	}
+    const QString fname = QDir("meta").absoluteFilePath(localFilename());
+    if (!QFile::exists(fname))
+    {
+        return false;
+    }
+    // TODO: check if the file has the expected checksum
+    try
+    {
+        parse(Json::requireObject(Json::requireDocument(fname, fname), fname));
+        return true;
+    }
+    catch (const Exception &e)
+    {
+        qDebug() << QString("Unable to parse file %1: %2").arg(fname, e.cause());
+        // just make sure it's gone and we never consider it again.
+        QFile::remove(fname);
+        return false;
+    }
 }
 
 void Meta::BaseEntity::load(Net::Mode loadType)
 {
-	// load local file if nothing is loaded yet
-	if(!isLoaded())
-	{
-		if(loadLocalFile())
-		{
-			m_loadStatus = LoadStatus::Local;
-		}
-	}
-	// if we need remote update, run the update task
-	if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate())
-	{
-		return;
-	}
-	NetJob *job = new NetJob(QObject::tr("Download of meta file %1").arg(localFilename()));
-	auto url = this->url();
-	auto entry = ENV.metacache()->resolveEntry("meta", localFilename());
-	entry->setStale(true);
-	auto dl = Net::Download::makeCached(url, entry);
-	/*
-	 * The validator parses the file and loads it into the object.
-	 * If that fails, the file is not written to storage.
-	 */
-	dl->addValidator(new ParsingValidator(this));
-	job->addNetAction(dl);
-	m_updateStatus = UpdateStatus::InProgress;
-	m_updateTask.reset(job);
-	QObject::connect(job, &NetJob::succeeded, [&]()
-	{
-		m_loadStatus = LoadStatus::Remote;
-		m_updateStatus = UpdateStatus::Succeeded;
-		m_updateTask.reset();
-	});
-	QObject::connect(job, &NetJob::failed, [&]()
-	{
-		m_updateStatus = UpdateStatus::Failed;
-		m_updateTask.reset();
-	});
-	m_updateTask->start();
+    // load local file if nothing is loaded yet
+    if(!isLoaded())
+    {
+        if(loadLocalFile())
+        {
+            m_loadStatus = LoadStatus::Local;
+        }
+    }
+    // if we need remote update, run the update task
+    if(loadType == Net::Mode::Offline || !shouldStartRemoteUpdate())
+    {
+        return;
+    }
+    NetJob *job = new NetJob(QObject::tr("Download of meta file %1").arg(localFilename()));
+    auto url = this->url();
+    auto entry = ENV.metacache()->resolveEntry("meta", localFilename());
+    entry->setStale(true);
+    auto dl = Net::Download::makeCached(url, entry);
+    /*
+     * The validator parses the file and loads it into the object.
+     * If that fails, the file is not written to storage.
+     */
+    dl->addValidator(new ParsingValidator(this));
+    job->addNetAction(dl);
+    m_updateStatus = UpdateStatus::InProgress;
+    m_updateTask.reset(job);
+    QObject::connect(job, &NetJob::succeeded, [&]()
+    {
+        m_loadStatus = LoadStatus::Remote;
+        m_updateStatus = UpdateStatus::Succeeded;
+        m_updateTask.reset();
+    });
+    QObject::connect(job, &NetJob::failed, [&]()
+    {
+        m_updateStatus = UpdateStatus::Failed;
+        m_updateTask.reset();
+    });
+    m_updateTask->start();
 }
 
 bool Meta::BaseEntity::isLoaded() const
 {
-	return m_loadStatus > LoadStatus::NotLoaded;
+    return m_loadStatus > LoadStatus::NotLoaded;
 }
 
 bool Meta::BaseEntity::shouldStartRemoteUpdate() const
 {
-	// TODO: version-locks and offline mode?
-	return m_updateStatus != UpdateStatus::InProgress;
+    // TODO: version-locks and offline mode?
+    return m_updateStatus != UpdateStatus::InProgress;
 }
 
 shared_qobject_ptr<Task> Meta::BaseEntity::getCurrentTask()
 {
-	if(m_updateStatus == UpdateStatus::InProgress)
-	{
-		return m_updateTask;
-	}
-	return nullptr;
+    if(m_updateStatus == UpdateStatus::InProgress)
+    {
+        return m_updateTask;
+    }
+    return nullptr;
 }
diff --git a/api/logic/meta/BaseEntity.h b/api/logic/meta/BaseEntity.h
index 418c979f..19dd2c18 100644
--- a/api/logic/meta/BaseEntity.h
+++ b/api/logic/meta/BaseEntity.h
@@ -28,41 +28,41 @@ namespace Meta
 class MULTIMC_LOGIC_EXPORT BaseEntity
 {
 public: /* types */
-	using Ptr = std::shared_ptr<BaseEntity>;
-	enum class LoadStatus
-	{
-		NotLoaded,
-		Local,
-		Remote
-	};
-	enum class UpdateStatus
-	{
-		NotDone,
-		InProgress,
-		Failed,
-		Succeeded
-	};
+    using Ptr = std::shared_ptr<BaseEntity>;
+    enum class LoadStatus
+    {
+        NotLoaded,
+        Local,
+        Remote
+    };
+    enum class UpdateStatus
+    {
+        NotDone,
+        InProgress,
+        Failed,
+        Succeeded
+    };
 
 public:
-	virtual ~BaseEntity();
+    virtual ~BaseEntity();
 
-	virtual void parse(const QJsonObject &obj) = 0;
+    virtual void parse(const QJsonObject &obj) = 0;
 
-	virtual QString localFilename() const = 0;
-	virtual QUrl url() const;
+    virtual QString localFilename() const = 0;
+    virtual QUrl url() const;
 
-	bool isLoaded() const;
-	bool shouldStartRemoteUpdate() const;
+    bool isLoaded() const;
+    bool shouldStartRemoteUpdate() const;
 
-	void load(Net::Mode loadType);
-	shared_qobject_ptr<Task> getCurrentTask();
+    void load(Net::Mode loadType);
+    shared_qobject_ptr<Task> getCurrentTask();
 
 protected: /* methods */
-	bool loadLocalFile();
+    bool loadLocalFile();
 
 private:
-	LoadStatus m_loadStatus = LoadStatus::NotLoaded;
-	UpdateStatus m_updateStatus = UpdateStatus::NotDone;
-	shared_qobject_ptr<Task> m_updateTask;
+    LoadStatus m_loadStatus = LoadStatus::NotLoaded;
+    UpdateStatus m_updateStatus = UpdateStatus::NotDone;
+    shared_qobject_ptr<Task> m_updateTask;
 };
 }
diff --git a/api/logic/meta/Index.cpp b/api/logic/meta/Index.cpp
index 6e1e34cd..4dbc0a86 100644
--- a/api/logic/meta/Index.cpp
+++ b/api/logic/meta/Index.cpp
@@ -21,128 +21,128 @@
 namespace Meta
 {
 Index::Index(QObject *parent)
-	: QAbstractListModel(parent)
+    : QAbstractListModel(parent)
 {
 }
 Index::Index(const QVector<VersionListPtr> &lists, QObject *parent)
-	: QAbstractListModel(parent), m_lists(lists)
+    : QAbstractListModel(parent), m_lists(lists)
 {
-	for (int i = 0; i < m_lists.size(); ++i)
-	{
-		m_uids.insert(m_lists.at(i)->uid(), m_lists.at(i));
-		connectVersionList(i, m_lists.at(i));
-	}
+    for (int i = 0; i < m_lists.size(); ++i)
+    {
+        m_uids.insert(m_lists.at(i)->uid(), m_lists.at(i));
+        connectVersionList(i, m_lists.at(i));
+    }
 }
 
 QVariant Index::data(const QModelIndex &index, int role) const
 {
-	if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size())
-	{
-		return QVariant();
-	}
+    if (index.parent().isValid() || index.row() < 0 || index.row() >= m_lists.size())
+    {
+        return QVariant();
+    }
 
-	VersionListPtr list = m_lists.at(index.row());
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (index.column())
-		{
-		case 0: return list->humanReadable();
-		default: break;
-		}
-	case UidRole: return list->uid();
-	case NameRole: return list->name();
-	case ListPtrRole: return QVariant::fromValue(list);
-	}
-	return QVariant();
+    VersionListPtr list = m_lists.at(index.row());
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (index.column())
+        {
+        case 0: return list->humanReadable();
+        default: break;
+        }
+    case UidRole: return list->uid();
+    case NameRole: return list->name();
+    case ListPtrRole: return QVariant::fromValue(list);
+    }
+    return QVariant();
 }
 int Index::rowCount(const QModelIndex &parent) const
 {
-	return m_lists.size();
+    return m_lists.size();
 }
 int Index::columnCount(const QModelIndex &parent) const
 {
-	return 1;
+    return 1;
 }
 QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
-	{
-		return tr("Name");
-	}
-	else
-	{
-		return QVariant();
-	}
+    if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
+    {
+        return tr("Name");
+    }
+    else
+    {
+        return QVariant();
+    }
 }
 
 bool Index::hasUid(const QString &uid) const
 {
-	return m_uids.contains(uid);
+    return m_uids.contains(uid);
 }
 
 VersionListPtr Index::get(const QString &uid)
 {
-	VersionListPtr out = m_uids.value(uid, nullptr);
-	if(!out)
-	{
-		out = std::make_shared<VersionList>(uid);
-		m_uids[uid] = out;
-	}
-	return out;
+    VersionListPtr out = m_uids.value(uid, nullptr);
+    if(!out)
+    {
+        out = std::make_shared<VersionList>(uid);
+        m_uids[uid] = out;
+    }
+    return out;
 }
 
 VersionPtr Index::get(const QString &uid, const QString &version)
 {
-	auto list = get(uid);
-	return list->getVersion(version);
+    auto list = get(uid);
+    return list->getVersion(version);
 }
 
 void Index::parse(const QJsonObject& obj)
 {
-	parseIndex(obj, this);
+    parseIndex(obj, this);
 }
 
 void Index::merge(const std::shared_ptr<Index> &other)
 {
-	const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
-	// initial load, no need to merge
-	if (m_lists.isEmpty())
-	{
-		beginResetModel();
-		m_lists = lists;
-		for (int i = 0; i < lists.size(); ++i)
-		{
-			m_uids.insert(lists.at(i)->uid(), lists.at(i));
-			connectVersionList(i, lists.at(i));
-		}
-		endResetModel();
-	}
-	else
-	{
-		for (const VersionListPtr &list : lists)
-		{
-			if (m_uids.contains(list->uid()))
-			{
-				m_uids[list->uid()]->mergeFromIndex(list);
-			}
-			else
-			{
-				beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size());
-				connectVersionList(m_lists.size(), list);
-				m_lists.append(list);
-				m_uids.insert(list->uid(), list);
-				endInsertRows();
-			}
-		}
-	}
+    const QVector<VersionListPtr> lists = std::dynamic_pointer_cast<Index>(other)->m_lists;
+    // initial load, no need to merge
+    if (m_lists.isEmpty())
+    {
+        beginResetModel();
+        m_lists = lists;
+        for (int i = 0; i < lists.size(); ++i)
+        {
+            m_uids.insert(lists.at(i)->uid(), lists.at(i));
+            connectVersionList(i, lists.at(i));
+        }
+        endResetModel();
+    }
+    else
+    {
+        for (const VersionListPtr &list : lists)
+        {
+            if (m_uids.contains(list->uid()))
+            {
+                m_uids[list->uid()]->mergeFromIndex(list);
+            }
+            else
+            {
+                beginInsertRows(QModelIndex(), m_lists.size(), m_lists.size());
+                connectVersionList(m_lists.size(), list);
+                m_lists.append(list);
+                m_uids.insert(list->uid(), list);
+                endInsertRows();
+            }
+        }
+    }
 }
 
 void Index::connectVersionList(const int row, const VersionListPtr &list)
 {
-	connect(list.get(), &VersionList::nameChanged, this, [this, row]()
-	{
-		emit dataChanged(index(row), index(row), QVector<int>() << Qt::DisplayRole);
-	});
+    connect(list.get(), &VersionList::nameChanged, this, [this, row]()
+    {
+        emit dataChanged(index(row), index(row), QVector<int>() << Qt::DisplayRole);
+    });
 }
 }
diff --git a/api/logic/meta/Index.h b/api/logic/meta/Index.h
index 0ec43f96..c81b4c54 100644
--- a/api/logic/meta/Index.h
+++ b/api/logic/meta/Index.h
@@ -31,41 +31,41 @@ using VersionPtr = std::shared_ptr<class Version>;
 
 class MULTIMC_LOGIC_EXPORT Index : public QAbstractListModel, public BaseEntity
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit Index(QObject *parent = nullptr);
-	explicit Index(const QVector<VersionListPtr> &lists, QObject *parent = nullptr);
+    explicit Index(QObject *parent = nullptr);
+    explicit Index(const QVector<VersionListPtr> &lists, QObject *parent = nullptr);
 
-	enum
-	{
-		UidRole = Qt::UserRole,
-		NameRole,
-		ListPtrRole
-	};
+    enum
+    {
+        UidRole = Qt::UserRole,
+        NameRole,
+        ListPtrRole
+    };
 
-	QVariant data(const QModelIndex &index, int role) const override;
-	int rowCount(const QModelIndex &parent) const override;
-	int columnCount(const QModelIndex &parent) const override;
-	QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+    QVariant data(const QModelIndex &index, int role) const override;
+    int rowCount(const QModelIndex &parent) const override;
+    int columnCount(const QModelIndex &parent) const override;
+    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
 
-	QString localFilename() const override { return "index.json"; }
+    QString localFilename() const override { return "index.json"; }
 
-	// queries
-	VersionListPtr get(const QString &uid);
-	VersionPtr get(const QString &uid, const QString &version);
-	bool hasUid(const QString &uid) const;
+    // queries
+    VersionListPtr get(const QString &uid);
+    VersionPtr get(const QString &uid, const QString &version);
+    bool hasUid(const QString &uid) const;
 
-	QVector<VersionListPtr> lists() const { return m_lists; }
+    QVector<VersionListPtr> lists() const { return m_lists; }
 
 public: // for usage by parsers only
-	void merge(const std::shared_ptr<Index> &other);
-	void parse(const QJsonObject &obj) override;
+    void merge(const std::shared_ptr<Index> &other);
+    void parse(const QJsonObject &obj) override;
 
 private:
-	QVector<VersionListPtr> m_lists;
-	QHash<QString, VersionListPtr> m_uids;
+    QVector<VersionListPtr> m_lists;
+    QHash<QString, VersionListPtr> m_uids;
 
-	void connectVersionList(const int row, const VersionListPtr &list);
+    void connectVersionList(const int row, const VersionListPtr &list);
 };
 }
 
diff --git a/api/logic/meta/Index_test.cpp b/api/logic/meta/Index_test.cpp
index 1c5face2..b0892070 100644
--- a/api/logic/meta/Index_test.cpp
+++ b/api/logic/meta/Index_test.cpp
@@ -7,36 +7,36 @@
 
 class IndexTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void test_isProvidedByEnv()
-	{
-		QVERIFY(ENV.metadataIndex());
-		QCOMPARE(ENV.metadataIndex(), ENV.metadataIndex());
-	}
+    void test_isProvidedByEnv()
+    {
+        QVERIFY(ENV.metadataIndex());
+        QCOMPARE(ENV.metadataIndex(), ENV.metadataIndex());
+    }
 
-	void test_hasUid_and_getList()
-	{
-		Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")});
-		QVERIFY(windex.hasUid("list1"));
-		QVERIFY(!windex.hasUid("asdf"));
-		QVERIFY(windex.get("list2") != nullptr);
-		QCOMPARE(windex.get("list2")->uid(), QString("list2"));
-		QVERIFY(windex.get("adsf") != nullptr);
-	}
+    void test_hasUid_and_getList()
+    {
+        Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")});
+        QVERIFY(windex.hasUid("list1"));
+        QVERIFY(!windex.hasUid("asdf"));
+        QVERIFY(windex.get("list2") != nullptr);
+        QCOMPARE(windex.get("list2")->uid(), QString("list2"));
+        QVERIFY(windex.get("adsf") != nullptr);
+    }
 
-	void test_merge()
-	{
-		Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")});
-		QCOMPARE(windex.lists().size(), 3);
-		windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")})));
-		QCOMPARE(windex.lists().size(), 3);
-		windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list4"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list5")})));
-		QCOMPARE(windex.lists().size(), 5);
-		windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list6")})));
-		QCOMPARE(windex.lists().size(), 6);
-	}
+    void test_merge()
+    {
+        Meta::Index windex({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")});
+        QCOMPARE(windex.lists().size(), 3);
+        windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list1"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list3")})));
+        QCOMPARE(windex.lists().size(), 3);
+        windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list4"), std::make_shared<Meta::VersionList>("list2"), std::make_shared<Meta::VersionList>("list5")})));
+        QCOMPARE(windex.lists().size(), 5);
+        windex.merge(std::shared_ptr<Meta::Index>(new Meta::Index({std::make_shared<Meta::VersionList>("list6")})));
+        QCOMPARE(windex.lists().size(), 6);
+    }
 };
 
 QTEST_GUILESS_MAIN(IndexTest)
diff --git a/api/logic/meta/JsonFormat.cpp b/api/logic/meta/JsonFormat.cpp
index 2183e579..12da266f 100644
--- a/api/logic/meta/JsonFormat.cpp
+++ b/api/logic/meta/JsonFormat.cpp
@@ -30,141 +30,141 @@ namespace Meta
 
 MetadataVersion currentFormatVersion()
 {
-	return MetadataVersion::InitialRelease;
+    return MetadataVersion::InitialRelease;
 }
 
 // Index
 static std::shared_ptr<Index> parseIndexInternal(const QJsonObject &obj)
 {
-	const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages");
-	QVector<VersionListPtr> lists;
-	lists.reserve(objects.size());
-	std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj)
-	{
-		VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid"));
-		list->setName(ensureString(obj, "name", QString()));
-		return list;
-	});
-	return std::make_shared<Index>(lists);
+    const QVector<QJsonObject> objects = requireIsArrayOf<QJsonObject>(obj, "packages");
+    QVector<VersionListPtr> lists;
+    lists.reserve(objects.size());
+    std::transform(objects.begin(), objects.end(), std::back_inserter(lists), [](const QJsonObject &obj)
+    {
+        VersionListPtr list = std::make_shared<VersionList>(requireString(obj, "uid"));
+        list->setName(ensureString(obj, "name", QString()));
+        return list;
+    });
+    return std::make_shared<Index>(lists);
 }
 
 // Version
 static VersionPtr parseCommonVersion(const QString &uid, const QJsonObject &obj)
 {
-	VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version"));
-	version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
-	version->setType(ensureString(obj, "type", QString()));
-	version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
-	version->setVolatile(ensureBoolean(obj, QString("volatile"), false));
-	RequireSet requires, conflicts;
-	parseRequires(obj, &requires, "requires");
-	parseRequires(obj, &conflicts, "conflicts");
-	version->setRequires(requires, conflicts);
-	return version;
+    VersionPtr version = std::make_shared<Version>(uid, requireString(obj, "version"));
+    version->setTime(QDateTime::fromString(requireString(obj, "releaseTime"), Qt::ISODate).toMSecsSinceEpoch() / 1000);
+    version->setType(ensureString(obj, "type", QString()));
+    version->setRecommended(ensureBoolean(obj, QString("recommended"), false));
+    version->setVolatile(ensureBoolean(obj, QString("volatile"), false));
+    RequireSet requires, conflicts;
+    parseRequires(obj, &requires, "requires");
+    parseRequires(obj, &conflicts, "conflicts");
+    version->setRequires(requires, conflicts);
+    return version;
 }
 
 static std::shared_ptr<Version> parseVersionInternal(const QJsonObject &obj)
 {
-	VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj);
+    VersionPtr version = parseCommonVersion(requireString(obj, "uid"), obj);
 
-	version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj),
-										   QString("%1/%2.json").arg(version->uid(), version->version()),
-										   obj.contains("order")));
-	return version;
+    version->setData(OneSixVersionFormat::versionFileFromJson(QJsonDocument(obj),
+                                           QString("%1/%2.json").arg(version->uid(), version->version()),
+                                           obj.contains("order")));
+    return version;
 }
 
 // Version list / package
 static std::shared_ptr<VersionList> parseVersionListInternal(const QJsonObject &obj)
 {
-	const QString uid = requireString(obj, "uid");
-
-	const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions");
-	QVector<VersionPtr> versions;
-	versions.reserve(versionsRaw.size());
-	std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj)
-	{
-		auto version = parseCommonVersion(uid, vObj);
-		version->setProvidesRecommendations();
-		return version;
-	});
-
-	VersionListPtr list = std::make_shared<VersionList>(uid);
-	list->setName(ensureString(obj, "name", QString()));
-	list->setVersions(versions);
-	return list;
+    const QString uid = requireString(obj, "uid");
+
+    const QVector<QJsonObject> versionsRaw = requireIsArrayOf<QJsonObject>(obj, "versions");
+    QVector<VersionPtr> versions;
+    versions.reserve(versionsRaw.size());
+    std::transform(versionsRaw.begin(), versionsRaw.end(), std::back_inserter(versions), [uid](const QJsonObject &vObj)
+    {
+        auto version = parseCommonVersion(uid, vObj);
+        version->setProvidesRecommendations();
+        return version;
+    });
+
+    VersionListPtr list = std::make_shared<VersionList>(uid);
+    list->setName(ensureString(obj, "name", QString()));
+    list->setVersions(versions);
+    return list;
 }
 
 
 MetadataVersion parseFormatVersion(const QJsonObject &obj, bool required)
 {
-	if (!obj.contains("formatVersion"))
-	{
-		if(required)
-		{
-			return MetadataVersion::Invalid;
-		}
-		return MetadataVersion::InitialRelease;
-	}
-	if (!obj.value("formatVersion").isDouble())
-	{
-		return MetadataVersion::Invalid;
-	}
-	switch(obj.value("formatVersion").toInt())
-	{
-		case 0:
-		case 1:
-			return MetadataVersion::InitialRelease;
-		default:
-			return MetadataVersion::Invalid;
-	}
+    if (!obj.contains("formatVersion"))
+    {
+        if(required)
+        {
+            return MetadataVersion::Invalid;
+        }
+        return MetadataVersion::InitialRelease;
+    }
+    if (!obj.value("formatVersion").isDouble())
+    {
+        return MetadataVersion::Invalid;
+    }
+    switch(obj.value("formatVersion").toInt())
+    {
+        case 0:
+        case 1:
+            return MetadataVersion::InitialRelease;
+        default:
+            return MetadataVersion::Invalid;
+    }
 }
 
 void serializeFormatVersion(QJsonObject& obj, Meta::MetadataVersion version)
 {
-	if(version == MetadataVersion::Invalid)
-	{
-		return;
-	}
-	obj.insert("formatVersion", int(version));
+    if(version == MetadataVersion::Invalid)
+    {
+        return;
+    }
+    obj.insert("formatVersion", int(version));
 }
 
 void parseIndex(const QJsonObject &obj, Index *ptr)
 {
-	const MetadataVersion version = parseFormatVersion(obj);
-	switch (version)
-	{
-	case MetadataVersion::InitialRelease:
-		ptr->merge(parseIndexInternal(obj));
-		break;
-	case MetadataVersion::Invalid:
-		throw ParseException(QObject::tr("Unknown format version!"));
-	}
+    const MetadataVersion version = parseFormatVersion(obj);
+    switch (version)
+    {
+    case MetadataVersion::InitialRelease:
+        ptr->merge(parseIndexInternal(obj));
+        break;
+    case MetadataVersion::Invalid:
+        throw ParseException(QObject::tr("Unknown format version!"));
+    }
 }
 
 void parseVersionList(const QJsonObject &obj, VersionList *ptr)
 {
-	const MetadataVersion version = parseFormatVersion(obj);
-	switch (version)
-	{
-	case MetadataVersion::InitialRelease:
-		ptr->merge(parseVersionListInternal(obj));
-		break;
-	case MetadataVersion::Invalid:
-		throw ParseException(QObject::tr("Unknown format version!"));
-	}
+    const MetadataVersion version = parseFormatVersion(obj);
+    switch (version)
+    {
+    case MetadataVersion::InitialRelease:
+        ptr->merge(parseVersionListInternal(obj));
+        break;
+    case MetadataVersion::Invalid:
+        throw ParseException(QObject::tr("Unknown format version!"));
+    }
 }
 
 void parseVersion(const QJsonObject &obj, Version *ptr)
 {
-	const MetadataVersion version = parseFormatVersion(obj);
-	switch (version)
-	{
-	case MetadataVersion::InitialRelease:
-		ptr->merge(parseVersionInternal(obj));
-		break;
-	case MetadataVersion::Invalid:
-		throw ParseException(QObject::tr("Unknown format version!"));
-	}
+    const MetadataVersion version = parseFormatVersion(obj);
+    switch (version)
+    {
+    case MetadataVersion::InitialRelease:
+        ptr->merge(parseVersionInternal(obj));
+        break;
+    case MetadataVersion::Invalid:
+        throw ParseException(QObject::tr("Unknown format version!"));
+    }
 }
 
 /*
@@ -174,44 +174,44 @@ void parseVersion(const QJsonObject &obj, Version *ptr)
 */
 void parseRequires(const QJsonObject& obj, RequireSet* ptr, const char * keyName)
 {
-	if(obj.contains(keyName))
-	{
-		QSet<QString> requires;
-		auto reqArray = requireArray(obj, keyName);
-		auto iter = reqArray.begin();
-		while(iter != reqArray.end())
-		{
-			auto reqObject = requireObject(*iter);
-			auto uid = requireString(reqObject, "uid");
-			auto equals = ensureString(reqObject, "equals", QString());
-			auto suggests = ensureString(reqObject, "suggests", QString());
-			ptr->insert({uid, equals, suggests});
-			iter++;
-		}
-	}
+    if(obj.contains(keyName))
+    {
+        QSet<QString> requires;
+        auto reqArray = requireArray(obj, keyName);
+        auto iter = reqArray.begin();
+        while(iter != reqArray.end())
+        {
+            auto reqObject = requireObject(*iter);
+            auto uid = requireString(reqObject, "uid");
+            auto equals = ensureString(reqObject, "equals", QString());
+            auto suggests = ensureString(reqObject, "suggests", QString());
+            ptr->insert({uid, equals, suggests});
+            iter++;
+        }
+    }
 }
 void serializeRequires(QJsonObject& obj, RequireSet* ptr, const char * keyName)
 {
-	if(!ptr || ptr->empty())
-	{
-		return;
-	}
-	QJsonArray arrOut;
-	for(auto &iter: *ptr)
-	{
-		QJsonObject reqOut;
-		reqOut.insert("uid", iter.uid);
-		if(!iter.equalsVersion.isEmpty())
-		{
-			reqOut.insert("equals", iter.equalsVersion);
-		}
-		if(!iter.suggests.isEmpty())
-		{
-			reqOut.insert("suggests", iter.suggests);
-		}
-		arrOut.append(reqOut);
-	}
-	obj.insert(keyName, arrOut);
+    if(!ptr || ptr->empty())
+    {
+        return;
+    }
+    QJsonArray arrOut;
+    for(auto &iter: *ptr)
+    {
+        QJsonObject reqOut;
+        reqOut.insert("uid", iter.uid);
+        if(!iter.equalsVersion.isEmpty())
+        {
+            reqOut.insert("equals", iter.equalsVersion);
+        }
+        if(!iter.suggests.isEmpty())
+        {
+            reqOut.insert("suggests", iter.suggests);
+        }
+        arrOut.append(reqOut);
+    }
+    obj.insert(keyName, arrOut);
 }
 
 }
diff --git a/api/logic/meta/JsonFormat.h b/api/logic/meta/JsonFormat.h
index cc2c8f83..62351ad6 100644
--- a/api/logic/meta/JsonFormat.h
+++ b/api/logic/meta/JsonFormat.h
@@ -30,39 +30,39 @@ class VersionList;
 
 enum class MetadataVersion
 {
-	Invalid = -1,
-	InitialRelease = 1
+    Invalid = -1,
+    InitialRelease = 1
 };
 
 class ParseException : public Exception
 {
 public:
-	using Exception::Exception;
+    using Exception::Exception;
 };
 struct Require
 {
-	bool operator==(const Require & rhs) const
-	{
-		return uid == rhs.uid;
-	}
-	bool operator<(const Require & rhs) const
-	{
-		return uid < rhs.uid;
-	}
-	bool deepEquals(const Require & rhs) const
-	{
-		return uid == rhs.uid
-			&& equalsVersion == rhs.equalsVersion
-			&& suggests == rhs.suggests;
-	}
-	QString uid;
-	QString equalsVersion;
-	QString suggests;
+    bool operator==(const Require & rhs) const
+    {
+        return uid == rhs.uid;
+    }
+    bool operator<(const Require & rhs) const
+    {
+        return uid < rhs.uid;
+    }
+    bool deepEquals(const Require & rhs) const
+    {
+        return uid == rhs.uid
+            && equalsVersion == rhs.equalsVersion
+            && suggests == rhs.suggests;
+    }
+    QString uid;
+    QString equalsVersion;
+    QString suggests;
 };
 
 inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW
 {
-	return qHash(key.uid, seed);
+    return qHash(key.uid, seed);
 }
 
 using RequireSet = std::set<Require>;
diff --git a/api/logic/meta/Version.cpp b/api/logic/meta/Version.cpp
index edc70f33..05a76b41 100644
--- a/api/logic/meta/Version.cpp
+++ b/api/logic/meta/Version.cpp
@@ -21,7 +21,7 @@
 #include "minecraft/ComponentList.h"
 
 Meta::Version::Version(const QString &uid, const QString &version)
-	: BaseVersion(), m_uid(uid), m_version(version)
+    : BaseVersion(), m_uid(uid), m_version(version)
 {
 }
 
@@ -31,110 +31,110 @@ Meta::Version::~Version()
 
 QString Meta::Version::descriptor()
 {
-	return m_version;
+    return m_version;
 }
 QString Meta::Version::name()
 {
-	if(m_data)
-		return m_data->name;
-	return m_uid;
+    if(m_data)
+        return m_data->name;
+    return m_uid;
 }
 QString Meta::Version::typeString() const
 {
-	return m_type;
+    return m_type;
 }
 
 QDateTime Meta::Version::time() const
 {
-	return QDateTime::fromMSecsSinceEpoch(m_time * 1000, Qt::UTC);
+    return QDateTime::fromMSecsSinceEpoch(m_time * 1000, Qt::UTC);
 }
 
 void Meta::Version::parse(const QJsonObject& obj)
 {
-	parseVersion(obj, this);
+    parseVersion(obj, this);
 }
 
 void Meta::Version::mergeFromList(const Meta::VersionPtr& other)
 {
-	if(other->m_providesRecommendations)
-	{
-		if(m_recommended != other->m_recommended)
-		{
-			setRecommended(other->m_recommended);
-		}
-	}
-	if (m_type != other->m_type)
-	{
-		setType(other->m_type);
-	}
-	if (m_time != other->m_time)
-	{
-		setTime(other->m_time);
-	}
-	if (m_requires != other->m_requires)
-	{
-		m_requires = other->m_requires;
-	}
-	if (m_conflicts != other->m_conflicts)
-	{
-		m_conflicts = other->m_conflicts;
-	}
-	if(m_volatile != other->m_volatile)
-	{
-		setVolatile(other->m_volatile);
-	}
+    if(other->m_providesRecommendations)
+    {
+        if(m_recommended != other->m_recommended)
+        {
+            setRecommended(other->m_recommended);
+        }
+    }
+    if (m_type != other->m_type)
+    {
+        setType(other->m_type);
+    }
+    if (m_time != other->m_time)
+    {
+        setTime(other->m_time);
+    }
+    if (m_requires != other->m_requires)
+    {
+        m_requires = other->m_requires;
+    }
+    if (m_conflicts != other->m_conflicts)
+    {
+        m_conflicts = other->m_conflicts;
+    }
+    if(m_volatile != other->m_volatile)
+    {
+        setVolatile(other->m_volatile);
+    }
 }
 
 void Meta::Version::merge(const VersionPtr &other)
 {
-	mergeFromList(other);
-	if(other->m_data)
-	{
-		setData(other->m_data);
-	}
+    mergeFromList(other);
+    if(other->m_data)
+    {
+        setData(other->m_data);
+    }
 }
 
 QString Meta::Version::localFilename() const
 {
-	return m_uid + '/' + m_version + ".json";
+    return m_uid + '/' + m_version + ".json";
 }
 
 void Meta::Version::setType(const QString &type)
 {
-	m_type = type;
-	emit typeChanged();
+    m_type = type;
+    emit typeChanged();
 }
 
 void Meta::Version::setTime(const qint64 time)
 {
-	m_time = time;
-	emit timeChanged();
+    m_time = time;
+    emit timeChanged();
 }
 
 void Meta::Version::setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts)
 {
-	m_requires = requires;
-	m_conflicts = conflicts;
-	emit requiresChanged();
+    m_requires = requires;
+    m_conflicts = conflicts;
+    emit requiresChanged();
 }
 
 void Meta::Version::setVolatile(bool volatile_)
 {
-	m_volatile = volatile_;
+    m_volatile = volatile_;
 }
 
 
 void Meta::Version::setData(const VersionFilePtr &data)
 {
-	m_data = data;
+    m_data = data;
 }
 
 void Meta::Version::setProvidesRecommendations()
 {
-	m_providesRecommendations = true;
+    m_providesRecommendations = true;
 }
 
 void Meta::Version::setRecommended(bool recommended)
 {
-	m_recommended = recommended;
+    m_recommended = recommended;
 }
diff --git a/api/logic/meta/Version.h b/api/logic/meta/Version.h
index 33bd5b35..6506d486 100644
--- a/api/logic/meta/Version.h
+++ b/api/logic/meta/Version.h
@@ -36,82 +36,82 @@ using VersionPtr = std::shared_ptr<class Version>;
 
 class MULTIMC_LOGIC_EXPORT Version : public QObject, public BaseVersion, public BaseEntity
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public: /* con/des */
-	explicit Version(const QString &uid, const QString &version);
-	virtual ~Version();
-
-	QString descriptor() override;
-	QString name() override;
-	QString typeString() const override;
-
-	QString uid() const
-	{
-		return m_uid;
-	}
-	QString version() const
-	{
-		return m_version;
-	}
-	QString type() const
-	{
-		return m_type;
-	}
-	QDateTime time() const;
-	qint64 rawTime() const
-	{
-		return m_time;
-	}
-	const Meta::RequireSet &requires() const
-	{
-		return m_requires;
-	}
-	VersionFilePtr data() const
-	{
-		return m_data;
-	}
-	bool isRecommended() const
-	{
-		return m_recommended;
-	}
-	bool isLoaded() const
-	{
-		return m_data != nullptr;
-	}
-
-	void merge(const VersionPtr &other);
-	void mergeFromList(const VersionPtr &other);
-	void parse(const QJsonObject &obj) override;
-
-	QString localFilename() const override;
+    explicit Version(const QString &uid, const QString &version);
+    virtual ~Version();
+
+    QString descriptor() override;
+    QString name() override;
+    QString typeString() const override;
+
+    QString uid() const
+    {
+        return m_uid;
+    }
+    QString version() const
+    {
+        return m_version;
+    }
+    QString type() const
+    {
+        return m_type;
+    }
+    QDateTime time() const;
+    qint64 rawTime() const
+    {
+        return m_time;
+    }
+    const Meta::RequireSet &requires() const
+    {
+        return m_requires;
+    }
+    VersionFilePtr data() const
+    {
+        return m_data;
+    }
+    bool isRecommended() const
+    {
+        return m_recommended;
+    }
+    bool isLoaded() const
+    {
+        return m_data != nullptr;
+    }
+
+    void merge(const VersionPtr &other);
+    void mergeFromList(const VersionPtr &other);
+    void parse(const QJsonObject &obj) override;
+
+    QString localFilename() const override;
 
 public: // for usage by format parsers only
-	void setType(const QString &type);
-	void setTime(const qint64 time);
-	void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts);
-	void setVolatile(bool volatile_);
-	void setRecommended(bool recommended);
-	void setProvidesRecommendations();
-	void setData(const VersionFilePtr &data);
+    void setType(const QString &type);
+    void setTime(const qint64 time);
+    void setRequires(const Meta::RequireSet &requires, const Meta::RequireSet &conflicts);
+    void setVolatile(bool volatile_);
+    void setRecommended(bool recommended);
+    void setProvidesRecommendations();
+    void setData(const VersionFilePtr &data);
 
 signals:
-	void typeChanged();
-	void timeChanged();
-	void requiresChanged();
+    void typeChanged();
+    void timeChanged();
+    void requiresChanged();
 
 private:
-	bool m_providesRecommendations = false;
-	bool m_recommended = false;
-	QString m_name;
-	QString m_uid;
-	QString m_version;
-	QString m_type;
-	qint64 m_time = 0;
-	Meta::RequireSet m_requires;
-	Meta::RequireSet m_conflicts;
-	bool m_volatile = false;
-	VersionFilePtr m_data;
+    bool m_providesRecommendations = false;
+    bool m_recommended = false;
+    QString m_name;
+    QString m_uid;
+    QString m_version;
+    QString m_type;
+    qint64 m_time = 0;
+    Meta::RequireSet m_requires;
+    Meta::RequireSet m_conflicts;
+    bool m_volatile = false;
+    VersionFilePtr m_data;
 };
 }
 
diff --git a/api/logic/meta/VersionList.cpp b/api/logic/meta/VersionList.cpp
index 9ae02301..526fe165 100644
--- a/api/logic/meta/VersionList.cpp
+++ b/api/logic/meta/VersionList.cpp
@@ -24,222 +24,222 @@
 namespace Meta
 {
 VersionList::VersionList(const QString &uid, QObject *parent)
-	: BaseVersionList(parent), m_uid(uid)
+    : BaseVersionList(parent), m_uid(uid)
 {
-	setObjectName("Version list: " + uid);
+    setObjectName("Version list: " + uid);
 }
 
 shared_qobject_ptr<Task> VersionList::getLoadTask()
 {
-	load(Net::Mode::Online);
-	return getCurrentTask();
+    load(Net::Mode::Online);
+    return getCurrentTask();
 }
 
 bool VersionList::isLoaded()
 {
-	return BaseEntity::isLoaded();
+    return BaseEntity::isLoaded();
 }
 
 const BaseVersionPtr VersionList::at(int i) const
 {
-	return m_versions.at(i);
+    return m_versions.at(i);
 }
 int VersionList::count() const
 {
-	return m_versions.size();
+    return m_versions.size();
 }
 
 void VersionList::sortVersions()
 {
-	beginResetModel();
-	std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
-	{
-		return *a.get() < *b.get();
-	});
-	endResetModel();
+    beginResetModel();
+    std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
+    {
+        return *a.get() < *b.get();
+    });
+    endResetModel();
 }
 
 QVariant VersionList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid())
-	{
-		return QVariant();
-	}
-
-	VersionPtr version = m_versions.at(index.row());
-
-	switch (role)
-	{
-	case VersionPointerRole: return QVariant::fromValue(std::dynamic_pointer_cast<BaseVersion>(version));
-	case VersionRole:
-	case VersionIdRole:
-		return version->version();
-	case ParentVersionRole:
-	{
-		// FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'.
-		auto & reqs = version->requires();
-		auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req)
-		{
-			return req.uid == "net.minecraft";
-		});
-		if (iter != reqs.end())
-		{
-			return (*iter).equalsVersion;
-		}
-		return QVariant();
-	}
-	case TypeRole: return version->type();
-
-	case UidRole: return version->uid();
-	case TimeRole: return version->time();
-	case RequiresRole: return QVariant::fromValue(version->requires());
-	case SortRole: return version->rawTime();
-	case VersionPtrRole: return QVariant::fromValue(version);
-	case RecommendedRole: return version->isRecommended();
-	// FIXME: this should be determined in whatever view/proxy is used...
-	// case LatestRole: return version == getLatestStable();
-	default: return QVariant();
-	}
+    if (!index.isValid() || index.row() < 0 || index.row() >= m_versions.size() || index.parent().isValid())
+    {
+        return QVariant();
+    }
+
+    VersionPtr version = m_versions.at(index.row());
+
+    switch (role)
+    {
+    case VersionPointerRole: return QVariant::fromValue(std::dynamic_pointer_cast<BaseVersion>(version));
+    case VersionRole:
+    case VersionIdRole:
+        return version->version();
+    case ParentVersionRole:
+    {
+        // FIXME: HACK: this should be generic and be replaced by something else. Anything that is a hard 'equals' dep is a 'parent uid'.
+        auto & reqs = version->requires();
+        auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Require & req)
+        {
+            return req.uid == "net.minecraft";
+        });
+        if (iter != reqs.end())
+        {
+            return (*iter).equalsVersion;
+        }
+        return QVariant();
+    }
+    case TypeRole: return version->type();
+
+    case UidRole: return version->uid();
+    case TimeRole: return version->time();
+    case RequiresRole: return QVariant::fromValue(version->requires());
+    case SortRole: return version->rawTime();
+    case VersionPtrRole: return QVariant::fromValue(version);
+    case RecommendedRole: return version->isRecommended();
+    // FIXME: this should be determined in whatever view/proxy is used...
+    // case LatestRole: return version == getLatestStable();
+    default: return QVariant();
+    }
 }
 
 BaseVersionList::RoleList VersionList::providesRoles() const
 {
-	return {VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole,
-				TypeRole, UidRole, TimeRole, RequiresRole, SortRole,
-				RecommendedRole, LatestRole, VersionPtrRole};
+    return {VersionPointerRole, VersionRole, VersionIdRole, ParentVersionRole,
+                TypeRole, UidRole, TimeRole, RequiresRole, SortRole,
+                RecommendedRole, LatestRole, VersionPtrRole};
 }
 
 QHash<int, QByteArray> VersionList::roleNames() const
 {
-	QHash<int, QByteArray> roles = BaseVersionList::roleNames();
-	roles.insert(UidRole, "uid");
-	roles.insert(TimeRole, "time");
-	roles.insert(SortRole, "sort");
-	roles.insert(RequiresRole, "requires");
-	return roles;
+    QHash<int, QByteArray> roles = BaseVersionList::roleNames();
+    roles.insert(UidRole, "uid");
+    roles.insert(TimeRole, "time");
+    roles.insert(SortRole, "sort");
+    roles.insert(RequiresRole, "requires");
+    return roles;
 }
 
 QString VersionList::localFilename() const
 {
-	return m_uid + "/index.json";
+    return m_uid + "/index.json";
 }
 
 QString VersionList::humanReadable() const
 {
-	return m_name.isEmpty() ? m_uid : m_name;
+    return m_name.isEmpty() ? m_uid : m_name;
 }
 
 VersionPtr VersionList::getVersion(const QString &version)
 {
-	VersionPtr out = m_lookup.value(version, nullptr);
-	if(!out)
-	{
-		out = std::make_shared<Version>(m_uid, version);
-		m_lookup[version] = out;
-	}
-	return out;
+    VersionPtr out = m_lookup.value(version, nullptr);
+    if(!out)
+    {
+        out = std::make_shared<Version>(m_uid, version);
+        m_lookup[version] = out;
+    }
+    return out;
 }
 
 void VersionList::setName(const QString &name)
 {
-	m_name = name;
-	emit nameChanged(name);
+    m_name = name;
+    emit nameChanged(name);
 }
 
 void VersionList::setVersions(const QVector<VersionPtr> &versions)
 {
-	beginResetModel();
-	m_versions = versions;
-	std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
-	{
-		return a->rawTime() > b->rawTime();
-	});
-	for (int i = 0; i < m_versions.size(); ++i)
-	{
-		m_lookup.insert(m_versions.at(i)->version(), m_versions.at(i));
-		setupAddedVersion(i, m_versions.at(i));
-	}
+    beginResetModel();
+    m_versions = versions;
+    std::sort(m_versions.begin(), m_versions.end(), [](const VersionPtr &a, const VersionPtr &b)
+    {
+        return a->rawTime() > b->rawTime();
+    });
+    for (int i = 0; i < m_versions.size(); ++i)
+    {
+        m_lookup.insert(m_versions.at(i)->version(), m_versions.at(i));
+        setupAddedVersion(i, m_versions.at(i));
+    }
 
-	// FIXME: this is dumb, we have 'recommended' as part of the metadata already...
-	auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; });
-	m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
-	endResetModel();
+    // FIXME: this is dumb, we have 'recommended' as part of the metadata already...
+    auto recommendedIt = std::find_if(m_versions.constBegin(), m_versions.constEnd(), [](const VersionPtr &ptr) { return ptr->type() == "release"; });
+    m_recommended = recommendedIt == m_versions.constEnd() ? nullptr : *recommendedIt;
+    endResetModel();
 }
 
 void VersionList::parse(const QJsonObject& obj)
 {
-	parseVersionList(obj, this);
+    parseVersionList(obj, this);
 }
 
 // FIXME: this is dumb, we have 'recommended' as part of the metadata already...
 static const Meta::VersionPtr &getBetterVersion(const Meta::VersionPtr &a, const Meta::VersionPtr &b)
 {
-	if(!a)
-		return b;
-	if(!b)
-		return a;
-	if(a->type() == b->type())
-	{
-		// newer of same type wins
-		return (a->rawTime() > b->rawTime() ? a : b);
-	}
-	// 'release' type wins
-	return (a->type() == "release" ? a : b);
+    if(!a)
+        return b;
+    if(!b)
+        return a;
+    if(a->type() == b->type())
+    {
+        // newer of same type wins
+        return (a->rawTime() > b->rawTime() ? a : b);
+    }
+    // 'release' type wins
+    return (a->type() == "release" ? a : b);
 }
 
 void VersionList::mergeFromIndex(const VersionListPtr &other)
 {
-	if (m_name != other->m_name)
-	{
-		setName(other->m_name);
-	}
+    if (m_name != other->m_name)
+    {
+        setName(other->m_name);
+    }
 }
 
 void VersionList::merge(const VersionListPtr &other)
 {
-	if (m_name != other->m_name)
-	{
-		setName(other->m_name);
-	}
-
-	// TODO: do not reset the whole model. maybe?
-	beginResetModel();
-	m_versions.clear();
-	if(other->m_versions.isEmpty())
-	{
-		qWarning() << "Empty list loaded ...";
-	}
-	for (const VersionPtr &version : other->m_versions)
-	{
-		// we already have the version. merge the contents
-		if (m_lookup.contains(version->version()))
-		{
-			m_lookup.value(version->version())->mergeFromList(version);
-		}
-		else
-		{
-			m_lookup.insert(version->uid(), version);
-		}
-		// connect it.
-		setupAddedVersion(m_versions.size(), version);
-		m_versions.append(version);
-		m_recommended = getBetterVersion(m_recommended, version);
-	}
-	endResetModel();
+    if (m_name != other->m_name)
+    {
+        setName(other->m_name);
+    }
+
+    // TODO: do not reset the whole model. maybe?
+    beginResetModel();
+    m_versions.clear();
+    if(other->m_versions.isEmpty())
+    {
+        qWarning() << "Empty list loaded ...";
+    }
+    for (const VersionPtr &version : other->m_versions)
+    {
+        // we already have the version. merge the contents
+        if (m_lookup.contains(version->version()))
+        {
+            m_lookup.value(version->version())->mergeFromList(version);
+        }
+        else
+        {
+            m_lookup.insert(version->uid(), version);
+        }
+        // connect it.
+        setupAddedVersion(m_versions.size(), version);
+        m_versions.append(version);
+        m_recommended = getBetterVersion(m_recommended, version);
+    }
+    endResetModel();
 }
 
 void VersionList::setupAddedVersion(const int row, const VersionPtr &version)
 {
-	// FIXME: do not disconnect from everythin, disconnect only the lambdas here
-	version->disconnect();
-	connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << RequiresRole); });
-	connect(version.get(), &Version::timeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TimeRole << SortRole); });
-	connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); });
+    // FIXME: do not disconnect from everythin, disconnect only the lambdas here
+    version->disconnect();
+    connect(version.get(), &Version::requiresChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << RequiresRole); });
+    connect(version.get(), &Version::timeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TimeRole << SortRole); });
+    connect(version.get(), &Version::typeChanged, this, [this, row]() { emit dataChanged(index(row), index(row), QVector<int>() << TypeRole); });
 }
 
 BaseVersionPtr VersionList::getRecommended() const
 {
-	return m_recommended;
+    return m_recommended;
 }
 
 }
diff --git a/api/logic/meta/VersionList.h b/api/logic/meta/VersionList.h
index ad8733cc..0be074dd 100644
--- a/api/logic/meta/VersionList.h
+++ b/api/logic/meta/VersionList.h
@@ -27,75 +27,75 @@ using VersionListPtr = std::shared_ptr<class VersionList>;
 
 class MULTIMC_LOGIC_EXPORT VersionList : public BaseVersionList, public BaseEntity
 {
-	Q_OBJECT
-	Q_PROPERTY(QString uid READ uid CONSTANT)
-	Q_PROPERTY(QString name READ name NOTIFY nameChanged)
+    Q_OBJECT
+    Q_PROPERTY(QString uid READ uid CONSTANT)
+    Q_PROPERTY(QString name READ name NOTIFY nameChanged)
 public:
-	explicit VersionList(const QString &uid, QObject *parent = nullptr);
-
-	enum Roles
-	{
-		UidRole = Qt::UserRole + 100,
-		TimeRole,
-		RequiresRole,
-		VersionPtrRole
-	};
-
-	shared_qobject_ptr<Task> getLoadTask() override;
-	bool isLoaded() override;
-	const BaseVersionPtr at(int i) const override;
-	int count() const override;
-	void sortVersions() override;
-
-	BaseVersionPtr getRecommended() const override;
-
-	QVariant data(const QModelIndex &index, int role) const override;
-	RoleList providesRoles() const override;
-	QHash<int, QByteArray> roleNames() const override;
-
-	QString localFilename() const override;
-
-	QString uid() const
-	{
-		return m_uid;
-	}
-	QString name() const
-	{
-		return m_name;
-	}
-	QString humanReadable() const;
-
-	VersionPtr getVersion(const QString &version);
-
-	QVector<VersionPtr> versions() const
-	{
-		return m_versions;
-	}
+    explicit VersionList(const QString &uid, QObject *parent = nullptr);
+
+    enum Roles
+    {
+        UidRole = Qt::UserRole + 100,
+        TimeRole,
+        RequiresRole,
+        VersionPtrRole
+    };
+
+    shared_qobject_ptr<Task> getLoadTask() override;
+    bool isLoaded() override;
+    const BaseVersionPtr at(int i) const override;
+    int count() const override;
+    void sortVersions() override;
+
+    BaseVersionPtr getRecommended() const override;
+
+    QVariant data(const QModelIndex &index, int role) const override;
+    RoleList providesRoles() const override;
+    QHash<int, QByteArray> roleNames() const override;
+
+    QString localFilename() const override;
+
+    QString uid() const
+    {
+        return m_uid;
+    }
+    QString name() const
+    {
+        return m_name;
+    }
+    QString humanReadable() const;
+
+    VersionPtr getVersion(const QString &version);
+
+    QVector<VersionPtr> versions() const
+    {
+        return m_versions;
+    }
 
 public: // for usage only by parsers
-	void setName(const QString &name);
-	void setVersions(const QVector<VersionPtr> &versions);
-	void merge(const VersionListPtr &other);
-	void mergeFromIndex(const VersionListPtr &other);
-	void parse(const QJsonObject &obj) override;
+    void setName(const QString &name);
+    void setVersions(const QVector<VersionPtr> &versions);
+    void merge(const VersionListPtr &other);
+    void mergeFromIndex(const VersionListPtr &other);
+    void parse(const QJsonObject &obj) override;
 
 signals:
-	void nameChanged(const QString &name);
+    void nameChanged(const QString &name);
 
 protected slots:
-	void updateListData(QList<BaseVersionPtr>) override
-	{
-	}
+    void updateListData(QList<BaseVersionPtr>) override
+    {
+    }
 
 private:
-	QVector<VersionPtr> m_versions;
-	QHash<QString, VersionPtr> m_lookup;
-	QString m_uid;
-	QString m_name;
+    QVector<VersionPtr> m_versions;
+    QHash<QString, VersionPtr> m_lookup;
+    QString m_uid;
+    QString m_name;
 
-	VersionPtr m_recommended;
+    VersionPtr m_recommended;
 
-	void setupAddedVersion(const int row, const VersionPtr &version);
+    void setupAddedVersion(const int row, const VersionPtr &version);
 };
 }
 Q_DECLARE_METATYPE(Meta::VersionListPtr)
diff --git a/api/logic/minecraft/AssetsUtils.cpp b/api/logic/minecraft/AssetsUtils.cpp
index 5b25bede..a2274492 100644
--- a/api/logic/minecraft/AssetsUtils.cpp
+++ b/api/logic/minecraft/AssetsUtils.cpp
@@ -38,200 +38,200 @@ namespace AssetsUtils
  */
 bool loadAssetsIndexJson(QString assetsId, QString path, AssetsIndex *index)
 {
-	/*
-	{
-	  "objects": {
-		"icons/icon_16x16.png": {
-		  "hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a",
-		  "size": 3665
-		},
-		...
-		}
-	  }
-	}
-	*/
-
-	QFile file(path);
-
-	// Try to open the file and fail if we can't.
-	// TODO: We should probably report this error to the user.
-	if (!file.open(QIODevice::ReadOnly))
-	{
-		qCritical() << "Failed to read assets index file" << path;
-		return false;
-	}
-	index->id = assetsId;
-
-	// Read the file and close it.
-	QByteArray jsonData = file.readAll();
-	file.close();
-
-	QJsonParseError parseError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
-
-	// Fail if the JSON is invalid.
-	if (parseError.error != QJsonParseError::NoError)
-	{
-		qCritical() << "Failed to parse assets index file:" << parseError.errorString()
-					 << "at offset " << QString::number(parseError.offset);
-		return false;
-	}
-
-	// Make sure the root is an object.
-	if (!jsonDoc.isObject())
-	{
-		qCritical() << "Invalid assets index JSON: Root should be an array.";
-		return false;
-	}
-
-	QJsonObject root = jsonDoc.object();
-
-	QJsonValue isVirtual = root.value("virtual");
-	if (!isVirtual.isUndefined())
-	{
-		index->isVirtual = isVirtual.toBool(false);
-	}
-
-	QJsonValue objects = root.value("objects");
-	QVariantMap map = objects.toVariant().toMap();
-
-	for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
-	{
-		// qDebug() << iter.key();
-
-		QVariant variant = iter.value();
-		QVariantMap nested_objects = variant.toMap();
-
-		AssetObject object;
-
-		for (QVariantMap::const_iterator nested_iter = nested_objects.begin();
-			 nested_iter != nested_objects.end(); ++nested_iter)
-		{
-			// qDebug() << nested_iter.key() << nested_iter.value().toString();
-			QString key = nested_iter.key();
-			QVariant value = nested_iter.value();
-
-			if (key == "hash")
-			{
-				object.hash = value.toString();
-			}
-			else if (key == "size")
-			{
-				object.size = value.toDouble();
-			}
-		}
-
-		index->objects.insert(iter.key(), object);
-	}
-
-	return true;
+    /*
+    {
+      "objects": {
+        "icons/icon_16x16.png": {
+          "hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a",
+          "size": 3665
+        },
+        ...
+        }
+      }
+    }
+    */
+
+    QFile file(path);
+
+    // Try to open the file and fail if we can't.
+    // TODO: We should probably report this error to the user.
+    if (!file.open(QIODevice::ReadOnly))
+    {
+        qCritical() << "Failed to read assets index file" << path;
+        return false;
+    }
+    index->id = assetsId;
+
+    // Read the file and close it.
+    QByteArray jsonData = file.readAll();
+    file.close();
+
+    QJsonParseError parseError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+
+    // Fail if the JSON is invalid.
+    if (parseError.error != QJsonParseError::NoError)
+    {
+        qCritical() << "Failed to parse assets index file:" << parseError.errorString()
+                     << "at offset " << QString::number(parseError.offset);
+        return false;
+    }
+
+    // Make sure the root is an object.
+    if (!jsonDoc.isObject())
+    {
+        qCritical() << "Invalid assets index JSON: Root should be an array.";
+        return false;
+    }
+
+    QJsonObject root = jsonDoc.object();
+
+    QJsonValue isVirtual = root.value("virtual");
+    if (!isVirtual.isUndefined())
+    {
+        index->isVirtual = isVirtual.toBool(false);
+    }
+
+    QJsonValue objects = root.value("objects");
+    QVariantMap map = objects.toVariant().toMap();
+
+    for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
+    {
+        // qDebug() << iter.key();
+
+        QVariant variant = iter.value();
+        QVariantMap nested_objects = variant.toMap();
+
+        AssetObject object;
+
+        for (QVariantMap::const_iterator nested_iter = nested_objects.begin();
+             nested_iter != nested_objects.end(); ++nested_iter)
+        {
+            // qDebug() << nested_iter.key() << nested_iter.value().toString();
+            QString key = nested_iter.key();
+            QVariant value = nested_iter.value();
+
+            if (key == "hash")
+            {
+                object.hash = value.toString();
+            }
+            else if (key == "size")
+            {
+                object.size = value.toDouble();
+            }
+        }
+
+        index->objects.insert(iter.key(), object);
+    }
+
+    return true;
 }
 
 QDir reconstructAssets(QString assetsId)
 {
-	QDir assetsDir = QDir("assets/");
-	QDir indexDir = QDir(FS::PathCombine(assetsDir.path(), "indexes"));
-	QDir objectDir = QDir(FS::PathCombine(assetsDir.path(), "objects"));
-	QDir virtualDir = QDir(FS::PathCombine(assetsDir.path(), "virtual"));
-
-	QString indexPath = FS::PathCombine(indexDir.path(), assetsId + ".json");
-	QFile indexFile(indexPath);
-	QDir virtualRoot(FS::PathCombine(virtualDir.path(), assetsId));
-
-	if (!indexFile.exists())
-	{
-		qCritical() << "No assets index file" << indexPath << "; can't reconstruct assets";
-		return virtualRoot;
-	}
-
-	qDebug() << "reconstructAssets" << assetsDir.path() << indexDir.path()
-				 << objectDir.path() << virtualDir.path() << virtualRoot.path();
-
-	AssetsIndex index;
-	bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, &index);
-
-	if (loadAssetsIndex && index.isVirtual)
-	{
-		qDebug() << "Reconstructing virtual assets folder at" << virtualRoot.path();
-
-		for (QString map : index.objects.keys())
-		{
-			AssetObject asset_object = index.objects.value(map);
-			QString target_path = FS::PathCombine(virtualRoot.path(), map);
-			QFile target(target_path);
-
-			QString tlk = asset_object.hash.left(2);
-
-			QString original_path = FS::PathCombine(objectDir.path(), tlk, asset_object.hash);
-			QFile original(original_path);
-			if (!original.exists())
-				continue;
-			if (!target.exists())
-			{
-				QFileInfo info(target_path);
-				QDir target_dir = info.dir();
-				// qDebug() << target_dir;
-				if (!target_dir.exists())
-					QDir("").mkpath(target_dir.path());
-
-				bool couldCopy = original.copy(target_path);
-				qDebug() << " Copying" << original_path << "to" << target_path
-							 << QString::number(couldCopy); // << original.errorString();
-			}
-		}
-
-		// TODO: Write last used time to virtualRoot/.lastused
-	}
-
-	return virtualRoot;
+    QDir assetsDir = QDir("assets/");
+    QDir indexDir = QDir(FS::PathCombine(assetsDir.path(), "indexes"));
+    QDir objectDir = QDir(FS::PathCombine(assetsDir.path(), "objects"));
+    QDir virtualDir = QDir(FS::PathCombine(assetsDir.path(), "virtual"));
+
+    QString indexPath = FS::PathCombine(indexDir.path(), assetsId + ".json");
+    QFile indexFile(indexPath);
+    QDir virtualRoot(FS::PathCombine(virtualDir.path(), assetsId));
+
+    if (!indexFile.exists())
+    {
+        qCritical() << "No assets index file" << indexPath << "; can't reconstruct assets";
+        return virtualRoot;
+    }
+
+    qDebug() << "reconstructAssets" << assetsDir.path() << indexDir.path()
+                 << objectDir.path() << virtualDir.path() << virtualRoot.path();
+
+    AssetsIndex index;
+    bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(assetsId, indexPath, &index);
+
+    if (loadAssetsIndex && index.isVirtual)
+    {
+        qDebug() << "Reconstructing virtual assets folder at" << virtualRoot.path();
+
+        for (QString map : index.objects.keys())
+        {
+            AssetObject asset_object = index.objects.value(map);
+            QString target_path = FS::PathCombine(virtualRoot.path(), map);
+            QFile target(target_path);
+
+            QString tlk = asset_object.hash.left(2);
+
+            QString original_path = FS::PathCombine(objectDir.path(), tlk, asset_object.hash);
+            QFile original(original_path);
+            if (!original.exists())
+                continue;
+            if (!target.exists())
+            {
+                QFileInfo info(target_path);
+                QDir target_dir = info.dir();
+                // qDebug() << target_dir;
+                if (!target_dir.exists())
+                    QDir("").mkpath(target_dir.path());
+
+                bool couldCopy = original.copy(target_path);
+                qDebug() << " Copying" << original_path << "to" << target_path
+                             << QString::number(couldCopy); // << original.errorString();
+            }
+        }
+
+        // TODO: Write last used time to virtualRoot/.lastused
+    }
+
+    return virtualRoot;
 }
 
 }
 
 NetActionPtr AssetObject::getDownloadAction()
 {
-	QFileInfo objectFile(getLocalPath());
-	if ((!objectFile.isFile()) || (objectFile.size() != size))
-	{
-		auto objectDL = Net::Download::makeFile(getUrl(), objectFile.filePath());
-		if(hash.size())
-		{
-			auto rawHash = QByteArray::fromHex(hash.toLatin1());
-			objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash));
-		}
-		objectDL->m_total_progress = size;
-		return objectDL;
-	}
-	return nullptr;
+    QFileInfo objectFile(getLocalPath());
+    if ((!objectFile.isFile()) || (objectFile.size() != size))
+    {
+        auto objectDL = Net::Download::makeFile(getUrl(), objectFile.filePath());
+        if(hash.size())
+        {
+            auto rawHash = QByteArray::fromHex(hash.toLatin1());
+            objectDL->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawHash));
+        }
+        objectDL->m_total_progress = size;
+        return objectDL;
+    }
+    return nullptr;
 }
 
 QString AssetObject::getLocalPath()
 {
-	return "assets/objects/" + getRelPath();
+    return "assets/objects/" + getRelPath();
 }
 
 QUrl AssetObject::getUrl()
 {
-	return QUrl("http://resources.download.minecraft.net/" + getRelPath());
+    return QUrl("http://resources.download.minecraft.net/" + getRelPath());
 }
 
 QString AssetObject::getRelPath()
 {
-	return hash.left(2) + "/" + hash;
+    return hash.left(2) + "/" + hash;
 }
 
 NetJobPtr AssetsIndex::getDownloadJob()
 {
-	auto job = new NetJob(QObject::tr("Assets for %1").arg(id));
-	for (auto &object : objects.values())
-	{
-		auto dl = object.getDownloadAction();
-		if(dl)
-		{
-			job->addNetAction(dl);
-		}
-	}
-	if(job->size())
-		return job;
-	return nullptr;
+    auto job = new NetJob(QObject::tr("Assets for %1").arg(id));
+    for (auto &object : objects.values())
+    {
+        auto dl = object.getDownloadAction();
+        if(dl)
+        {
+            job->addNetAction(dl);
+        }
+    }
+    if(job->size())
+        return job;
+    return nullptr;
 }
diff --git a/api/logic/minecraft/AssetsUtils.h b/api/logic/minecraft/AssetsUtils.h
index b7ea9cc1..063c1237 100644
--- a/api/logic/minecraft/AssetsUtils.h
+++ b/api/logic/minecraft/AssetsUtils.h
@@ -22,22 +22,22 @@
 
 struct AssetObject
 {
-	QString getRelPath();
-	QUrl getUrl();
-	QString getLocalPath();
-	NetActionPtr getDownloadAction();
+    QString getRelPath();
+    QUrl getUrl();
+    QString getLocalPath();
+    NetActionPtr getDownloadAction();
 
-	QString hash;
-	qint64 size;
+    QString hash;
+    qint64 size;
 };
 
 struct AssetsIndex
 {
-	NetJobPtr getDownloadJob();
+    NetJobPtr getDownloadJob();
 
-	QString id;
-	QMap<QString, AssetObject> objects;
-	bool isVirtual = false;
+    QString id;
+    QMap<QString, AssetObject> objects;
+    bool isVirtual = false;
 };
 
 namespace AssetsUtils
diff --git a/api/logic/minecraft/Component.cpp b/api/logic/minecraft/Component.cpp
index 7c52271e..51957d17 100644
--- a/api/logic/minecraft/Component.cpp
+++ b/api/logic/minecraft/Component.cpp
@@ -13,356 +13,356 @@
 
 Component::Component(ComponentList * parent, const QString& uid)
 {
-	assert(parent);
-	m_parent = parent;
+    assert(parent);
+    m_parent = parent;
 
-	m_uid = uid;
+    m_uid = uid;
 }
 
 Component::Component(ComponentList * parent, std::shared_ptr<Meta::Version> version)
 {
-	assert(parent);
-	m_parent = parent;
+    assert(parent);
+    m_parent = parent;
 
-	m_metaVersion = version;
-	m_uid = version->uid();
-	m_version = m_cachedVersion = version->version();
-	m_cachedName = version->name();
-	m_loaded = version->isLoaded();
+    m_metaVersion = version;
+    m_uid = version->uid();
+    m_version = m_cachedVersion = version->version();
+    m_cachedName = version->name();
+    m_loaded = version->isLoaded();
 }
 
 Component::Component(ComponentList * parent, const QString& uid, std::shared_ptr<VersionFile> file)
 {
-	assert(parent);
-	m_parent = parent;
+    assert(parent);
+    m_parent = parent;
 
-	m_file = file;
-	m_uid = uid;
-	m_cachedVersion = m_file->version;
-	m_cachedName = m_file->name;
-	m_loaded = true;
+    m_file = file;
+    m_uid = uid;
+    m_cachedVersion = m_file->version;
+    m_cachedName = m_file->name;
+    m_loaded = true;
 }
 
 std::shared_ptr<Meta::Version> Component::getMeta()
 {
-	return m_metaVersion;
+    return m_metaVersion;
 }
 
 void Component::applyTo(LaunchProfile* profile)
 {
-	// do not apply disabled components
-	if(!isEnabled())
-	{
-		return;
-	}
-	auto vfile = getVersionFile();
-	if(vfile)
-	{
-		vfile->applyTo(profile);
-	}
-	else
-	{
-		profile->applyProblemSeverity(getProblemSeverity());
-	}
+    // do not apply disabled components
+    if(!isEnabled())
+    {
+        return;
+    }
+    auto vfile = getVersionFile();
+    if(vfile)
+    {
+        vfile->applyTo(profile);
+    }
+    else
+    {
+        profile->applyProblemSeverity(getProblemSeverity());
+    }
 }
 
 std::shared_ptr<class VersionFile> Component::getVersionFile() const
 {
-	if(m_metaVersion)
-	{
-		if(!m_metaVersion->isLoaded())
-		{
-			m_metaVersion->load(Net::Mode::Online);
-		}
-		return m_metaVersion->data();
-	}
-	else
-	{
-		return m_file;
-	}
+    if(m_metaVersion)
+    {
+        if(!m_metaVersion->isLoaded())
+        {
+            m_metaVersion->load(Net::Mode::Online);
+        }
+        return m_metaVersion->data();
+    }
+    else
+    {
+        return m_file;
+    }
 }
 
 std::shared_ptr<class Meta::VersionList> Component::getVersionList() const
 {
-	// FIXME: what if the metadata index isn't loaded yet?
-	if(ENV.metadataIndex()->hasUid(m_uid))
-	{
-		return ENV.metadataIndex()->get(m_uid);
-	}
-	return nullptr;
+    // FIXME: what if the metadata index isn't loaded yet?
+    if(ENV.metadataIndex()->hasUid(m_uid))
+    {
+        return ENV.metadataIndex()->get(m_uid);
+    }
+    return nullptr;
 }
 
 int Component::getOrder()
 {
-	if(m_orderOverride)
-		return m_order;
+    if(m_orderOverride)
+        return m_order;
 
-	auto vfile = getVersionFile();
-	if(vfile)
-	{
-		return vfile->order;
-	}
-	return 0;
+    auto vfile = getVersionFile();
+    if(vfile)
+    {
+        return vfile->order;
+    }
+    return 0;
 }
 void Component::setOrder(int order)
 {
-	m_orderOverride = true;
-	m_order = order;
+    m_orderOverride = true;
+    m_order = order;
 }
 QString Component::getID()
 {
-	return m_uid;
+    return m_uid;
 }
 QString Component::getName()
 {
-	if (!m_cachedName.isEmpty())
-		return m_cachedName;
-	return m_uid;
+    if (!m_cachedName.isEmpty())
+        return m_cachedName;
+    return m_uid;
 }
 QString Component::getVersion()
 {
-	return m_cachedVersion;
+    return m_cachedVersion;
 }
 QString Component::getFilename()
 {
-	return m_parent->patchFilePathForUid(m_uid);
+    return m_parent->patchFilePathForUid(m_uid);
 }
 QDateTime Component::getReleaseDateTime()
 {
-	if(m_metaVersion)
-	{
-		return m_metaVersion->time();
-	}
-	auto vfile = getVersionFile();
-	if(vfile)
-	{
-		return vfile->releaseTime;
-	}
-	// FIXME: fake
-	return QDateTime::currentDateTime();
+    if(m_metaVersion)
+    {
+        return m_metaVersion->time();
+    }
+    auto vfile = getVersionFile();
+    if(vfile)
+    {
+        return vfile->releaseTime;
+    }
+    // FIXME: fake
+    return QDateTime::currentDateTime();
 }
 
 bool Component::isEnabled()
 {
-	return !canBeDisabled() || !m_disabled;
+    return !canBeDisabled() || !m_disabled;
 }
 
 bool Component::canBeDisabled()
 {
-	return isRemovable() && !m_dependencyOnly;
+    return isRemovable() && !m_dependencyOnly;
 }
 
 bool Component::setEnabled(bool state)
 {
-	bool intendedDisabled = !state;
-	if (!canBeDisabled())
-	{
-		intendedDisabled = false;
-	}
-	if(intendedDisabled != m_disabled)
-	{
-		m_disabled = intendedDisabled;
-		emit dataChanged();
-		return true;
-	}
-	return false;
+    bool intendedDisabled = !state;
+    if (!canBeDisabled())
+    {
+        intendedDisabled = false;
+    }
+    if(intendedDisabled != m_disabled)
+    {
+        m_disabled = intendedDisabled;
+        emit dataChanged();
+        return true;
+    }
+    return false;
 }
 
 bool Component::isCustom()
 {
-	return m_file != nullptr;
+    return m_file != nullptr;
 }
 
 bool Component::isCustomizable()
 {
-	if(m_metaVersion)
-	{
-		if(getVersionFile())
-		{
-			return true;
-		}
-	}
-	return false;
+    if(m_metaVersion)
+    {
+        if(getVersionFile())
+        {
+            return true;
+        }
+    }
+    return false;
 }
 bool Component::isRemovable()
 {
-	return !m_important;
+    return !m_important;
 }
 bool Component::isRevertible()
 {
-	if (isCustom())
-	{
-		if(ENV.metadataIndex()->hasUid(m_uid))
-		{
-			return true;
-		}
-	}
-	return false;
+    if (isCustom())
+    {
+        if(ENV.metadataIndex()->hasUid(m_uid))
+        {
+            return true;
+        }
+    }
+    return false;
 }
 bool Component::isMoveable()
 {
-	// HACK, FIXME: this was too dumb and wouldn't follow dependency constraints anyway. For now hardcoded to 'true'.
-	return true;
+    // HACK, FIXME: this was too dumb and wouldn't follow dependency constraints anyway. For now hardcoded to 'true'.
+    return true;
 }
 bool Component::isVersionChangeable()
 {
-	auto list = getVersionList();
-	if(list)
-	{
-		if(!list->isLoaded())
-		{
-			list->load(Net::Mode::Online);
-		}
-		return list->count() != 0;
-	}
-	return false;
+    auto list = getVersionList();
+    if(list)
+    {
+        if(!list->isLoaded())
+        {
+            list->load(Net::Mode::Online);
+        }
+        return list->count() != 0;
+    }
+    return false;
 }
 
 void Component::setImportant(bool state)
 {
-	if(m_important != state)
-	{
-		m_important = state;
-		emit dataChanged();
-	}
+    if(m_important != state)
+    {
+        m_important = state;
+        emit dataChanged();
+    }
 }
 
 ProblemSeverity Component::getProblemSeverity() const
 {
-	auto file = getVersionFile();
-	if(file)
-	{
-		return file->getProblemSeverity();
-	}
-	return ProblemSeverity::Error;
+    auto file = getVersionFile();
+    if(file)
+    {
+        return file->getProblemSeverity();
+    }
+    return ProblemSeverity::Error;
 }
 
 const QList<PatchProblem> Component::getProblems() const
 {
-	auto file = getVersionFile();
-	if(file)
-	{
-		return file->getProblems();
-	}
-	return {{ProblemSeverity::Error, QObject::tr("Patch is not loaded yet.")}};
+    auto file = getVersionFile();
+    if(file)
+    {
+        return file->getProblems();
+    }
+    return {{ProblemSeverity::Error, QObject::tr("Patch is not loaded yet.")}};
 }
 
 void Component::setVersion(const QString& version)
 {
-	if(version == m_version)
-	{
-		return;
-	}
-	m_version = version;
-	if(m_loaded)
-	{
-		// we are loaded and potentially have state to invalidate
-		if(m_file)
-		{
-			// we have a file... explicit version has been changed and there is nothing else to do.
-		}
-		else
-		{
-			// we don't have a file, therefore we are loaded with metadata
-			m_cachedVersion = version;
-			// see if the meta version is loaded
-			auto metaVersion = ENV.metadataIndex()->get(m_uid, version);
-			if(metaVersion->isLoaded())
-			{
-				// if yes, we can continue with that.
-				m_metaVersion = metaVersion;
-			}
-			else
-			{
-				// if not, we need loading
-				m_metaVersion.reset();
-				m_loaded = false;
-			}
-			updateCachedData();
-		}
-	}
-	else
-	{
-		// not loaded... assume it will be sorted out later by the update task
-	}
-	emit dataChanged();
+    if(version == m_version)
+    {
+        return;
+    }
+    m_version = version;
+    if(m_loaded)
+    {
+        // we are loaded and potentially have state to invalidate
+        if(m_file)
+        {
+            // we have a file... explicit version has been changed and there is nothing else to do.
+        }
+        else
+        {
+            // we don't have a file, therefore we are loaded with metadata
+            m_cachedVersion = version;
+            // see if the meta version is loaded
+            auto metaVersion = ENV.metadataIndex()->get(m_uid, version);
+            if(metaVersion->isLoaded())
+            {
+                // if yes, we can continue with that.
+                m_metaVersion = metaVersion;
+            }
+            else
+            {
+                // if not, we need loading
+                m_metaVersion.reset();
+                m_loaded = false;
+            }
+            updateCachedData();
+        }
+    }
+    else
+    {
+        // not loaded... assume it will be sorted out later by the update task
+    }
+    emit dataChanged();
 }
 
 bool Component::customize()
 {
-	if(isCustom())
-	{
-		return false;
-	}
+    if(isCustom())
+    {
+        return false;
+    }
 
-	auto filename = getFilename();
-	if(!FS::ensureFilePathExists(filename))
-	{
-		return false;
-	}
-	// FIXME: get rid of this try-catch.
-	try
-	{
-		QSaveFile jsonFile(filename);
-		if(!jsonFile.open(QIODevice::WriteOnly))
-		{
-			return false;
-		}
-		auto vfile = getVersionFile();
-		if(!vfile)
-		{
-			return false;
-		}
-		auto document = OneSixVersionFormat::versionFileToJson(vfile);
-		jsonFile.write(document.toJson());
-		if(!jsonFile.commit())
-		{
-			return false;
-		}
-		m_file = vfile;
-		m_metaVersion.reset();
-		emit dataChanged();
-	}
-	catch (const Exception &error)
-	{
-		qWarning() << "Version could not be loaded:" << error.cause();
-	}
-	return true;
+    auto filename = getFilename();
+    if(!FS::ensureFilePathExists(filename))
+    {
+        return false;
+    }
+    // FIXME: get rid of this try-catch.
+    try
+    {
+        QSaveFile jsonFile(filename);
+        if(!jsonFile.open(QIODevice::WriteOnly))
+        {
+            return false;
+        }
+        auto vfile = getVersionFile();
+        if(!vfile)
+        {
+            return false;
+        }
+        auto document = OneSixVersionFormat::versionFileToJson(vfile);
+        jsonFile.write(document.toJson());
+        if(!jsonFile.commit())
+        {
+            return false;
+        }
+        m_file = vfile;
+        m_metaVersion.reset();
+        emit dataChanged();
+    }
+    catch (const Exception &error)
+    {
+        qWarning() << "Version could not be loaded:" << error.cause();
+    }
+    return true;
 }
 
 bool Component::revert()
 {
-	if(!isCustom())
-	{
-		// already not custom
-		return true;
-	}
-	auto filename = getFilename();
-	bool result = true;
-	// just kill the file and reload
-	if(QFile::exists(filename))
-	{
-		result = QFile::remove(filename);
-	}
-	if(result)
-	{
-		// file gone...
-		m_file.reset();
+    if(!isCustom())
+    {
+        // already not custom
+        return true;
+    }
+    auto filename = getFilename();
+    bool result = true;
+    // just kill the file and reload
+    if(QFile::exists(filename))
+    {
+        result = QFile::remove(filename);
+    }
+    if(result)
+    {
+        // file gone...
+        m_file.reset();
 
-		// check local cache for metadata...
-		auto version = ENV.metadataIndex()->get(m_uid, m_version);
-		if(version->isLoaded())
-		{
-			m_metaVersion = version;
-		}
-		else
-		{
-			m_metaVersion.reset();
-			m_loaded = false;
-		}
-		emit dataChanged();
-	}
-	return result;
+        // check local cache for metadata...
+        auto version = ENV.metadataIndex()->get(m_uid, m_version);
+        if(version->isLoaded())
+        {
+            m_metaVersion = version;
+        }
+        else
+        {
+            m_metaVersion.reset();
+            m_loaded = false;
+        }
+        emit dataChanged();
+    }
+    return result;
 }
 
 /**
@@ -372,68 +372,68 @@ bool Component::revert()
  */
 static bool deepCompare(const std::set<Meta::Require> & a, const std::set<Meta::Require> & b)
 {
-	// NOTE: this needs to be rewritten if the type of Meta::RequireSet changes
-	if(a.size() != b.size())
-	{
-		return false;
-	}
-	for(const auto & reqA :a)
-	{
-		const auto &iter2 = b.find(reqA);
-		if(iter2 == b.cend())
-		{
-			return false;
-		}
-		const auto & reqB = *iter2;
-		if(!reqA.deepEquals(reqB))
-		{
-			return false;
-		}
-	}
-	return true;
+    // NOTE: this needs to be rewritten if the type of Meta::RequireSet changes
+    if(a.size() != b.size())
+    {
+        return false;
+    }
+    for(const auto & reqA :a)
+    {
+        const auto &iter2 = b.find(reqA);
+        if(iter2 == b.cend())
+        {
+            return false;
+        }
+        const auto & reqB = *iter2;
+        if(!reqA.deepEquals(reqB))
+        {
+            return false;
+        }
+    }
+    return true;
 }
 
 void Component::updateCachedData()
 {
-	auto file = getVersionFile();
-	if(file)
-	{
-		bool changed = false;
-		if(m_cachedName != file->name)
-		{
-			m_cachedName = file->name;
-			changed = true;
-		}
-		if(m_cachedVersion != file->version)
-		{
-			m_cachedVersion = file->version;
-			changed = true;
-		}
-		if(m_cachedVolatile != file->m_volatile)
-		{
-			m_cachedVolatile = file->m_volatile;
-			changed = true;
-		}
-		if(!deepCompare(m_cachedRequires, file->requires))
-		{
-			m_cachedRequires = file->requires;
-			changed = true;
-		}
-		if(!deepCompare(m_cachedConflicts, file->conflicts))
-		{
-			m_cachedConflicts = file->conflicts;
-			changed = true;
-		}
-		if(changed)
-		{
-			emit dataChanged();
-		}
-	}
-	else
-	{
-		// in case we removed all the metadata
-		m_cachedRequires.clear();
-		m_cachedConflicts.clear();
-		emit dataChanged();
-	}
+    auto file = getVersionFile();
+    if(file)
+    {
+        bool changed = false;
+        if(m_cachedName != file->name)
+        {
+            m_cachedName = file->name;
+            changed = true;
+        }
+        if(m_cachedVersion != file->version)
+        {
+            m_cachedVersion = file->version;
+            changed = true;
+        }
+        if(m_cachedVolatile != file->m_volatile)
+        {
+            m_cachedVolatile = file->m_volatile;
+            changed = true;
+        }
+        if(!deepCompare(m_cachedRequires, file->requires))
+        {
+            m_cachedRequires = file->requires;
+            changed = true;
+        }
+        if(!deepCompare(m_cachedConflicts, file->conflicts))
+        {
+            m_cachedConflicts = file->conflicts;
+            changed = true;
+        }
+        if(changed)
+        {
+            emit dataChanged();
+        }
+    }
+    else
+    {
+        // in case we removed all the metadata
+        m_cachedRequires.clear();
+        m_cachedConflicts.clear();
+        emit dataChanged();
+    }
 }
diff --git a/api/logic/minecraft/Component.h b/api/logic/minecraft/Component.h
index 778fbb18..6a0f86c8 100644
--- a/api/logic/minecraft/Component.h
+++ b/api/logic/minecraft/Component.h
@@ -13,8 +13,8 @@ class ComponentList;
 class LaunchProfile;
 namespace Meta
 {
-	class Version;
-	class VersionList;
+    class Version;
+    class VersionList;
 }
 class VersionFile;
 
@@ -22,90 +22,90 @@ class MULTIMC_LOGIC_EXPORT Component : public QObject, public ProblemProvider
 {
 Q_OBJECT
 public:
-	Component(ComponentList * parent, const QString &uid);
+    Component(ComponentList * parent, const QString &uid);
 
-	// DEPRECATED: remove these constructors?
-	Component(ComponentList * parent, std::shared_ptr<Meta::Version> version);
-	Component(ComponentList * parent, const QString & uid, std::shared_ptr<VersionFile> file);
+    // DEPRECATED: remove these constructors?
+    Component(ComponentList * parent, std::shared_ptr<Meta::Version> version);
+    Component(ComponentList * parent, const QString & uid, std::shared_ptr<VersionFile> file);
 
-	virtual ~Component(){};
-	void applyTo(LaunchProfile *profile);
+    virtual ~Component(){};
+    void applyTo(LaunchProfile *profile);
 
-	bool isEnabled();
-	bool setEnabled (bool state);
-	bool canBeDisabled();
+    bool isEnabled();
+    bool setEnabled (bool state);
+    bool canBeDisabled();
 
-	bool isMoveable();
-	bool isCustomizable();
-	bool isRevertible();
-	bool isRemovable();
-	bool isCustom();
-	bool isVersionChangeable();
+    bool isMoveable();
+    bool isCustomizable();
+    bool isRevertible();
+    bool isRemovable();
+    bool isCustom();
+    bool isVersionChangeable();
 
-	// DEPRECATED: explicit numeric order values, used for loading old non-component config. TODO: refactor and move to migration code
-	void setOrder(int order);
-	int getOrder();
+    // DEPRECATED: explicit numeric order values, used for loading old non-component config. TODO: refactor and move to migration code
+    void setOrder(int order);
+    int getOrder();
 
-	QString getID();
-	QString getName();
-	QString getVersion();
-	std::shared_ptr<Meta::Version> getMeta();
-	QDateTime getReleaseDateTime();
+    QString getID();
+    QString getName();
+    QString getVersion();
+    std::shared_ptr<Meta::Version> getMeta();
+    QDateTime getReleaseDateTime();
 
-	QString getFilename();
+    QString getFilename();
 
-	std::shared_ptr<class VersionFile> getVersionFile() const;
-	std::shared_ptr<class Meta::VersionList> getVersionList() const;
+    std::shared_ptr<class VersionFile> getVersionFile() const;
+    std::shared_ptr<class Meta::VersionList> getVersionList() const;
 
-	void setImportant (bool state);
+    void setImportant (bool state);
 
 
-	const QList<PatchProblem> getProblems() const override;
-	ProblemSeverity getProblemSeverity() const override;
+    const QList<PatchProblem> getProblems() const override;
+    ProblemSeverity getProblemSeverity() const override;
 
-	void setVersion(const QString & version);
-	bool customize();
-	bool revert();
+    void setVersion(const QString & version);
+    bool customize();
+    bool revert();
 
-	void updateCachedData();
+    void updateCachedData();
 
 signals:
-	void dataChanged();
+    void dataChanged();
 
 public: /* data */
-	ComponentList * m_parent;
-
-	// BEGIN: persistent component list properties
-	/// ID of the component
-	QString m_uid;
-	/// version of the component - when there's a custom json override, this is also the version the component reverts to
-	QString m_version;
-	/// if true, this has been added automatically to satisfy dependencies and may be automatically removed
-	bool m_dependencyOnly = false;
-	/// if true, the component is either the main component of the instance, or otherwise important and cannot be removed.
-	bool m_important = false;
-	/// if true, the component is disabled
-	bool m_disabled = false;
-
-	/// cached name for display purposes, taken from the version file (meta or local override)
-	QString m_cachedName;
-	/// cached version for display AND other purposes, taken from the version file (meta or local override)
-	QString m_cachedVersion;
-	/// cached set of requirements, taken from the version file (meta or local override)
-	Meta::RequireSet m_cachedRequires;
-	Meta::RequireSet m_cachedConflicts;
-	/// if true, the component is volatile and may be automatically removed when no longer needed
-	bool m_cachedVolatile = false;
-	// END: persistent component list properties
-
-	// DEPRECATED: explicit numeric order values, used for loading old non-component config. TODO: refactor and move to migration code
-	bool m_orderOverride = false;
-	int m_order = 0;
-
-	// load state
-	std::shared_ptr<Meta::Version> m_metaVersion;
-	std::shared_ptr<VersionFile> m_file;
-	bool m_loaded = false;
+    ComponentList * m_parent;
+
+    // BEGIN: persistent component list properties
+    /// ID of the component
+    QString m_uid;
+    /// version of the component - when there's a custom json override, this is also the version the component reverts to
+    QString m_version;
+    /// if true, this has been added automatically to satisfy dependencies and may be automatically removed
+    bool m_dependencyOnly = false;
+    /// if true, the component is either the main component of the instance, or otherwise important and cannot be removed.
+    bool m_important = false;
+    /// if true, the component is disabled
+    bool m_disabled = false;
+
+    /// cached name for display purposes, taken from the version file (meta or local override)
+    QString m_cachedName;
+    /// cached version for display AND other purposes, taken from the version file (meta or local override)
+    QString m_cachedVersion;
+    /// cached set of requirements, taken from the version file (meta or local override)
+    Meta::RequireSet m_cachedRequires;
+    Meta::RequireSet m_cachedConflicts;
+    /// if true, the component is volatile and may be automatically removed when no longer needed
+    bool m_cachedVolatile = false;
+    // END: persistent component list properties
+
+    // DEPRECATED: explicit numeric order values, used for loading old non-component config. TODO: refactor and move to migration code
+    bool m_orderOverride = false;
+    int m_order = 0;
+
+    // load state
+    std::shared_ptr<Meta::Version> m_metaVersion;
+    std::shared_ptr<VersionFile> m_file;
+    bool m_loaded = false;
 };
 
 typedef shared_qobject_ptr<Component> ComponentPtr;
diff --git a/api/logic/minecraft/ComponentList.cpp b/api/logic/minecraft/ComponentList.cpp
index e373d499..7a865c60 100644
--- a/api/logic/minecraft/ComponentList.cpp
+++ b/api/logic/minecraft/ComponentList.cpp
@@ -37,18 +37,18 @@
 #include "ComponentUpdateTask.h"
 
 ComponentList::ComponentList(MinecraftInstance * instance)
-	: QAbstractListModel()
+    : QAbstractListModel()
 {
-	d.reset(new ComponentListData);
-	d->m_instance = instance;
-	d->m_saveTimer.setSingleShot(true);
-	d->m_saveTimer.setInterval(5000);
-	connect(&d->m_saveTimer, &QTimer::timeout, this, &ComponentList::save_internal);
+    d.reset(new ComponentListData);
+    d->m_instance = instance;
+    d->m_saveTimer.setSingleShot(true);
+    d->m_saveTimer.setInterval(5000);
+    connect(&d->m_saveTimer, &QTimer::timeout, this, &ComponentList::save_internal);
 }
 
 ComponentList::~ComponentList()
 {
-	saveNow();
+    saveNow();
 }
 
 // BEGIN: component file format
@@ -57,151 +57,151 @@ static const int currentComponentsFileVersion = 1;
 
 static QJsonObject componentToJsonV1(ComponentPtr component)
 {
-	QJsonObject obj;
-	// critical
-	obj.insert("uid", component->m_uid);
-	if(!component->m_version.isEmpty())
-	{
-		obj.insert("version", component->m_version);
-	}
-	if(component->m_dependencyOnly)
-	{
-		obj.insert("dependencyOnly", true);
-	}
-	if(component->m_important)
-	{
-		obj.insert("important", true);
-	}
-	if(component->m_disabled)
-	{
-		obj.insert("disabled", true);
-	}
-
-	// cached
-	if(!component->m_cachedVersion.isEmpty())
-	{
-		obj.insert("cachedVersion", component->m_cachedVersion);
-	}
-	if(!component->m_cachedName.isEmpty())
-	{
-		obj.insert("cachedName", component->m_cachedName);
-	}
-	Meta::serializeRequires(obj, &component->m_cachedRequires, "cachedRequires");
-	Meta::serializeRequires(obj, &component->m_cachedConflicts, "cachedConflicts");
-	if(component->m_cachedVolatile)
-	{
-		obj.insert("cachedVolatile", true);
-	}
-	return obj;
+    QJsonObject obj;
+    // critical
+    obj.insert("uid", component->m_uid);
+    if(!component->m_version.isEmpty())
+    {
+        obj.insert("version", component->m_version);
+    }
+    if(component->m_dependencyOnly)
+    {
+        obj.insert("dependencyOnly", true);
+    }
+    if(component->m_important)
+    {
+        obj.insert("important", true);
+    }
+    if(component->m_disabled)
+    {
+        obj.insert("disabled", true);
+    }
+
+    // cached
+    if(!component->m_cachedVersion.isEmpty())
+    {
+        obj.insert("cachedVersion", component->m_cachedVersion);
+    }
+    if(!component->m_cachedName.isEmpty())
+    {
+        obj.insert("cachedName", component->m_cachedName);
+    }
+    Meta::serializeRequires(obj, &component->m_cachedRequires, "cachedRequires");
+    Meta::serializeRequires(obj, &component->m_cachedConflicts, "cachedConflicts");
+    if(component->m_cachedVolatile)
+    {
+        obj.insert("cachedVolatile", true);
+    }
+    return obj;
 }
 
 static ComponentPtr componentFromJsonV1(ComponentList * parent, const QString & componentJsonPattern, const QJsonObject &obj)
 {
-	// critical
-	auto uid = Json::requireString(obj.value("uid"));
-	auto filePath = componentJsonPattern.arg(uid);
-	auto component = new Component(parent, uid);
-	component->m_version = Json::ensureString(obj.value("version"));
-	component->m_dependencyOnly = Json::ensureBoolean(obj.value("dependencyOnly"), false);
-	component->m_important = Json::ensureBoolean(obj.value("important"), false);
-
-	// cached
-	// TODO @RESILIENCE: ignore invalid values/structure here?
-	component->m_cachedVersion = Json::ensureString(obj.value("cachedVersion"));
-	component->m_cachedName = Json::ensureString(obj.value("cachedName"));
-	Meta::parseRequires(obj, &component->m_cachedRequires, "cachedRequires");
-	Meta::parseRequires(obj, &component->m_cachedConflicts, "cachedConflicts");
-	component->m_cachedVolatile = Json::ensureBoolean(obj.value("volatile"), false);
-	bool disabled = Json::ensureBoolean(obj.value("disabled"), false);
-	component->setEnabled(!disabled);
-	return component;
+    // critical
+    auto uid = Json::requireString(obj.value("uid"));
+    auto filePath = componentJsonPattern.arg(uid);
+    auto component = new Component(parent, uid);
+    component->m_version = Json::ensureString(obj.value("version"));
+    component->m_dependencyOnly = Json::ensureBoolean(obj.value("dependencyOnly"), false);
+    component->m_important = Json::ensureBoolean(obj.value("important"), false);
+
+    // cached
+    // TODO @RESILIENCE: ignore invalid values/structure here?
+    component->m_cachedVersion = Json::ensureString(obj.value("cachedVersion"));
+    component->m_cachedName = Json::ensureString(obj.value("cachedName"));
+    Meta::parseRequires(obj, &component->m_cachedRequires, "cachedRequires");
+    Meta::parseRequires(obj, &component->m_cachedConflicts, "cachedConflicts");
+    component->m_cachedVolatile = Json::ensureBoolean(obj.value("volatile"), false);
+    bool disabled = Json::ensureBoolean(obj.value("disabled"), false);
+    component->setEnabled(!disabled);
+    return component;
 }
 
 // Save the given component container data to a file
 static bool saveComponentList(const QString & filename, const ComponentContainer & container)
 {
-	QJsonObject obj;
-	obj.insert("formatVersion", currentComponentsFileVersion);
-	QJsonArray orderArray;
-	for(auto component: container)
-	{
-		orderArray.append(componentToJsonV1(component));
-	}
-	obj.insert("components", orderArray);
-	QSaveFile outFile(filename);
-	if (!outFile.open(QFile::WriteOnly))
-	{
-		qCritical() << "Couldn't open" << outFile.fileName()
-					 << "for writing:" << outFile.errorString();
-		return false;
-	}
-	auto data = QJsonDocument(obj).toJson(QJsonDocument::Indented);
-	if(outFile.write(data) != data.size())
-	{
-		qCritical() << "Couldn't write all the data into" << outFile.fileName()
-					 << "because:" << outFile.errorString();
-		return false;
-	}
-	if(!outFile.commit())
-	{
-		qCritical() << "Couldn't save" << outFile.fileName()
-					 << "because:" << outFile.errorString();
-	}
-	return true;
+    QJsonObject obj;
+    obj.insert("formatVersion", currentComponentsFileVersion);
+    QJsonArray orderArray;
+    for(auto component: container)
+    {
+        orderArray.append(componentToJsonV1(component));
+    }
+    obj.insert("components", orderArray);
+    QSaveFile outFile(filename);
+    if (!outFile.open(QFile::WriteOnly))
+    {
+        qCritical() << "Couldn't open" << outFile.fileName()
+                     << "for writing:" << outFile.errorString();
+        return false;
+    }
+    auto data = QJsonDocument(obj).toJson(QJsonDocument::Indented);
+    if(outFile.write(data) != data.size())
+    {
+        qCritical() << "Couldn't write all the data into" << outFile.fileName()
+                     << "because:" << outFile.errorString();
+        return false;
+    }
+    if(!outFile.commit())
+    {
+        qCritical() << "Couldn't save" << outFile.fileName()
+                     << "because:" << outFile.errorString();
+    }
+    return true;
 }
 
 // Read the given file into component containers
 static bool loadComponentList(ComponentList * parent, const QString & filename, const QString & componentJsonPattern, ComponentContainer & container)
 {
-	QFile componentsFile(filename);
-	if (!componentsFile.exists())
-	{
-		qWarning() << "Components file doesn't exist. This should never happen.";
-		return false;
-	}
-	if (!componentsFile.open(QFile::ReadOnly))
-	{
-		qCritical() << "Couldn't open" << componentsFile.fileName()
-					 << " for reading:" << componentsFile.errorString();
-		qWarning() << "Ignoring overriden order";
-		return false;
-	}
-
-	// and it's valid JSON
-	QJsonParseError error;
-	QJsonDocument doc = QJsonDocument::fromJson(componentsFile.readAll(), &error);
-	if (error.error != QJsonParseError::NoError)
-	{
-		qCritical() << "Couldn't parse" << componentsFile.fileName() << ":" << error.errorString();
-		qWarning() << "Ignoring overriden order";
-		return false;
-	}
-
-	// and then read it and process it if all above is true.
-	try
-	{
-		auto obj = Json::requireObject(doc);
-		// check order file version.
-		auto version = Json::requireInteger(obj.value("formatVersion"));
-		if (version != currentComponentsFileVersion)
-		{
-			throw JSONValidationError(QObject::tr("Invalid component file version, expected %1")
-										  .arg(currentComponentsFileVersion));
-		}
-		auto orderArray = Json::requireArray(obj.value("components"));
-		for(auto item: orderArray)
-		{
-			auto obj = Json::requireObject(item, "Component must be an object.");
-			container.append(componentFromJsonV1(parent, componentJsonPattern, obj));
-		}
-	}
-	catch (const JSONValidationError &err)
-	{
-		qCritical() << "Couldn't parse" << componentsFile.fileName() << ": bad file format";
-		container.clear();
-		return false;
-	}
-	return true;
+    QFile componentsFile(filename);
+    if (!componentsFile.exists())
+    {
+        qWarning() << "Components file doesn't exist. This should never happen.";
+        return false;
+    }
+    if (!componentsFile.open(QFile::ReadOnly))
+    {
+        qCritical() << "Couldn't open" << componentsFile.fileName()
+                     << " for reading:" << componentsFile.errorString();
+        qWarning() << "Ignoring overriden order";
+        return false;
+    }
+
+    // and it's valid JSON
+    QJsonParseError error;
+    QJsonDocument doc = QJsonDocument::fromJson(componentsFile.readAll(), &error);
+    if (error.error != QJsonParseError::NoError)
+    {
+        qCritical() << "Couldn't parse" << componentsFile.fileName() << ":" << error.errorString();
+        qWarning() << "Ignoring overriden order";
+        return false;
+    }
+
+    // and then read it and process it if all above is true.
+    try
+    {
+        auto obj = Json::requireObject(doc);
+        // check order file version.
+        auto version = Json::requireInteger(obj.value("formatVersion"));
+        if (version != currentComponentsFileVersion)
+        {
+            throw JSONValidationError(QObject::tr("Invalid component file version, expected %1")
+                                          .arg(currentComponentsFileVersion));
+        }
+        auto orderArray = Json::requireArray(obj.value("components"));
+        for(auto item: orderArray)
+        {
+            auto obj = Json::requireObject(item, "Component must be an object.");
+            container.append(componentFromJsonV1(parent, componentJsonPattern, obj));
+        }
+    }
+    catch (const JSONValidationError &err)
+    {
+        qCritical() << "Couldn't parse" << componentsFile.fileName() << ": bad file format";
+        container.clear();
+        return false;
+    }
+    return true;
 }
 
 // END: component file format
@@ -210,217 +210,217 @@ static bool loadComponentList(ComponentList * parent, const QString & filename,
 
 void ComponentList::saveNow()
 {
-	if(saveIsScheduled())
-	{
-		d->m_saveTimer.stop();
-		save_internal();
-	}
+    if(saveIsScheduled())
+    {
+        d->m_saveTimer.stop();
+        save_internal();
+    }
 }
 
 bool ComponentList::saveIsScheduled() const
 {
-	return d->dirty;
+    return d->dirty;
 }
 
 void ComponentList::buildingFromScratch()
 {
-	d->loaded = true;
-	d->dirty = true;
+    d->loaded = true;
+    d->dirty = true;
 }
 
 void ComponentList::scheduleSave()
 {
-	if(!d->loaded)
-	{
-		qDebug() << "Component list should never save if it didn't successfully load, instance:" << d->m_instance->name();
-		return;
-	}
-	if(!d->dirty)
-	{
-		d->dirty = true;
-		qDebug() << "Component list save is scheduled for" << d->m_instance->name();
-	}
-	d->m_saveTimer.start();
+    if(!d->loaded)
+    {
+        qDebug() << "Component list should never save if it didn't successfully load, instance:" << d->m_instance->name();
+        return;
+    }
+    if(!d->dirty)
+    {
+        d->dirty = true;
+        qDebug() << "Component list save is scheduled for" << d->m_instance->name();
+    }
+    d->m_saveTimer.start();
 }
 
 QString ComponentList::componentsFilePath() const
 {
-	return FS::PathCombine(d->m_instance->instanceRoot(), "mmc-pack.json");
+    return FS::PathCombine(d->m_instance->instanceRoot(), "mmc-pack.json");
 }
 
 QString ComponentList::patchesPattern() const
 {
-	return FS::PathCombine(d->m_instance->instanceRoot(), "patches", "%1.json");
+    return FS::PathCombine(d->m_instance->instanceRoot(), "patches", "%1.json");
 }
 
 QString ComponentList::patchFilePathForUid(const QString& uid) const
 {
-	return patchesPattern().arg(uid);
+    return patchesPattern().arg(uid);
 }
 
 void ComponentList::save_internal()
 {
-	qDebug() << "Component list save performed now for" << d->m_instance->name();
-	auto filename = componentsFilePath();
-	saveComponentList(filename, d->components);
-	d->dirty = false;
+    qDebug() << "Component list save performed now for" << d->m_instance->name();
+    auto filename = componentsFilePath();
+    saveComponentList(filename, d->components);
+    d->dirty = false;
 }
 
 bool ComponentList::load()
 {
-	auto filename = componentsFilePath();
-	QFile componentsFile(filename);
-
-	// migrate old config to new one, if needed
-	if(!componentsFile.exists())
-	{
-		if(!migratePreComponentConfig())
-		{
-			// FIXME: the user should be notified...
-			qCritical() << "Failed to convert old pre-component config for instance" << d->m_instance->name();
-			return false;
-		}
-	}
-
-	// load the new component list and swap it with the current one...
-	ComponentContainer newComponents;
-	if(!loadComponentList(this, filename, patchesPattern(), newComponents))
-	{
-		qCritical() << "Failed to load the component config for instance" << d->m_instance->name();
-		return false;
-	}
-	else
-	{
-		// FIXME: actually use fine-grained updates, not this...
-		beginResetModel();
-		// disconnect all the old components
-		for(auto component: d->components)
-		{
-			disconnect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
-		}
-		d->components.clear();
-		d->componentIndex.clear();
-		for(auto component: newComponents)
-		{
-			if(d->componentIndex.contains(component->m_uid))
-			{
-				qWarning() << "Ignoring duplicate component entry" << component->m_uid;
-				continue;
-			}
-			connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
-			d->components.append(component);
-			d->componentIndex[component->m_uid] = component;
-		}
-		endResetModel();
-		d->loaded = true;
-		return true;
-	}
+    auto filename = componentsFilePath();
+    QFile componentsFile(filename);
+
+    // migrate old config to new one, if needed
+    if(!componentsFile.exists())
+    {
+        if(!migratePreComponentConfig())
+        {
+            // FIXME: the user should be notified...
+            qCritical() << "Failed to convert old pre-component config for instance" << d->m_instance->name();
+            return false;
+        }
+    }
+
+    // load the new component list and swap it with the current one...
+    ComponentContainer newComponents;
+    if(!loadComponentList(this, filename, patchesPattern(), newComponents))
+    {
+        qCritical() << "Failed to load the component config for instance" << d->m_instance->name();
+        return false;
+    }
+    else
+    {
+        // FIXME: actually use fine-grained updates, not this...
+        beginResetModel();
+        // disconnect all the old components
+        for(auto component: d->components)
+        {
+            disconnect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
+        }
+        d->components.clear();
+        d->componentIndex.clear();
+        for(auto component: newComponents)
+        {
+            if(d->componentIndex.contains(component->m_uid))
+            {
+                qWarning() << "Ignoring duplicate component entry" << component->m_uid;
+                continue;
+            }
+            connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
+            d->components.append(component);
+            d->componentIndex[component->m_uid] = component;
+        }
+        endResetModel();
+        d->loaded = true;
+        return true;
+    }
 }
 
 void ComponentList::reload(Net::Mode netmode)
 {
-	// Do not reload when the update/resolve task is running. It is in control.
-	if(d->m_updateTask)
-	{
-		return;
-	}
-
-	// flush any scheduled saves to not lose state
-	saveNow();
-
-	// FIXME: differentiate when a reapply is required by propagating state from components
-	invalidateLaunchProfile();
-
-	if(load())
-	{
-		resolve(netmode);
-	}
+    // Do not reload when the update/resolve task is running. It is in control.
+    if(d->m_updateTask)
+    {
+        return;
+    }
+
+    // flush any scheduled saves to not lose state
+    saveNow();
+
+    // FIXME: differentiate when a reapply is required by propagating state from components
+    invalidateLaunchProfile();
+
+    if(load())
+    {
+        resolve(netmode);
+    }
 }
 
 shared_qobject_ptr<Task> ComponentList::getCurrentTask()
 {
-	return d->m_updateTask;
+    return d->m_updateTask;
 }
 
 void ComponentList::resolve(Net::Mode netmode)
 {
-	auto updateTask = new ComponentUpdateTask(ComponentUpdateTask::Mode::Resolution, netmode, this);
-	d->m_updateTask.reset(updateTask);
-	connect(updateTask, &ComponentUpdateTask::succeeded, this, &ComponentList::updateSucceeded);
-	connect(updateTask, &ComponentUpdateTask::failed, this, &ComponentList::updateFailed);
-	d->m_updateTask->start();
+    auto updateTask = new ComponentUpdateTask(ComponentUpdateTask::Mode::Resolution, netmode, this);
+    d->m_updateTask.reset(updateTask);
+    connect(updateTask, &ComponentUpdateTask::succeeded, this, &ComponentList::updateSucceeded);
+    connect(updateTask, &ComponentUpdateTask::failed, this, &ComponentList::updateFailed);
+    d->m_updateTask->start();
 }
 
 
 void ComponentList::updateSucceeded()
 {
-	qDebug() << "Component list update/resolve task succeeded for" << d->m_instance->name();
-	d->m_updateTask.reset();
-	invalidateLaunchProfile();
+    qDebug() << "Component list update/resolve task succeeded for" << d->m_instance->name();
+    d->m_updateTask.reset();
+    invalidateLaunchProfile();
 }
 
 void ComponentList::updateFailed(const QString& error)
 {
-	qDebug() << "Component list update/resolve task failed for" << d->m_instance->name() << "Reason:" << error;
-	d->m_updateTask.reset();
-	invalidateLaunchProfile();
+    qDebug() << "Component list update/resolve task failed for" << d->m_instance->name() << "Reason:" << error;
+    d->m_updateTask.reset();
+    invalidateLaunchProfile();
 }
 
 // NOTE this is really old stuff, and only needs to be used when loading the old hardcoded component-unaware format (loadPreComponentConfig).
 static void upgradeDeprecatedFiles(QString root, QString instanceName)
 {
-	auto versionJsonPath = FS::PathCombine(root, "version.json");
-	auto customJsonPath = FS::PathCombine(root, "custom.json");
-	auto mcJson = FS::PathCombine(root, "patches" , "net.minecraft.json");
-
-	QString sourceFile;
-	QString renameFile;
-
-	// convert old crap.
-	if(QFile::exists(customJsonPath))
-	{
-		sourceFile = customJsonPath;
-		renameFile = versionJsonPath;
-	}
-	else if(QFile::exists(versionJsonPath))
-	{
-		sourceFile = versionJsonPath;
-	}
-	if(!sourceFile.isEmpty() && !QFile::exists(mcJson))
-	{
-		if(!FS::ensureFilePathExists(mcJson))
-		{
-			qWarning() << "Couldn't create patches folder for" << instanceName;
-			return;
-		}
-		if(!renameFile.isEmpty() && QFile::exists(renameFile))
-		{
-			if(!QFile::rename(renameFile, renameFile + ".old"))
-			{
-				qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << instanceName;
-				return;
-			}
-		}
-		auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
-		ProfileUtils::removeLwjglFromPatch(file);
-		file->uid = "net.minecraft";
-		file->version = file->minecraftVersion;
-		file->name = "Minecraft";
-
-		Meta::Require needsLwjgl;
-		needsLwjgl.uid = "org.lwjgl";
-		file->requires.insert(needsLwjgl);
-
-		if(!ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), mcJson))
-		{
-			return;
-		}
-		if(!QFile::rename(sourceFile, sourceFile + ".old"))
-		{
-			qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << instanceName;
-			return;
-		}
-	}
+    auto versionJsonPath = FS::PathCombine(root, "version.json");
+    auto customJsonPath = FS::PathCombine(root, "custom.json");
+    auto mcJson = FS::PathCombine(root, "patches" , "net.minecraft.json");
+
+    QString sourceFile;
+    QString renameFile;
+
+    // convert old crap.
+    if(QFile::exists(customJsonPath))
+    {
+        sourceFile = customJsonPath;
+        renameFile = versionJsonPath;
+    }
+    else if(QFile::exists(versionJsonPath))
+    {
+        sourceFile = versionJsonPath;
+    }
+    if(!sourceFile.isEmpty() && !QFile::exists(mcJson))
+    {
+        if(!FS::ensureFilePathExists(mcJson))
+        {
+            qWarning() << "Couldn't create patches folder for" << instanceName;
+            return;
+        }
+        if(!renameFile.isEmpty() && QFile::exists(renameFile))
+        {
+            if(!QFile::rename(renameFile, renameFile + ".old"))
+            {
+                qWarning() << "Couldn't rename" << renameFile << "to" << renameFile + ".old" << "in" << instanceName;
+                return;
+            }
+        }
+        auto file = ProfileUtils::parseJsonFile(QFileInfo(sourceFile), false);
+        ProfileUtils::removeLwjglFromPatch(file);
+        file->uid = "net.minecraft";
+        file->version = file->minecraftVersion;
+        file->name = "Minecraft";
+
+        Meta::Require needsLwjgl;
+        needsLwjgl.uid = "org.lwjgl";
+        file->requires.insert(needsLwjgl);
+
+        if(!ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), mcJson))
+        {
+            return;
+        }
+        if(!QFile::rename(sourceFile, sourceFile + ".old"))
+        {
+            qWarning() << "Couldn't rename" << sourceFile << "to" << sourceFile + ".old" << "in" << instanceName;
+            return;
+        }
+    }
 }
 
 /*
@@ -431,774 +431,774 @@ static void upgradeDeprecatedFiles(QString root, QString instanceName)
  */
 bool ComponentList::migratePreComponentConfig()
 {
-	// upgrade the very old files from the beginnings of MultiMC 5
-	upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
-
-	QList<ComponentPtr> components;
-	QSet<QString> loaded;
-
-	auto addBuiltinPatch = [&](const QString &uid, bool asDependency, const QString & emptyVersion, const Meta::Require & req, const Meta::Require & conflict)
-	{
-		auto jsonFilePath = FS::PathCombine(d->m_instance->instanceRoot(), "patches" , uid + ".json");
-		auto intendedVersion = d->getOldConfigVersion(uid);
-		// load up the base minecraft patch
-		ComponentPtr component;
-		if(QFile::exists(jsonFilePath))
-		{
-			if(intendedVersion.isEmpty())
-			{
-				intendedVersion = emptyVersion;
-			}
-			auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
-			// fix uid
-			file->uid = uid;
-			// if version is missing, add it from the outside.
-			if(file->version.isEmpty())
-			{
-				file->version = intendedVersion;
-			}
-			// if this is a dependency (LWJGL), mark it also as volatile
-			if(asDependency)
-			{
-				file->m_volatile = true;
-			}
-			// insert requirements if needed
-			if(!req.uid.isEmpty())
-			{
-				file->requires.insert(req);
-			}
-			// insert conflicts if needed
-			if(!conflict.uid.isEmpty())
-			{
-				file->conflicts.insert(conflict);
-			}
-			// FIXME: @QUALITY do not ignore return value
-			ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
-			component = new Component(this, uid, file);
-			component->m_version = intendedVersion;
-		}
-		else if(!intendedVersion.isEmpty())
-		{
-			auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion);
-			component = new Component(this, metaVersion);
-		}
-		else
-		{
-			return;
-		}
-		component->m_dependencyOnly = asDependency;
-		component->m_important = !asDependency;
-		components.append(component);
-	};
-	// TODO: insert depends and conflicts here if these are customized files...
-	Meta::Require reqLwjgl;
-	reqLwjgl.uid = "org.lwjgl";
-	reqLwjgl.suggests = "2.9.1";
-	Meta::Require conflictLwjgl3;
-	conflictLwjgl3.uid = "org.lwjgl3";
-	Meta::Require nullReq;
-	addBuiltinPatch("org.lwjgl", true, "2.9.1", nullReq, conflictLwjgl3);
-	addBuiltinPatch("net.minecraft", false, QString(), reqLwjgl, nullReq);
-
-	// first, collect all other file-based patches and load them
-	QMap<QString, ComponentPtr> loadedComponents;
-	QDir patchesDir(FS::PathCombine(d->m_instance->instanceRoot(),"patches"));
-	for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files))
-	{
-		// parse the file
-		qDebug() << "Reading" << info.fileName();
-		auto file = ProfileUtils::parseJsonFile(info, true);
-
-		// correct missing or wrong uid based on the file name
-		QString uid = info.completeBaseName();
-
-		// ignore builtins, they've been handled already
-		if (uid == "net.minecraft")
-			continue;
-		if (uid == "org.lwjgl")
-			continue;
-
-		// handle horrible corner cases
-		if(uid.isEmpty())
-		{
-			// if you have a file named '.json', make it just go away.
-			// FIXME: @QUALITY do not ignore return value
-			QFile::remove(info.absoluteFilePath());
-			continue;
-		}
-		file->uid = uid;
-		// FIXME: @QUALITY do not ignore return value
-		ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
-
-		auto component = new Component(this, file->uid, file);
-		auto version = d->getOldConfigVersion(file->uid);
-		if(!version.isEmpty())
-		{
-			component->m_version = version;
-		}
-		loadedComponents[file->uid] = component;
-	}
-	// try to load the other 'hardcoded' patches (forge, liteloader), if they weren't loaded from files
-	auto loadSpecial = [&](const QString & uid, int order)
-	{
-		auto patchVersion = d->getOldConfigVersion(uid);
-		if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
-		{
-			auto patch = new Component(this, ENV.metadataIndex()->get(uid, patchVersion));
-			patch->setOrder(order);
-			loadedComponents[uid] = patch;
-		}
-	};
-	loadSpecial("net.minecraftforge", 5);
-	loadSpecial("com.mumfrey.liteloader", 10);
-
-	// load the old order.json file, if present
-	ProfileUtils::PatchOrder userOrder;
-	ProfileUtils::readOverrideOrders(FS::PathCombine(d->m_instance->instanceRoot(), "order.json"), userOrder);
-
-	// now add all the patches by user sort order
-	for (auto uid : userOrder)
-	{
-		// ignore builtins
-		if (uid == "net.minecraft")
-			continue;
-		if (uid == "org.lwjgl")
-			continue;
-		// ordering has a patch that is gone?
-		if(!loadedComponents.contains(uid))
-		{
-			continue;
-		}
-		components.append(loadedComponents.take(uid));
-	}
-
-	// is there anything left to sort? - this is used when there are leftover components that aren't part of the order.json
-	if(!loadedComponents.isEmpty())
-	{
-		// inserting into multimap by order number as key sorts the patches and detects duplicates
-		QMultiMap<int, ComponentPtr> files;
-		auto iter = loadedComponents.begin();
-		while(iter != loadedComponents.end())
-		{
-			files.insert((*iter)->getOrder(), *iter);
-			iter++;
-		}
-
-		// then just extract the patches and put them in the list
-		for (auto order : files.keys())
-		{
-			const auto &values = files.values(order);
-			for(auto &value: values)
-			{
-				// TODO: put back the insertion of problem messages here, so the user knows about the id duplication
-				components.append(value);
-			}
-		}
-	}
-	// new we have a complete list of components...
-	return saveComponentList(componentsFilePath(), components);
+    // upgrade the very old files from the beginnings of MultiMC 5
+    upgradeDeprecatedFiles(d->m_instance->instanceRoot(), d->m_instance->name());
+
+    QList<ComponentPtr> components;
+    QSet<QString> loaded;
+
+    auto addBuiltinPatch = [&](const QString &uid, bool asDependency, const QString & emptyVersion, const Meta::Require & req, const Meta::Require & conflict)
+    {
+        auto jsonFilePath = FS::PathCombine(d->m_instance->instanceRoot(), "patches" , uid + ".json");
+        auto intendedVersion = d->getOldConfigVersion(uid);
+        // load up the base minecraft patch
+        ComponentPtr component;
+        if(QFile::exists(jsonFilePath))
+        {
+            if(intendedVersion.isEmpty())
+            {
+                intendedVersion = emptyVersion;
+            }
+            auto file = ProfileUtils::parseJsonFile(QFileInfo(jsonFilePath), false);
+            // fix uid
+            file->uid = uid;
+            // if version is missing, add it from the outside.
+            if(file->version.isEmpty())
+            {
+                file->version = intendedVersion;
+            }
+            // if this is a dependency (LWJGL), mark it also as volatile
+            if(asDependency)
+            {
+                file->m_volatile = true;
+            }
+            // insert requirements if needed
+            if(!req.uid.isEmpty())
+            {
+                file->requires.insert(req);
+            }
+            // insert conflicts if needed
+            if(!conflict.uid.isEmpty())
+            {
+                file->conflicts.insert(conflict);
+            }
+            // FIXME: @QUALITY do not ignore return value
+            ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), jsonFilePath);
+            component = new Component(this, uid, file);
+            component->m_version = intendedVersion;
+        }
+        else if(!intendedVersion.isEmpty())
+        {
+            auto metaVersion = ENV.metadataIndex()->get(uid, intendedVersion);
+            component = new Component(this, metaVersion);
+        }
+        else
+        {
+            return;
+        }
+        component->m_dependencyOnly = asDependency;
+        component->m_important = !asDependency;
+        components.append(component);
+    };
+    // TODO: insert depends and conflicts here if these are customized files...
+    Meta::Require reqLwjgl;
+    reqLwjgl.uid = "org.lwjgl";
+    reqLwjgl.suggests = "2.9.1";
+    Meta::Require conflictLwjgl3;
+    conflictLwjgl3.uid = "org.lwjgl3";
+    Meta::Require nullReq;
+    addBuiltinPatch("org.lwjgl", true, "2.9.1", nullReq, conflictLwjgl3);
+    addBuiltinPatch("net.minecraft", false, QString(), reqLwjgl, nullReq);
+
+    // first, collect all other file-based patches and load them
+    QMap<QString, ComponentPtr> loadedComponents;
+    QDir patchesDir(FS::PathCombine(d->m_instance->instanceRoot(),"patches"));
+    for (auto info : patchesDir.entryInfoList(QStringList() << "*.json", QDir::Files))
+    {
+        // parse the file
+        qDebug() << "Reading" << info.fileName();
+        auto file = ProfileUtils::parseJsonFile(info, true);
+
+        // correct missing or wrong uid based on the file name
+        QString uid = info.completeBaseName();
+
+        // ignore builtins, they've been handled already
+        if (uid == "net.minecraft")
+            continue;
+        if (uid == "org.lwjgl")
+            continue;
+
+        // handle horrible corner cases
+        if(uid.isEmpty())
+        {
+            // if you have a file named '.json', make it just go away.
+            // FIXME: @QUALITY do not ignore return value
+            QFile::remove(info.absoluteFilePath());
+            continue;
+        }
+        file->uid = uid;
+        // FIXME: @QUALITY do not ignore return value
+        ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), info.absoluteFilePath());
+
+        auto component = new Component(this, file->uid, file);
+        auto version = d->getOldConfigVersion(file->uid);
+        if(!version.isEmpty())
+        {
+            component->m_version = version;
+        }
+        loadedComponents[file->uid] = component;
+    }
+    // try to load the other 'hardcoded' patches (forge, liteloader), if they weren't loaded from files
+    auto loadSpecial = [&](const QString & uid, int order)
+    {
+        auto patchVersion = d->getOldConfigVersion(uid);
+        if(!patchVersion.isEmpty() && !loadedComponents.contains(uid))
+        {
+            auto patch = new Component(this, ENV.metadataIndex()->get(uid, patchVersion));
+            patch->setOrder(order);
+            loadedComponents[uid] = patch;
+        }
+    };
+    loadSpecial("net.minecraftforge", 5);
+    loadSpecial("com.mumfrey.liteloader", 10);
+
+    // load the old order.json file, if present
+    ProfileUtils::PatchOrder userOrder;
+    ProfileUtils::readOverrideOrders(FS::PathCombine(d->m_instance->instanceRoot(), "order.json"), userOrder);
+
+    // now add all the patches by user sort order
+    for (auto uid : userOrder)
+    {
+        // ignore builtins
+        if (uid == "net.minecraft")
+            continue;
+        if (uid == "org.lwjgl")
+            continue;
+        // ordering has a patch that is gone?
+        if(!loadedComponents.contains(uid))
+        {
+            continue;
+        }
+        components.append(loadedComponents.take(uid));
+    }
+
+    // is there anything left to sort? - this is used when there are leftover components that aren't part of the order.json
+    if(!loadedComponents.isEmpty())
+    {
+        // inserting into multimap by order number as key sorts the patches and detects duplicates
+        QMultiMap<int, ComponentPtr> files;
+        auto iter = loadedComponents.begin();
+        while(iter != loadedComponents.end())
+        {
+            files.insert((*iter)->getOrder(), *iter);
+            iter++;
+        }
+
+        // then just extract the patches and put them in the list
+        for (auto order : files.keys())
+        {
+            const auto &values = files.values(order);
+            for(auto &value: values)
+            {
+                // TODO: put back the insertion of problem messages here, so the user knows about the id duplication
+                components.append(value);
+            }
+        }
+    }
+    // new we have a complete list of components...
+    return saveComponentList(componentsFilePath(), components);
 }
 
 // END: save/load
 
 void ComponentList::appendComponent(ComponentPtr component)
 {
-	insertComponent(d->components.size(), component);
+    insertComponent(d->components.size(), component);
 }
 
 void ComponentList::insertComponent(size_t index, ComponentPtr component)
 {
-	auto id = component->getID();
-	if(id.isEmpty())
-	{
-		qWarning() << "Attempt to add a component with empty ID!";
-		return;
-	}
-	if(d->componentIndex.contains(id))
-	{
-		qWarning() << "Attempt to add a component that is already present!";
-		return;
-	}
-	beginInsertRows(QModelIndex(), index, index);
-	d->components.insert(index, component);
-	d->componentIndex[id] = component;
-	endInsertRows();
-	connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
-	scheduleSave();
+    auto id = component->getID();
+    if(id.isEmpty())
+    {
+        qWarning() << "Attempt to add a component with empty ID!";
+        return;
+    }
+    if(d->componentIndex.contains(id))
+    {
+        qWarning() << "Attempt to add a component that is already present!";
+        return;
+    }
+    beginInsertRows(QModelIndex(), index, index);
+    d->components.insert(index, component);
+    d->componentIndex[id] = component;
+    endInsertRows();
+    connect(component.get(), &Component::dataChanged, this, &ComponentList::componentDataChanged);
+    scheduleSave();
 }
 
 void ComponentList::componentDataChanged()
 {
-	auto objPtr = qobject_cast<Component *>(sender());
-	if(!objPtr)
-	{
-		qWarning() << "ComponentList got dataChenged signal from a non-Component!";
-		return;
-	}
-	// figure out which one is it... in a seriously dumb way.
-	int index = 0;
-	for (auto component: d->components)
-	{
-		if(component.get() == objPtr)
-		{
-			emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
-			scheduleSave();
-			return;
-		}
-		index++;
-	}
-	qWarning() << "ComponentList got dataChenged signal from a Component which does not belong to it!";
+    auto objPtr = qobject_cast<Component *>(sender());
+    if(!objPtr)
+    {
+        qWarning() << "ComponentList got dataChenged signal from a non-Component!";
+        return;
+    }
+    // figure out which one is it... in a seriously dumb way.
+    int index = 0;
+    for (auto component: d->components)
+    {
+        if(component.get() == objPtr)
+        {
+            emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
+            scheduleSave();
+            return;
+        }
+        index++;
+    }
+    qWarning() << "ComponentList got dataChenged signal from a Component which does not belong to it!";
 }
 
 bool ComponentList::remove(const int index)
 {
-	auto patch = getComponent(index);
-	if (!patch->isRemovable())
-	{
-		qWarning() << "Patch" << patch->getID() << "is non-removable";
-		return false;
-	}
-
-	if(!removeComponent_internal(patch))
-	{
-		qCritical() << "Patch" << patch->getID() << "could not be removed";
-		return false;
-	}
-
-	beginRemoveRows(QModelIndex(), index, index);
-	d->components.removeAt(index);
-	d->componentIndex.remove(patch->getID());
-	endRemoveRows();
-	invalidateLaunchProfile();
-	scheduleSave();
-	return true;
+    auto patch = getComponent(index);
+    if (!patch->isRemovable())
+    {
+        qWarning() << "Patch" << patch->getID() << "is non-removable";
+        return false;
+    }
+
+    if(!removeComponent_internal(patch))
+    {
+        qCritical() << "Patch" << patch->getID() << "could not be removed";
+        return false;
+    }
+
+    beginRemoveRows(QModelIndex(), index, index);
+    d->components.removeAt(index);
+    d->componentIndex.remove(patch->getID());
+    endRemoveRows();
+    invalidateLaunchProfile();
+    scheduleSave();
+    return true;
 }
 
 bool ComponentList::remove(const QString id)
 {
-	int i = 0;
-	for (auto patch : d->components)
-	{
-		if (patch->getID() == id)
-		{
-			return remove(i);
-		}
-		i++;
-	}
-	return false;
+    int i = 0;
+    for (auto patch : d->components)
+    {
+        if (patch->getID() == id)
+        {
+            return remove(i);
+        }
+        i++;
+    }
+    return false;
 }
 
 bool ComponentList::customize(int index)
 {
-	auto patch = getComponent(index);
-	if (!patch->isCustomizable())
-	{
-		qDebug() << "Patch" << patch->getID() << "is not customizable";
-		return false;
-	}
-	if(!patch->customize())
-	{
-		qCritical() << "Patch" << patch->getID() << "could not be customized";
-		return false;
-	}
-	invalidateLaunchProfile();
-	scheduleSave();
-	return true;
+    auto patch = getComponent(index);
+    if (!patch->isCustomizable())
+    {
+        qDebug() << "Patch" << patch->getID() << "is not customizable";
+        return false;
+    }
+    if(!patch->customize())
+    {
+        qCritical() << "Patch" << patch->getID() << "could not be customized";
+        return false;
+    }
+    invalidateLaunchProfile();
+    scheduleSave();
+    return true;
 }
 
 bool ComponentList::revertToBase(int index)
 {
-	auto patch = getComponent(index);
-	if (!patch->isRevertible())
-	{
-		qDebug() << "Patch" << patch->getID() << "is not revertible";
-		return false;
-	}
-	if(!patch->revert())
-	{
-		qCritical() << "Patch" << patch->getID() << "could not be reverted";
-		return false;
-	}
-	invalidateLaunchProfile();
-	scheduleSave();
-	return true;
+    auto patch = getComponent(index);
+    if (!patch->isRevertible())
+    {
+        qDebug() << "Patch" << patch->getID() << "is not revertible";
+        return false;
+    }
+    if(!patch->revert())
+    {
+        qCritical() << "Patch" << patch->getID() << "could not be reverted";
+        return false;
+    }
+    invalidateLaunchProfile();
+    scheduleSave();
+    return true;
 }
 
 Component * ComponentList::getComponent(const QString &id)
 {
-	auto iter = d->componentIndex.find(id);
-	if (iter == d->componentIndex.end())
-	{
-		return nullptr;
-	}
-	return (*iter).get();
+    auto iter = d->componentIndex.find(id);
+    if (iter == d->componentIndex.end())
+    {
+        return nullptr;
+    }
+    return (*iter).get();
 }
 
 Component * ComponentList::getComponent(int index)
 {
-	if(index < 0 || index >= d->components.size())
-	{
-		return nullptr;
-	}
-	return d->components[index].get();
+    if(index < 0 || index >= d->components.size())
+    {
+        return nullptr;
+    }
+    return d->components[index].get();
 }
 
 QVariant ComponentList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	int row = index.row();
-	int column = index.column();
-
-	if (row < 0 || row >= d->components.size())
-		return QVariant();
-
-	auto patch = d->components.at(row);
-
-	switch (role)
-	{
-	case Qt::CheckStateRole:
-	{
-		switch (column)
-		{
-			case NameColumn:
-				return d->components.at(row)->isEnabled() ? Qt::Checked : Qt::Unchecked;
-			default:
-				return QVariant();
-		}
-	}
-	case Qt::DisplayRole:
-	{
-		switch (column)
-		{
-		case NameColumn:
-			return d->components.at(row)->getName();
-		case VersionColumn:
-		{
-			if(patch->isCustom())
-			{
-				return QString("%1 (Custom)").arg(patch->getVersion());
-			}
-			else
-			{
-				return patch->getVersion();
-			}
-		}
-		default:
-			return QVariant();
-		}
-	}
-	case Qt::DecorationRole:
-	{
-		switch(column)
-		{
-		case NameColumn:
-		{
-			auto severity = patch->getProblemSeverity();
-			switch (severity)
-			{
-				case ProblemSeverity::Warning:
-					return "warning";
-				case ProblemSeverity::Error:
-					return "error";
-				default:
-					return QVariant();
-			}
-		}
-		default:
-		{
-			return QVariant();
-		}
-		}
-	}
-	}
-	return QVariant();
+    if (!index.isValid())
+        return QVariant();
+
+    int row = index.row();
+    int column = index.column();
+
+    if (row < 0 || row >= d->components.size())
+        return QVariant();
+
+    auto patch = d->components.at(row);
+
+    switch (role)
+    {
+    case Qt::CheckStateRole:
+    {
+        switch (column)
+        {
+            case NameColumn:
+                return d->components.at(row)->isEnabled() ? Qt::Checked : Qt::Unchecked;
+            default:
+                return QVariant();
+        }
+    }
+    case Qt::DisplayRole:
+    {
+        switch (column)
+        {
+        case NameColumn:
+            return d->components.at(row)->getName();
+        case VersionColumn:
+        {
+            if(patch->isCustom())
+            {
+                return QString("%1 (Custom)").arg(patch->getVersion());
+            }
+            else
+            {
+                return patch->getVersion();
+            }
+        }
+        default:
+            return QVariant();
+        }
+    }
+    case Qt::DecorationRole:
+    {
+        switch(column)
+        {
+        case NameColumn:
+        {
+            auto severity = patch->getProblemSeverity();
+            switch (severity)
+            {
+                case ProblemSeverity::Warning:
+                    return "warning";
+                case ProblemSeverity::Error:
+                    return "error";
+                default:
+                    return QVariant();
+            }
+        }
+        default:
+        {
+            return QVariant();
+        }
+        }
+    }
+    }
+    return QVariant();
 }
 
 bool ComponentList::setData(const QModelIndex& index, const QVariant& value, int role)
 {
-	if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
-	{
-		return false;
-	}
-
-	if (role == Qt::CheckStateRole)
-	{
-		auto component = d->components[index.row()];
-		if (component->setEnabled(!component->isEnabled()))
-		{
-			return true;
-		}
-	}
-	return false;
+    if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
+    {
+        return false;
+    }
+
+    if (role == Qt::CheckStateRole)
+    {
+        auto component = d->components[index.row()];
+        if (component->setEnabled(!component->isEnabled()))
+        {
+            return true;
+        }
+    }
+    return false;
 }
 
 QVariant ComponentList::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	if (orientation == Qt::Horizontal)
-	{
-		if (role == Qt::DisplayRole)
-		{
-			switch (section)
-			{
-			case NameColumn:
-				return tr("Name");
-			case VersionColumn:
-				return tr("Version");
-			default:
-				return QVariant();
-			}
-		}
-	}
-	return QVariant();
+    if (orientation == Qt::Horizontal)
+    {
+        if (role == Qt::DisplayRole)
+        {
+            switch (section)
+            {
+            case NameColumn:
+                return tr("Name");
+            case VersionColumn:
+                return tr("Version");
+            default:
+                return QVariant();
+            }
+        }
+    }
+    return QVariant();
 }
 Qt::ItemFlags ComponentList::flags(const QModelIndex &index) const
 {
-	if (!index.isValid())
-		return Qt::NoItemFlags;
+    if (!index.isValid())
+        return Qt::NoItemFlags;
 
-	Qt::ItemFlags outFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+    Qt::ItemFlags outFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
 
-	int row = index.row();
+    int row = index.row();
 
-	if (row < 0 || row >= d->components.size())
-		return Qt::NoItemFlags;
+    if (row < 0 || row >= d->components.size())
+        return Qt::NoItemFlags;
 
-	auto patch = d->components.at(row);
-	// TODO: this will need fine-tuning later...
-	if(patch->canBeDisabled())
-	{
-		outFlags |= Qt::ItemIsUserCheckable;
-	}
-	return outFlags;
+    auto patch = d->components.at(row);
+    // TODO: this will need fine-tuning later...
+    if(patch->canBeDisabled())
+    {
+        outFlags |= Qt::ItemIsUserCheckable;
+    }
+    return outFlags;
 }
 
 int ComponentList::rowCount(const QModelIndex &parent) const
 {
-	return d->components.size();
+    return d->components.size();
 }
 
 int ComponentList::columnCount(const QModelIndex &parent) const
 {
-	return NUM_COLUMNS;
+    return NUM_COLUMNS;
 }
 
 void ComponentList::move(const int index, const MoveDirection direction)
 {
-	int theirIndex;
-	if (direction == MoveUp)
-	{
-		theirIndex = index - 1;
-	}
-	else
-	{
-		theirIndex = index + 1;
-	}
-
-	if (index < 0 || index >= d->components.size())
-		return;
-	if (theirIndex >= rowCount())
-		theirIndex = rowCount() - 1;
-	if (theirIndex == -1)
-		theirIndex = rowCount() - 1;
-	if (index == theirIndex)
-		return;
-	int togap = theirIndex > index ? theirIndex + 1 : theirIndex;
-
-	auto from = getComponent(index);
-	auto to = getComponent(theirIndex);
-
-	if (!from || !to || !to->isMoveable() || !from->isMoveable())
-	{
-		return;
-	}
-	beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap);
-	d->components.swap(index, theirIndex);
-	endMoveRows();
-	invalidateLaunchProfile();
-	scheduleSave();
+    int theirIndex;
+    if (direction == MoveUp)
+    {
+        theirIndex = index - 1;
+    }
+    else
+    {
+        theirIndex = index + 1;
+    }
+
+    if (index < 0 || index >= d->components.size())
+        return;
+    if (theirIndex >= rowCount())
+        theirIndex = rowCount() - 1;
+    if (theirIndex == -1)
+        theirIndex = rowCount() - 1;
+    if (index == theirIndex)
+        return;
+    int togap = theirIndex > index ? theirIndex + 1 : theirIndex;
+
+    auto from = getComponent(index);
+    auto to = getComponent(theirIndex);
+
+    if (!from || !to || !to->isMoveable() || !from->isMoveable())
+    {
+        return;
+    }
+    beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap);
+    d->components.swap(index, theirIndex);
+    endMoveRows();
+    invalidateLaunchProfile();
+    scheduleSave();
 }
 
 void ComponentList::invalidateLaunchProfile()
 {
-	d->m_profile.reset();
+    d->m_profile.reset();
 }
 
 void ComponentList::installJarMods(QStringList selectedFiles)
 {
-	installJarMods_internal(selectedFiles);
+    installJarMods_internal(selectedFiles);
 }
 
 void ComponentList::installCustomJar(QString selectedFile)
 {
-	installCustomJar_internal(selectedFile);
+    installCustomJar_internal(selectedFile);
 }
 
 bool ComponentList::installEmpty(const QString& uid, const QString& name)
 {
-	QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
-	if(!FS::ensureFolderPathExists(patchDir))
-	{
-		return false;
-	}
-	auto f = std::make_shared<VersionFile>();
-	f->name = name;
-	f->uid = uid;
-	f->version = "1";
-	QString patchFileName = FS::PathCombine(patchDir, uid + ".json");
-	QFile file(patchFileName);
-	if (!file.open(QFile::WriteOnly))
-	{
-		qCritical() << "Error opening" << file.fileName()
-					<< "for reading:" << file.errorString();
-		return false;
-	}
-	file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
-	file.close();
-
-	appendComponent(new Component(this, f->uid, f));
-	scheduleSave();
-	invalidateLaunchProfile();
-	return true;
+    QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
+    if(!FS::ensureFolderPathExists(patchDir))
+    {
+        return false;
+    }
+    auto f = std::make_shared<VersionFile>();
+    f->name = name;
+    f->uid = uid;
+    f->version = "1";
+    QString patchFileName = FS::PathCombine(patchDir, uid + ".json");
+    QFile file(patchFileName);
+    if (!file.open(QFile::WriteOnly))
+    {
+        qCritical() << "Error opening" << file.fileName()
+                    << "for reading:" << file.errorString();
+        return false;
+    }
+    file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
+    file.close();
+
+    appendComponent(new Component(this, f->uid, f));
+    scheduleSave();
+    invalidateLaunchProfile();
+    return true;
 }
 
 bool ComponentList::removeComponent_internal(ComponentPtr patch)
 {
-	bool ok = true;
-	// first, remove the patch file. this ensures it's not used anymore
-	auto fileName = patch->getFilename();
-	if(fileName.size())
-	{
-		QFile patchFile(fileName);
-		if(patchFile.exists() && !patchFile.remove())
-		{
-			qCritical() << "File" << fileName << "could not be removed because:" << patchFile.errorString();
-			return false;
-		}
-	}
-
-	// FIXME: we need a generic way of removing local resources, not just jar mods...
-	auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool
-	{
-		if (!jarMod->isLocal())
-		{
-			return true;
-		}
-		QStringList jar, temp1, temp2, temp3;
-		jarMod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, d->m_instance->jarmodsPath().absolutePath());
-		QFileInfo finfo (jar[0]);
-		if(finfo.exists())
-		{
-			QFile jarModFile(jar[0]);
-			if(!jarModFile.remove())
-			{
-				qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString();
-				return false;
-			}
-			return true;
-		}
-		return true;
-	};
-
-	auto vFile = patch->getVersionFile();
-	if(vFile)
-	{
-		auto &jarMods = vFile->jarMods;
-		for(auto &jarmod: jarMods)
-		{
-			ok &= preRemoveJarMod(jarmod);
-		}
-	}
-	return ok;
+    bool ok = true;
+    // first, remove the patch file. this ensures it's not used anymore
+    auto fileName = patch->getFilename();
+    if(fileName.size())
+    {
+        QFile patchFile(fileName);
+        if(patchFile.exists() && !patchFile.remove())
+        {
+            qCritical() << "File" << fileName << "could not be removed because:" << patchFile.errorString();
+            return false;
+        }
+    }
+
+    // FIXME: we need a generic way of removing local resources, not just jar mods...
+    auto preRemoveJarMod = [&](LibraryPtr jarMod) -> bool
+    {
+        if (!jarMod->isLocal())
+        {
+            return true;
+        }
+        QStringList jar, temp1, temp2, temp3;
+        jarMod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, d->m_instance->jarmodsPath().absolutePath());
+        QFileInfo finfo (jar[0]);
+        if(finfo.exists())
+        {
+            QFile jarModFile(jar[0]);
+            if(!jarModFile.remove())
+            {
+                qCritical() << "File" << jar[0] << "could not be removed because:" << jarModFile.errorString();
+                return false;
+            }
+            return true;
+        }
+        return true;
+    };
+
+    auto vFile = patch->getVersionFile();
+    if(vFile)
+    {
+        auto &jarMods = vFile->jarMods;
+        for(auto &jarmod: jarMods)
+        {
+            ok &= preRemoveJarMod(jarmod);
+        }
+    }
+    return ok;
 }
 
 bool ComponentList::installJarMods_internal(QStringList filepaths)
 {
-	QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
-	if(!FS::ensureFolderPathExists(patchDir))
-	{
-		return false;
-	}
-
-	if (!FS::ensureFolderPathExists(d->m_instance->jarModsDir()))
-	{
-		return false;
-	}
-
-	for(auto filepath:filepaths)
-	{
-		QFileInfo sourceInfo(filepath);
-		auto uuid = QUuid::createUuid();
-		QString id = uuid.toString().remove('{').remove('}');
-		QString target_filename = id + ".jar";
-		QString target_id = "org.multimc.jarmod." + id;
-		QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
-		QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename);
-
-		QFileInfo targetInfo(finalPath);
-		if(targetInfo.exists())
-		{
-			return false;
-		}
-
-		if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
-		{
-			return false;
-		}
-
-		auto f = std::make_shared<VersionFile>();
-		auto jarMod = std::make_shared<Library>();
-		jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1"));
-		jarMod->setFilename(target_filename);
-		jarMod->setDisplayName(sourceInfo.completeBaseName());
-		jarMod->setHint("local");
-		f->jarMods.append(jarMod);
-		f->name = target_name;
-		f->uid = target_id;
-		QString patchFileName = FS::PathCombine(patchDir, target_id + ".json");
-
-		QFile file(patchFileName);
-		if (!file.open(QFile::WriteOnly))
-		{
-			qCritical() << "Error opening" << file.fileName()
-						<< "for reading:" << file.errorString();
-			return false;
-		}
-		file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
-		file.close();
-
-		appendComponent(new Component(this, f->uid, f));
-	}
-	scheduleSave();
-	invalidateLaunchProfile();
-	return true;
+    QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
+    if(!FS::ensureFolderPathExists(patchDir))
+    {
+        return false;
+    }
+
+    if (!FS::ensureFolderPathExists(d->m_instance->jarModsDir()))
+    {
+        return false;
+    }
+
+    for(auto filepath:filepaths)
+    {
+        QFileInfo sourceInfo(filepath);
+        auto uuid = QUuid::createUuid();
+        QString id = uuid.toString().remove('{').remove('}');
+        QString target_filename = id + ".jar";
+        QString target_id = "org.multimc.jarmod." + id;
+        QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
+        QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename);
+
+        QFileInfo targetInfo(finalPath);
+        if(targetInfo.exists())
+        {
+            return false;
+        }
+
+        if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
+        {
+            return false;
+        }
+
+        auto f = std::make_shared<VersionFile>();
+        auto jarMod = std::make_shared<Library>();
+        jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1"));
+        jarMod->setFilename(target_filename);
+        jarMod->setDisplayName(sourceInfo.completeBaseName());
+        jarMod->setHint("local");
+        f->jarMods.append(jarMod);
+        f->name = target_name;
+        f->uid = target_id;
+        QString patchFileName = FS::PathCombine(patchDir, target_id + ".json");
+
+        QFile file(patchFileName);
+        if (!file.open(QFile::WriteOnly))
+        {
+            qCritical() << "Error opening" << file.fileName()
+                        << "for reading:" << file.errorString();
+            return false;
+        }
+        file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
+        file.close();
+
+        appendComponent(new Component(this, f->uid, f));
+    }
+    scheduleSave();
+    invalidateLaunchProfile();
+    return true;
 }
 
 bool ComponentList::installCustomJar_internal(QString filepath)
 {
-	QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
-	if(!FS::ensureFolderPathExists(patchDir))
-	{
-		return false;
-	}
-
-	QString libDir = d->m_instance->getLocalLibraryPath();
-	if (!FS::ensureFolderPathExists(libDir))
-	{
-		return false;
-	}
-
-	auto specifier = GradleSpecifier("org.multimc:customjar:1");
-	QFileInfo sourceInfo(filepath);
-	QString target_filename = specifier.getFileName();
-	QString target_id = specifier.artifactId();
-	QString target_name = sourceInfo.completeBaseName() + " (custom jar)";
-	QString finalPath = FS::PathCombine(libDir, target_filename);
-
-	QFileInfo jarInfo(finalPath);
-	if (jarInfo.exists())
-	{
-		if(!QFile::remove(finalPath))
-		{
-			return false;
-		}
-	}
-	if (!QFile::copy(filepath, finalPath))
-	{
-		return false;
-	}
-
-	auto f = std::make_shared<VersionFile>();
-	auto jarMod = std::make_shared<Library>();
-	jarMod->setRawName(specifier);
-	jarMod->setDisplayName(sourceInfo.completeBaseName());
-	jarMod->setHint("local");
-	f->mainJar = jarMod;
-	f->name = target_name;
-	f->uid = target_id;
-	QString patchFileName = FS::PathCombine(patchDir, target_id + ".json");
-
-	QFile file(patchFileName);
-	if (!file.open(QFile::WriteOnly))
-	{
-		qCritical() << "Error opening" << file.fileName()
-					<< "for reading:" << file.errorString();
-		return false;
-	}
-	file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
-	file.close();
-
-	appendComponent(new Component(this, f->uid, f));
-
-	scheduleSave();
-	invalidateLaunchProfile();
-	return true;
+    QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
+    if(!FS::ensureFolderPathExists(patchDir))
+    {
+        return false;
+    }
+
+    QString libDir = d->m_instance->getLocalLibraryPath();
+    if (!FS::ensureFolderPathExists(libDir))
+    {
+        return false;
+    }
+
+    auto specifier = GradleSpecifier("org.multimc:customjar:1");
+    QFileInfo sourceInfo(filepath);
+    QString target_filename = specifier.getFileName();
+    QString target_id = specifier.artifactId();
+    QString target_name = sourceInfo.completeBaseName() + " (custom jar)";
+    QString finalPath = FS::PathCombine(libDir, target_filename);
+
+    QFileInfo jarInfo(finalPath);
+    if (jarInfo.exists())
+    {
+        if(!QFile::remove(finalPath))
+        {
+            return false;
+        }
+    }
+    if (!QFile::copy(filepath, finalPath))
+    {
+        return false;
+    }
+
+    auto f = std::make_shared<VersionFile>();
+    auto jarMod = std::make_shared<Library>();
+    jarMod->setRawName(specifier);
+    jarMod->setDisplayName(sourceInfo.completeBaseName());
+    jarMod->setHint("local");
+    f->mainJar = jarMod;
+    f->name = target_name;
+    f->uid = target_id;
+    QString patchFileName = FS::PathCombine(patchDir, target_id + ".json");
+
+    QFile file(patchFileName);
+    if (!file.open(QFile::WriteOnly))
+    {
+        qCritical() << "Error opening" << file.fileName()
+                    << "for reading:" << file.errorString();
+        return false;
+    }
+    file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
+    file.close();
+
+    appendComponent(new Component(this, f->uid, f));
+
+    scheduleSave();
+    invalidateLaunchProfile();
+    return true;
 }
 
 std::shared_ptr<LaunchProfile> ComponentList::getProfile() const
 {
-	if(!d->m_profile)
-	{
-		try
-		{
-			auto profile = std::make_shared<LaunchProfile>();
-			for(auto file: d->components)
-			{
-				qDebug() << "Applying" << file->getID() << (file->getProblemSeverity() == ProblemSeverity::Error ? "ERROR" : "GOOD");
-				file->applyTo(profile.get());
-			}
-			d->m_profile = profile;
-		}
-		catch (const Exception &error)
-		{
-			qWarning() << "Couldn't apply profile patches because: " << error.cause();
-		}
-	}
-	return d->m_profile;
+    if(!d->m_profile)
+    {
+        try
+        {
+            auto profile = std::make_shared<LaunchProfile>();
+            for(auto file: d->components)
+            {
+                qDebug() << "Applying" << file->getID() << (file->getProblemSeverity() == ProblemSeverity::Error ? "ERROR" : "GOOD");
+                file->applyTo(profile.get());
+            }
+            d->m_profile = profile;
+        }
+        catch (const Exception &error)
+        {
+            qWarning() << "Couldn't apply profile patches because: " << error.cause();
+        }
+    }
+    return d->m_profile;
 }
 
 void ComponentList::setOldConfigVersion(const QString& uid, const QString& version)
 {
-	if(version.isEmpty())
-	{
-		return;
-	}
-	d->m_oldConfigVersions[uid] = version;
+    if(version.isEmpty())
+    {
+        return;
+    }
+    d->m_oldConfigVersions[uid] = version;
 }
 
 bool ComponentList::setComponentVersion(const QString& uid, const QString& version, bool important)
 {
-	auto iter = d->componentIndex.find(uid);
-	if(iter != d->componentIndex.end())
-	{
-		ComponentPtr component = *iter;
-		// set existing
-		if(component->revert())
-		{
-			component->setVersion(version);
-			component->setImportant(important);
-			return true;
-		}
-		return false;
-	}
-	else
-	{
-		// add new
-		auto component = new Component(this, uid);
-		component->m_version = version;
-		component->m_important = important;
-		appendComponent(component);
-		return true;
-	}
+    auto iter = d->componentIndex.find(uid);
+    if(iter != d->componentIndex.end())
+    {
+        ComponentPtr component = *iter;
+        // set existing
+        if(component->revert())
+        {
+            component->setVersion(version);
+            component->setImportant(important);
+            return true;
+        }
+        return false;
+    }
+    else
+    {
+        // add new
+        auto component = new Component(this, uid);
+        component->m_version = version;
+        component->m_important = important;
+        appendComponent(component);
+        return true;
+    }
 }
 
 QString ComponentList::getComponentVersion(const QString& uid) const
 {
-	const auto iter = d->componentIndex.find(uid);
-	if (iter != d->componentIndex.end())
-	{
-		return (*iter)->getVersion();
-	}
-	return QString();
+    const auto iter = d->componentIndex.find(uid);
+    if (iter != d->componentIndex.end())
+    {
+        return (*iter)->getVersion();
+    }
+    return QString();
 }
diff --git a/api/logic/minecraft/ComponentList.h b/api/logic/minecraft/ComponentList.h
index cf4d9975..6ddc09eb 100644
--- a/api/logic/minecraft/ComponentList.h
+++ b/api/logic/minecraft/ComponentList.h
@@ -36,111 +36,111 @@ class ComponentUpdateTask;
 
 class MULTIMC_LOGIC_EXPORT ComponentList : public QAbstractListModel
 {
-	Q_OBJECT
-	friend ComponentUpdateTask;
+    Q_OBJECT
+    friend ComponentUpdateTask;
 public:
-	enum Columns
-	{
-		NameColumn = 0,
-		VersionColumn,
-		NUM_COLUMNS
-	};
+    enum Columns
+    {
+        NameColumn = 0,
+        VersionColumn,
+        NUM_COLUMNS
+    };
 
-	explicit ComponentList(MinecraftInstance * instance);
-	virtual ~ComponentList();
+    explicit ComponentList(MinecraftInstance * instance);
+    virtual ~ComponentList();
 
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-	virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
-	virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
-	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-	virtual int columnCount(const QModelIndex &parent) const override;
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    virtual int columnCount(const QModelIndex &parent) const override;
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
 
-	/// call this to explicitly mark the component list as loaded - this is used to build a new component list from scratch.
-	void buildingFromScratch();
+    /// call this to explicitly mark the component list as loaded - this is used to build a new component list from scratch.
+    void buildingFromScratch();
 
-	/// install more jar mods
-	void installJarMods(QStringList selectedFiles);
+    /// install more jar mods
+    void installJarMods(QStringList selectedFiles);
 
-	/// install a jar/zip as a replacement for the main jar
-	void installCustomJar(QString selectedFile);
+    /// install a jar/zip as a replacement for the main jar
+    void installCustomJar(QString selectedFile);
 
-	enum MoveDirection { MoveUp, MoveDown };
-	/// move component file # up or down the list
-	void move(const int index, const MoveDirection direction);
+    enum MoveDirection { MoveUp, MoveDown };
+    /// move component file # up or down the list
+    void move(const int index, const MoveDirection direction);
 
-	/// remove component file # - including files/records
-	bool remove(const int index);
+    /// remove component file # - including files/records
+    bool remove(const int index);
 
-	/// remove component file by id - including files/records
-	bool remove(const QString id);
+    /// remove component file by id - including files/records
+    bool remove(const QString id);
 
-	bool customize(int index);
+    bool customize(int index);
 
-	bool revertToBase(int index);
+    bool revertToBase(int index);
 
-	/// reload the list, reload all components, resolve dependencies
-	void reload(Net::Mode netmode);
+    /// reload the list, reload all components, resolve dependencies
+    void reload(Net::Mode netmode);
 
-	// reload all components, resolve dependencies
-	void resolve(Net::Mode netmode);
+    // reload all components, resolve dependencies
+    void resolve(Net::Mode netmode);
 
-	/// get current running task...
-	shared_qobject_ptr<Task> getCurrentTask();
+    /// get current running task...
+    shared_qobject_ptr<Task> getCurrentTask();
 
-	std::shared_ptr<LaunchProfile> getProfile() const;
+    std::shared_ptr<LaunchProfile> getProfile() const;
 
-	// NOTE: used ONLY by MinecraftInstance to provide legacy version mappings from instance config
-	void setOldConfigVersion(const QString &uid, const QString &version);
+    // NOTE: used ONLY by MinecraftInstance to provide legacy version mappings from instance config
+    void setOldConfigVersion(const QString &uid, const QString &version);
 
-	QString getComponentVersion(const QString &uid) const;
+    QString getComponentVersion(const QString &uid) const;
 
-	bool setComponentVersion(const QString &uid, const QString &version, bool important = false);
+    bool setComponentVersion(const QString &uid, const QString &version, bool important = false);
 
-	bool installEmpty(const QString &uid, const QString &name);
+    bool installEmpty(const QString &uid, const QString &name);
 
-	QString patchFilePathForUid(const QString &uid) const;
+    QString patchFilePathForUid(const QString &uid) const;
 
-	/// if there is a save scheduled, do it now.
-	void saveNow();
+    /// if there is a save scheduled, do it now.
+    void saveNow();
 
 public:
-	/// get the profile component by id
-	Component * getComponent(const QString &id);
+    /// get the profile component by id
+    Component * getComponent(const QString &id);
 
-	/// get the profile component by index
-	Component * getComponent(int index);
+    /// get the profile component by index
+    Component * getComponent(int index);
 
 private:
-	void scheduleSave();
-	bool saveIsScheduled() const;
+    void scheduleSave();
+    bool saveIsScheduled() const;
 
-	/// apply the component patches. Catches all the errors and returns true/false for success/failure
-	void invalidateLaunchProfile();
+    /// apply the component patches. Catches all the errors and returns true/false for success/failure
+    void invalidateLaunchProfile();
 
-	/// Add the component to the internal list of patches
-	void appendComponent(ComponentPtr component);
-	/// insert component so that its index is ideally the specified one (returns real index)
-	void insertComponent(size_t index, ComponentPtr component);
+    /// Add the component to the internal list of patches
+    void appendComponent(ComponentPtr component);
+    /// insert component so that its index is ideally the specified one (returns real index)
+    void insertComponent(size_t index, ComponentPtr component);
 
-	QString componentsFilePath() const;
-	QString patchesPattern() const;
+    QString componentsFilePath() const;
+    QString patchesPattern() const;
 
 private slots:
-	void save_internal();
-	void updateSucceeded();
-	void updateFailed(const QString & error);
-	void componentDataChanged();
+    void save_internal();
+    void updateSucceeded();
+    void updateFailed(const QString & error);
+    void componentDataChanged();
 
 private:
-	bool load();
-	bool installJarMods_internal(QStringList filepaths);
+    bool load();
+    bool installJarMods_internal(QStringList filepaths);
     bool installCustomJar_internal(QString filepath);
-	bool removeComponent_internal(ComponentPtr patch);
+    bool removeComponent_internal(ComponentPtr patch);
 
-	bool migratePreComponentConfig();
+    bool migratePreComponentConfig();
 
 private: /* data */
 
-	std::unique_ptr<ComponentListData> d;
+    std::unique_ptr<ComponentListData> d;
 };
diff --git a/api/logic/minecraft/ComponentList_p.h b/api/logic/minecraft/ComponentList_p.h
index 26ca5049..aed65337 100644
--- a/api/logic/minecraft/ComponentList_p.h
+++ b/api/logic/minecraft/ComponentList_p.h
@@ -13,30 +13,30 @@ using ConnectionList = QList<QMetaObject::Connection>;
 
 struct ComponentListData
 {
-	// the instance this belongs to
-	MinecraftInstance *m_instance;
+    // the instance this belongs to
+    MinecraftInstance *m_instance;
 
-	// the launch profile (volatile, temporary thing created on demand)
-	std::shared_ptr<LaunchProfile> m_profile;
+    // the launch profile (volatile, temporary thing created on demand)
+    std::shared_ptr<LaunchProfile> m_profile;
 
-	// version information migrated from instance.cfg file. Single use on migration!
-	std::map<QString, QString> m_oldConfigVersions;
-	QString getOldConfigVersion(const QString& uid) const
-	{
-		const auto iter = m_oldConfigVersions.find(uid);
-		if(iter != m_oldConfigVersions.cend())
-		{
-			return (*iter).second;
-		}
-		return QString();
-	}
+    // version information migrated from instance.cfg file. Single use on migration!
+    std::map<QString, QString> m_oldConfigVersions;
+    QString getOldConfigVersion(const QString& uid) const
+    {
+        const auto iter = m_oldConfigVersions.find(uid);
+        if(iter != m_oldConfigVersions.cend())
+        {
+            return (*iter).second;
+        }
+        return QString();
+    }
 
-	// persistent list of components and related machinery
-	ComponentContainer components;
-	ComponentIndex componentIndex;
-	bool dirty = false;
-	QTimer m_saveTimer;
-	shared_qobject_ptr<Task> m_updateTask;
-	bool loaded = false;
+    // persistent list of components and related machinery
+    ComponentContainer components;
+    ComponentIndex componentIndex;
+    bool dirty = false;
+    QTimer m_saveTimer;
+    shared_qobject_ptr<Task> m_updateTask;
+    bool loaded = false;
 };
 
diff --git a/api/logic/minecraft/ComponentUpdateTask.cpp b/api/logic/minecraft/ComponentUpdateTask.cpp
index 2d6ceb91..37cc488d 100644
--- a/api/logic/minecraft/ComponentUpdateTask.cpp
+++ b/api/logic/minecraft/ComponentUpdateTask.cpp
@@ -32,12 +32,12 @@
  */
 
 ComponentUpdateTask::ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList* list, QObject* parent)
-	: Task(parent)
+    : Task(parent)
 {
-	d.reset(new ComponentUpdateTaskData);
-	d->m_list = list;
-	d->mode = mode;
-	d->netmode = netmode;
+    d.reset(new ComponentUpdateTaskData);
+    d->m_list = list;
+    d->mode = mode;
+    d->netmode = netmode;
 }
 
 ComponentUpdateTask::~ComponentUpdateTask()
@@ -46,356 +46,356 @@ ComponentUpdateTask::~ComponentUpdateTask()
 
 void ComponentUpdateTask::executeTask()
 {
-	qDebug() << "Loading components";
-	loadComponents();
+    qDebug() << "Loading components";
+    loadComponents();
 }
 
 namespace
 {
 enum class LoadResult
 {
-	LoadedLocal,
-	RequiresRemote,
-	Failed
+    LoadedLocal,
+    RequiresRemote,
+    Failed
 };
 
 LoadResult composeLoadResult(LoadResult a, LoadResult b)
 {
-	if (a < b)
-	{
-		return b;
-	}
-	return a;
+    if (a < b)
+    {
+        return b;
+    }
+    return a;
 }
 
 static LoadResult loadComponent(ComponentPtr component, shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
 {
-	if(component->m_loaded)
-	{
-		qDebug() << component->getName() << "is already loaded";
-		return LoadResult::LoadedLocal;
-	}
-
-	LoadResult result = LoadResult::Failed;
-	auto customPatchFilename = component->getFilename();
-	if(QFile::exists(customPatchFilename))
-	{
-		// if local file exists...
-
-		// check for uid problems inside...
-		bool fileChanged = false;
-		auto file = ProfileUtils::parseJsonFile(QFileInfo(customPatchFilename), false);
-		if(file->uid != component->m_uid)
-		{
-			file->uid = component->m_uid;
-			fileChanged = true;
-		}
-		if(fileChanged)
-		{
-			// FIXME: @QUALITY do not ignore return value
-			ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), customPatchFilename);
-		}
-
-		component->m_file = file;
-		component->m_loaded = true;
-		result = LoadResult::LoadedLocal;
-	}
-	else
-	{
-		auto metaVersion = ENV.metadataIndex()->get(component->m_uid, component->m_version);
-		component->m_metaVersion = metaVersion;
-		if(metaVersion->isLoaded())
-		{
-			component->m_loaded = true;
-			result = LoadResult::LoadedLocal;
-		}
-		else
-		{
-			metaVersion->load(netmode);
-			loadTask = metaVersion->getCurrentTask();
-			if(loadTask)
-				result = LoadResult::RequiresRemote;
-			else if (metaVersion->isLoaded())
-				result = LoadResult::LoadedLocal;
-			else
-				result = LoadResult::Failed;
-		}
-	}
-	return result;
+    if(component->m_loaded)
+    {
+        qDebug() << component->getName() << "is already loaded";
+        return LoadResult::LoadedLocal;
+    }
+
+    LoadResult result = LoadResult::Failed;
+    auto customPatchFilename = component->getFilename();
+    if(QFile::exists(customPatchFilename))
+    {
+        // if local file exists...
+
+        // check for uid problems inside...
+        bool fileChanged = false;
+        auto file = ProfileUtils::parseJsonFile(QFileInfo(customPatchFilename), false);
+        if(file->uid != component->m_uid)
+        {
+            file->uid = component->m_uid;
+            fileChanged = true;
+        }
+        if(fileChanged)
+        {
+            // FIXME: @QUALITY do not ignore return value
+            ProfileUtils::saveJsonFile(OneSixVersionFormat::versionFileToJson(file), customPatchFilename);
+        }
+
+        component->m_file = file;
+        component->m_loaded = true;
+        result = LoadResult::LoadedLocal;
+    }
+    else
+    {
+        auto metaVersion = ENV.metadataIndex()->get(component->m_uid, component->m_version);
+        component->m_metaVersion = metaVersion;
+        if(metaVersion->isLoaded())
+        {
+            component->m_loaded = true;
+            result = LoadResult::LoadedLocal;
+        }
+        else
+        {
+            metaVersion->load(netmode);
+            loadTask = metaVersion->getCurrentTask();
+            if(loadTask)
+                result = LoadResult::RequiresRemote;
+            else if (metaVersion->isLoaded())
+                result = LoadResult::LoadedLocal;
+            else
+                result = LoadResult::Failed;
+        }
+    }
+    return result;
 }
 
 // FIXME: dead code. determine if this can still be useful?
 /*
 static LoadResult loadComponentList(ComponentPtr component, shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
 {
-	if(component->m_loaded)
-	{
-		qDebug() << component->getName() << "is already loaded";
-		return LoadResult::LoadedLocal;
-	}
-
-	LoadResult result = LoadResult::Failed;
-	auto metaList = ENV.metadataIndex()->get(component->m_uid);
-	if(metaList->isLoaded())
-	{
-		component->m_loaded = true;
-		result = LoadResult::LoadedLocal;
-	}
-	else
-	{
-		metaList->load(netmode);
-		loadTask = metaList->getCurrentTask();
-		result = LoadResult::RequiresRemote;
-	}
-	return result;
+    if(component->m_loaded)
+    {
+        qDebug() << component->getName() << "is already loaded";
+        return LoadResult::LoadedLocal;
+    }
+
+    LoadResult result = LoadResult::Failed;
+    auto metaList = ENV.metadataIndex()->get(component->m_uid);
+    if(metaList->isLoaded())
+    {
+        component->m_loaded = true;
+        result = LoadResult::LoadedLocal;
+    }
+    else
+    {
+        metaList->load(netmode);
+        loadTask = metaList->getCurrentTask();
+        result = LoadResult::RequiresRemote;
+    }
+    return result;
 }
 */
 
 static LoadResult loadIndex(shared_qobject_ptr<Task>& loadTask, Net::Mode netmode)
 {
-	// FIXME: DECIDE. do we want to run the update task anyway?
-	if(ENV.metadataIndex()->isLoaded())
-	{
-		qDebug() << "Index is already loaded";
-		return LoadResult::LoadedLocal;
-	}
-	ENV.metadataIndex()->load(netmode);
-	loadTask = ENV.metadataIndex()->getCurrentTask();
-	if(loadTask)
-	{
-		return LoadResult::RequiresRemote;
-	}
-	// FIXME: this is assuming the load succeeded... did it really?
-	return LoadResult::LoadedLocal;
+    // FIXME: DECIDE. do we want to run the update task anyway?
+    if(ENV.metadataIndex()->isLoaded())
+    {
+        qDebug() << "Index is already loaded";
+        return LoadResult::LoadedLocal;
+    }
+    ENV.metadataIndex()->load(netmode);
+    loadTask = ENV.metadataIndex()->getCurrentTask();
+    if(loadTask)
+    {
+        return LoadResult::RequiresRemote;
+    }
+    // FIXME: this is assuming the load succeeded... did it really?
+    return LoadResult::LoadedLocal;
 }
 }
 
 void ComponentUpdateTask::loadComponents()
 {
-	LoadResult result = LoadResult::LoadedLocal;
-	size_t taskIndex = 0;
-	size_t componentIndex = 0;
-	d->remoteLoadSuccessful = true;
-	// load the main index (it is needed to determine if components can revert)
-	{
-		// FIXME: tear out as a method? or lambda?
-		shared_qobject_ptr<Task> indexLoadTask;
-		auto singleResult = loadIndex(indexLoadTask, d->netmode);
-		result = composeLoadResult(result, singleResult);
-		if(indexLoadTask)
-		{
-			qDebug() << "Remote loading is being run for metadata index";
-			RemoteLoadStatus status;
-			status.type = RemoteLoadStatus::Type::Index;
-			d->remoteLoadStatusList.append(status);
-			connect(indexLoadTask.get(), &Task::succeeded, [=]()
-			{
-				remoteLoadSucceeded(taskIndex);
-			});
-			connect(indexLoadTask.get(), &Task::failed, [=](const QString & error)
-			{
-				remoteLoadFailed(taskIndex, error);
-			});
-			taskIndex++;
-		}
-	}
-	// load all the components OR their lists...
-	for (auto component: d->m_list->d->components)
-	{
-		shared_qobject_ptr<Task> loadTask;
-		LoadResult singleResult;
-		RemoteLoadStatus::Type loadType;
-		// FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now, ignore all that...
+    LoadResult result = LoadResult::LoadedLocal;
+    size_t taskIndex = 0;
+    size_t componentIndex = 0;
+    d->remoteLoadSuccessful = true;
+    // load the main index (it is needed to determine if components can revert)
+    {
+        // FIXME: tear out as a method? or lambda?
+        shared_qobject_ptr<Task> indexLoadTask;
+        auto singleResult = loadIndex(indexLoadTask, d->netmode);
+        result = composeLoadResult(result, singleResult);
+        if(indexLoadTask)
+        {
+            qDebug() << "Remote loading is being run for metadata index";
+            RemoteLoadStatus status;
+            status.type = RemoteLoadStatus::Type::Index;
+            d->remoteLoadStatusList.append(status);
+            connect(indexLoadTask.get(), &Task::succeeded, [=]()
+            {
+                remoteLoadSucceeded(taskIndex);
+            });
+            connect(indexLoadTask.get(), &Task::failed, [=](const QString & error)
+            {
+                remoteLoadFailed(taskIndex, error);
+            });
+            taskIndex++;
+        }
+    }
+    // load all the components OR their lists...
+    for (auto component: d->m_list->d->components)
+    {
+        shared_qobject_ptr<Task> loadTask;
+        LoadResult singleResult;
+        RemoteLoadStatus::Type loadType;
+        // FIXME: to do this right, we need to load the lists and decide on which versions to use during dependency resolution. For now, ignore all that...
 #if 0
-		switch(d->mode)
-		{
-			case Mode::Launch:
-			{
-				singleResult = loadComponent(component, loadTask, d->netmode);
-				loadType = RemoteLoadStatus::Type::Version;
-				break;
-			}
-			case Mode::Resolution:
-			{
-				singleResult = loadComponentList(component, loadTask, d->netmode);
-				loadType = RemoteLoadStatus::Type::List;
-				break;
-			}
-		}
+        switch(d->mode)
+        {
+            case Mode::Launch:
+            {
+                singleResult = loadComponent(component, loadTask, d->netmode);
+                loadType = RemoteLoadStatus::Type::Version;
+                break;
+            }
+            case Mode::Resolution:
+            {
+                singleResult = loadComponentList(component, loadTask, d->netmode);
+                loadType = RemoteLoadStatus::Type::List;
+                break;
+            }
+        }
 #else
-		singleResult = loadComponent(component, loadTask, d->netmode);
-		loadType = RemoteLoadStatus::Type::Version;
+        singleResult = loadComponent(component, loadTask, d->netmode);
+        loadType = RemoteLoadStatus::Type::Version;
 #endif
-		if(singleResult == LoadResult::LoadedLocal)
-		{
-			component->updateCachedData();
-		}
-		result = composeLoadResult(result, singleResult);
-		if (loadTask)
-		{
-			qDebug() << "Remote loading is being run for" << component->getName();
-			connect(loadTask.get(), &Task::succeeded, [=]()
-			{
-				remoteLoadSucceeded(taskIndex);
-			});
-			connect(loadTask.get(), &Task::failed, [=](const QString & error)
-			{
-				remoteLoadFailed(taskIndex, error);
-			});
-			RemoteLoadStatus status;
-			status.type = loadType;
-			status.componentListIndex = componentIndex;
-			d->remoteLoadStatusList.append(status);
-			taskIndex++;
-		}
-		componentIndex++;
-	}
-	d->remoteTasksInProgress = taskIndex;
-	switch(result)
-	{
-		case LoadResult::LoadedLocal:
-		{
-			// Everything got loaded. Advance to dependency resolution.
-			resolveDependencies(d->mode == Mode::Launch || d->netmode == Net::Mode::Offline);
-			break;
-		}
-		case LoadResult::RequiresRemote:
-		{
-			// we wait for signals.
-			break;
-		}
-		case LoadResult::Failed:
-		{
-			emitFailed(tr("Some component metadata load tasks failed."));
-			break;
-		}
-	}
+        if(singleResult == LoadResult::LoadedLocal)
+        {
+            component->updateCachedData();
+        }
+        result = composeLoadResult(result, singleResult);
+        if (loadTask)
+        {
+            qDebug() << "Remote loading is being run for" << component->getName();
+            connect(loadTask.get(), &Task::succeeded, [=]()
+            {
+                remoteLoadSucceeded(taskIndex);
+            });
+            connect(loadTask.get(), &Task::failed, [=](const QString & error)
+            {
+                remoteLoadFailed(taskIndex, error);
+            });
+            RemoteLoadStatus status;
+            status.type = loadType;
+            status.componentListIndex = componentIndex;
+            d->remoteLoadStatusList.append(status);
+            taskIndex++;
+        }
+        componentIndex++;
+    }
+    d->remoteTasksInProgress = taskIndex;
+    switch(result)
+    {
+        case LoadResult::LoadedLocal:
+        {
+            // Everything got loaded. Advance to dependency resolution.
+            resolveDependencies(d->mode == Mode::Launch || d->netmode == Net::Mode::Offline);
+            break;
+        }
+        case LoadResult::RequiresRemote:
+        {
+            // we wait for signals.
+            break;
+        }
+        case LoadResult::Failed:
+        {
+            emitFailed(tr("Some component metadata load tasks failed."));
+            break;
+        }
+    }
 }
 
 namespace
 {
-	struct RequireEx : public Meta::Require
-	{
-		size_t indexOfFirstDependee = 0;
-	};
-	struct RequireCompositionResult
-	{
-		bool ok;
-		RequireEx outcome;
-	};
-	using RequireExSet = std::set<RequireEx>;
+    struct RequireEx : public Meta::Require
+    {
+        size_t indexOfFirstDependee = 0;
+    };
+    struct RequireCompositionResult
+    {
+        bool ok;
+        RequireEx outcome;
+    };
+    using RequireExSet = std::set<RequireEx>;
 }
 
 static RequireCompositionResult composeRequirement(const RequireEx & a, const RequireEx & b)
 {
-	assert(a.uid == b.uid);
-	RequireEx out;
-	out.uid = a.uid;
-	out.indexOfFirstDependee = std::min(a.indexOfFirstDependee, b.indexOfFirstDependee);
-	if(a.equalsVersion.isEmpty())
-	{
-		out.equalsVersion = b.equalsVersion;
-	}
-	else if (b.equalsVersion.isEmpty())
-	{
-		out.equalsVersion = a.equalsVersion;
-	}
-	else if (a.equalsVersion == b.equalsVersion)
-	{
-		out.equalsVersion = a.equalsVersion;
-	}
-	else
-	{
-		// FIXME: mark error as explicit version conflict
-		return {false, out};
-	}
-
-	if(a.suggests.isEmpty())
-	{
-		out.suggests = b.suggests;
-	}
-	else if (b.suggests.isEmpty())
-	{
-		out.suggests = a.suggests;
-	}
-	else
-	{
-		Version aVer(a.suggests);
-		Version bVer(b.suggests);
-		out.suggests = (aVer < bVer ? b.suggests : a.suggests);
-	}
-	return {true, out};
+    assert(a.uid == b.uid);
+    RequireEx out;
+    out.uid = a.uid;
+    out.indexOfFirstDependee = std::min(a.indexOfFirstDependee, b.indexOfFirstDependee);
+    if(a.equalsVersion.isEmpty())
+    {
+        out.equalsVersion = b.equalsVersion;
+    }
+    else if (b.equalsVersion.isEmpty())
+    {
+        out.equalsVersion = a.equalsVersion;
+    }
+    else if (a.equalsVersion == b.equalsVersion)
+    {
+        out.equalsVersion = a.equalsVersion;
+    }
+    else
+    {
+        // FIXME: mark error as explicit version conflict
+        return {false, out};
+    }
+
+    if(a.suggests.isEmpty())
+    {
+        out.suggests = b.suggests;
+    }
+    else if (b.suggests.isEmpty())
+    {
+        out.suggests = a.suggests;
+    }
+    else
+    {
+        Version aVer(a.suggests);
+        Version bVer(b.suggests);
+        out.suggests = (aVer < bVer ? b.suggests : a.suggests);
+    }
+    return {true, out};
 }
 
 // gather the requirements from all components, finding any obvious conflicts
 static bool gatherRequirementsFromComponents(const ComponentContainer & input, RequireExSet & output)
 {
-	bool succeeded = true;
-	size_t componentNum = 0;
-	for(auto component: input)
-	{
-		auto &componentRequires = component->m_cachedRequires;
-		for(const auto & componentRequire: componentRequires)
-		{
-			auto found = std::find_if(output.cbegin(), output.cend(), [componentRequire](const Meta::Require & req){
-				return req.uid == componentRequire.uid;
-			});
-
-			RequireEx componenRequireEx;
-			componenRequireEx.uid = componentRequire.uid;
-			componenRequireEx.suggests = componentRequire.suggests;
-			componenRequireEx.equalsVersion = componentRequire.equalsVersion;
-			componenRequireEx.indexOfFirstDependee = componentNum;
-
-			if(found != output.cend())
-			{
-				// found... process it further
-				auto result = composeRequirement(componenRequireEx, *found);
-				if(result.ok)
-				{
-					output.erase(componenRequireEx);
-					output.insert(result.outcome);
-				}
-				else
-				{
-					qCritical()
-						<< "Conflicting requirements:"
-						<< componentRequire.uid
-						<< "versions:"
-						<< componentRequire.equalsVersion
-						<< ";"
-						<< (*found).equalsVersion;
-				}
-				succeeded &= result.ok;
-			}
-			else
-			{
-				// not found, accumulate
-				output.insert(componenRequireEx);
-			}
-		}
-		componentNum++;
-	}
-	return succeeded;
+    bool succeeded = true;
+    size_t componentNum = 0;
+    for(auto component: input)
+    {
+        auto &componentRequires = component->m_cachedRequires;
+        for(const auto & componentRequire: componentRequires)
+        {
+            auto found = std::find_if(output.cbegin(), output.cend(), [componentRequire](const Meta::Require & req){
+                return req.uid == componentRequire.uid;
+            });
+
+            RequireEx componenRequireEx;
+            componenRequireEx.uid = componentRequire.uid;
+            componenRequireEx.suggests = componentRequire.suggests;
+            componenRequireEx.equalsVersion = componentRequire.equalsVersion;
+            componenRequireEx.indexOfFirstDependee = componentNum;
+
+            if(found != output.cend())
+            {
+                // found... process it further
+                auto result = composeRequirement(componenRequireEx, *found);
+                if(result.ok)
+                {
+                    output.erase(componenRequireEx);
+                    output.insert(result.outcome);
+                }
+                else
+                {
+                    qCritical()
+                        << "Conflicting requirements:"
+                        << componentRequire.uid
+                        << "versions:"
+                        << componentRequire.equalsVersion
+                        << ";"
+                        << (*found).equalsVersion;
+                }
+                succeeded &= result.ok;
+            }
+            else
+            {
+                // not found, accumulate
+                output.insert(componenRequireEx);
+            }
+        }
+        componentNum++;
+    }
+    return succeeded;
 }
 
 /// Get list of uids that can be trivially removed because nothing is depending on them anymore (and they are installed as deps)
 static void getTrivialRemovals(const ComponentContainer & components, const RequireExSet & reqs, QStringList &toRemove)
 {
-	for(const auto & component: components)
-	{
-		if(!component->m_dependencyOnly)
-			continue;
-		if(!component->m_cachedVolatile)
-			continue;
-		RequireEx reqNeedle;
-		reqNeedle.uid = component->m_uid;
-		const auto iter = reqs.find(reqNeedle);
-		if(iter == reqs.cend())
-		{
-			toRemove.append(component->m_uid);
-		}
-	}
+    for(const auto & component: components)
+    {
+        if(!component->m_dependencyOnly)
+            continue;
+        if(!component->m_cachedVolatile)
+            continue;
+        RequireEx reqNeedle;
+        reqNeedle.uid = component->m_uid;
+        const auto iter = reqs.find(reqNeedle);
+        if(iter == reqs.cend())
+        {
+            toRemove.append(component->m_uid);
+        }
+    }
 }
 
 /**
@@ -408,86 +408,86 @@ static void getTrivialRemovals(const ComponentContainer & components, const Requ
  */
 static bool getTrivialComponentChanges(const ComponentIndex & index, const RequireExSet & input, RequireExSet & toAdd, RequireExSet & toChange)
 {
-	enum class Decision
-	{
-		Undetermined,
-		Met,
-		Missing,
-		VersionNotSame,
-		LockedVersionNotSame
-	} decision = Decision::Undetermined;
-
-	QString reqStr;
-	bool succeeded = true;
-	// list the composed requirements and say if they are met or unmet
-	for(auto & req: input)
-	{
-		do
-		{
-			if(req.equalsVersion.isEmpty())
-			{
-				reqStr = QString("Req: %1").arg(req.uid);
-				if(index.contains(req.uid))
-				{
-					decision = Decision::Met;
-				}
-				else
-				{
-					toAdd.insert(req);
-					decision = Decision::Missing;
-				}
-				break;
-			}
-			else
-			{
-				reqStr = QString("Req: %1 == %2").arg(req.uid, req.equalsVersion);
-				const auto & compIter = index.find(req.uid);
-				if(compIter == index.cend())
-				{
-					toAdd.insert(req);
-					decision = Decision::Missing;
-					break;
-				}
-				auto & comp = (*compIter);
-				if(comp->getVersion() != req.equalsVersion)
-				{
-					if(comp->m_dependencyOnly)
-					{
-						decision = Decision::VersionNotSame;
-					}
-					else
-					{
-						decision = Decision::LockedVersionNotSame;
-					}
-					break;
-				}
-				decision = Decision::Met;
-			}
-		} while(false);
-		switch(decision)
-		{
-			case Decision::Undetermined:
-				qCritical() << "No decision for" << reqStr;
-				succeeded = false;
-				break;
-			case Decision::Met:
-				qDebug() << reqStr << "Is met.";
-				break;
-			case Decision::Missing:
-				qDebug() << reqStr << "Is missing and should be added at" << req.indexOfFirstDependee;
-				toAdd.insert(req);
-				break;
-			case Decision::VersionNotSame:
-				qDebug() << reqStr << "already has different version that can be changed.";
-				toChange.insert(req);
-				break;
-			case Decision::LockedVersionNotSame:
-				qDebug() << reqStr << "already has different version that cannot be changed.";
-				succeeded = false;
-				break;
-		}
-	}
-	return succeeded;
+    enum class Decision
+    {
+        Undetermined,
+        Met,
+        Missing,
+        VersionNotSame,
+        LockedVersionNotSame
+    } decision = Decision::Undetermined;
+
+    QString reqStr;
+    bool succeeded = true;
+    // list the composed requirements and say if they are met or unmet
+    for(auto & req: input)
+    {
+        do
+        {
+            if(req.equalsVersion.isEmpty())
+            {
+                reqStr = QString("Req: %1").arg(req.uid);
+                if(index.contains(req.uid))
+                {
+                    decision = Decision::Met;
+                }
+                else
+                {
+                    toAdd.insert(req);
+                    decision = Decision::Missing;
+                }
+                break;
+            }
+            else
+            {
+                reqStr = QString("Req: %1 == %2").arg(req.uid, req.equalsVersion);
+                const auto & compIter = index.find(req.uid);
+                if(compIter == index.cend())
+                {
+                    toAdd.insert(req);
+                    decision = Decision::Missing;
+                    break;
+                }
+                auto & comp = (*compIter);
+                if(comp->getVersion() != req.equalsVersion)
+                {
+                    if(comp->m_dependencyOnly)
+                    {
+                        decision = Decision::VersionNotSame;
+                    }
+                    else
+                    {
+                        decision = Decision::LockedVersionNotSame;
+                    }
+                    break;
+                }
+                decision = Decision::Met;
+            }
+        } while(false);
+        switch(decision)
+        {
+            case Decision::Undetermined:
+                qCritical() << "No decision for" << reqStr;
+                succeeded = false;
+                break;
+            case Decision::Met:
+                qDebug() << reqStr << "Is met.";
+                break;
+            case Decision::Missing:
+                qDebug() << reqStr << "Is missing and should be added at" << req.indexOfFirstDependee;
+                toAdd.insert(req);
+                break;
+            case Decision::VersionNotSame:
+                qDebug() << reqStr << "already has different version that can be changed.";
+                toChange.insert(req);
+                break;
+            case Decision::LockedVersionNotSame:
+                qDebug() << reqStr << "already has different version that cannot be changed.";
+                succeeded = false;
+                break;
+        }
+    }
+    return succeeded;
 }
 
 // FIXME, TODO: decouple dependency resolution from loading
@@ -495,197 +495,197 @@ static bool getTrivialComponentChanges(const ComponentIndex & index, const Requi
 // FIXME: throw all this away and use a graph
 void ComponentUpdateTask::resolveDependencies(bool checkOnly)
 {
-	qDebug() << "Resolving dependencies";
-	/*
-	 * this is a naive dependency resolving algorithm. all it does is check for following conditions and react in simple ways:
-	 * 1. There are conflicting dependencies on the same uid with different exact version numbers
-	 *    -> hard error
-	 * 2. A dependency has non-matching exact version number
-	 *    -> hard error
-	 * 3. A dependency is entirely missing and needs to be injected before the dependee(s)
-	 *    -> requirements are injected
-	 *
-	 * NOTE: this is a placeholder and should eventually be replaced with something 'serious'
-	 */
-	auto & components = d->m_list->d->components;
-	auto & componentIndex = d->m_list->d->componentIndex;
-
-	RequireExSet allRequires;
-	QStringList toRemove;
-	do
-	{
-		allRequires.clear();
-		toRemove.clear();
-		if(!gatherRequirementsFromComponents(components, allRequires))
-		{
-			emitFailed(tr("Conflicting requirements detected during dependency checking!"));
-			return;
-		}
-		getTrivialRemovals(components, allRequires, toRemove);
-		if(!toRemove.isEmpty())
-		{
-			qDebug() << "Removing obsolete components...";
-			for(auto & remove : toRemove)
-			{
-				qDebug() << "Removing" << remove;
-				d->m_list->remove(remove);
-			}
-		}
-	} while (!toRemove.isEmpty());
-	RequireExSet toAdd;
-	RequireExSet toChange;
-	bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange);
-	if(!succeeded)
-	{
-		emitFailed(tr("Instance has conflicting dependencies."));
-		return;
-	}
-	if(checkOnly)
-	{
-		if(toAdd.size() || toChange.size())
-		{
-			emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch."));
-		}
-		else
-		{
-			emitSucceeded();
-		}
-		return;
-	}
-
-	bool recursionNeeded = false;
-	if(toAdd.size())
-	{
-		// add stuff...
-		for(auto &add: toAdd)
-		{
-			ComponentPtr component = new Component(d->m_list, add.uid);
-			if(!add.equalsVersion.isEmpty())
-			{
-				// exact version
-				qDebug() << "Adding" << add.uid << "version" << add.equalsVersion << "at position" << add.indexOfFirstDependee;
-				component->m_version = add.equalsVersion;
-			}
-			else
-			{
-				// version needs to be decided
-				qDebug() << "Adding" << add.uid << "at position" << add.indexOfFirstDependee;
+    qDebug() << "Resolving dependencies";
+    /*
+     * this is a naive dependency resolving algorithm. all it does is check for following conditions and react in simple ways:
+     * 1. There are conflicting dependencies on the same uid with different exact version numbers
+     *    -> hard error
+     * 2. A dependency has non-matching exact version number
+     *    -> hard error
+     * 3. A dependency is entirely missing and needs to be injected before the dependee(s)
+     *    -> requirements are injected
+     *
+     * NOTE: this is a placeholder and should eventually be replaced with something 'serious'
+     */
+    auto & components = d->m_list->d->components;
+    auto & componentIndex = d->m_list->d->componentIndex;
+
+    RequireExSet allRequires;
+    QStringList toRemove;
+    do
+    {
+        allRequires.clear();
+        toRemove.clear();
+        if(!gatherRequirementsFromComponents(components, allRequires))
+        {
+            emitFailed(tr("Conflicting requirements detected during dependency checking!"));
+            return;
+        }
+        getTrivialRemovals(components, allRequires, toRemove);
+        if(!toRemove.isEmpty())
+        {
+            qDebug() << "Removing obsolete components...";
+            for(auto & remove : toRemove)
+            {
+                qDebug() << "Removing" << remove;
+                d->m_list->remove(remove);
+            }
+        }
+    } while (!toRemove.isEmpty());
+    RequireExSet toAdd;
+    RequireExSet toChange;
+    bool succeeded = getTrivialComponentChanges(componentIndex, allRequires, toAdd, toChange);
+    if(!succeeded)
+    {
+        emitFailed(tr("Instance has conflicting dependencies."));
+        return;
+    }
+    if(checkOnly)
+    {
+        if(toAdd.size() || toChange.size())
+        {
+            emitFailed(tr("Instance has unresolved dependencies while loading/checking for launch."));
+        }
+        else
+        {
+            emitSucceeded();
+        }
+        return;
+    }
+
+    bool recursionNeeded = false;
+    if(toAdd.size())
+    {
+        // add stuff...
+        for(auto &add: toAdd)
+        {
+            ComponentPtr component = new Component(d->m_list, add.uid);
+            if(!add.equalsVersion.isEmpty())
+            {
+                // exact version
+                qDebug() << "Adding" << add.uid << "version" << add.equalsVersion << "at position" << add.indexOfFirstDependee;
+                component->m_version = add.equalsVersion;
+            }
+            else
+            {
+                // version needs to be decided
+                qDebug() << "Adding" << add.uid << "at position" << add.indexOfFirstDependee;
 // ############################################################################################################
 // HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded.
-				if(!add.suggests.isEmpty())
-				{
-					component->m_version = add.suggests;
-				}
-				else
-				{
-					if(add.uid == "org.lwjgl")
-					{
-						component->m_version = "2.9.1";
-					}
-					else if (add.uid == "org.lwjgl3")
-					{
-						component->m_version = "3.1.2";
-					}
-				}
+                if(!add.suggests.isEmpty())
+                {
+                    component->m_version = add.suggests;
+                }
+                else
+                {
+                    if(add.uid == "org.lwjgl")
+                    {
+                        component->m_version = "2.9.1";
+                    }
+                    else if (add.uid == "org.lwjgl3")
+                    {
+                        component->m_version = "3.1.2";
+                    }
+                }
 // HACK HACK HACK HACK FIXME: this is a placeholder for deciding what version to use. For now, it is hardcoded.
 // ############################################################################################################
-			}
-			component->m_dependencyOnly = true;
-			// FIXME: this should not work directly with the component list
-			d->m_list->insertComponent(add.indexOfFirstDependee, component);
-			componentIndex[add.uid] = component;
-		}
-		recursionNeeded = true;
-	}
-	if(toChange.size())
-	{
-		// change a version of something that exists
-		for(auto &change: toChange)
-		{
-			// FIXME: this should not work directly with the component list
-			qDebug() << "Setting version of " << change.uid << "to" << change.equalsVersion;
-			auto component = componentIndex[change.uid];
-			component->setVersion(change.equalsVersion);
-		}
-		recursionNeeded = true;
-	}
-
-	if(recursionNeeded)
-	{
-		loadComponents();
-	}
-	else
-	{
-		emitSucceeded();
-	}
+            }
+            component->m_dependencyOnly = true;
+            // FIXME: this should not work directly with the component list
+            d->m_list->insertComponent(add.indexOfFirstDependee, component);
+            componentIndex[add.uid] = component;
+        }
+        recursionNeeded = true;
+    }
+    if(toChange.size())
+    {
+        // change a version of something that exists
+        for(auto &change: toChange)
+        {
+            // FIXME: this should not work directly with the component list
+            qDebug() << "Setting version of " << change.uid << "to" << change.equalsVersion;
+            auto component = componentIndex[change.uid];
+            component->setVersion(change.equalsVersion);
+        }
+        recursionNeeded = true;
+    }
+
+    if(recursionNeeded)
+    {
+        loadComponents();
+    }
+    else
+    {
+        emitSucceeded();
+    }
 }
 
 void ComponentUpdateTask::remoteLoadSucceeded(size_t taskIndex)
 {
-	auto &taskSlot = d->remoteLoadStatusList[taskIndex];
-	if(taskSlot.finished)
-	{
-		qWarning() << "Got multiple results from remote load task" << taskIndex;
-		return;
-	}
-	qDebug() << "Remote task" << taskIndex << "succeeded";
-	taskSlot.succeeded = false;
-	taskSlot.finished = true;
-	d->remoteTasksInProgress --;
-	// update the cached data of the component from the downloaded version file.
-	if (taskSlot.type == RemoteLoadStatus::Type::Version)
-	{
-		auto component = d->m_list->getComponent(taskSlot.componentListIndex);
-		component->m_loaded = true;
-		component->updateCachedData();
-	}
-	checkIfAllFinished();
+    auto &taskSlot = d->remoteLoadStatusList[taskIndex];
+    if(taskSlot.finished)
+    {
+        qWarning() << "Got multiple results from remote load task" << taskIndex;
+        return;
+    }
+    qDebug() << "Remote task" << taskIndex << "succeeded";
+    taskSlot.succeeded = false;
+    taskSlot.finished = true;
+    d->remoteTasksInProgress --;
+    // update the cached data of the component from the downloaded version file.
+    if (taskSlot.type == RemoteLoadStatus::Type::Version)
+    {
+        auto component = d->m_list->getComponent(taskSlot.componentListIndex);
+        component->m_loaded = true;
+        component->updateCachedData();
+    }
+    checkIfAllFinished();
 }
 
 
 void ComponentUpdateTask::remoteLoadFailed(size_t taskIndex, const QString& msg)
 {
-	auto &taskSlot = d->remoteLoadStatusList[taskIndex];
-	if(taskSlot.finished)
-	{
-		qWarning() << "Got multiple results from remote load task" << taskIndex;
-		return;
-	}
-	qDebug() << "Remote task" << taskIndex << "failed: " << msg;
-	d->remoteLoadSuccessful = false;
-	taskSlot.succeeded = false;
-	taskSlot.finished = true;
-	taskSlot.error = msg;
-	d->remoteTasksInProgress --;
-	checkIfAllFinished();
+    auto &taskSlot = d->remoteLoadStatusList[taskIndex];
+    if(taskSlot.finished)
+    {
+        qWarning() << "Got multiple results from remote load task" << taskIndex;
+        return;
+    }
+    qDebug() << "Remote task" << taskIndex << "failed: " << msg;
+    d->remoteLoadSuccessful = false;
+    taskSlot.succeeded = false;
+    taskSlot.finished = true;
+    taskSlot.error = msg;
+    d->remoteTasksInProgress --;
+    checkIfAllFinished();
 }
 
 void ComponentUpdateTask::checkIfAllFinished()
 {
-	if(d->remoteTasksInProgress)
-	{
-		// not yet...
-		return;
-	}
-	if(d->remoteLoadSuccessful)
-	{
-		// nothing bad happened... clear the temp load status and proceed with looking at dependencies
-		d->remoteLoadStatusList.clear();
-		resolveDependencies(d->mode == Mode::Launch);
-	}
-	else
-	{
-		// remote load failed... report error and bail
-		QStringList allErrorsList;
-		for(auto & item: d->remoteLoadStatusList)
-		{
-			if(!item.succeeded)
-			{
-				allErrorsList.append(item.error);
-			}
-		}
-		auto allErrors = allErrorsList.join("\n");
-		emitFailed(tr("Component metadata update task failed while downloading from remote server:\n%1").arg(allErrors));
-		d->remoteLoadStatusList.clear();
-	}
+    if(d->remoteTasksInProgress)
+    {
+        // not yet...
+        return;
+    }
+    if(d->remoteLoadSuccessful)
+    {
+        // nothing bad happened... clear the temp load status and proceed with looking at dependencies
+        d->remoteLoadStatusList.clear();
+        resolveDependencies(d->mode == Mode::Launch);
+    }
+    else
+    {
+        // remote load failed... report error and bail
+        QStringList allErrorsList;
+        for(auto & item: d->remoteLoadStatusList)
+        {
+            if(!item.succeeded)
+            {
+                allErrorsList.append(item.error);
+            }
+        }
+        auto allErrors = allErrorsList.join("\n");
+        emitFailed(tr("Component metadata update task failed while downloading from remote server:\n%1").arg(allErrors));
+        d->remoteLoadStatusList.clear();
+    }
 }
diff --git a/api/logic/minecraft/ComponentUpdateTask.h b/api/logic/minecraft/ComponentUpdateTask.h
index 11d122b6..4cb29a89 100644
--- a/api/logic/minecraft/ComponentUpdateTask.h
+++ b/api/logic/minecraft/ComponentUpdateTask.h
@@ -9,29 +9,29 @@ struct ComponentUpdateTaskData;
 
 class ComponentUpdateTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum class Mode
-	{
-		Launch,
-		Resolution
-	};
+    enum class Mode
+    {
+        Launch,
+        Resolution
+    };
 
 public:
-	explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList * list, QObject *parent = 0);
-	virtual ~ComponentUpdateTask();
+    explicit ComponentUpdateTask(Mode mode, Net::Mode netmode, ComponentList * list, QObject *parent = 0);
+    virtual ~ComponentUpdateTask();
 
 protected:
-	void executeTask();
+    void executeTask();
 
 private:
-	void loadComponents();
-	void resolveDependencies(bool checkOnly);
+    void loadComponents();
+    void resolveDependencies(bool checkOnly);
 
-	void remoteLoadSucceeded(size_t index);
-	void remoteLoadFailed(size_t index, const QString &msg);
-	void checkIfAllFinished();
+    void remoteLoadSucceeded(size_t index);
+    void remoteLoadFailed(size_t index, const QString &msg);
+    void checkIfAllFinished();
 
 private:
-	std::unique_ptr<ComponentUpdateTaskData> d;
+    std::unique_ptr<ComponentUpdateTaskData> d;
 };
diff --git a/api/logic/minecraft/ComponentUpdateTask_p.h b/api/logic/minecraft/ComponentUpdateTask_p.h
index a5216506..5989cf07 100644
--- a/api/logic/minecraft/ComponentUpdateTask_p.h
+++ b/api/logic/minecraft/ComponentUpdateTask_p.h
@@ -9,24 +9,24 @@ class ComponentList;
 
 struct RemoteLoadStatus
 {
-	enum class Type
-	{
-		Index,
-		List,
-		Version
-	} type = Type::Version;
-	size_t componentListIndex = 0;
-	bool finished = false;
-	bool succeeded = false;
-	QString error;
+    enum class Type
+    {
+        Index,
+        List,
+        Version
+    } type = Type::Version;
+    size_t componentListIndex = 0;
+    bool finished = false;
+    bool succeeded = false;
+    QString error;
 };
 
 struct ComponentUpdateTaskData
 {
-	ComponentList * m_list = nullptr;
-	QList<RemoteLoadStatus> remoteLoadStatusList;
-	bool remoteLoadSuccessful = true;
-	size_t remoteTasksInProgress = 0;
-	ComponentUpdateTask::Mode mode;
-	Net::Mode netmode;
+    ComponentList * m_list = nullptr;
+    QList<RemoteLoadStatus> remoteLoadStatusList;
+    bool remoteLoadSuccessful = true;
+    size_t remoteTasksInProgress = 0;
+    ComponentUpdateTask::Mode mode;
+    Net::Mode netmode;
 };
diff --git a/api/logic/minecraft/GradleSpecifier.h b/api/logic/minecraft/GradleSpecifier.h
index f842008c..959325c6 100644
--- a/api/logic/minecraft/GradleSpecifier.h
+++ b/api/logic/minecraft/GradleSpecifier.h
@@ -6,138 +6,138 @@
 
 struct GradleSpecifier
 {
-	GradleSpecifier()
-	{
-		m_valid = false;
-	}
-	GradleSpecifier(QString value)
-	{
-		operator=(value);
-	}
-	GradleSpecifier & operator =(const QString & value)
-	{
-		/*
-		org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar
-		DEBUG   0 "org.gradle.test.classifiers:service:1.0:jdk15@jar" 
-		DEBUG   1 "org.gradle.test.classifiers" 
-		DEBUG   2 "service" 
-		DEBUG   3 "1.0" 
-		DEBUG   4 ":jdk15" 
-		DEBUG   5 "jdk15" 
-		DEBUG   6 "@jar" 
-		DEBUG   7 "jar"
-		*/
-		QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(:([^:@]+))?" "(@([^:@]+))?");
-		m_valid = matcher.exactMatch(value);
-		auto elements = matcher.capturedTexts();
-		m_groupId = elements[1];
-		m_artifactId = elements[2];
-		m_version = elements[3];
-		m_classifier = elements[5];
-		if(!elements[7].isEmpty())
-		{
-			m_extension = elements[7];
-		}
-		return *this;
-	}
-	operator QString() const
-	{
-		if(!m_valid)
-			return "INVALID";
-		QString retval = m_groupId + ":" + m_artifactId + ":" + m_version;
-		if(!m_classifier.isEmpty())
-		{
-			retval += ":" + m_classifier;
-		}
-		if(m_extension.isExplicit())
-		{
-			retval += "@" + m_extension;
-		}
-		return retval;
-	}
-	QString getFileName() const
-	{
-		QString filename = m_artifactId + '-' + m_version;
-		if(!m_classifier.isEmpty())
-		{
-			filename += "-" + m_classifier;
-		}
-		filename += "." + m_extension;
-		return filename;
-	}
-	QString toPath(const QString & filenameOverride = QString()) const
-	{
-		if(!m_valid)
-			return "INVALID";
-		QString filename;
-		if(filenameOverride.isEmpty())
-		{
-			filename = getFileName();
-		}
-		else
-		{
-			filename = filenameOverride;
-		}
-		QString path = m_groupId;
-		path.replace('.', '/');
-		path += '/' + m_artifactId + '/' + m_version + '/' + filename;
-		return path;
-	}
-	inline bool valid() const
-	{
-		return m_valid;
-	}
-	inline QString version() const
-	{
-		return m_version;
-	}
-	inline QString groupId() const
-	{
-		return m_groupId;
-	}
-	inline QString artifactId() const
-	{
-		return m_artifactId;
-	}
-	inline void setClassifier(const QString & classifier)
-	{
-		m_classifier = classifier;
-	}
-	inline QString classifier() const
-	{
-		return m_classifier;
-	}
-	inline QString extension() const
-	{
-		return m_extension;
-	}
-	inline QString artifactPrefix() const
-	{
-		return m_groupId + ":" + m_artifactId;
-	}
-	bool matchName(const GradleSpecifier & other) const
-	{
-		return other.artifactId() == artifactId() && other.groupId() == groupId();
-	}
-	bool operator==(const GradleSpecifier & other) const
-	{
-		if(m_groupId != other.m_groupId)
-			return false;
-		if(m_artifactId != other.m_artifactId)
-			return false;
-		if(m_version != other.m_version)
-			return false;
-		if(m_classifier != other.m_classifier)
-			return false;
-		if(m_extension != other.m_extension)
-			return false;
-		return true;
-	}
+    GradleSpecifier()
+    {
+        m_valid = false;
+    }
+    GradleSpecifier(QString value)
+    {
+        operator=(value);
+    }
+    GradleSpecifier & operator =(const QString & value)
+    {
+        /*
+        org.gradle.test.classifiers : service : 1.0 : jdk15 @ jar
+        DEBUG   0 "org.gradle.test.classifiers:service:1.0:jdk15@jar" 
+        DEBUG   1 "org.gradle.test.classifiers" 
+        DEBUG   2 "service" 
+        DEBUG   3 "1.0" 
+        DEBUG   4 ":jdk15" 
+        DEBUG   5 "jdk15" 
+        DEBUG   6 "@jar" 
+        DEBUG   7 "jar"
+        */
+        QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(:([^:@]+))?" "(@([^:@]+))?");
+        m_valid = matcher.exactMatch(value);
+        auto elements = matcher.capturedTexts();
+        m_groupId = elements[1];
+        m_artifactId = elements[2];
+        m_version = elements[3];
+        m_classifier = elements[5];
+        if(!elements[7].isEmpty())
+        {
+            m_extension = elements[7];
+        }
+        return *this;
+    }
+    operator QString() const
+    {
+        if(!m_valid)
+            return "INVALID";
+        QString retval = m_groupId + ":" + m_artifactId + ":" + m_version;
+        if(!m_classifier.isEmpty())
+        {
+            retval += ":" + m_classifier;
+        }
+        if(m_extension.isExplicit())
+        {
+            retval += "@" + m_extension;
+        }
+        return retval;
+    }
+    QString getFileName() const
+    {
+        QString filename = m_artifactId + '-' + m_version;
+        if(!m_classifier.isEmpty())
+        {
+            filename += "-" + m_classifier;
+        }
+        filename += "." + m_extension;
+        return filename;
+    }
+    QString toPath(const QString & filenameOverride = QString()) const
+    {
+        if(!m_valid)
+            return "INVALID";
+        QString filename;
+        if(filenameOverride.isEmpty())
+        {
+            filename = getFileName();
+        }
+        else
+        {
+            filename = filenameOverride;
+        }
+        QString path = m_groupId;
+        path.replace('.', '/');
+        path += '/' + m_artifactId + '/' + m_version + '/' + filename;
+        return path;
+    }
+    inline bool valid() const
+    {
+        return m_valid;
+    }
+    inline QString version() const
+    {
+        return m_version;
+    }
+    inline QString groupId() const
+    {
+        return m_groupId;
+    }
+    inline QString artifactId() const
+    {
+        return m_artifactId;
+    }
+    inline void setClassifier(const QString & classifier)
+    {
+        m_classifier = classifier;
+    }
+    inline QString classifier() const
+    {
+        return m_classifier;
+    }
+    inline QString extension() const
+    {
+        return m_extension;
+    }
+    inline QString artifactPrefix() const
+    {
+        return m_groupId + ":" + m_artifactId;
+    }
+    bool matchName(const GradleSpecifier & other) const
+    {
+        return other.artifactId() == artifactId() && other.groupId() == groupId();
+    }
+    bool operator==(const GradleSpecifier & other) const
+    {
+        if(m_groupId != other.m_groupId)
+            return false;
+        if(m_artifactId != other.m_artifactId)
+            return false;
+        if(m_version != other.m_version)
+            return false;
+        if(m_classifier != other.m_classifier)
+            return false;
+        if(m_extension != other.m_extension)
+            return false;
+        return true;
+    }
 private:
-	QString m_groupId;
-	QString m_artifactId;
-	QString m_version;
-	QString m_classifier;
-	DefaultVariable<QString> m_extension = DefaultVariable<QString>("jar");
-	bool m_valid = false;
+    QString m_groupId;
+    QString m_artifactId;
+    QString m_version;
+    QString m_classifier;
+    DefaultVariable<QString> m_extension = DefaultVariable<QString>("jar");
+    bool m_valid = false;
 };
diff --git a/api/logic/minecraft/GradleSpecifier_test.cpp b/api/logic/minecraft/GradleSpecifier_test.cpp
index 155522cd..f49ec718 100644
--- a/api/logic/minecraft/GradleSpecifier_test.cpp
+++ b/api/logic/minecraft/GradleSpecifier_test.cpp
@@ -5,71 +5,71 @@
 
 class GradleSpecifierTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void initTestCase()
-	{
-
-	}
-	void cleanupTestCase()
-	{
-
-	}
-
-	void test_Positive_data()
-	{
-		QTest::addColumn<QString>("through");
-
-		QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
-		QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
-		QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
-		QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
-		QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
-	}
-	void test_Positive()
-	{
-		QFETCH(QString, through);
-
-		QString converted = GradleSpecifier(through);
-
-		QCOMPARE(converted, through);
-	}
-
-	void test_Path_data()
-	{
-		QTest::addColumn<QString>("spec");
-		QTest::addColumn<QString>("expected");
-
-		QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar";
-		QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad";
-	}
-	void test_Path()
-	{
-		QFETCH(QString, spec);
-		QFETCH(QString, expected);
-
-		QString converted = GradleSpecifier(spec).toPath();
-
-		QCOMPARE(converted, expected);
-	}
-	void test_Negative_data()
-	{
-		QTest::addColumn<QString>("input");
-
-		QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
-		QTest::newRow("nonsense") << "I like turtles";
-		QTest::newRow("empty string") << "";
-		QTest::newRow("missing version") << "herp.derp:artifact";
-	}
-	void test_Negative()
-	{
-		QFETCH(QString, input);
-
-		GradleSpecifier spec(input);
-		QVERIFY(!spec.valid());
-		QCOMPARE(spec.operator QString(), QString("INVALID"));
-	}
+    void initTestCase()
+    {
+
+    }
+    void cleanupTestCase()
+    {
+
+    }
+
+    void test_Positive_data()
+    {
+        QTest::addColumn<QString>("through");
+
+        QTest::newRow("3 parter") << "org.gradle.test.classifiers:service:1.0";
+        QTest::newRow("classifier") << "org.gradle.test.classifiers:service:1.0:jdk15";
+        QTest::newRow("jarextension") << "org.gradle.test.classifiers:service:1.0@jar";
+        QTest::newRow("jarboth") << "org.gradle.test.classifiers:service:1.0:jdk15@jar";
+        QTest::newRow("packxz") << "org.gradle.test.classifiers:service:1.0:jdk15@jar.pack.xz";
+    }
+    void test_Positive()
+    {
+        QFETCH(QString, through);
+
+        QString converted = GradleSpecifier(through);
+
+        QCOMPARE(converted, through);
+    }
+
+    void test_Path_data()
+    {
+        QTest::addColumn<QString>("spec");
+        QTest::addColumn<QString>("expected");
+
+        QTest::newRow("3 parter") << "group.id:artifact:1.0" << "group/id/artifact/1.0/artifact-1.0.jar";
+        QTest::newRow("doom") << "id.software:doom:1.666:demons@wad" << "id/software/doom/1.666/doom-1.666-demons.wad";
+    }
+    void test_Path()
+    {
+        QFETCH(QString, spec);
+        QFETCH(QString, expected);
+
+        QString converted = GradleSpecifier(spec).toPath();
+
+        QCOMPARE(converted, expected);
+    }
+    void test_Negative_data()
+    {
+        QTest::addColumn<QString>("input");
+
+        QTest::newRow("too many :") << "org:gradle.test:class:::ifiers:service:1.0::";
+        QTest::newRow("nonsense") << "I like turtles";
+        QTest::newRow("empty string") << "";
+        QTest::newRow("missing version") << "herp.derp:artifact";
+    }
+    void test_Negative()
+    {
+        QFETCH(QString, input);
+
+        GradleSpecifier spec(input);
+        QVERIFY(!spec.valid());
+        QCOMPARE(spec.operator QString(), QString("INVALID"));
+    }
 };
 
 QTEST_GUILESS_MAIN(GradleSpecifierTest)
diff --git a/api/logic/minecraft/LaunchProfile.cpp b/api/logic/minecraft/LaunchProfile.cpp
index 436a39d9..c39bdf04 100644
--- a/api/logic/minecraft/LaunchProfile.cpp
+++ b/api/logic/minecraft/LaunchProfile.cpp
@@ -3,295 +3,295 @@
 
 void LaunchProfile::clear()
 {
-	m_minecraftVersion.clear();
-	m_minecraftVersionType.clear();
-	m_minecraftAssets.reset();
-	m_minecraftArguments.clear();
-	m_tweakers.clear();
-	m_mainClass.clear();
-	m_appletClass.clear();
-	m_libraries.clear();
-	m_traits.clear();
-	m_jarMods.clear();
-	m_mainJar.reset();
-	m_problemSeverity = ProblemSeverity::None;
+    m_minecraftVersion.clear();
+    m_minecraftVersionType.clear();
+    m_minecraftAssets.reset();
+    m_minecraftArguments.clear();
+    m_tweakers.clear();
+    m_mainClass.clear();
+    m_appletClass.clear();
+    m_libraries.clear();
+    m_traits.clear();
+    m_jarMods.clear();
+    m_mainJar.reset();
+    m_problemSeverity = ProblemSeverity::None;
 }
 
 static void applyString(const QString & from, QString & to)
 {
-	if(from.isEmpty())
-		return;
-	to = from;
+    if(from.isEmpty())
+        return;
+    to = from;
 }
 
 void LaunchProfile::applyMinecraftVersion(const QString& id)
 {
-	applyString(id, this->m_minecraftVersion);
+    applyString(id, this->m_minecraftVersion);
 }
 
 void LaunchProfile::applyAppletClass(const QString& appletClass)
 {
-	applyString(appletClass, this->m_appletClass);
+    applyString(appletClass, this->m_appletClass);
 }
 
 void LaunchProfile::applyMainClass(const QString& mainClass)
 {
-	applyString(mainClass, this->m_mainClass);
+    applyString(mainClass, this->m_mainClass);
 }
 
 void LaunchProfile::applyMinecraftArguments(const QString& minecraftArguments)
 {
-	applyString(minecraftArguments, this->m_minecraftArguments);
+    applyString(minecraftArguments, this->m_minecraftArguments);
 }
 
 void LaunchProfile::applyMinecraftVersionType(const QString& type)
 {
-	applyString(type, this->m_minecraftVersionType);
+    applyString(type, this->m_minecraftVersionType);
 }
 
 void LaunchProfile::applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets)
 {
-	if(assets)
-	{
-		m_minecraftAssets = assets;
-	}
+    if(assets)
+    {
+        m_minecraftAssets = assets;
+    }
 }
 
 void LaunchProfile::applyTraits(const QSet<QString>& traits)
 {
-	this->m_traits.unite(traits);
+    this->m_traits.unite(traits);
 }
 
 void LaunchProfile::applyTweakers(const QStringList& tweakers)
 {
-	// if the applied tweakers override an existing one, skip it. this effectively moves it later in the sequence
-	QStringList newTweakers;
-	for(auto & tweaker: m_tweakers)
-	{
-		if (tweakers.contains(tweaker))
-		{
-			continue;
-		}
-		newTweakers.append(tweaker);
-	}
-	// then just append the new tweakers (or moved original ones)
-	newTweakers += tweakers;
-	m_tweakers = newTweakers;
+    // if the applied tweakers override an existing one, skip it. this effectively moves it later in the sequence
+    QStringList newTweakers;
+    for(auto & tweaker: m_tweakers)
+    {
+        if (tweakers.contains(tweaker))
+        {
+            continue;
+        }
+        newTweakers.append(tweaker);
+    }
+    // then just append the new tweakers (or moved original ones)
+    newTweakers += tweakers;
+    m_tweakers = newTweakers;
 }
 
 void LaunchProfile::applyJarMods(const QList<LibraryPtr>& jarMods)
 {
-	this->m_jarMods.append(jarMods);
+    this->m_jarMods.append(jarMods);
 }
 
 static int findLibraryByName(QList<LibraryPtr> *haystack, const GradleSpecifier &needle)
 {
-	int retval = -1;
-	for (int i = 0; i < haystack->size(); ++i)
-	{
-		if (haystack->at(i)->rawName().matchName(needle))
-		{
-			// only one is allowed.
-			if (retval != -1)
-				return -1;
-			retval = i;
-		}
-	}
-	return retval;
+    int retval = -1;
+    for (int i = 0; i < haystack->size(); ++i)
+    {
+        if (haystack->at(i)->rawName().matchName(needle))
+        {
+            // only one is allowed.
+            if (retval != -1)
+                return -1;
+            retval = i;
+        }
+    }
+    return retval;
 }
 
 void LaunchProfile::applyMods(const QList<LibraryPtr>& mods)
 {
-	QList<LibraryPtr> * list = &m_mods;
-	for(auto & mod: mods)
-	{
-		auto modCopy = Library::limitedCopy(mod);
-
-		// find the mod by name.
-		const int index = findLibraryByName(list, mod->rawName());
-		// mod not found? just add it.
-		if (index < 0)
-		{
-			list->append(modCopy);
-			return;
-		}
-
-		auto existingLibrary = list->at(index);
-		// if we are higher it means we should update
-		if (Version(mod->version()) > Version(existingLibrary->version()))
-		{
-			list->replace(index, modCopy);
-		}
-	}
+    QList<LibraryPtr> * list = &m_mods;
+    for(auto & mod: mods)
+    {
+        auto modCopy = Library::limitedCopy(mod);
+
+        // find the mod by name.
+        const int index = findLibraryByName(list, mod->rawName());
+        // mod not found? just add it.
+        if (index < 0)
+        {
+            list->append(modCopy);
+            return;
+        }
+
+        auto existingLibrary = list->at(index);
+        // if we are higher it means we should update
+        if (Version(mod->version()) > Version(existingLibrary->version()))
+        {
+            list->replace(index, modCopy);
+        }
+    }
 }
 
 void LaunchProfile::applyLibrary(LibraryPtr library)
 {
-	if(!library->isActive())
-	{
-		return;
-	}
+    if(!library->isActive())
+    {
+        return;
+    }
 
-	QList<LibraryPtr> * list = &m_libraries;
-	if(library->isNative())
-	{
-		list = &m_nativeLibraries;
-	}
+    QList<LibraryPtr> * list = &m_libraries;
+    if(library->isNative())
+    {
+        list = &m_nativeLibraries;
+    }
 
-	auto libraryCopy = Library::limitedCopy(library);
+    auto libraryCopy = Library::limitedCopy(library);
 
-	// find the library by name.
-	const int index = findLibraryByName(list, library->rawName());
-	// library not found? just add it.
-	if (index < 0)
-	{
-		list->append(libraryCopy);
-		return;
-	}
+    // find the library by name.
+    const int index = findLibraryByName(list, library->rawName());
+    // library not found? just add it.
+    if (index < 0)
+    {
+        list->append(libraryCopy);
+        return;
+    }
 
-	auto existingLibrary = list->at(index);
-	// if we are higher it means we should update
-	if (Version(library->version()) > Version(existingLibrary->version()))
-	{
-		list->replace(index, libraryCopy);
-	}
+    auto existingLibrary = list->at(index);
+    // if we are higher it means we should update
+    if (Version(library->version()) > Version(existingLibrary->version()))
+    {
+        list->replace(index, libraryCopy);
+    }
 }
 
 const LibraryPtr LaunchProfile::getMainJar() const
 {
-	return m_mainJar;
+    return m_mainJar;
 }
 
 void LaunchProfile::applyMainJar(LibraryPtr jar)
 {
-	if(jar)
-	{
-		m_mainJar = jar;
-	}
+    if(jar)
+    {
+        m_mainJar = jar;
+    }
 }
 
 void LaunchProfile::applyProblemSeverity(ProblemSeverity severity)
 {
-	if (m_problemSeverity < severity)
-	{
-		m_problemSeverity = severity;
-	}
+    if (m_problemSeverity < severity)
+    {
+        m_problemSeverity = severity;
+    }
 }
 
 const QList<PatchProblem> LaunchProfile::getProblems() const
 {
-	// FIXME: implement something that actually makes sense here
-	return {};
+    // FIXME: implement something that actually makes sense here
+    return {};
 }
 
 QString LaunchProfile::getMinecraftVersion() const
 {
-	return m_minecraftVersion;
+    return m_minecraftVersion;
 }
 
 QString LaunchProfile::getAppletClass() const
 {
-	return m_appletClass;
+    return m_appletClass;
 }
 
 QString LaunchProfile::getMainClass() const
 {
-	return m_mainClass;
+    return m_mainClass;
 }
 
 const QSet<QString> &LaunchProfile::getTraits() const
 {
-	return m_traits;
+    return m_traits;
 }
 
 const QStringList & LaunchProfile::getTweakers() const
 {
-	return m_tweakers;
+    return m_tweakers;
 }
 
 bool LaunchProfile::hasTrait(const QString& trait) const
 {
-	return m_traits.contains(trait);
+    return m_traits.contains(trait);
 }
 
 ProblemSeverity LaunchProfile::getProblemSeverity() const
 {
-	return m_problemSeverity;
+    return m_problemSeverity;
 }
 
 QString LaunchProfile::getMinecraftVersionType() const
 {
-	return m_minecraftVersionType;
+    return m_minecraftVersionType;
 }
 
 std::shared_ptr<MojangAssetIndexInfo> LaunchProfile::getMinecraftAssets() const
 {
-	if(!m_minecraftAssets)
-	{
-		return std::make_shared<MojangAssetIndexInfo>("legacy");
-	}
-	return m_minecraftAssets;
+    if(!m_minecraftAssets)
+    {
+        return std::make_shared<MojangAssetIndexInfo>("legacy");
+    }
+    return m_minecraftAssets;
 }
 
 QString LaunchProfile::getMinecraftArguments() const
 {
-	return m_minecraftArguments;
+    return m_minecraftArguments;
 }
 
 const QList<LibraryPtr> & LaunchProfile::getJarMods() const
 {
-	return m_jarMods;
+    return m_jarMods;
 }
 
 const QList<LibraryPtr> & LaunchProfile::getLibraries() const
 {
-	return m_libraries;
+    return m_libraries;
 }
 
 const QList<LibraryPtr> & LaunchProfile::getNativeLibraries() const
 {
-	return m_nativeLibraries;
+    return m_nativeLibraries;
 }
 
 void LaunchProfile::getLibraryFiles(
-	const QString& architecture,
-	QStringList& jars,
-	QStringList& nativeJars,
-	const QString& overridePath,
-	const QString& tempPath
+    const QString& architecture,
+    QStringList& jars,
+    QStringList& nativeJars,
+    const QString& overridePath,
+    const QString& tempPath
 ) const
 {
-	QStringList native32, native64;
-	jars.clear();
-	nativeJars.clear();
-	for (auto lib : getLibraries())
-	{
-		lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
-	}
-	// NOTE: order is important here, add main jar last to the lists
-	if(m_mainJar)
-	{
-		// FIXME: HACK!! jar modding is weird and unsystematic!
-		if(m_jarMods.size())
-		{
-			QDir tempDir(tempPath);
-			jars.append(tempDir.absoluteFilePath("minecraft.jar"));
-		}
-		else
-		{
-			m_mainJar->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
-		}
-	}
-	for (auto lib : getNativeLibraries())
-	{
-		lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
-	}
-	if(architecture == "32")
-	{
-		nativeJars.append(native32);
-	}
-	else if(architecture == "64")
-	{
-		nativeJars.append(native64);
-	}
+    QStringList native32, native64;
+    jars.clear();
+    nativeJars.clear();
+    for (auto lib : getLibraries())
+    {
+        lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
+    }
+    // NOTE: order is important here, add main jar last to the lists
+    if(m_mainJar)
+    {
+        // FIXME: HACK!! jar modding is weird and unsystematic!
+        if(m_jarMods.size())
+        {
+            QDir tempDir(tempPath);
+            jars.append(tempDir.absoluteFilePath("minecraft.jar"));
+        }
+        else
+        {
+            m_mainJar->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
+        }
+    }
+    for (auto lib : getNativeLibraries())
+    {
+        lib->getApplicableFiles(currentSystem, jars, nativeJars, native32, native64, overridePath);
+    }
+    if(architecture == "32")
+    {
+        nativeJars.append(native32);
+    }
+    else if(architecture == "64")
+    {
+        nativeJars.append(native64);
+    }
 }
diff --git a/api/logic/minecraft/LaunchProfile.h b/api/logic/minecraft/LaunchProfile.h
index e7f5f4af..77174079 100644
--- a/api/logic/minecraft/LaunchProfile.h
+++ b/api/logic/minecraft/LaunchProfile.h
@@ -6,94 +6,94 @@
 class LaunchProfile: public ProblemProvider
 {
 public:
-	virtual ~LaunchProfile() {};
+    virtual ~LaunchProfile() {};
 
 public: /* application of profile variables from patches */
-	void applyMinecraftVersion(const QString& id);
-	void applyMainClass(const QString& mainClass);
-	void applyAppletClass(const QString& appletClass);
-	void applyMinecraftArguments(const QString& minecraftArguments);
-	void applyMinecraftVersionType(const QString& type);
-	void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets);
-	void applyTraits(const QSet<QString> &traits);
-	void applyTweakers(const QStringList &tweakers);
-	void applyJarMods(const QList<LibraryPtr> &jarMods);
-	void applyMods(const QList<LibraryPtr> &jarMods);
-	void applyLibrary(LibraryPtr library);
-	void applyMainJar(LibraryPtr jar);
-	void applyProblemSeverity(ProblemSeverity severity);
-	/// clear the profile
-	void clear();
+    void applyMinecraftVersion(const QString& id);
+    void applyMainClass(const QString& mainClass);
+    void applyAppletClass(const QString& appletClass);
+    void applyMinecraftArguments(const QString& minecraftArguments);
+    void applyMinecraftVersionType(const QString& type);
+    void applyMinecraftAssets(MojangAssetIndexInfo::Ptr assets);
+    void applyTraits(const QSet<QString> &traits);
+    void applyTweakers(const QStringList &tweakers);
+    void applyJarMods(const QList<LibraryPtr> &jarMods);
+    void applyMods(const QList<LibraryPtr> &jarMods);
+    void applyLibrary(LibraryPtr library);
+    void applyMainJar(LibraryPtr jar);
+    void applyProblemSeverity(ProblemSeverity severity);
+    /// clear the profile
+    void clear();
 
 public: /* getters for profile variables */
-	QString getMinecraftVersion() const;
-	QString getMainClass() const;
-	QString getAppletClass() const;
-	QString getMinecraftVersionType() const;
-	MojangAssetIndexInfo::Ptr getMinecraftAssets() const;
-	QString getMinecraftArguments() const;
-	const QSet<QString> & getTraits() const;
-	const QStringList & getTweakers() const;
-	const QList<LibraryPtr> & getJarMods() const;
-	const QList<LibraryPtr> & getLibraries() const;
-	const QList<LibraryPtr> & getNativeLibraries() const;
-	const LibraryPtr getMainJar() const;
-	void getLibraryFiles(
-		const QString & architecture,
-		QStringList & jars,
-		QStringList & nativeJars,
-		const QString & overridePath,
-		const QString & tempPath
-	) const;
-	bool hasTrait(const QString & trait) const;
-	ProblemSeverity getProblemSeverity() const override;
-	const QList<PatchProblem> getProblems() const override;
+    QString getMinecraftVersion() const;
+    QString getMainClass() const;
+    QString getAppletClass() const;
+    QString getMinecraftVersionType() const;
+    MojangAssetIndexInfo::Ptr getMinecraftAssets() const;
+    QString getMinecraftArguments() const;
+    const QSet<QString> & getTraits() const;
+    const QStringList & getTweakers() const;
+    const QList<LibraryPtr> & getJarMods() const;
+    const QList<LibraryPtr> & getLibraries() const;
+    const QList<LibraryPtr> & getNativeLibraries() const;
+    const LibraryPtr getMainJar() const;
+    void getLibraryFiles(
+        const QString & architecture,
+        QStringList & jars,
+        QStringList & nativeJars,
+        const QString & overridePath,
+        const QString & tempPath
+    ) const;
+    bool hasTrait(const QString & trait) const;
+    ProblemSeverity getProblemSeverity() const override;
+    const QList<PatchProblem> getProblems() const override;
 
 private:
-	/// the version of Minecraft - jar to use
-	QString m_minecraftVersion;
+    /// the version of Minecraft - jar to use
+    QString m_minecraftVersion;
 
-	/// Release type - "release" or "snapshot"
-	QString m_minecraftVersionType;
+    /// Release type - "release" or "snapshot"
+    QString m_minecraftVersionType;
 
-	/// Assets type - "legacy" or a version ID
-	MojangAssetIndexInfo::Ptr m_minecraftAssets;
+    /// Assets type - "legacy" or a version ID
+    MojangAssetIndexInfo::Ptr m_minecraftAssets;
 
-	/**
-	 * arguments that should be used for launching minecraft
-	 *
-	 * ex: "--username ${auth_player_name} --session ${auth_session}
-	 *      --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}"
-	 */
-	QString m_minecraftArguments;
+    /**
+     * arguments that should be used for launching minecraft
+     *
+     * ex: "--username ${auth_player_name} --session ${auth_session}
+     *      --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}"
+     */
+    QString m_minecraftArguments;
 
-	/// A list of all tweaker classes
-	QStringList m_tweakers;
+    /// A list of all tweaker classes
+    QStringList m_tweakers;
 
-	/// The main class to load first
-	QString m_mainClass;
+    /// The main class to load first
+    QString m_mainClass;
 
-	/// The applet class, for some very old minecraft releases
-	QString m_appletClass;
+    /// The applet class, for some very old minecraft releases
+    QString m_appletClass;
 
-	/// the list of libraries
-	QList<LibraryPtr> m_libraries;
+    /// the list of libraries
+    QList<LibraryPtr> m_libraries;
 
-	/// the main jar
-	LibraryPtr m_mainJar;
+    /// the main jar
+    LibraryPtr m_mainJar;
 
-	/// the list of libraries
-	QList<LibraryPtr> m_nativeLibraries;
+    /// the list of libraries
+    QList<LibraryPtr> m_nativeLibraries;
 
-	/// traits, collected from all the version files (version files can only add)
-	QSet<QString> m_traits;
+    /// traits, collected from all the version files (version files can only add)
+    QSet<QString> m_traits;
 
-	/// A list of jar mods. version files can add those.
-	QList<LibraryPtr> m_jarMods;
+    /// A list of jar mods. version files can add those.
+    QList<LibraryPtr> m_jarMods;
 
-	/// the list of mods
-	QList<LibraryPtr> m_mods;
+    /// the list of mods
+    QList<LibraryPtr> m_mods;
 
-	ProblemSeverity m_problemSeverity = ProblemSeverity::None;
+    ProblemSeverity m_problemSeverity = ProblemSeverity::None;
 
 };
diff --git a/api/logic/minecraft/Library.cpp b/api/logic/minecraft/Library.cpp
index 237edaf1..a6ec0301 100644
--- a/api/logic/minecraft/Library.cpp
+++ b/api/logic/minecraft/Library.cpp
@@ -9,316 +9,316 @@
 
 
 void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32,
-								 QStringList& native64, const QString &overridePath) const
+                                 QStringList& native64, const QString &overridePath) const
 {
-	bool local = isLocal();
-	auto actualPath = [&](QString relPath)
-	{
-		QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
-		if(local && !overridePath.isEmpty())
-		{
-			QString fileName = out.fileName();
-			auto fullPath = FS::PathCombine(overridePath, fileName);
-			qDebug() << fullPath;
-			QFileInfo fileinfo(fullPath);
-			if(fileinfo.exists())
-			{
-				return fileinfo.absoluteFilePath();
-			}
-		}
-		return out.absoluteFilePath();
-	};
-	QString raw_storage = storageSuffix(system);
-	if(isNative())
-	{
-		if (raw_storage.contains("${arch}"))
-		{
-			auto nat32Storage = raw_storage;
-			nat32Storage.replace("${arch}", "32");
-			auto nat64Storage = raw_storage;
-			nat64Storage.replace("${arch}", "64");
-			native32 += actualPath(nat32Storage);
-			native64 += actualPath(nat64Storage);
-		}
-		else
-		{
-			native += actualPath(raw_storage);
-		}
-	}
-	else
-	{
-		jar += actualPath(raw_storage);
-	}
+    bool local = isLocal();
+    auto actualPath = [&](QString relPath)
+    {
+        QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
+        if(local && !overridePath.isEmpty())
+        {
+            QString fileName = out.fileName();
+            auto fullPath = FS::PathCombine(overridePath, fileName);
+            qDebug() << fullPath;
+            QFileInfo fileinfo(fullPath);
+            if(fileinfo.exists())
+            {
+                return fileinfo.absoluteFilePath();
+            }
+        }
+        return out.absoluteFilePath();
+    };
+    QString raw_storage = storageSuffix(system);
+    if(isNative())
+    {
+        if (raw_storage.contains("${arch}"))
+        {
+            auto nat32Storage = raw_storage;
+            nat32Storage.replace("${arch}", "32");
+            auto nat64Storage = raw_storage;
+            nat64Storage.replace("${arch}", "64");
+            native32 += actualPath(nat32Storage);
+            native64 += actualPath(nat64Storage);
+        }
+        else
+        {
+            native += actualPath(raw_storage);
+        }
+    }
+    else
+    {
+        jar += actualPath(raw_storage);
+    }
 }
 
 QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class HttpMetaCache* cache,
-															QStringList& failedFiles, const QString & overridePath) const
+                                                            QStringList& failedFiles, const QString & overridePath) const
 {
-	QList<NetActionPtr> out;
-	bool isAlwaysStale = (hint() == "always-stale");
-	bool local = isLocal();
-	bool isForge = (hint() == "forge-pack-xz");
+    QList<NetActionPtr> out;
+    bool isAlwaysStale = (hint() == "always-stale");
+    bool local = isLocal();
+    bool isForge = (hint() == "forge-pack-xz");
 
-	auto add_download = [&](QString storage, QString url, QString sha1)
-	{
-		auto entry = cache->resolveEntry("libraries", storage);
-		if(isAlwaysStale)
-		{
-			entry->setStale(true);
-		}
-		if (!entry->isStale())
-			return true;
-		if(local)
-		{
-			if(!overridePath.isEmpty())
-			{
-				QString fileName;
-				int position = storage.lastIndexOf('/');
-				if(position == -1)
-				{
-					fileName = storage;
-				}
-				else
-				{
-					fileName = storage.mid(position);
-				}
-				auto fullPath = FS::PathCombine(overridePath, fileName);
-				QFileInfo fileinfo(fullPath);
-				if(fileinfo.exists())
-				{
-					return true;
-				}
-			}
-			QFileInfo fileinfo(entry->getFullPath());
-			if(!fileinfo.exists())
-			{
-				failedFiles.append(entry->getFullPath());
-				return false;
-			}
-			return true;
-		}
-		Net::Download::Options options;
-		if(isAlwaysStale)
-		{
-			options |= Net::Download::Option::AcceptLocalFiles;
-		}
-		if (isForge)
-		{
-			qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
-			out.append(ForgeXzDownload::make(storage, entry));
-		}
-		else
-		{
-			if(sha1.size())
-			{
-				auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
-				auto dl = Net::Download::makeCached(url, entry, options);
-				dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
-				qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
-				out.append(dl);
-			}
-			else
-			{
-				out.append(Net::Download::makeCached(url, entry, options));
-				qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
-			}
-		}
-		return true;
-	};
+    auto add_download = [&](QString storage, QString url, QString sha1)
+    {
+        auto entry = cache->resolveEntry("libraries", storage);
+        if(isAlwaysStale)
+        {
+            entry->setStale(true);
+        }
+        if (!entry->isStale())
+            return true;
+        if(local)
+        {
+            if(!overridePath.isEmpty())
+            {
+                QString fileName;
+                int position = storage.lastIndexOf('/');
+                if(position == -1)
+                {
+                    fileName = storage;
+                }
+                else
+                {
+                    fileName = storage.mid(position);
+                }
+                auto fullPath = FS::PathCombine(overridePath, fileName);
+                QFileInfo fileinfo(fullPath);
+                if(fileinfo.exists())
+                {
+                    return true;
+                }
+            }
+            QFileInfo fileinfo(entry->getFullPath());
+            if(!fileinfo.exists())
+            {
+                failedFiles.append(entry->getFullPath());
+                return false;
+            }
+            return true;
+        }
+        Net::Download::Options options;
+        if(isAlwaysStale)
+        {
+            options |= Net::Download::Option::AcceptLocalFiles;
+        }
+        if (isForge)
+        {
+            qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
+            out.append(ForgeXzDownload::make(storage, entry));
+        }
+        else
+        {
+            if(sha1.size())
+            {
+                auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
+                auto dl = Net::Download::makeCached(url, entry, options);
+                dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
+                qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
+                out.append(dl);
+            }
+            else
+            {
+                out.append(Net::Download::makeCached(url, entry, options));
+                qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
+            }
+        }
+        return true;
+    };
 
-	QString raw_storage = storageSuffix(system);
-	if(m_mojangDownloads)
-	{
-		if(isNative())
-		{
-			if(m_nativeClassifiers.contains(system))
-			{
-				auto nativeClassifier = m_nativeClassifiers[system];
-				if(nativeClassifier.contains("${arch}"))
-				{
-					auto nat32Classifier = nativeClassifier;
-					nat32Classifier.replace("${arch}", "32");
-					auto nat64Classifier = nativeClassifier;
-					nat64Classifier.replace("${arch}", "64");
-					auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
-					if(nat32info)
-					{
-						auto cooked_storage = raw_storage;
-						cooked_storage.replace("${arch}", "32");
-						add_download(cooked_storage, nat32info->url, nat32info->sha1);
-					}
-					auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
-					if(nat64info)
-					{
-						auto cooked_storage = raw_storage;
-						cooked_storage.replace("${arch}", "64");
-						add_download(cooked_storage, nat64info->url, nat64info->sha1);
-					}
-				}
-				else
-				{
-					auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier);
-					if(info)
-					{
-						add_download(raw_storage, info->url, info->sha1);
-					}
-				}
-			}
-			else
-			{
-				qDebug() << "Ignoring native library" << m_name << "because it has no classifier for current OS";
-			}
-		}
-		else
-		{
-			if(m_mojangDownloads->artifact)
-			{
-				auto artifact = m_mojangDownloads->artifact;
-				add_download(raw_storage, artifact->url, artifact->sha1);
-			}
-			else
-			{
-				qDebug() << "Ignoring java library" << m_name << "because it has no artifact";
-			}
-		}
-	}
-	else
-	{
-		auto raw_dl = [&](){
-			if (!m_absoluteURL.isEmpty())
-			{
-				return m_absoluteURL;
-			}
+    QString raw_storage = storageSuffix(system);
+    if(m_mojangDownloads)
+    {
+        if(isNative())
+        {
+            if(m_nativeClassifiers.contains(system))
+            {
+                auto nativeClassifier = m_nativeClassifiers[system];
+                if(nativeClassifier.contains("${arch}"))
+                {
+                    auto nat32Classifier = nativeClassifier;
+                    nat32Classifier.replace("${arch}", "32");
+                    auto nat64Classifier = nativeClassifier;
+                    nat64Classifier.replace("${arch}", "64");
+                    auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
+                    if(nat32info)
+                    {
+                        auto cooked_storage = raw_storage;
+                        cooked_storage.replace("${arch}", "32");
+                        add_download(cooked_storage, nat32info->url, nat32info->sha1);
+                    }
+                    auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
+                    if(nat64info)
+                    {
+                        auto cooked_storage = raw_storage;
+                        cooked_storage.replace("${arch}", "64");
+                        add_download(cooked_storage, nat64info->url, nat64info->sha1);
+                    }
+                }
+                else
+                {
+                    auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier);
+                    if(info)
+                    {
+                        add_download(raw_storage, info->url, info->sha1);
+                    }
+                }
+            }
+            else
+            {
+                qDebug() << "Ignoring native library" << m_name << "because it has no classifier for current OS";
+            }
+        }
+        else
+        {
+            if(m_mojangDownloads->artifact)
+            {
+                auto artifact = m_mojangDownloads->artifact;
+                add_download(raw_storage, artifact->url, artifact->sha1);
+            }
+            else
+            {
+                qDebug() << "Ignoring java library" << m_name << "because it has no artifact";
+            }
+        }
+    }
+    else
+    {
+        auto raw_dl = [&](){
+            if (!m_absoluteURL.isEmpty())
+            {
+                return m_absoluteURL;
+            }
 
-			if (m_repositoryURL.isEmpty())
-			{
-				return QString("https://" + URLConstants::LIBRARY_BASE) + raw_storage;
-			}
+            if (m_repositoryURL.isEmpty())
+            {
+                return QString("https://" + URLConstants::LIBRARY_BASE) + raw_storage;
+            }
 
-			if(m_repositoryURL.endsWith('/'))
-			{
-				return m_repositoryURL + raw_storage;
-			}
-			else
-			{
-				return m_repositoryURL + QChar('/') + raw_storage;
-			}
-		}();
-		if (raw_storage.contains("${arch}"))
-		{
-			QString cooked_storage = raw_storage;
-			QString cooked_dl = raw_dl;
-			add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"), QString());
-			cooked_storage = raw_storage;
-			cooked_dl = raw_dl;
-			add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"), QString());
-		}
-		else
-		{
-			add_download(raw_storage, raw_dl, QString());
-		}
-	}
-	return out;
+            if(m_repositoryURL.endsWith('/'))
+            {
+                return m_repositoryURL + raw_storage;
+            }
+            else
+            {
+                return m_repositoryURL + QChar('/') + raw_storage;
+            }
+        }();
+        if (raw_storage.contains("${arch}"))
+        {
+            QString cooked_storage = raw_storage;
+            QString cooked_dl = raw_dl;
+            add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"), QString());
+            cooked_storage = raw_storage;
+            cooked_dl = raw_dl;
+            add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"), QString());
+        }
+        else
+        {
+            add_download(raw_storage, raw_dl, QString());
+        }
+    }
+    return out;
 }
 
 bool Library::isActive() const
 {
-	bool result = true;
-	if (m_rules.empty())
-	{
-		result = true;
-	}
-	else
-	{
-		RuleAction ruleResult = Disallow;
-		for (auto rule : m_rules)
-		{
-			RuleAction temp = rule->apply(this);
-			if (temp != Defer)
-				ruleResult = temp;
-		}
-		result = result && (ruleResult == Allow);
-	}
-	if (isNative())
-	{
-		result = result && m_nativeClassifiers.contains(currentSystem);
-	}
-	return result;
+    bool result = true;
+    if (m_rules.empty())
+    {
+        result = true;
+    }
+    else
+    {
+        RuleAction ruleResult = Disallow;
+        for (auto rule : m_rules)
+        {
+            RuleAction temp = rule->apply(this);
+            if (temp != Defer)
+                ruleResult = temp;
+        }
+        result = result && (ruleResult == Allow);
+    }
+    if (isNative())
+    {
+        result = result && m_nativeClassifiers.contains(currentSystem);
+    }
+    return result;
 }
 
 bool Library::isLocal() const
 {
-	return m_hint == "local";
+    return m_hint == "local";
 }
 
 void Library::setStoragePrefix(QString prefix)
 {
-	m_storagePrefix = prefix;
+    m_storagePrefix = prefix;
 }
 
 QString Library::defaultStoragePrefix()
 {
-	return "libraries/";
+    return "libraries/";
 }
 
 QString Library::storagePrefix() const
 {
-	if(m_storagePrefix.isEmpty())
-	{
-		return defaultStoragePrefix();
-	}
-	return m_storagePrefix;
+    if(m_storagePrefix.isEmpty())
+    {
+        return defaultStoragePrefix();
+    }
+    return m_storagePrefix;
 }
 
 QString Library::filename(OpSys system) const
 {
-	if(!m_filename.isEmpty())
-	{
-		return m_filename;
-	}
-	// non-native? use only the gradle specifier
-	if (!isNative())
-	{
-		return m_name.getFileName();
-	}
+    if(!m_filename.isEmpty())
+    {
+        return m_filename;
+    }
+    // non-native? use only the gradle specifier
+    if (!isNative())
+    {
+        return m_name.getFileName();
+    }
 
-	// otherwise native, override classifiers. Mojang HACK!
-	GradleSpecifier nativeSpec = m_name;
-	if (m_nativeClassifiers.contains(system))
-	{
-		nativeSpec.setClassifier(m_nativeClassifiers[system]);
-	}
-	else
-	{
-		nativeSpec.setClassifier("INVALID");
-	}
-	return nativeSpec.getFileName();
+    // otherwise native, override classifiers. Mojang HACK!
+    GradleSpecifier nativeSpec = m_name;
+    if (m_nativeClassifiers.contains(system))
+    {
+        nativeSpec.setClassifier(m_nativeClassifiers[system]);
+    }
+    else
+    {
+        nativeSpec.setClassifier("INVALID");
+    }
+    return nativeSpec.getFileName();
 }
 
 QString Library::displayName(OpSys system) const
 {
-	if(!m_displayname.isEmpty())
-		return m_displayname;
-	return filename(system);
+    if(!m_displayname.isEmpty())
+        return m_displayname;
+    return filename(system);
 }
 
 QString Library::storageSuffix(OpSys system) const
 {
-	// non-native? use only the gradle specifier
-	if (!isNative())
-	{
-		return m_name.toPath(m_filename);
-	}
+    // non-native? use only the gradle specifier
+    if (!isNative())
+    {
+        return m_name.toPath(m_filename);
+    }
 
-	// otherwise native, override classifiers. Mojang HACK!
-	GradleSpecifier nativeSpec = m_name;
-	if (m_nativeClassifiers.contains(system))
-	{
-		nativeSpec.setClassifier(m_nativeClassifiers[system]);
-	}
-	else
-	{
-		nativeSpec.setClassifier("INVALID");
-	}
-	return nativeSpec.toPath(m_filename);
+    // otherwise native, override classifiers. Mojang HACK!
+    GradleSpecifier nativeSpec = m_name;
+    if (m_nativeClassifiers.contains(system))
+    {
+        nativeSpec.setClassifier(m_nativeClassifiers[system]);
+    }
+    else
+    {
+        nativeSpec.setClassifier("INVALID");
+    }
+    return nativeSpec.toPath(m_filename);
 }
diff --git a/api/logic/minecraft/Library.h b/api/logic/minecraft/Library.h
index 9577de33..5fcff316 100644
--- a/api/logic/minecraft/Library.h
+++ b/api/logic/minecraft/Library.h
@@ -24,191 +24,191 @@ typedef std::shared_ptr<Library> LibraryPtr;
 
 class MULTIMC_LOGIC_EXPORT Library
 {
-	friend class OneSixVersionFormat;
-	friend class MojangVersionFormat;
-	friend class LibraryTest;
+    friend class OneSixVersionFormat;
+    friend class MojangVersionFormat;
+    friend class LibraryTest;
 public:
-	Library()
-	{
-	}
-	Library(const QString &name)
-	{
-		m_name = name;
-	}
-	/// limited copy without some data. TODO: why?
-	static LibraryPtr limitedCopy(LibraryPtr base)
-	{
-		auto newlib = std::make_shared<Library>();
-		newlib->m_name = base->m_name;
-		newlib->m_repositoryURL = base->m_repositoryURL;
-		newlib->m_hint = base->m_hint;
-		newlib->m_absoluteURL = base->m_absoluteURL;
-		newlib->m_extractExcludes = base->m_extractExcludes;
-		newlib->m_nativeClassifiers = base->m_nativeClassifiers;
-		newlib->m_rules = base->m_rules;
-		newlib->m_storagePrefix = base->m_storagePrefix;
-		newlib->m_mojangDownloads = base->m_mojangDownloads;
-		newlib->m_filename = base->m_filename;
-		return newlib;
-	}
+    Library()
+    {
+    }
+    Library(const QString &name)
+    {
+        m_name = name;
+    }
+    /// limited copy without some data. TODO: why?
+    static LibraryPtr limitedCopy(LibraryPtr base)
+    {
+        auto newlib = std::make_shared<Library>();
+        newlib->m_name = base->m_name;
+        newlib->m_repositoryURL = base->m_repositoryURL;
+        newlib->m_hint = base->m_hint;
+        newlib->m_absoluteURL = base->m_absoluteURL;
+        newlib->m_extractExcludes = base->m_extractExcludes;
+        newlib->m_nativeClassifiers = base->m_nativeClassifiers;
+        newlib->m_rules = base->m_rules;
+        newlib->m_storagePrefix = base->m_storagePrefix;
+        newlib->m_mojangDownloads = base->m_mojangDownloads;
+        newlib->m_filename = base->m_filename;
+        return newlib;
+    }
 
 public: /* methods */
-	/// Returns the raw name field
-	const GradleSpecifier & rawName() const
-	{
-		return m_name;
-	}
-
-	void setRawName(const GradleSpecifier & spec)
-	{
-		m_name = spec;
-	}
-
-	void setClassifier(const QString & spec)
-	{
-		m_name.setClassifier(spec);
-	}
-
-	/// returns the full group and artifact prefix
-	QString artifactPrefix() const
-	{
-		return m_name.artifactPrefix();
-	}
-
-	/// get the artifact ID
-	QString artifactId() const
-	{
-		return m_name.artifactId();
-	}
-
-	/// get the artifact version
-	QString version() const
-	{
-		return m_name.version();
-	}
-
-	/// Returns true if the library is native
-	bool isNative() const
-	{
-		return m_nativeClassifiers.size() != 0;
-	}
-
-	void setStoragePrefix(QString prefix = QString());
-
-	/// Set the url base for downloads
-	void setRepositoryURL(const QString &base_url)
-	{
-		m_repositoryURL = base_url;
-	}
-
-	void getApplicableFiles(OpSys system, QStringList & jar, QStringList & native,
-							QStringList & native32, QStringList & native64, const QString & overridePath) const;
-
-	void setAbsoluteUrl(const QString &absolute_url)
-	{
-		m_absoluteURL = absolute_url;
-	}
-
-	void setFilename(const QString &filename)
-	{
-		m_filename = filename;
-	}
-
-	/// Get the file name of the library
-	QString filename(OpSys system) const;
-
-	// DEPRECATED: set a display name, used by jar mods only
-	void setDisplayName(const QString & displayName)
-	{
-		m_displayname = displayName;
-	}
-
-	/// Get the file name of the library
-	QString displayName(OpSys system) const;
-
-	void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info)
-	{
-		m_mojangDownloads = info;
-	}
-
-	void setHint(const QString &hint)
-	{
-		m_hint = hint;
-	}
-
-	/// Set the load rules
-	void setRules(QList<std::shared_ptr<Rule>> rules)
-	{
-		m_rules = rules;
-	}
-
-	/// Returns true if the library should be loaded (or extracted, in case of natives)
-	bool isActive() const;
-
-	/// Returns true if the library is contained in an instance and false if it is shared
-	bool isLocal() const;
-
-	// Get a list of downloads for this library
-	QList<NetActionPtr> getDownloads(OpSys system, class HttpMetaCache * cache,
-									 QStringList & failedFiles, const QString & overridePath) const;
+    /// Returns the raw name field
+    const GradleSpecifier & rawName() const
+    {
+        return m_name;
+    }
+
+    void setRawName(const GradleSpecifier & spec)
+    {
+        m_name = spec;
+    }
+
+    void setClassifier(const QString & spec)
+    {
+        m_name.setClassifier(spec);
+    }
+
+    /// returns the full group and artifact prefix
+    QString artifactPrefix() const
+    {
+        return m_name.artifactPrefix();
+    }
+
+    /// get the artifact ID
+    QString artifactId() const
+    {
+        return m_name.artifactId();
+    }
+
+    /// get the artifact version
+    QString version() const
+    {
+        return m_name.version();
+    }
+
+    /// Returns true if the library is native
+    bool isNative() const
+    {
+        return m_nativeClassifiers.size() != 0;
+    }
+
+    void setStoragePrefix(QString prefix = QString());
+
+    /// Set the url base for downloads
+    void setRepositoryURL(const QString &base_url)
+    {
+        m_repositoryURL = base_url;
+    }
+
+    void getApplicableFiles(OpSys system, QStringList & jar, QStringList & native,
+                            QStringList & native32, QStringList & native64, const QString & overridePath) const;
+
+    void setAbsoluteUrl(const QString &absolute_url)
+    {
+        m_absoluteURL = absolute_url;
+    }
+
+    void setFilename(const QString &filename)
+    {
+        m_filename = filename;
+    }
+
+    /// Get the file name of the library
+    QString filename(OpSys system) const;
+
+    // DEPRECATED: set a display name, used by jar mods only
+    void setDisplayName(const QString & displayName)
+    {
+        m_displayname = displayName;
+    }
+
+    /// Get the file name of the library
+    QString displayName(OpSys system) const;
+
+    void setMojangDownloadInfo(MojangLibraryDownloadInfo::Ptr info)
+    {
+        m_mojangDownloads = info;
+    }
+
+    void setHint(const QString &hint)
+    {
+        m_hint = hint;
+    }
+
+    /// Set the load rules
+    void setRules(QList<std::shared_ptr<Rule>> rules)
+    {
+        m_rules = rules;
+    }
+
+    /// Returns true if the library should be loaded (or extracted, in case of natives)
+    bool isActive() const;
+
+    /// Returns true if the library is contained in an instance and false if it is shared
+    bool isLocal() const;
+
+    // Get a list of downloads for this library
+    QList<NetActionPtr> getDownloads(OpSys system, class HttpMetaCache * cache,
+                                     QStringList & failedFiles, const QString & overridePath) const;
 
 private: /* methods */
-	/// the default storage prefix used by MultiMC
-	static QString defaultStoragePrefix();
+    /// the default storage prefix used by MultiMC
+    static QString defaultStoragePrefix();
 
-	/// Get the prefix - root of the storage to be used
-	QString storagePrefix() const;
+    /// Get the prefix - root of the storage to be used
+    QString storagePrefix() const;
 
-	/// Get the relative file path where the library should be saved
-	QString storageSuffix(OpSys system) const;
+    /// Get the relative file path where the library should be saved
+    QString storageSuffix(OpSys system) const;
 
-	QString hint() const
-	{
-		return m_hint;
-	}
+    QString hint() const
+    {
+        return m_hint;
+    }
 
 protected: /* data */
-	/// the basic gradle dependency specifier.
-	GradleSpecifier m_name;
+    /// the basic gradle dependency specifier.
+    GradleSpecifier m_name;
 
-	/// DEPRECATED URL prefix of the maven repo where the file can be downloaded
-	QString m_repositoryURL;
+    /// DEPRECATED URL prefix of the maven repo where the file can be downloaded
+    QString m_repositoryURL;
 
-	/// DEPRECATED: MultiMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined
-	QString m_absoluteURL;
+    /// DEPRECATED: MultiMC-specific absolute URL. takes precedence over the implicit maven repo URL, if defined
+    QString m_absoluteURL;
 
-	/// MultiMC extension - filename override
-	QString m_filename;
+    /// MultiMC extension - filename override
+    QString m_filename;
 
-	/// DEPRECATED MultiMC extension - display name
-	QString m_displayname;
+    /// DEPRECATED MultiMC extension - display name
+    QString m_displayname;
 
-	/**
-	 * MultiMC-specific type hint - modifies how the library is treated
-	 */
-	QString m_hint;
+    /**
+     * MultiMC-specific type hint - modifies how the library is treated
+     */
+    QString m_hint;
 
-	/**
-	 * storage - by default the local libraries folder in multimc, but could be elsewhere
-	 * MultiMC specific, because of FTB.
-	 */
-	QString m_storagePrefix;
+    /**
+     * storage - by default the local libraries folder in multimc, but could be elsewhere
+     * MultiMC specific, because of FTB.
+     */
+    QString m_storagePrefix;
 
-	/// true if the library had an extract/excludes section (even empty)
-	bool m_hasExcludes = false;
+    /// true if the library had an extract/excludes section (even empty)
+    bool m_hasExcludes = false;
 
-	/// a list of files that shouldn't be extracted from the library
-	QStringList m_extractExcludes;
+    /// a list of files that shouldn't be extracted from the library
+    QStringList m_extractExcludes;
 
-	/// native suffixes per OS
-	QMap<OpSys, QString> m_nativeClassifiers;
+    /// native suffixes per OS
+    QMap<OpSys, QString> m_nativeClassifiers;
 
-	/// true if the library had a rules section (even empty)
-	bool applyRules = false;
+    /// true if the library had a rules section (even empty)
+    bool applyRules = false;
 
-	/// rules associated with the library
-	QList<std::shared_ptr<Rule>> m_rules;
+    /// rules associated with the library
+    QList<std::shared_ptr<Rule>> m_rules;
 
-	/// MOJANG: container with Mojang style download info
-	MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
+    /// MOJANG: container with Mojang style download info
+    MojangLibraryDownloadInfo::Ptr m_mojangDownloads;
 };
diff --git a/api/logic/minecraft/Library_test.cpp b/api/logic/minecraft/Library_test.cpp
index 1aac951b..4f9c8006 100644
--- a/api/logic/minecraft/Library_test.cpp
+++ b/api/logic/minecraft/Library_test.cpp
@@ -9,261 +9,261 @@
 
 class LibraryTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private:
-	LibraryPtr readMojangJson(const char *file)
-	{
-		auto path = QFINDTESTDATA(file);
-		QFile jsonFile(path);
-		jsonFile.open(QIODevice::ReadOnly);
-		auto data = jsonFile.readAll();
-		jsonFile.close();
-		return MojangVersionFormat::libraryFromJson(QJsonDocument::fromJson(data).object(), file);
-	}
-	// get absolute path to expected storage, assuming default cache prefix
-	QStringList getStorage(QString relative)
-	{
-		return {FS::PathCombine(cache->getBasePath("libraries"), relative)};
-	}
+    LibraryPtr readMojangJson(const char *file)
+    {
+        auto path = QFINDTESTDATA(file);
+        QFile jsonFile(path);
+        jsonFile.open(QIODevice::ReadOnly);
+        auto data = jsonFile.readAll();
+        jsonFile.close();
+        return MojangVersionFormat::libraryFromJson(QJsonDocument::fromJson(data).object(), file);
+    }
+    // get absolute path to expected storage, assuming default cache prefix
+    QStringList getStorage(QString relative)
+    {
+        return {FS::PathCombine(cache->getBasePath("libraries"), relative)};
+    }
 private
 slots:
-	void initTestCase()
-	{
-		cache.reset(new HttpMetaCache());
-		cache->addBase("libraries", QDir("libraries").absolutePath());
-		dataDir = QDir("data").absolutePath();
-	}
-	void test_legacy()
-	{
-		Library test("test.package:testname:testversion");
-		QCOMPARE(test.artifactPrefix(), QString("test.package:testname"));
-		QCOMPARE(test.isNative(), false);
+    void initTestCase()
+    {
+        cache.reset(new HttpMetaCache());
+        cache->addBase("libraries", QDir("libraries").absolutePath());
+        dataDir = QDir("data").absolutePath();
+    }
+    void test_legacy()
+    {
+        Library test("test.package:testname:testversion");
+        QCOMPARE(test.artifactPrefix(), QString("test.package:testname"));
+        QCOMPARE(test.isNative(), false);
 
-		QStringList jar, native, native32, native64;
-		test.getApplicableFiles(currentSystem, jar, native, native32, native64, QString());
-		QCOMPARE(jar, getStorage("test/package/testname/testversion/testname-testversion.jar"));
-		QCOMPARE(native, {});
-		QCOMPARE(native32, {});
-		QCOMPARE(native64, {});
-	}
-	void test_legacy_url()
-	{
-		QStringList failedFiles;
-		Library test("test.package:testname:testversion");
-		test.setRepositoryURL("file://foo/bar");
-		auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString());
-		QCOMPARE(downloads.size(), 1);
-		QCOMPARE(failedFiles, {});
-		NetActionPtr dl = downloads[0];
-		QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion.jar"));
-	}
-	void test_legacy_url_local_broken()
-	{
-		Library test("test.package:testname:testversion");
-		QCOMPARE(test.isNative(), false);
-		QStringList failedFiles;
-		test.setHint("local");
-		auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString());
-		QCOMPARE(downloads.size(), 0);
-		QCOMPARE(failedFiles, getStorage("test/package/testname/testversion/testname-testversion.jar"));
-	}
-	void test_legacy_url_local_override()
-	{
-		Library test("com.paulscode:codecwav:20101023");
-		QCOMPARE(test.isNative(), false);
-		QStringList failedFiles;
-		test.setHint("local");
-		auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString("data"));
-		QCOMPARE(downloads.size(), 0);
-		qDebug() << failedFiles;
-		QCOMPARE(failedFiles.size(), 0);
+        QStringList jar, native, native32, native64;
+        test.getApplicableFiles(currentSystem, jar, native, native32, native64, QString());
+        QCOMPARE(jar, getStorage("test/package/testname/testversion/testname-testversion.jar"));
+        QCOMPARE(native, {});
+        QCOMPARE(native32, {});
+        QCOMPARE(native64, {});
+    }
+    void test_legacy_url()
+    {
+        QStringList failedFiles;
+        Library test("test.package:testname:testversion");
+        test.setRepositoryURL("file://foo/bar");
+        auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString());
+        QCOMPARE(downloads.size(), 1);
+        QCOMPARE(failedFiles, {});
+        NetActionPtr dl = downloads[0];
+        QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion.jar"));
+    }
+    void test_legacy_url_local_broken()
+    {
+        Library test("test.package:testname:testversion");
+        QCOMPARE(test.isNative(), false);
+        QStringList failedFiles;
+        test.setHint("local");
+        auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString());
+        QCOMPARE(downloads.size(), 0);
+        QCOMPARE(failedFiles, getStorage("test/package/testname/testversion/testname-testversion.jar"));
+    }
+    void test_legacy_url_local_override()
+    {
+        Library test("com.paulscode:codecwav:20101023");
+        QCOMPARE(test.isNative(), false);
+        QStringList failedFiles;
+        test.setHint("local");
+        auto downloads = test.getDownloads(currentSystem, cache.get(), failedFiles, QString("data"));
+        QCOMPARE(downloads.size(), 0);
+        qDebug() << failedFiles;
+        QCOMPARE(failedFiles.size(), 0);
 
-		QStringList jar, native, native32, native64;
-		test.getApplicableFiles(currentSystem, jar, native, native32, native64, QString("data"));
-		QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
-		QCOMPARE(native, {});
-		QCOMPARE(native32, {});
-		QCOMPARE(native64, {});
-	}
-	void test_legacy_native()
-	{
-		Library test("test.package:testname:testversion");
-		test.m_nativeClassifiers[OpSys::Os_Linux]="linux";
-		QCOMPARE(test.isNative(), true);
-		test.setRepositoryURL("file://foo/bar");
-		{
-			QStringList jar, native, native32, native64;
-			test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString());
-			QCOMPARE(jar, {});
-			QCOMPARE(native, getStorage("test/package/testname/testversion/testname-testversion-linux.jar"));
-			QCOMPARE(native32, {});
-			QCOMPARE(native64, {});
-			QStringList failedFiles;
-			auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString());
-			QCOMPARE(dls.size(), 1);
-			QCOMPARE(failedFiles, {});
-			auto dl = dls[0];
-			QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux.jar"));
-		}
-	}
-	void test_legacy_native_arch()
-	{
-		Library test("test.package:testname:testversion");
-		test.m_nativeClassifiers[OpSys::Os_Linux]="linux-${arch}";
-		test.m_nativeClassifiers[OpSys::Os_OSX]="osx-${arch}";
-		test.m_nativeClassifiers[OpSys::Os_Windows]="windows-${arch}";
-		QCOMPARE(test.isNative(), true);
-		test.setRepositoryURL("file://foo/bar");
-		{
-			QStringList jar, native, native32, native64;
-			test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString());
-			QCOMPARE(jar, {});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-linux-32.jar"));
-			QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
-			QStringList failedFiles;
-			auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString());
-			QCOMPARE(dls.size(), 2);
-			QCOMPARE(failedFiles, {});
-			QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-32.jar"));
-			QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-64.jar"));
-		}
-		{
-			QStringList jar, native, native32, native64;
-			test.getApplicableFiles(Os_Windows, jar, native, native32, native64, QString());
-			QCOMPARE(jar, {});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-windows-32.jar"));
-			QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-windows-64.jar"));
-			QStringList failedFiles;
-			auto dls = test.getDownloads(Os_Windows, cache.get(), failedFiles, QString());
-			QCOMPARE(dls.size(), 2);
-			QCOMPARE(failedFiles, {});
-			QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-32.jar"));
-			QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-64.jar"));
-		}
-		{
-			QStringList jar, native, native32, native64;
-			test.getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
-			QCOMPARE(jar, {});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-osx-32.jar"));
-			QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-osx-64.jar"));
-			QStringList failedFiles;
-			auto dls = test.getDownloads(Os_OSX, cache.get(), failedFiles, QString());
-			QCOMPARE(dls.size(), 2);
-			QCOMPARE(failedFiles, {});
-			QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-32.jar"));
-			QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-64.jar"));
-		}
-	}
-	void test_legacy_native_arch_local_override()
-	{
-		Library test("test.package:testname:testversion");
-		test.m_nativeClassifiers[OpSys::Os_Linux]="linux-${arch}";
-		test.setHint("local");
-		QCOMPARE(test.isNative(), true);
-		test.setRepositoryURL("file://foo/bar");
-		{
-			QStringList jar, native, native32, native64;
-			test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString("data"));
-			QCOMPARE(jar, {});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, {QFileInfo("data/testname-testversion-linux-32.jar").absoluteFilePath()});
-			QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
-			QStringList failedFiles;
-			auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
-			QCOMPARE(dls.size(), 0);
-			QCOMPARE(failedFiles, {getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar")});
-		}
-	}
-	void test_onenine()
-	{
-		auto test = readMojangJson("data/lib-simple.json");
-		{
-			QStringList jar, native, native32, native64;
-			test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
-			QCOMPARE(jar, getStorage("com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
-			QCOMPARE(native, {});
-			QCOMPARE(native32, {});
-			QCOMPARE(native64, {});
-		}
-		{
-			QStringList failedFiles;
-			auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString());
-			QCOMPARE(dls.size(), 1);
-			QCOMPARE(failedFiles, {});
-			QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
-		}
-		test->setHint("local");
-		{
-			QStringList jar, native, native32, native64;
-			test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString("data"));
-			QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, {});
-			QCOMPARE(native64, {});
-		}
-		{
-			QStringList failedFiles;
-			auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
-			QCOMPARE(dls.size(), 0);
-			QCOMPARE(failedFiles, {});
-		}
-	}
-	void test_onenine_local_override()
-	{
-		auto test = readMojangJson("data/lib-simple.json");
-		test->setHint("local");
-		{
-			QStringList jar, native, native32, native64;
-			test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString("data"));
-			QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
-			QCOMPARE(native, {});
-			QCOMPARE(native32, {});
-			QCOMPARE(native64, {});
-		}
-		{
-			QStringList failedFiles;
-			auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
-			QCOMPARE(dls.size(), 0);
-			QCOMPARE(failedFiles, {});
-		}
-	}
-	void test_onenine_native()
-	{
-		auto test = readMojangJson("data/lib-native.json");
-		QStringList jar, native, native32, native64;
-		test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
-		QCOMPARE(jar, QStringList());
-		QCOMPARE(native, getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
-		QCOMPARE(native32, {});
-		QCOMPARE(native64, {});
-		QStringList failedFiles;
-		auto dls = test->getDownloads(Os_OSX, cache.get(), failedFiles, QString());
-		QCOMPARE(dls.size(), 1);
-		QCOMPARE(failedFiles, {});
-		QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
-	}
-	void test_onenine_native_arch()
-	{
-		auto test = readMojangJson("data/lib-native-arch.json");
-		QStringList jar, native, native32, native64;
-		test->getApplicableFiles(Os_Windows, jar, native, native32, native64, QString());
-		QCOMPARE(jar, {});
-		QCOMPARE(native, {});
-		QCOMPARE(native32, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
-		QCOMPARE(native64, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
-		QStringList failedFiles;
-		auto dls = test->getDownloads(Os_Windows, cache.get(), failedFiles, QString());
-		QCOMPARE(dls.size(), 2);
-		QCOMPARE(failedFiles, {});
-		QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
-		QCOMPARE(dls[1]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
-	}
+        QStringList jar, native, native32, native64;
+        test.getApplicableFiles(currentSystem, jar, native, native32, native64, QString("data"));
+        QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
+        QCOMPARE(native, {});
+        QCOMPARE(native32, {});
+        QCOMPARE(native64, {});
+    }
+    void test_legacy_native()
+    {
+        Library test("test.package:testname:testversion");
+        test.m_nativeClassifiers[OpSys::Os_Linux]="linux";
+        QCOMPARE(test.isNative(), true);
+        test.setRepositoryURL("file://foo/bar");
+        {
+            QStringList jar, native, native32, native64;
+            test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString());
+            QCOMPARE(jar, {});
+            QCOMPARE(native, getStorage("test/package/testname/testversion/testname-testversion-linux.jar"));
+            QCOMPARE(native32, {});
+            QCOMPARE(native64, {});
+            QStringList failedFiles;
+            auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString());
+            QCOMPARE(dls.size(), 1);
+            QCOMPARE(failedFiles, {});
+            auto dl = dls[0];
+            QCOMPARE(dl->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux.jar"));
+        }
+    }
+    void test_legacy_native_arch()
+    {
+        Library test("test.package:testname:testversion");
+        test.m_nativeClassifiers[OpSys::Os_Linux]="linux-${arch}";
+        test.m_nativeClassifiers[OpSys::Os_OSX]="osx-${arch}";
+        test.m_nativeClassifiers[OpSys::Os_Windows]="windows-${arch}";
+        QCOMPARE(test.isNative(), true);
+        test.setRepositoryURL("file://foo/bar");
+        {
+            QStringList jar, native, native32, native64;
+            test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString());
+            QCOMPARE(jar, {});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-linux-32.jar"));
+            QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
+            QStringList failedFiles;
+            auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString());
+            QCOMPARE(dls.size(), 2);
+            QCOMPARE(failedFiles, {});
+            QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-32.jar"));
+            QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-linux-64.jar"));
+        }
+        {
+            QStringList jar, native, native32, native64;
+            test.getApplicableFiles(Os_Windows, jar, native, native32, native64, QString());
+            QCOMPARE(jar, {});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-windows-32.jar"));
+            QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-windows-64.jar"));
+            QStringList failedFiles;
+            auto dls = test.getDownloads(Os_Windows, cache.get(), failedFiles, QString());
+            QCOMPARE(dls.size(), 2);
+            QCOMPARE(failedFiles, {});
+            QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-32.jar"));
+            QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-windows-64.jar"));
+        }
+        {
+            QStringList jar, native, native32, native64;
+            test.getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
+            QCOMPARE(jar, {});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, getStorage("test/package/testname/testversion/testname-testversion-osx-32.jar"));
+            QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-osx-64.jar"));
+            QStringList failedFiles;
+            auto dls = test.getDownloads(Os_OSX, cache.get(), failedFiles, QString());
+            QCOMPARE(dls.size(), 2);
+            QCOMPARE(failedFiles, {});
+            QCOMPARE(dls[0]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-32.jar"));
+            QCOMPARE(dls[1]->m_url, QUrl("file://foo/bar/test/package/testname/testversion/testname-testversion-osx-64.jar"));
+        }
+    }
+    void test_legacy_native_arch_local_override()
+    {
+        Library test("test.package:testname:testversion");
+        test.m_nativeClassifiers[OpSys::Os_Linux]="linux-${arch}";
+        test.setHint("local");
+        QCOMPARE(test.isNative(), true);
+        test.setRepositoryURL("file://foo/bar");
+        {
+            QStringList jar, native, native32, native64;
+            test.getApplicableFiles(Os_Linux, jar, native, native32, native64, QString("data"));
+            QCOMPARE(jar, {});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, {QFileInfo("data/testname-testversion-linux-32.jar").absoluteFilePath()});
+            QCOMPARE(native64, getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar"));
+            QStringList failedFiles;
+            auto dls = test.getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
+            QCOMPARE(dls.size(), 0);
+            QCOMPARE(failedFiles, {getStorage("test/package/testname/testversion/testname-testversion-linux-64.jar")});
+        }
+    }
+    void test_onenine()
+    {
+        auto test = readMojangJson("data/lib-simple.json");
+        {
+            QStringList jar, native, native32, native64;
+            test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
+            QCOMPARE(jar, getStorage("com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+            QCOMPARE(native, {});
+            QCOMPARE(native32, {});
+            QCOMPARE(native64, {});
+        }
+        {
+            QStringList failedFiles;
+            auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString());
+            QCOMPARE(dls.size(), 1);
+            QCOMPARE(failedFiles, {});
+            QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"));
+        }
+        test->setHint("local");
+        {
+            QStringList jar, native, native32, native64;
+            test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString("data"));
+            QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, {});
+            QCOMPARE(native64, {});
+        }
+        {
+            QStringList failedFiles;
+            auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
+            QCOMPARE(dls.size(), 0);
+            QCOMPARE(failedFiles, {});
+        }
+    }
+    void test_onenine_local_override()
+    {
+        auto test = readMojangJson("data/lib-simple.json");
+        test->setHint("local");
+        {
+            QStringList jar, native, native32, native64;
+            test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString("data"));
+            QCOMPARE(jar, {QFileInfo("data/codecwav-20101023.jar").absoluteFilePath()});
+            QCOMPARE(native, {});
+            QCOMPARE(native32, {});
+            QCOMPARE(native64, {});
+        }
+        {
+            QStringList failedFiles;
+            auto dls = test->getDownloads(Os_Linux, cache.get(), failedFiles, QString("data"));
+            QCOMPARE(dls.size(), 0);
+            QCOMPARE(failedFiles, {});
+        }
+    }
+    void test_onenine_native()
+    {
+        auto test = readMojangJson("data/lib-native.json");
+        QStringList jar, native, native32, native64;
+        test->getApplicableFiles(Os_OSX, jar, native, native32, native64, QString());
+        QCOMPARE(jar, QStringList());
+        QCOMPARE(native, getStorage("org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
+        QCOMPARE(native32, {});
+        QCOMPARE(native64, {});
+        QStringList failedFiles;
+        auto dls = test->getDownloads(Os_OSX, cache.get(), failedFiles, QString());
+        QCOMPARE(dls.size(), 1);
+        QCOMPARE(failedFiles, {});
+        QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"));
+    }
+    void test_onenine_native_arch()
+    {
+        auto test = readMojangJson("data/lib-native-arch.json");
+        QStringList jar, native, native32, native64;
+        test->getApplicableFiles(Os_Windows, jar, native, native32, native64, QString());
+        QCOMPARE(jar, {});
+        QCOMPARE(native, {});
+        QCOMPARE(native32, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+        QCOMPARE(native64, getStorage("tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+        QStringList failedFiles;
+        auto dls = test->getDownloads(Os_Windows, cache.get(), failedFiles, QString());
+        QCOMPARE(dls.size(), 2);
+        QCOMPARE(failedFiles, {});
+        QCOMPARE(dls[0]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"));
+        QCOMPARE(dls[1]->m_url, QUrl("https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"));
+    }
 private:
-	std::unique_ptr<HttpMetaCache> cache;
-	QString dataDir;
+    std::unique_ptr<HttpMetaCache> cache;
+    QString dataDir;
 };
 
 QTEST_GUILESS_MAIN(LibraryTest)
diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp
index e9f67b31..698c1ee2 100644
--- a/api/logic/minecraft/MinecraftInstance.cpp
+++ b/api/logic/minecraft/MinecraftInstance.cpp
@@ -43,73 +43,73 @@
 // if either of the settings {a, b} is true, this also resolves to true
 class OrSetting : public Setting
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	OrSetting(QString id, std::shared_ptr<Setting> a, std::shared_ptr<Setting> b)
-	:Setting({id}, false), m_a(a), m_b(b)
-	{
-	}
-	virtual QVariant get() const
-	{
-		bool a = m_a->get().toBool();
-		bool b = m_b->get().toBool();
-		return a || b;
-	}
-	virtual void reset() {}
-	virtual void set(QVariant value) {}
+    OrSetting(QString id, std::shared_ptr<Setting> a, std::shared_ptr<Setting> b)
+    :Setting({id}, false), m_a(a), m_b(b)
+    {
+    }
+    virtual QVariant get() const
+    {
+        bool a = m_a->get().toBool();
+        bool b = m_b->get().toBool();
+        return a || b;
+    }
+    virtual void reset() {}
+    virtual void set(QVariant value) {}
 private:
-	std::shared_ptr<Setting> m_a;
-	std::shared_ptr<Setting> m_b;
+    std::shared_ptr<Setting> m_a;
+    std::shared_ptr<Setting> m_b;
 };
 
 MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
-	: BaseInstance(globalSettings, settings, rootDir)
-{
-	// Java Settings
-	auto javaOverride = m_settings->registerSetting("OverrideJava", false);
-	auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false);
-	auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false);
-
-	// combinations
-	auto javaOrLocation = std::make_shared<OrSetting>("JavaOrLocationOverride", javaOverride, locationOverride);
-	auto javaOrArgs = std::make_shared<OrSetting>("JavaOrArgsOverride", javaOverride, argsOverride);
-
-	m_settings->registerOverride(globalSettings->getSetting("JavaPath"), javaOrLocation);
-	m_settings->registerOverride(globalSettings->getSetting("JvmArgs"), javaOrArgs);
-
-	// special!
-	m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation);
-	m_settings->registerPassthrough(globalSettings->getSetting("JavaVersion"), javaOrLocation);
-	m_settings->registerPassthrough(globalSettings->getSetting("JavaArchitecture"), javaOrLocation);
-
-	// Window Size
-	auto windowSetting = m_settings->registerSetting("OverrideWindow", false);
-	m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"), windowSetting);
-	m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"), windowSetting);
-	m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"), windowSetting);
-
-	// Memory
-	auto memorySetting = m_settings->registerSetting("OverrideMemory", false);
-	m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"), memorySetting);
-	m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"), memorySetting);
-	m_settings->registerOverride(globalSettings->getSetting("PermGen"), memorySetting);
-
-	// Minecraft launch method
-	auto launchMethodOverride = m_settings->registerSetting("OverrideMCLaunchMethod", false);
-	m_settings->registerOverride(globalSettings->getSetting("MCLaunchMethod"), launchMethodOverride);
-
-	// DEPRECATED: Read what versions the user configuration thinks should be used
-	m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
-	m_settings->registerSetting("LWJGLVersion", "");
-	m_settings->registerSetting("ForgeVersion", "");
-	m_settings->registerSetting("LiteloaderVersion", "");
-
-	m_components.reset(new ComponentList(this));
-	m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
-	auto setting = m_settings->getSetting("LWJGLVersion");
-	m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
-	m_components->setOldConfigVersion("net.minecraftforge", m_settings->get("ForgeVersion").toString());
-	m_components->setOldConfigVersion("com.mumfrey.liteloader", m_settings->get("LiteloaderVersion").toString());
+    : BaseInstance(globalSettings, settings, rootDir)
+{
+    // Java Settings
+    auto javaOverride = m_settings->registerSetting("OverrideJava", false);
+    auto locationOverride = m_settings->registerSetting("OverrideJavaLocation", false);
+    auto argsOverride = m_settings->registerSetting("OverrideJavaArgs", false);
+
+    // combinations
+    auto javaOrLocation = std::make_shared<OrSetting>("JavaOrLocationOverride", javaOverride, locationOverride);
+    auto javaOrArgs = std::make_shared<OrSetting>("JavaOrArgsOverride", javaOverride, argsOverride);
+
+    m_settings->registerOverride(globalSettings->getSetting("JavaPath"), javaOrLocation);
+    m_settings->registerOverride(globalSettings->getSetting("JvmArgs"), javaOrArgs);
+
+    // special!
+    m_settings->registerPassthrough(globalSettings->getSetting("JavaTimestamp"), javaOrLocation);
+    m_settings->registerPassthrough(globalSettings->getSetting("JavaVersion"), javaOrLocation);
+    m_settings->registerPassthrough(globalSettings->getSetting("JavaArchitecture"), javaOrLocation);
+
+    // Window Size
+    auto windowSetting = m_settings->registerSetting("OverrideWindow", false);
+    m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"), windowSetting);
+    m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"), windowSetting);
+    m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"), windowSetting);
+
+    // Memory
+    auto memorySetting = m_settings->registerSetting("OverrideMemory", false);
+    m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"), memorySetting);
+    m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"), memorySetting);
+    m_settings->registerOverride(globalSettings->getSetting("PermGen"), memorySetting);
+
+    // Minecraft launch method
+    auto launchMethodOverride = m_settings->registerSetting("OverrideMCLaunchMethod", false);
+    m_settings->registerOverride(globalSettings->getSetting("MCLaunchMethod"), launchMethodOverride);
+
+    // DEPRECATED: Read what versions the user configuration thinks should be used
+    m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
+    m_settings->registerSetting("LWJGLVersion", "");
+    m_settings->registerSetting("ForgeVersion", "");
+    m_settings->registerSetting("LiteloaderVersion", "");
+
+    m_components.reset(new ComponentList(this));
+    m_components->setOldConfigVersion("net.minecraft", m_settings->get("IntendedVersion").toString());
+    auto setting = m_settings->getSetting("LWJGLVersion");
+    m_components->setOldConfigVersion("org.lwjgl", m_settings->get("LWJGLVersion").toString());
+    m_components->setOldConfigVersion("net.minecraftforge", m_settings->get("ForgeVersion").toString());
+    m_components->setOldConfigVersion("com.mumfrey.liteloader", m_settings->get("LiteloaderVersion").toString());
 }
 
 void MinecraftInstance::init()
@@ -118,849 +118,849 @@ void MinecraftInstance::init()
 
 void MinecraftInstance::saveNow()
 {
-	m_components->saveNow();
+    m_components->saveNow();
 }
 
 QString MinecraftInstance::typeName() const
 {
-	return "Minecraft";
+    return "Minecraft";
 }
 
 std::shared_ptr<ComponentList> MinecraftInstance::getComponentList() const
 {
-	return m_components;
+    return m_components;
 }
 
 QSet<QString> MinecraftInstance::traits() const
 {
-	auto components = getComponentList();
-	if (!components)
-	{
-		return {"version-incomplete"};
-	}
-	auto profile = components->getProfile();
-	if (!profile)
-	{
-		return {"version-incomplete"};
-	}
-	return profile->getTraits();
+    auto components = getComponentList();
+    if (!components)
+    {
+        return {"version-incomplete"};
+    }
+    auto profile = components->getProfile();
+    if (!profile)
+    {
+        return {"version-incomplete"};
+    }
+    return profile->getTraits();
 }
 
 QString MinecraftInstance::minecraftRoot() const
 {
-	QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
-	QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
+    QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
+    QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
 
-	if (mcDir.exists() && !dotMCDir.exists())
-		return mcDir.filePath();
-	else
-		return dotMCDir.filePath();
+    if (mcDir.exists() && !dotMCDir.exists())
+        return mcDir.filePath();
+    else
+        return dotMCDir.filePath();
 }
 
 QString MinecraftInstance::binRoot() const
 {
-	return FS::PathCombine(minecraftRoot(), "bin");
+    return FS::PathCombine(minecraftRoot(), "bin");
 }
 
 QString MinecraftInstance::getNativePath() const
 {
-	QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
-	return natives_dir.absolutePath();
+    QDir natives_dir(FS::PathCombine(instanceRoot(), "natives/"));
+    return natives_dir.absolutePath();
 }
 
 QString MinecraftInstance::getLocalLibraryPath() const
 {
-	QDir libraries_dir(FS::PathCombine(instanceRoot(), "libraries/"));
-	return libraries_dir.absolutePath();
+    QDir libraries_dir(FS::PathCombine(instanceRoot(), "libraries/"));
+    return libraries_dir.absolutePath();
 }
 
 QString MinecraftInstance::loaderModsDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "mods");
+    return FS::PathCombine(minecraftRoot(), "mods");
 }
 
 QString MinecraftInstance::modsCacheLocation() const
 {
-	return FS::PathCombine(instanceRoot(), "mods.cache");
+    return FS::PathCombine(instanceRoot(), "mods.cache");
 }
 
 QString MinecraftInstance::coreModsDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "coremods");
+    return FS::PathCombine(minecraftRoot(), "coremods");
 }
 
 QString MinecraftInstance::resourcePacksDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "resourcepacks");
+    return FS::PathCombine(minecraftRoot(), "resourcepacks");
 }
 
 QString MinecraftInstance::texturePacksDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "texturepacks");
+    return FS::PathCombine(minecraftRoot(), "texturepacks");
 }
 
 QString MinecraftInstance::instanceConfigFolder() const
 {
-	return FS::PathCombine(minecraftRoot(), "config");
+    return FS::PathCombine(minecraftRoot(), "config");
 }
 
 QString MinecraftInstance::jarModsDir() const
 {
-	return FS::PathCombine(instanceRoot(), "jarmods");
+    return FS::PathCombine(instanceRoot(), "jarmods");
 }
 
 QString MinecraftInstance::libDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "lib");
+    return FS::PathCombine(minecraftRoot(), "lib");
 }
 
 QString MinecraftInstance::worldDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "saves");
+    return FS::PathCombine(minecraftRoot(), "saves");
 }
 
 QDir MinecraftInstance::librariesPath() const
 {
-	return QDir::current().absoluteFilePath("libraries");
+    return QDir::current().absoluteFilePath("libraries");
 }
 
 QDir MinecraftInstance::jarmodsPath() const
 {
-	return QDir(jarModsDir());
+    return QDir(jarModsDir());
 }
 
 QDir MinecraftInstance::versionsPath() const
 {
-	return QDir::current().absoluteFilePath("versions");
+    return QDir::current().absoluteFilePath("versions");
 }
 
 QStringList MinecraftInstance::getClassPath() const
 {
-	QStringList jars, nativeJars;
-	auto javaArchitecture = settings()->get("JavaArchitecture").toString();
-	auto profile = m_components->getProfile();
-	profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
-	return jars;
+    QStringList jars, nativeJars;
+    auto javaArchitecture = settings()->get("JavaArchitecture").toString();
+    auto profile = m_components->getProfile();
+    profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
+    return jars;
 }
 
 QString MinecraftInstance::getMainClass() const
 {
-	auto profile = m_components->getProfile();
-	return profile->getMainClass();
+    auto profile = m_components->getProfile();
+    return profile->getMainClass();
 }
 
 QStringList MinecraftInstance::getNativeJars() const
 {
-	QStringList jars, nativeJars;
-	auto javaArchitecture = settings()->get("JavaArchitecture").toString();
-	auto profile = m_components->getProfile();
-	profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
-	return nativeJars;
+    QStringList jars, nativeJars;
+    auto javaArchitecture = settings()->get("JavaArchitecture").toString();
+    auto profile = m_components->getProfile();
+    profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
+    return nativeJars;
 }
 
 QStringList MinecraftInstance::extraArguments() const
 {
-	auto list = BaseInstance::extraArguments();
-	auto version = getComponentList();
-	if (!version)
-		return list;
-	auto jarMods = getJarMods();
-	if (!jarMods.isEmpty())
-	{
-		list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
-					 "-Dfml.ignorePatchDiscrepancies=true"});
-	}
-	return list;
+    auto list = BaseInstance::extraArguments();
+    auto version = getComponentList();
+    if (!version)
+        return list;
+    auto jarMods = getJarMods();
+    if (!jarMods.isEmpty())
+    {
+        list.append({"-Dfml.ignoreInvalidMinecraftCertificates=true",
+                     "-Dfml.ignorePatchDiscrepancies=true"});
+    }
+    return list;
 }
 
 QStringList MinecraftInstance::javaArguments() const
 {
-	QStringList args;
+    QStringList args;
 
-	// custom args go first. we want to override them if we have our own here.
-	args.append(extraArguments());
+    // custom args go first. we want to override them if we have our own here.
+    args.append(extraArguments());
 
-	// OSX dock icon and name
+    // OSX dock icon and name
 #ifdef Q_OS_MAC
-	args << "-Xdock:icon=icon.png";
-	args << QString("-Xdock:name=\"%1\"").arg(windowTitle());
+    args << "-Xdock:icon=icon.png";
+    args << QString("-Xdock:name=\"%1\"").arg(windowTitle());
 #endif
-	auto traits_ = traits();
-	// HACK: fix issues on macOS with 1.13 snapshots
-	// NOTE: Oracle Java option. if there are alternate jvm implementations, this would be the place to customize this for them
+    auto traits_ = traits();
+    // HACK: fix issues on macOS with 1.13 snapshots
+    // NOTE: Oracle Java option. if there are alternate jvm implementations, this would be the place to customize this for them
 #ifdef Q_OS_MAC
-	if(traits_.contains("FirstThreadOnMacOS"))
-	{
-		args << QString("-XstartOnFirstThread");
-	}
+    if(traits_.contains("FirstThreadOnMacOS"))
+    {
+        args << QString("-XstartOnFirstThread");
+    }
 #endif
 
-	// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
+    // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
 #ifdef Q_OS_WIN32
-	args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
-					"minecraft.exe.heapdump");
+    args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
+                    "minecraft.exe.heapdump");
 #endif
 
-	int min = settings()->get("MinMemAlloc").toInt();
-	int max = settings()->get("MaxMemAlloc").toInt();
-	if(min < max)
-	{
-		args << QString("-Xms%1m").arg(min);
-		args << QString("-Xmx%1m").arg(max);
-	}
-	else
-	{
-		args << QString("-Xms%1m").arg(max);
-		args << QString("-Xmx%1m").arg(min);
-	}
-
-	// No PermGen in newer java.
-	JavaVersion javaVersion = getJavaVersion();
-	if(javaVersion.requiresPermGen())
-	{
-		auto permgen = settings()->get("PermGen").toInt();
-		if (permgen != 64)
-		{
-			args << QString("-XX:PermSize=%1m").arg(permgen);
-		}
-	}
-
-	args << "-Duser.language=en";
-
-	return args;
+    int min = settings()->get("MinMemAlloc").toInt();
+    int max = settings()->get("MaxMemAlloc").toInt();
+    if(min < max)
+    {
+        args << QString("-Xms%1m").arg(min);
+        args << QString("-Xmx%1m").arg(max);
+    }
+    else
+    {
+        args << QString("-Xms%1m").arg(max);
+        args << QString("-Xmx%1m").arg(min);
+    }
+
+    // No PermGen in newer java.
+    JavaVersion javaVersion = getJavaVersion();
+    if(javaVersion.requiresPermGen())
+    {
+        auto permgen = settings()->get("PermGen").toInt();
+        if (permgen != 64)
+        {
+            args << QString("-XX:PermSize=%1m").arg(permgen);
+        }
+    }
+
+    args << "-Duser.language=en";
+
+    return args;
 }
 
 QMap<QString, QString> MinecraftInstance::getVariables() const
 {
-	QMap<QString, QString> out;
-	out.insert("INST_NAME", name());
-	out.insert("INST_ID", id());
-	out.insert("INST_DIR", QDir(instanceRoot()).absolutePath());
-	out.insert("INST_MC_DIR", QDir(minecraftRoot()).absolutePath());
-	out.insert("INST_JAVA", settings()->get("JavaPath").toString());
-	out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
-	return out;
+    QMap<QString, QString> out;
+    out.insert("INST_NAME", name());
+    out.insert("INST_ID", id());
+    out.insert("INST_DIR", QDir(instanceRoot()).absolutePath());
+    out.insert("INST_MC_DIR", QDir(minecraftRoot()).absolutePath());
+    out.insert("INST_JAVA", settings()->get("JavaPath").toString());
+    out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
+    return out;
 }
 
 QProcessEnvironment MinecraftInstance::createEnvironment()
 {
-	// prepare the process environment
-	QProcessEnvironment env = CleanEnviroment();
+    // prepare the process environment
+    QProcessEnvironment env = CleanEnviroment();
 
-	// export some infos
-	auto variables = getVariables();
-	for (auto it = variables.begin(); it != variables.end(); ++it)
-	{
-		env.insert(it.key(), it.value());
-	}
-	return env;
+    // export some infos
+    auto variables = getVariables();
+    for (auto it = variables.begin(); it != variables.end(); ++it)
+    {
+        env.insert(it.key(), it.value());
+    }
+    return env;
 }
 
 static QString replaceTokensIn(QString text, QMap<QString, QString> with)
 {
-	QString result;
-	QRegExp token_regexp("\\$\\{(.+)\\}");
-	token_regexp.setMinimal(true);
-	QStringList list;
-	int tail = 0;
-	int head = 0;
-	while ((head = token_regexp.indexIn(text, head)) != -1)
-	{
-		result.append(text.mid(tail, head - tail));
-		QString key = token_regexp.cap(1);
-		auto iter = with.find(key);
-		if (iter != with.end())
-		{
-			result.append(*iter);
-		}
-		head += token_regexp.matchedLength();
-		tail = head;
-	}
-	result.append(text.mid(tail));
-	return result;
+    QString result;
+    QRegExp token_regexp("\\$\\{(.+)\\}");
+    token_regexp.setMinimal(true);
+    QStringList list;
+    int tail = 0;
+    int head = 0;
+    while ((head = token_regexp.indexIn(text, head)) != -1)
+    {
+        result.append(text.mid(tail, head - tail));
+        QString key = token_regexp.cap(1);
+        auto iter = with.find(key);
+        if (iter != with.end())
+        {
+            result.append(*iter);
+        }
+        head += token_regexp.matchedLength();
+        tail = head;
+    }
+    result.append(text.mid(tail));
+    return result;
 }
 
 QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session) const
 {
-	auto profile = m_components->getProfile();
-	QString args_pattern = profile->getMinecraftArguments();
-	for (auto tweaker : profile->getTweakers())
-	{
-		args_pattern += " --tweakClass " + tweaker;
-	}
-
-	QMap<QString, QString> token_mapping;
-	// yggdrasil!
-	if(session)
-	{
-		token_mapping["auth_username"] = session->username;
-		token_mapping["auth_session"] = session->session;
-		token_mapping["auth_access_token"] = session->access_token;
-		token_mapping["auth_player_name"] = session->player_name;
-		token_mapping["auth_uuid"] = session->uuid;
-		token_mapping["user_properties"] = session->serializeUserProperties();
-		token_mapping["user_type"] = session->user_type;
-	}
-
-	// blatant self-promotion.
-	token_mapping["profile_name"] = token_mapping["version_name"] = "MultiMC5";
-
-	token_mapping["version_type"] = profile->getMinecraftVersionType();
-
-	QString absRootDir = QDir(minecraftRoot()).absolutePath();
-	token_mapping["game_directory"] = absRootDir;
-	QString absAssetsDir = QDir("assets/").absolutePath();
-	auto assets = profile->getMinecraftAssets();
-	// FIXME: this is wrong and should be run as an async task
-	token_mapping["game_assets"] = AssetsUtils::reconstructAssets(assets->id).absolutePath();
-
-	// 1.7.3+ assets tokens
-	token_mapping["assets_root"] = absAssetsDir;
-	token_mapping["assets_index_name"] = assets->id;
-
-	QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
-	for (int i = 0; i < parts.length(); i++)
-	{
-		parts[i] = replaceTokensIn(parts[i], token_mapping);
-	}
-	return parts;
+    auto profile = m_components->getProfile();
+    QString args_pattern = profile->getMinecraftArguments();
+    for (auto tweaker : profile->getTweakers())
+    {
+        args_pattern += " --tweakClass " + tweaker;
+    }
+
+    QMap<QString, QString> token_mapping;
+    // yggdrasil!
+    if(session)
+    {
+        token_mapping["auth_username"] = session->username;
+        token_mapping["auth_session"] = session->session;
+        token_mapping["auth_access_token"] = session->access_token;
+        token_mapping["auth_player_name"] = session->player_name;
+        token_mapping["auth_uuid"] = session->uuid;
+        token_mapping["user_properties"] = session->serializeUserProperties();
+        token_mapping["user_type"] = session->user_type;
+    }
+
+    // blatant self-promotion.
+    token_mapping["profile_name"] = token_mapping["version_name"] = "MultiMC5";
+
+    token_mapping["version_type"] = profile->getMinecraftVersionType();
+
+    QString absRootDir = QDir(minecraftRoot()).absolutePath();
+    token_mapping["game_directory"] = absRootDir;
+    QString absAssetsDir = QDir("assets/").absolutePath();
+    auto assets = profile->getMinecraftAssets();
+    // FIXME: this is wrong and should be run as an async task
+    token_mapping["game_assets"] = AssetsUtils::reconstructAssets(assets->id).absolutePath();
+
+    // 1.7.3+ assets tokens
+    token_mapping["assets_root"] = absAssetsDir;
+    token_mapping["assets_index_name"] = assets->id;
+
+    QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
+    for (int i = 0; i < parts.length(); i++)
+    {
+        parts[i] = replaceTokensIn(parts[i], token_mapping);
+    }
+    return parts;
 }
 
 QString MinecraftInstance::createLaunchScript(AuthSessionPtr session)
 {
-	QString launchScript;
-
-	if (!m_components)
-		return QString();
-	auto profile = m_components->getProfile();
-	if(!profile)
-		return QString();
-
-	auto mainClass = getMainClass();
-	if (!mainClass.isEmpty())
-	{
-		launchScript += "mainClass " + mainClass + "\n";
-	}
-	auto appletClass = profile->getAppletClass();
-	if (!appletClass.isEmpty())
-	{
-		launchScript += "appletClass " + appletClass + "\n";
-	}
-
-	// generic minecraft params
-	for (auto param : processMinecraftArgs(session))
-	{
-		launchScript += "param " + param + "\n";
-	}
-
-	// window size, title and state, legacy
-	{
-		QString windowParams;
-		if (settings()->get("LaunchMaximized").toBool())
-			windowParams = "max";
-		else
-			windowParams = QString("%1x%2")
-							   .arg(settings()->get("MinecraftWinWidth").toInt())
-							   .arg(settings()->get("MinecraftWinHeight").toInt());
-		launchScript += "windowTitle " + windowTitle() + "\n";
-		launchScript += "windowParams " + windowParams + "\n";
-	}
-
-	// legacy auth
-	if(session)
-	{
-		launchScript += "userName " + session->player_name + "\n";
-		launchScript += "sessionId " + session->session + "\n";
-	}
-
-	// libraries and class path.
-	{
-		QStringList jars, nativeJars;
-		auto javaArchitecture = settings()->get("JavaArchitecture").toString();
-		profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
-		for(auto file: jars)
-		{
-			launchScript += "cp " + file + "\n";
-		}
-		for(auto file: nativeJars)
-		{
-			launchScript += "ext " + file + "\n";
-		}
-		launchScript += "natives " + getNativePath() + "\n";
-	}
-
-	for (auto trait : profile->getTraits())
-	{
-		launchScript += "traits " + trait + "\n";
-	}
-	launchScript += "launcher onesix\n";
-	// qDebug() << "Generated launch script:" << launchScript;
-	return launchScript;
+    QString launchScript;
+
+    if (!m_components)
+        return QString();
+    auto profile = m_components->getProfile();
+    if(!profile)
+        return QString();
+
+    auto mainClass = getMainClass();
+    if (!mainClass.isEmpty())
+    {
+        launchScript += "mainClass " + mainClass + "\n";
+    }
+    auto appletClass = profile->getAppletClass();
+    if (!appletClass.isEmpty())
+    {
+        launchScript += "appletClass " + appletClass + "\n";
+    }
+
+    // generic minecraft params
+    for (auto param : processMinecraftArgs(session))
+    {
+        launchScript += "param " + param + "\n";
+    }
+
+    // window size, title and state, legacy
+    {
+        QString windowParams;
+        if (settings()->get("LaunchMaximized").toBool())
+            windowParams = "max";
+        else
+            windowParams = QString("%1x%2")
+                               .arg(settings()->get("MinecraftWinWidth").toInt())
+                               .arg(settings()->get("MinecraftWinHeight").toInt());
+        launchScript += "windowTitle " + windowTitle() + "\n";
+        launchScript += "windowParams " + windowParams + "\n";
+    }
+
+    // legacy auth
+    if(session)
+    {
+        launchScript += "userName " + session->player_name + "\n";
+        launchScript += "sessionId " + session->session + "\n";
+    }
+
+    // libraries and class path.
+    {
+        QStringList jars, nativeJars;
+        auto javaArchitecture = settings()->get("JavaArchitecture").toString();
+        profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
+        for(auto file: jars)
+        {
+            launchScript += "cp " + file + "\n";
+        }
+        for(auto file: nativeJars)
+        {
+            launchScript += "ext " + file + "\n";
+        }
+        launchScript += "natives " + getNativePath() + "\n";
+    }
+
+    for (auto trait : profile->getTraits())
+    {
+        launchScript += "traits " + trait + "\n";
+    }
+    launchScript += "launcher onesix\n";
+    // qDebug() << "Generated launch script:" << launchScript;
+    return launchScript;
 }
 
 QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session)
 {
-	QStringList out;
-	out << "Main Class:" << "  " + getMainClass() << "";
-	out << "Native path:" << "  " + getNativePath() << "";
-
-	auto profile = m_components->getProfile();
-
-	auto alltraits = traits();
-	if(alltraits.size())
-	{
-		out << "Traits:";
-		for (auto trait : alltraits)
-		{
-			out << "traits " + trait;
-		}
-		out << "";
-	}
-
-	// libraries and class path.
-	{
-		out << "Libraries:";
-		QStringList jars, nativeJars;
-		auto javaArchitecture = settings()->get("JavaArchitecture").toString();
-		profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
-		auto printLibFile = [&](const QString & path)
-		{
-			QFileInfo info(path);
-			if(info.exists())
-			{
-				out << "  " + path;
-			}
-			else
-			{
-				out << "  " + path + " (missing)";
-			}
-		};
-		for(auto file: jars)
-		{
-			printLibFile(file);
-		}
-		out << "";
-		out << "Native libraries:";
-		for(auto file: nativeJars)
-		{
-			printLibFile(file);
-		}
-		out << "";
-	}
-
-	if(loaderModList()->size())
-	{
-		out << "Mods:";
-		for(auto & mod: loaderModList()->allMods())
-		{
-			if(!mod.enabled())
-				continue;
-			if(mod.type() == Mod::MOD_FOLDER)
-				continue;
-			// TODO: proper implementation would need to descend into folders.
-
-			out << "  " + mod.filename().completeBaseName();
-		}
-		out << "";
-	}
-
-	if(coreModList()->size())
-	{
-		out << "Core Mods:";
-		for(auto & coremod: coreModList()->allMods())
-		{
-			if(!coremod.enabled())
-				continue;
-			if(coremod.type() == Mod::MOD_FOLDER)
-				continue;
-			// TODO: proper implementation would need to descend into folders.
-
-			out << "  " + coremod.filename().completeBaseName();
-		}
-		out << "";
-	}
-
-	auto & jarMods = profile->getJarMods();
-	if(jarMods.size())
-	{
-		out << "Jar Mods:";
-		for(auto & jarmod: jarMods)
-		{
-			auto displayname = jarmod->displayName(currentSystem);
-			auto realname = jarmod->filename(currentSystem);
-			if(displayname != realname)
-			{
-				out << "  " + displayname + " (" + realname + ")";
-			}
-			else
-			{
-				out << "  " + realname;
-			}
-		}
-		out << "";
-	}
-
-	auto params = processMinecraftArgs(nullptr);
-	out << "Params:";
-	out << "  " + params.join(' ');
-	out << "";
-
-	QString windowParams;
-	if (settings()->get("LaunchMaximized").toBool())
-	{
-		out << "Window size: max (if available)";
-	}
-	else
-	{
-		auto width = settings()->get("MinecraftWinWidth").toInt();
-		auto height = settings()->get("MinecraftWinHeight").toInt();
-		out << "Window size: " + QString::number(width) + " x " + QString::number(height);
-	}
-	out << "";
-	return out;
+    QStringList out;
+    out << "Main Class:" << "  " + getMainClass() << "";
+    out << "Native path:" << "  " + getNativePath() << "";
+
+    auto profile = m_components->getProfile();
+
+    auto alltraits = traits();
+    if(alltraits.size())
+    {
+        out << "Traits:";
+        for (auto trait : alltraits)
+        {
+            out << "traits " + trait;
+        }
+        out << "";
+    }
+
+    // libraries and class path.
+    {
+        out << "Libraries:";
+        QStringList jars, nativeJars;
+        auto javaArchitecture = settings()->get("JavaArchitecture").toString();
+        profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot());
+        auto printLibFile = [&](const QString & path)
+        {
+            QFileInfo info(path);
+            if(info.exists())
+            {
+                out << "  " + path;
+            }
+            else
+            {
+                out << "  " + path + " (missing)";
+            }
+        };
+        for(auto file: jars)
+        {
+            printLibFile(file);
+        }
+        out << "";
+        out << "Native libraries:";
+        for(auto file: nativeJars)
+        {
+            printLibFile(file);
+        }
+        out << "";
+    }
+
+    if(loaderModList()->size())
+    {
+        out << "Mods:";
+        for(auto & mod: loaderModList()->allMods())
+        {
+            if(!mod.enabled())
+                continue;
+            if(mod.type() == Mod::MOD_FOLDER)
+                continue;
+            // TODO: proper implementation would need to descend into folders.
+
+            out << "  " + mod.filename().completeBaseName();
+        }
+        out << "";
+    }
+
+    if(coreModList()->size())
+    {
+        out << "Core Mods:";
+        for(auto & coremod: coreModList()->allMods())
+        {
+            if(!coremod.enabled())
+                continue;
+            if(coremod.type() == Mod::MOD_FOLDER)
+                continue;
+            // TODO: proper implementation would need to descend into folders.
+
+            out << "  " + coremod.filename().completeBaseName();
+        }
+        out << "";
+    }
+
+    auto & jarMods = profile->getJarMods();
+    if(jarMods.size())
+    {
+        out << "Jar Mods:";
+        for(auto & jarmod: jarMods)
+        {
+            auto displayname = jarmod->displayName(currentSystem);
+            auto realname = jarmod->filename(currentSystem);
+            if(displayname != realname)
+            {
+                out << "  " + displayname + " (" + realname + ")";
+            }
+            else
+            {
+                out << "  " + realname;
+            }
+        }
+        out << "";
+    }
+
+    auto params = processMinecraftArgs(nullptr);
+    out << "Params:";
+    out << "  " + params.join(' ');
+    out << "";
+
+    QString windowParams;
+    if (settings()->get("LaunchMaximized").toBool())
+    {
+        out << "Window size: max (if available)";
+    }
+    else
+    {
+        auto width = settings()->get("MinecraftWinWidth").toInt();
+        auto height = settings()->get("MinecraftWinHeight").toInt();
+        out << "Window size: " + QString::number(width) + " x " + QString::number(height);
+    }
+    out << "";
+    return out;
 }
 
 QMap<QString, QString> MinecraftInstance::createCensorFilterFromSession(AuthSessionPtr session)
 {
-	if(!session)
-	{
-		return QMap<QString, QString>();
-	}
-	auto & sessionRef = *session.get();
-	QMap<QString, QString> filter;
-	auto addToFilter = [&filter](QString key, QString value)
-	{
-		if(key.trimmed().size())
-		{
-			filter[key] = value;
-		}
-	};
-	if (sessionRef.session != "-")
-	{
-		addToFilter(sessionRef.session, tr("<SESSION ID>"));
-	}
-	addToFilter(sessionRef.access_token, tr("<ACCESS TOKEN>"));
-	addToFilter(sessionRef.client_token, tr("<CLIENT TOKEN>"));
-	addToFilter(sessionRef.uuid, tr("<PROFILE ID>"));
-
-	auto i = sessionRef.u.properties.begin();
-	while (i != sessionRef.u.properties.end())
-	{
-		if(i.key() == "preferredLanguage")
-		{
-			++i;
-			continue;
-		}
-		addToFilter(i.value(), "<" + i.key().toUpper() + ">");
-		++i;
-	}
-	return filter;
+    if(!session)
+    {
+        return QMap<QString, QString>();
+    }
+    auto & sessionRef = *session.get();
+    QMap<QString, QString> filter;
+    auto addToFilter = [&filter](QString key, QString value)
+    {
+        if(key.trimmed().size())
+        {
+            filter[key] = value;
+        }
+    };
+    if (sessionRef.session != "-")
+    {
+        addToFilter(sessionRef.session, tr("<SESSION ID>"));
+    }
+    addToFilter(sessionRef.access_token, tr("<ACCESS TOKEN>"));
+    addToFilter(sessionRef.client_token, tr("<CLIENT TOKEN>"));
+    addToFilter(sessionRef.uuid, tr("<PROFILE ID>"));
+
+    auto i = sessionRef.u.properties.begin();
+    while (i != sessionRef.u.properties.end())
+    {
+        if(i.key() == "preferredLanguage")
+        {
+            ++i;
+            continue;
+        }
+        addToFilter(i.value(), "<" + i.key().toUpper() + ">");
+        ++i;
+    }
+    return filter;
 }
 
 MessageLevel::Enum MinecraftInstance::guessLevel(const QString &line, MessageLevel::Enum level)
 {
-	QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
-	auto match = re.match(line);
-	if(match.hasMatch())
-	{
-		// New style logs from log4j
-		QString timestamp = match.captured("timestamp");
-		QString levelStr = match.captured("level");
-		if(levelStr == "INFO")
-			level = MessageLevel::Message;
-		if(levelStr == "WARN")
-			level = MessageLevel::Warning;
-		if(levelStr == "ERROR")
-			level = MessageLevel::Error;
-		if(levelStr == "FATAL")
-			level = MessageLevel::Fatal;
-		if(levelStr == "TRACE" || levelStr == "DEBUG")
-			level = MessageLevel::Debug;
-	}
-	else
-	{
-		// Old style forge logs
-		if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
-			line.contains("[FINER]") || line.contains("[FINEST]"))
-			level = MessageLevel::Message;
-		if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
-			level = MessageLevel::Error;
-		if (line.contains("[WARNING]"))
-			level = MessageLevel::Warning;
-		if (line.contains("[DEBUG]"))
-			level = MessageLevel::Debug;
-	}
-	if (line.contains("overwriting existing"))
-		return MessageLevel::Fatal;
-	//NOTE: this diverges from the real regexp. no unicode, the first section is + instead of *
-	static const QString javaSymbol = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";
-	if (line.contains("Exception in thread")
-		|| line.contains(QRegularExpression("\\s+at " + javaSymbol))
-		|| line.contains(QRegularExpression("Caused by: " + javaSymbol))
-		|| line.contains(QRegularExpression("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)"))
-		|| line.contains(QRegularExpression("... \\d+ more$"))
-		)
-		return MessageLevel::Error;
-	return level;
+    QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
+    auto match = re.match(line);
+    if(match.hasMatch())
+    {
+        // New style logs from log4j
+        QString timestamp = match.captured("timestamp");
+        QString levelStr = match.captured("level");
+        if(levelStr == "INFO")
+            level = MessageLevel::Message;
+        if(levelStr == "WARN")
+            level = MessageLevel::Warning;
+        if(levelStr == "ERROR")
+            level = MessageLevel::Error;
+        if(levelStr == "FATAL")
+            level = MessageLevel::Fatal;
+        if(levelStr == "TRACE" || levelStr == "DEBUG")
+            level = MessageLevel::Debug;
+    }
+    else
+    {
+        // Old style forge logs
+        if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
+            line.contains("[FINER]") || line.contains("[FINEST]"))
+            level = MessageLevel::Message;
+        if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
+            level = MessageLevel::Error;
+        if (line.contains("[WARNING]"))
+            level = MessageLevel::Warning;
+        if (line.contains("[DEBUG]"))
+            level = MessageLevel::Debug;
+    }
+    if (line.contains("overwriting existing"))
+        return MessageLevel::Fatal;
+    //NOTE: this diverges from the real regexp. no unicode, the first section is + instead of *
+    static const QString javaSymbol = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*";
+    if (line.contains("Exception in thread")
+        || line.contains(QRegularExpression("\\s+at " + javaSymbol))
+        || line.contains(QRegularExpression("Caused by: " + javaSymbol))
+        || line.contains(QRegularExpression("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)"))
+        || line.contains(QRegularExpression("... \\d+ more$"))
+        )
+        return MessageLevel::Error;
+    return level;
 }
 
 IPathMatcher::Ptr MinecraftInstance::getLogFileMatcher()
 {
-	auto combined = std::make_shared<MultiMatcher>();
-	combined->add(std::make_shared<RegexpMatcher>(".*\\.log(\\.[0-9]*)?(\\.gz)?$"));
-	combined->add(std::make_shared<RegexpMatcher>("crash-.*\\.txt"));
-	combined->add(std::make_shared<RegexpMatcher>("IDMap dump.*\\.txt$"));
-	combined->add(std::make_shared<RegexpMatcher>("ModLoader\\.txt(\\..*)?$"));
-	return combined;
+    auto combined = std::make_shared<MultiMatcher>();
+    combined->add(std::make_shared<RegexpMatcher>(".*\\.log(\\.[0-9]*)?(\\.gz)?$"));
+    combined->add(std::make_shared<RegexpMatcher>("crash-.*\\.txt"));
+    combined->add(std::make_shared<RegexpMatcher>("IDMap dump.*\\.txt$"));
+    combined->add(std::make_shared<RegexpMatcher>("ModLoader\\.txt(\\..*)?$"));
+    return combined;
 }
 
 QString MinecraftInstance::getLogFileRoot()
 {
-	return minecraftRoot();
+    return minecraftRoot();
 }
 
 QString MinecraftInstance::prettifyTimeDuration(int64_t duration)
 {
-	int seconds = (int) (duration % 60);
-	duration /= 60;
-	int minutes = (int) (duration % 60);
-	duration /= 60;
-	int hours = (int) (duration % 24);
-	int days = (int) (duration / 24);
-	if((hours == 0)&&(days == 0))
-	{
-		return tr("%1m %2s").arg(minutes).arg(seconds);
-	}
-	if (days == 0)
-	{
-		return tr("%1h %2m").arg(hours).arg(minutes);
-	}
-	return tr("%1d %2h %3m").arg(days).arg(hours).arg(minutes);
+    int seconds = (int) (duration % 60);
+    duration /= 60;
+    int minutes = (int) (duration % 60);
+    duration /= 60;
+    int hours = (int) (duration % 24);
+    int days = (int) (duration / 24);
+    if((hours == 0)&&(days == 0))
+    {
+        return tr("%1m %2s").arg(minutes).arg(seconds);
+    }
+    if (days == 0)
+    {
+        return tr("%1h %2m").arg(hours).arg(minutes);
+    }
+    return tr("%1d %2h %3m").arg(days).arg(hours).arg(minutes);
 }
 
 QString MinecraftInstance::getStatusbarDescription()
 {
-	QStringList traits;
-	if (hasVersionBroken())
-	{
-		traits.append(tr("broken"));
-	}
-
-	QString description;
-	description.append(tr("Minecraft %1 (%2)").arg(m_components->getComponentVersion("net.minecraft")).arg(typeName()));
-	if(totalTimePlayed() > 0)
-	{
-		description.append(tr(", played for %1").arg(prettifyTimeDuration(totalTimePlayed())));
-	}
-	if(hasCrashed())
-	{
-		description.append(tr(", has crashed."));
-	}
-	return description;
+    QStringList traits;
+    if (hasVersionBroken())
+    {
+        traits.append(tr("broken"));
+    }
+
+    QString description;
+    description.append(tr("Minecraft %1 (%2)").arg(m_components->getComponentVersion("net.minecraft")).arg(typeName()));
+    if(totalTimePlayed() > 0)
+    {
+        description.append(tr(", played for %1").arg(prettifyTimeDuration(totalTimePlayed())));
+    }
+    if(hasCrashed())
+    {
+        description.append(tr(", has crashed."));
+    }
+    return description;
 }
 
 shared_qobject_ptr<Task> MinecraftInstance::createUpdateTask(Net::Mode mode)
 {
-	switch (mode)
-	{
-		case Net::Mode::Offline:
-		{
-			return shared_qobject_ptr<Task>(new MinecraftLoadAndCheck(this));
-		}
-		case Net::Mode::Online:
-		{
-			return shared_qobject_ptr<Task>(new OneSixUpdate(this));
-		}
-	}
-	return nullptr;
+    switch (mode)
+    {
+        case Net::Mode::Offline:
+        {
+            return shared_qobject_ptr<Task>(new MinecraftLoadAndCheck(this));
+        }
+        case Net::Mode::Online:
+        {
+            return shared_qobject_ptr<Task>(new OneSixUpdate(this));
+        }
+    }
+    return nullptr;
 }
 
 std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr session)
 {
-	auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
-	auto pptr = process.get();
-
-	ENV.icons()->saveIcon(iconKey(), FS::PathCombine(minecraftRoot(), "icon.png"), "PNG");
-
-	// print a header
-	{
-		process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + minecraftRoot() + "\n\n", MessageLevel::MultiMC));
-	}
-
-	// check java
-	{
-		auto step = std::make_shared<CheckJava>(pptr);
-		process->appendStep(step);
-	}
-
-	// check launch method
-	QStringList validMethods = {"LauncherPart", "DirectJava"};
-	QString method = launchMethod();
-	if(!validMethods.contains(method))
-	{
-		process->appendStep(std::make_shared<TextPrint>(pptr, "Selected launch method \"" + method + "\" is not valid.\n", MessageLevel::Fatal));
-		return process;
-	}
-
-	// run pre-launch command if that's needed
-	if(getPreLaunchCommand().size())
-	{
-		auto step = std::make_shared<PreLaunchCommand>(pptr);
-		step->setWorkingDirectory(minecraftRoot());
-		process->appendStep(step);
-	}
-
-	// if we aren't in offline mode,.
-	if(session->status != AuthSession::PlayableOffline)
-	{
-		process->appendStep(std::make_shared<ClaimAccount>(pptr, session));
-		process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Online));
-	}
-	else
-	{
-		process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Offline));
-	}
-
-	// if there are any jar mods
-	{
-		auto step = std::make_shared<ModMinecraftJar>(pptr);
-		process->appendStep(step);
-	}
-
-	// print some instance info here...
-	{
-		auto step = std::make_shared<PrintInstanceInfo>(pptr, session);
-		process->appendStep(step);
-	}
-
-	// create the server-resource-packs folder (workaround for Minecraft bug MCL-3732)
-	{
-		auto step = std::make_shared<CreateServerResourcePacksFolder>(pptr);
-		process->appendStep(step);
-	}
-
-	// extract native jars if needed
-	{
-		auto step = std::make_shared<ExtractNatives>(pptr);
-		process->appendStep(step);
-	}
-
-	{
-		// actually launch the game
-		auto method = launchMethod();
-		if(method == "LauncherPart")
-		{
-			auto step = std::make_shared<LauncherPartLaunch>(pptr);
-			step->setWorkingDirectory(minecraftRoot());
-			step->setAuthSession(session);
-			process->appendStep(step);
-		}
-		else if (method == "DirectJava")
-		{
-			auto step = std::make_shared<DirectJavaLaunch>(pptr);
-			step->setWorkingDirectory(minecraftRoot());
-			step->setAuthSession(session);
-			process->appendStep(step);
-		}
-	}
-
-	// run post-exit command if that's needed
-	if(getPostExitCommand().size())
-	{
-		auto step = std::make_shared<PostLaunchCommand>(pptr);
-		step->setWorkingDirectory(minecraftRoot());
-		process->appendStep(step);
-	}
-	if (session)
-	{
-		process->setCensorFilter(createCensorFilterFromSession(session));
-	}
-	m_launchProcess = process;
-	emit launchTaskChanged(m_launchProcess);
-	return m_launchProcess;
+    auto process = LaunchTask::create(std::dynamic_pointer_cast<MinecraftInstance>(getSharedPtr()));
+    auto pptr = process.get();
+
+    ENV.icons()->saveIcon(iconKey(), FS::PathCombine(minecraftRoot(), "icon.png"), "PNG");
+
+    // print a header
+    {
+        process->appendStep(std::make_shared<TextPrint>(pptr, "Minecraft folder is:\n" + minecraftRoot() + "\n\n", MessageLevel::MultiMC));
+    }
+
+    // check java
+    {
+        auto step = std::make_shared<CheckJava>(pptr);
+        process->appendStep(step);
+    }
+
+    // check launch method
+    QStringList validMethods = {"LauncherPart", "DirectJava"};
+    QString method = launchMethod();
+    if(!validMethods.contains(method))
+    {
+        process->appendStep(std::make_shared<TextPrint>(pptr, "Selected launch method \"" + method + "\" is not valid.\n", MessageLevel::Fatal));
+        return process;
+    }
+
+    // run pre-launch command if that's needed
+    if(getPreLaunchCommand().size())
+    {
+        auto step = std::make_shared<PreLaunchCommand>(pptr);
+        step->setWorkingDirectory(minecraftRoot());
+        process->appendStep(step);
+    }
+
+    // if we aren't in offline mode,.
+    if(session->status != AuthSession::PlayableOffline)
+    {
+        process->appendStep(std::make_shared<ClaimAccount>(pptr, session));
+        process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Online));
+    }
+    else
+    {
+        process->appendStep(std::make_shared<Update>(pptr, Net::Mode::Offline));
+    }
+
+    // if there are any jar mods
+    {
+        auto step = std::make_shared<ModMinecraftJar>(pptr);
+        process->appendStep(step);
+    }
+
+    // print some instance info here...
+    {
+        auto step = std::make_shared<PrintInstanceInfo>(pptr, session);
+        process->appendStep(step);
+    }
+
+    // create the server-resource-packs folder (workaround for Minecraft bug MCL-3732)
+    {
+        auto step = std::make_shared<CreateServerResourcePacksFolder>(pptr);
+        process->appendStep(step);
+    }
+
+    // extract native jars if needed
+    {
+        auto step = std::make_shared<ExtractNatives>(pptr);
+        process->appendStep(step);
+    }
+
+    {
+        // actually launch the game
+        auto method = launchMethod();
+        if(method == "LauncherPart")
+        {
+            auto step = std::make_shared<LauncherPartLaunch>(pptr);
+            step->setWorkingDirectory(minecraftRoot());
+            step->setAuthSession(session);
+            process->appendStep(step);
+        }
+        else if (method == "DirectJava")
+        {
+            auto step = std::make_shared<DirectJavaLaunch>(pptr);
+            step->setWorkingDirectory(minecraftRoot());
+            step->setAuthSession(session);
+            process->appendStep(step);
+        }
+    }
+
+    // run post-exit command if that's needed
+    if(getPostExitCommand().size())
+    {
+        auto step = std::make_shared<PostLaunchCommand>(pptr);
+        step->setWorkingDirectory(minecraftRoot());
+        process->appendStep(step);
+    }
+    if (session)
+    {
+        process->setCensorFilter(createCensorFilterFromSession(session));
+    }
+    m_launchProcess = process;
+    emit launchTaskChanged(m_launchProcess);
+    return m_launchProcess;
 }
 
 QString MinecraftInstance::launchMethod()
 {
-	return m_settings->get("MCLaunchMethod").toString();
+    return m_settings->get("MCLaunchMethod").toString();
 }
 
 JavaVersion MinecraftInstance::getJavaVersion() const
 {
-	return JavaVersion(settings()->get("JavaVersion").toString());
+    return JavaVersion(settings()->get("JavaVersion").toString());
 }
 
 std::shared_ptr<SimpleModList> MinecraftInstance::loaderModList() const
 {
-	if (!m_loader_mod_list)
-	{
-		m_loader_mod_list.reset(new SimpleModList(loaderModsDir()));
-	}
-	m_loader_mod_list->update();
-	return m_loader_mod_list;
+    if (!m_loader_mod_list)
+    {
+        m_loader_mod_list.reset(new SimpleModList(loaderModsDir()));
+    }
+    m_loader_mod_list->update();
+    return m_loader_mod_list;
 }
 
 std::shared_ptr<ModsModel> MinecraftInstance::modsModel() const
 {
-	if (!m_mods_model)
-	{
-		m_mods_model.reset(new ModsModel(loaderModsDir(), coreModsDir(), modsCacheLocation()));
-	}
-	m_mods_model->update();
-	return m_mods_model;
+    if (!m_mods_model)
+    {
+        m_mods_model.reset(new ModsModel(loaderModsDir(), coreModsDir(), modsCacheLocation()));
+    }
+    m_mods_model->update();
+    return m_mods_model;
 }
 
 std::shared_ptr<SimpleModList> MinecraftInstance::coreModList() const
 {
-	if (!m_core_mod_list)
-	{
-		m_core_mod_list.reset(new SimpleModList(coreModsDir()));
-	}
-	m_core_mod_list->update();
-	return m_core_mod_list;
+    if (!m_core_mod_list)
+    {
+        m_core_mod_list.reset(new SimpleModList(coreModsDir()));
+    }
+    m_core_mod_list->update();
+    return m_core_mod_list;
 }
 
 std::shared_ptr<SimpleModList> MinecraftInstance::resourcePackList() const
 {
-	if (!m_resource_pack_list)
-	{
-		m_resource_pack_list.reset(new SimpleModList(resourcePacksDir()));
-	}
-	m_resource_pack_list->update();
-	return m_resource_pack_list;
+    if (!m_resource_pack_list)
+    {
+        m_resource_pack_list.reset(new SimpleModList(resourcePacksDir()));
+    }
+    m_resource_pack_list->update();
+    return m_resource_pack_list;
 }
 
 std::shared_ptr<SimpleModList> MinecraftInstance::texturePackList() const
 {
-	if (!m_texture_pack_list)
-	{
-		m_texture_pack_list.reset(new SimpleModList(texturePacksDir()));
-	}
-	m_texture_pack_list->update();
-	return m_texture_pack_list;
+    if (!m_texture_pack_list)
+    {
+        m_texture_pack_list.reset(new SimpleModList(texturePacksDir()));
+    }
+    m_texture_pack_list->update();
+    return m_texture_pack_list;
 }
 
 std::shared_ptr<WorldList> MinecraftInstance::worldList() const
 {
-	if (!m_world_list)
-	{
-		m_world_list.reset(new WorldList(worldDir()));
-	}
-	return m_world_list;
+    if (!m_world_list)
+    {
+        m_world_list.reset(new WorldList(worldDir()));
+    }
+    return m_world_list;
 }
 
 QList< Mod > MinecraftInstance::getJarMods() const
 {
-	auto profile = m_components->getProfile();
-	QList<Mod> mods;
-	for (auto jarmod : profile->getJarMods())
-	{
-		QStringList jar, temp1, temp2, temp3;
-		jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath());
-		// QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem));
-		mods.push_back(Mod(QFileInfo(jar[0])));
-	}
-	return mods;
+    auto profile = m_components->getProfile();
+    QList<Mod> mods;
+    for (auto jarmod : profile->getJarMods())
+    {
+        QStringList jar, temp1, temp2, temp3;
+        jarmod->getApplicableFiles(currentSystem, jar, temp1, temp2, temp3, jarmodsPath().absolutePath());
+        // QString filePath = jarmodsPath().absoluteFilePath(jarmod->filename(currentSystem));
+        mods.push_back(Mod(QFileInfo(jar[0])));
+    }
+    return mods;
 }
 
 
diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h
index f1499ef6..460900c8 100644
--- a/api/logic/minecraft/MinecraftInstance.h
+++ b/api/logic/minecraft/MinecraftInstance.h
@@ -14,115 +14,115 @@ class ComponentList;
 
 class MULTIMC_LOGIC_EXPORT MinecraftInstance: public BaseInstance
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
-	virtual ~MinecraftInstance() {};
-	virtual void init() override;
-	virtual void saveNow() override;
-
-	// FIXME: remove
-	QString typeName() const override;
-	// FIXME: remove
-	QSet<QString> traits() const override;
-
-	bool canEdit() const override
-	{
-		return true;
-	}
-
-	bool canExport() const override
-	{
-		return true;
-	}
-
-	////// Directories and files //////
-	QString jarModsDir() const;
-	QString resourcePacksDir() const;
-	QString texturePacksDir() const;
-	QString loaderModsDir() const;
-	QString coreModsDir() const;
+    MinecraftInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
+    virtual ~MinecraftInstance() {};
+    virtual void init() override;
+    virtual void saveNow() override;
+
+    // FIXME: remove
+    QString typeName() const override;
+    // FIXME: remove
+    QSet<QString> traits() const override;
+
+    bool canEdit() const override
+    {
+        return true;
+    }
+
+    bool canExport() const override
+    {
+        return true;
+    }
+
+    ////// Directories and files //////
+    QString jarModsDir() const;
+    QString resourcePacksDir() const;
+    QString texturePacksDir() const;
+    QString loaderModsDir() const;
+    QString coreModsDir() const;
     QString modsCacheLocation() const;
-	QString libDir() const;
-	QString worldDir() const;
-	QDir jarmodsPath() const;
-	QDir librariesPath() const;
-	QDir versionsPath() const;
-	QString instanceConfigFolder() const override;
-	QString minecraftRoot() const; // Path to the instance's minecraft directory.
-	QString binRoot() const; // Path to the instance's minecraft bin directory.
-	QString getNativePath() const; // where to put the natives during/before launch
-	QString getLocalLibraryPath() const; // where the instance-local libraries should be
-
-
-	//////  Profile management //////
-	std::shared_ptr<ComponentList> getComponentList() const;
-
-	//////  Mod Lists  //////
+    QString libDir() const;
+    QString worldDir() const;
+    QDir jarmodsPath() const;
+    QDir librariesPath() const;
+    QDir versionsPath() const;
+    QString instanceConfigFolder() const override;
+    QString minecraftRoot() const; // Path to the instance's minecraft directory.
+    QString binRoot() const; // Path to the instance's minecraft bin directory.
+    QString getNativePath() const; // where to put the natives during/before launch
+    QString getLocalLibraryPath() const; // where the instance-local libraries should be
+
+
+    //////  Profile management //////
+    std::shared_ptr<ComponentList> getComponentList() const;
+
+    //////  Mod Lists  //////
     std::shared_ptr<ModsModel> modsModel() const;
-	std::shared_ptr<SimpleModList> loaderModList() const;
-	std::shared_ptr<SimpleModList> coreModList() const;
-	std::shared_ptr<SimpleModList> resourcePackList() const;
-	std::shared_ptr<SimpleModList> texturePackList() const;
-	std::shared_ptr<WorldList> worldList() const;
+    std::shared_ptr<SimpleModList> loaderModList() const;
+    std::shared_ptr<SimpleModList> coreModList() const;
+    std::shared_ptr<SimpleModList> resourcePackList() const;
+    std::shared_ptr<SimpleModList> texturePackList() const;
+    std::shared_ptr<WorldList> worldList() const;
 
 
-	//////  Launch stuff //////
-	shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override;
-	std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
-	QStringList extraArguments() const override;
-	QStringList verboseDescription(AuthSessionPtr session) override;
-	QList<Mod> getJarMods() const;
-	QString createLaunchScript(AuthSessionPtr session);
-	/// get arguments passed to java
-	QStringList javaArguments() const;
+    //////  Launch stuff //////
+    shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override;
+    std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override;
+    QStringList extraArguments() const override;
+    QStringList verboseDescription(AuthSessionPtr session) override;
+    QList<Mod> getJarMods() const;
+    QString createLaunchScript(AuthSessionPtr session);
+    /// get arguments passed to java
+    QStringList javaArguments() const;
 
-	/// get variables for launch command variable substitution/environment
-	QMap<QString, QString> getVariables() const override;
+    /// get variables for launch command variable substitution/environment
+    QMap<QString, QString> getVariables() const override;
 
-	/// create an environment for launching processes
-	QProcessEnvironment createEnvironment() override;
+    /// create an environment for launching processes
+    QProcessEnvironment createEnvironment() override;
 
-	/// guess log level from a line of minecraft log
-	MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level) override;
+    /// guess log level from a line of minecraft log
+    MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level) override;
 
-	IPathMatcher::Ptr getLogFileMatcher() override;
+    IPathMatcher::Ptr getLogFileMatcher() override;
 
-	QString getLogFileRoot() override;
+    QString getLogFileRoot() override;
 
-	QString getStatusbarDescription() override;
+    QString getStatusbarDescription() override;
 
-	// FIXME: remove
-	virtual QStringList getClassPath() const;
-	// FIXME: remove
-	virtual QStringList getNativeJars() const;
-	// FIXME: remove
-	virtual QString getMainClass() const;
+    // FIXME: remove
+    virtual QStringList getClassPath() const;
+    // FIXME: remove
+    virtual QStringList getNativeJars() const;
+    // FIXME: remove
+    virtual QString getMainClass() const;
 
-	// FIXME: remove
-	virtual QStringList processMinecraftArgs(AuthSessionPtr account) const;
+    // FIXME: remove
+    virtual QStringList processMinecraftArgs(AuthSessionPtr account) const;
 
-	virtual JavaVersion getJavaVersion() const;
+    virtual JavaVersion getJavaVersion() const;
 
 signals:
-	void versionReloaded();
+    void versionReloaded();
 
 protected:
-	QMap<QString, QString> createCensorFilterFromSession(AuthSessionPtr session);
-	QStringList validLaunchMethods();
-	QString launchMethod();
+    QMap<QString, QString> createCensorFilterFromSession(AuthSessionPtr session);
+    QStringList validLaunchMethods();
+    QString launchMethod();
 
 private:
-	QString prettifyTimeDuration(int64_t duration);
+    QString prettifyTimeDuration(int64_t duration);
 
 protected: // data
-	std::shared_ptr<ComponentList> m_components;
-	mutable std::shared_ptr<ModsModel> m_mods_model;
-	mutable std::shared_ptr<SimpleModList> m_loader_mod_list;
-	mutable std::shared_ptr<SimpleModList> m_core_mod_list;
-	mutable std::shared_ptr<SimpleModList> m_resource_pack_list;
-	mutable std::shared_ptr<SimpleModList> m_texture_pack_list;
-	mutable std::shared_ptr<WorldList> m_world_list;
+    std::shared_ptr<ComponentList> m_components;
+    mutable std::shared_ptr<ModsModel> m_mods_model;
+    mutable std::shared_ptr<SimpleModList> m_loader_mod_list;
+    mutable std::shared_ptr<SimpleModList> m_core_mod_list;
+    mutable std::shared_ptr<SimpleModList> m_resource_pack_list;
+    mutable std::shared_ptr<SimpleModList> m_texture_pack_list;
+    mutable std::shared_ptr<WorldList> m_world_list;
 };
 
 typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr;
diff --git a/api/logic/minecraft/MinecraftLoadAndCheck.cpp b/api/logic/minecraft/MinecraftLoadAndCheck.cpp
index c64bbddf..a5052b53 100644
--- a/api/logic/minecraft/MinecraftLoadAndCheck.cpp
+++ b/api/logic/minecraft/MinecraftLoadAndCheck.cpp
@@ -8,38 +8,38 @@ MinecraftLoadAndCheck::MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *p
 
 void MinecraftLoadAndCheck::executeTask()
 {
-	// add offline metadata load task
-	auto components = m_inst->getComponentList();
-	components->reload(Net::Mode::Offline);
-	m_task = components->getCurrentTask();
+    // add offline metadata load task
+    auto components = m_inst->getComponentList();
+    components->reload(Net::Mode::Offline);
+    m_task = components->getCurrentTask();
 
-	if(!m_task)
-	{
-		emitSucceeded();
-		return;
-	}
-	connect(m_task.get(), &Task::succeeded, this, &MinecraftLoadAndCheck::subtaskSucceeded);
-	connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed);
-	connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress);
-	connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus);
+    if(!m_task)
+    {
+        emitSucceeded();
+        return;
+    }
+    connect(m_task.get(), &Task::succeeded, this, &MinecraftLoadAndCheck::subtaskSucceeded);
+    connect(m_task.get(), &Task::failed, this, &MinecraftLoadAndCheck::subtaskFailed);
+    connect(m_task.get(), &Task::progress, this, &MinecraftLoadAndCheck::progress);
+    connect(m_task.get(), &Task::status, this, &MinecraftLoadAndCheck::setStatus);
 }
 
 void MinecraftLoadAndCheck::subtaskSucceeded()
 {
-	if(isFinished())
-	{
-		qCritical() << "OneSixUpdate: Subtask" << sender() << "succeeded, but work was already done!";
-		return;
-	}
-	emitSucceeded();
+    if(isFinished())
+    {
+        qCritical() << "OneSixUpdate: Subtask" << sender() << "succeeded, but work was already done!";
+        return;
+    }
+    emitSucceeded();
 }
 
 void MinecraftLoadAndCheck::subtaskFailed(QString error)
 {
-	if(isFinished())
-	{
-		qCritical() << "OneSixUpdate: Subtask" << sender() << "failed, but work was already done!";
-		return;
-	}
-	emitFailed(error);
+    if(isFinished())
+    {
+        qCritical() << "OneSixUpdate: Subtask" << sender() << "failed, but work was already done!";
+        return;
+    }
+    emitFailed(error);
 }
diff --git a/api/logic/minecraft/MinecraftLoadAndCheck.h b/api/logic/minecraft/MinecraftLoadAndCheck.h
index 91aed674..1f5c2018 100644
--- a/api/logic/minecraft/MinecraftLoadAndCheck.h
+++ b/api/logic/minecraft/MinecraftLoadAndCheck.h
@@ -29,20 +29,20 @@ class MinecraftInstance;
 
 class MinecraftLoadAndCheck : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *parent = 0);
-	virtual ~MinecraftLoadAndCheck() {};
-	void executeTask() override;
+    explicit MinecraftLoadAndCheck(MinecraftInstance *inst, QObject *parent = 0);
+    virtual ~MinecraftLoadAndCheck() {};
+    void executeTask() override;
 
 private slots:
-	void subtaskSucceeded();
-	void subtaskFailed(QString error);
+    void subtaskSucceeded();
+    void subtaskFailed(QString error);
 
 private:
-	MinecraftInstance *m_inst = nullptr;
-	shared_qobject_ptr<Task> m_task;
-	QString m_preFailure;
-	QString m_fail_reason;
+    MinecraftInstance *m_inst = nullptr;
+    shared_qobject_ptr<Task> m_task;
+    QString m_preFailure;
+    QString m_fail_reason;
 };
 
diff --git a/api/logic/minecraft/MinecraftUpdate.cpp b/api/logic/minecraft/MinecraftUpdate.cpp
index 86835fa4..e62ff745 100644
--- a/api/logic/minecraft/MinecraftUpdate.cpp
+++ b/api/logic/minecraft/MinecraftUpdate.cpp
@@ -43,142 +43,142 @@ OneSixUpdate::OneSixUpdate(MinecraftInstance *inst, QObject *parent) : Task(pare
 
 void OneSixUpdate::executeTask()
 {
-	m_tasks.clear();
-	// create folders
-	{
-		m_tasks.append(std::make_shared<FoldersTask>(m_inst));
-	}
-
-	// add metadata update task if necessary
-	{
-		auto components = m_inst->getComponentList();
-		components->reload(Net::Mode::Online);
-		auto task = components->getCurrentTask();
-		if(task)
-		{
-			m_tasks.append(task.unwrap());
-		}
-	}
-
-	// libraries download
-	{
-		m_tasks.append(std::make_shared<LibrariesTask>(m_inst));
-	}
-
-	// FML libraries download and copy into the instance
-	{
-		m_tasks.append(std::make_shared<FMLLibrariesTask>(m_inst));
-	}
-
-	// assets update
-	{
-		m_tasks.append(std::make_shared<AssetUpdateTask>(m_inst));
-	}
-
-	if(!m_preFailure.isEmpty())
-	{
-		emitFailed(m_preFailure);
-		return;
-	}
-	next();
+    m_tasks.clear();
+    // create folders
+    {
+        m_tasks.append(std::make_shared<FoldersTask>(m_inst));
+    }
+
+    // add metadata update task if necessary
+    {
+        auto components = m_inst->getComponentList();
+        components->reload(Net::Mode::Online);
+        auto task = components->getCurrentTask();
+        if(task)
+        {
+            m_tasks.append(task.unwrap());
+        }
+    }
+
+    // libraries download
+    {
+        m_tasks.append(std::make_shared<LibrariesTask>(m_inst));
+    }
+
+    // FML libraries download and copy into the instance
+    {
+        m_tasks.append(std::make_shared<FMLLibrariesTask>(m_inst));
+    }
+
+    // assets update
+    {
+        m_tasks.append(std::make_shared<AssetUpdateTask>(m_inst));
+    }
+
+    if(!m_preFailure.isEmpty())
+    {
+        emitFailed(m_preFailure);
+        return;
+    }
+    next();
 }
 
 void OneSixUpdate::next()
 {
-	if(m_abort)
-	{
-		emitFailed(tr("Aborted by user."));
-		return;
-	}
-	if(m_failed_out_of_order)
-	{
-		emitFailed(m_fail_reason);
-		return;
-	}
-	m_currentTask ++;
-	if(m_currentTask > 0)
-	{
-		auto task = m_tasks[m_currentTask - 1];
-		disconnect(task.get(), &Task::succeeded, this, &OneSixUpdate::subtaskSucceeded);
-		disconnect(task.get(), &Task::failed, this, &OneSixUpdate::subtaskFailed);
-		disconnect(task.get(), &Task::progress, this, &OneSixUpdate::progress);
-		disconnect(task.get(), &Task::status, this, &OneSixUpdate::setStatus);
-	}
-	if(m_currentTask == m_tasks.size())
-	{
-		emitSucceeded();
-		return;
-	}
-	auto task = m_tasks[m_currentTask];
-	// if the task is already finished by the time we look at it, skip it
-	if(task->isFinished())
-	{
-		qCritical() << "OneSixUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get();
-		next();
-	}
-	connect(task.get(), &Task::succeeded, this, &OneSixUpdate::subtaskSucceeded);
-	connect(task.get(), &Task::failed, this, &OneSixUpdate::subtaskFailed);
-	connect(task.get(), &Task::progress, this, &OneSixUpdate::progress);
-	connect(task.get(), &Task::status, this, &OneSixUpdate::setStatus);
-	// if the task is already running, do not start it again
-	if(!task->isRunning())
-	{
-		task->start();
-	}
+    if(m_abort)
+    {
+        emitFailed(tr("Aborted by user."));
+        return;
+    }
+    if(m_failed_out_of_order)
+    {
+        emitFailed(m_fail_reason);
+        return;
+    }
+    m_currentTask ++;
+    if(m_currentTask > 0)
+    {
+        auto task = m_tasks[m_currentTask - 1];
+        disconnect(task.get(), &Task::succeeded, this, &OneSixUpdate::subtaskSucceeded);
+        disconnect(task.get(), &Task::failed, this, &OneSixUpdate::subtaskFailed);
+        disconnect(task.get(), &Task::progress, this, &OneSixUpdate::progress);
+        disconnect(task.get(), &Task::status, this, &OneSixUpdate::setStatus);
+    }
+    if(m_currentTask == m_tasks.size())
+    {
+        emitSucceeded();
+        return;
+    }
+    auto task = m_tasks[m_currentTask];
+    // if the task is already finished by the time we look at it, skip it
+    if(task->isFinished())
+    {
+        qCritical() << "OneSixUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get();
+        next();
+    }
+    connect(task.get(), &Task::succeeded, this, &OneSixUpdate::subtaskSucceeded);
+    connect(task.get(), &Task::failed, this, &OneSixUpdate::subtaskFailed);
+    connect(task.get(), &Task::progress, this, &OneSixUpdate::progress);
+    connect(task.get(), &Task::status, this, &OneSixUpdate::setStatus);
+    // if the task is already running, do not start it again
+    if(!task->isRunning())
+    {
+        task->start();
+    }
 }
 
 void OneSixUpdate::subtaskSucceeded()
 {
-	if(isFinished())
-	{
-		qCritical() << "OneSixUpdate: Subtask" << sender() << "succeeded, but work was already done!";
-		return;
-	}
-	auto senderTask = QObject::sender();
-	auto currentTask = m_tasks[m_currentTask].get();
-	if(senderTask != currentTask)
-	{
-		qDebug() << "OneSixUpdate: Subtask" << sender() << "succeeded out of order.";
-		return;
-	}
-	next();
+    if(isFinished())
+    {
+        qCritical() << "OneSixUpdate: Subtask" << sender() << "succeeded, but work was already done!";
+        return;
+    }
+    auto senderTask = QObject::sender();
+    auto currentTask = m_tasks[m_currentTask].get();
+    if(senderTask != currentTask)
+    {
+        qDebug() << "OneSixUpdate: Subtask" << sender() << "succeeded out of order.";
+        return;
+    }
+    next();
 }
 
 void OneSixUpdate::subtaskFailed(QString error)
 {
-	if(isFinished())
-	{
-		qCritical() << "OneSixUpdate: Subtask" << sender() << "failed, but work was already done!";
-		return;
-	}
-	auto senderTask = QObject::sender();
-	auto currentTask = m_tasks[m_currentTask].get();
-	if(senderTask != currentTask)
-	{
-		qDebug() << "OneSixUpdate: Subtask" << sender() << "failed out of order.";
-		m_failed_out_of_order = true;
-		m_fail_reason = error;
-		return;
-	}
-	emitFailed(error);
+    if(isFinished())
+    {
+        qCritical() << "OneSixUpdate: Subtask" << sender() << "failed, but work was already done!";
+        return;
+    }
+    auto senderTask = QObject::sender();
+    auto currentTask = m_tasks[m_currentTask].get();
+    if(senderTask != currentTask)
+    {
+        qDebug() << "OneSixUpdate: Subtask" << sender() << "failed out of order.";
+        m_failed_out_of_order = true;
+        m_fail_reason = error;
+        return;
+    }
+    emitFailed(error);
 }
 
 
 bool OneSixUpdate::abort()
 {
-	if(!m_abort)
-	{
-		m_abort = true;
-		auto task = m_tasks[m_currentTask];
-		if(task->canAbort())
-		{
-			return task->abort();
-		}
-	}
-	return true;
+    if(!m_abort)
+    {
+        m_abort = true;
+        auto task = m_tasks[m_currentTask];
+        if(task->canAbort())
+        {
+            return task->abort();
+        }
+    }
+    return true;
 }
 
 bool OneSixUpdate::canAbort() const
 {
-	return true;
+    return true;
 }
diff --git a/api/logic/minecraft/MinecraftUpdate.h b/api/logic/minecraft/MinecraftUpdate.h
index 543b2f64..f7b37d73 100644
--- a/api/logic/minecraft/MinecraftUpdate.h
+++ b/api/logic/minecraft/MinecraftUpdate.h
@@ -29,29 +29,29 @@ class MinecraftInstance;
 
 class OneSixUpdate : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit OneSixUpdate(MinecraftInstance *inst, QObject *parent = 0);
-	virtual ~OneSixUpdate() {};
+    explicit OneSixUpdate(MinecraftInstance *inst, QObject *parent = 0);
+    virtual ~OneSixUpdate() {};
 
-	void executeTask() override;
-	bool canAbort() const override;
+    void executeTask() override;
+    bool canAbort() const override;
 
 private
 slots:
-	bool abort() override;
-	void subtaskSucceeded();
-	void subtaskFailed(QString error);
+    bool abort() override;
+    void subtaskSucceeded();
+    void subtaskFailed(QString error);
 
 private:
-	void next();
+    void next();
 
 private:
-	MinecraftInstance *m_inst = nullptr;
-	QList<std::shared_ptr<Task>> m_tasks;
-	QString m_preFailure;
-	int m_currentTask = -1;
-	bool m_abort = false;
-	bool m_failed_out_of_order = false;
-	QString m_fail_reason;
+    MinecraftInstance *m_inst = nullptr;
+    QList<std::shared_ptr<Task>> m_tasks;
+    QString m_preFailure;
+    int m_currentTask = -1;
+    bool m_abort = false;
+    bool m_failed_out_of_order = false;
+    QString m_fail_reason;
 };
diff --git a/api/logic/minecraft/Mod.cpp b/api/logic/minecraft/Mod.cpp
index 03e04b2b..bd209211 100644
--- a/api/logic/minecraft/Mod.cpp
+++ b/api/logic/minecraft/Mod.cpp
@@ -29,124 +29,124 @@
 
 Mod::Mod(const QFileInfo &file)
 {
-	repath(file);
-	m_changedDateTime = file.lastModified();
+    repath(file);
+    m_changedDateTime = file.lastModified();
 }
 
 void Mod::repath(const QFileInfo &file)
 {
-	m_file = file;
-	QString name_base = file.fileName();
+    m_file = file;
+    QString name_base = file.fileName();
 
-	m_type = Mod::MOD_UNKNOWN;
+    m_type = Mod::MOD_UNKNOWN;
 
-	if (m_file.isDir())
-	{
-		m_type = MOD_FOLDER;
-		m_name = name_base;
-		m_mmc_id = name_base;
-	}
-	else if (m_file.isFile())
-	{
-		if (name_base.endsWith(".disabled"))
-		{
-			m_enabled = false;
-			name_base.chop(9);
-		}
-		else
-		{
-			m_enabled = true;
-		}
-		m_mmc_id = name_base;
-		if (name_base.endsWith(".zip") || name_base.endsWith(".jar"))
-		{
-			m_type = MOD_ZIPFILE;
-			name_base.chop(4);
-		}
-		else if (name_base.endsWith(".litemod"))
-		{
-			m_type = MOD_LITEMOD;
-			name_base.chop(8);
-		}
-		else
-		{
-			m_type = MOD_SINGLEFILE;
-		}
-		m_name = name_base;
-	}
+    if (m_file.isDir())
+    {
+        m_type = MOD_FOLDER;
+        m_name = name_base;
+        m_mmc_id = name_base;
+    }
+    else if (m_file.isFile())
+    {
+        if (name_base.endsWith(".disabled"))
+        {
+            m_enabled = false;
+            name_base.chop(9);
+        }
+        else
+        {
+            m_enabled = true;
+        }
+        m_mmc_id = name_base;
+        if (name_base.endsWith(".zip") || name_base.endsWith(".jar"))
+        {
+            m_type = MOD_ZIPFILE;
+            name_base.chop(4);
+        }
+        else if (name_base.endsWith(".litemod"))
+        {
+            m_type = MOD_LITEMOD;
+            name_base.chop(8);
+        }
+        else
+        {
+            m_type = MOD_SINGLEFILE;
+        }
+        m_name = name_base;
+    }
 
-	if (m_type == MOD_ZIPFILE)
-	{
-		QuaZip zip(m_file.filePath());
-		if (!zip.open(QuaZip::mdUnzip))
-			return;
+    if (m_type == MOD_ZIPFILE)
+    {
+        QuaZip zip(m_file.filePath());
+        if (!zip.open(QuaZip::mdUnzip))
+            return;
 
-		QuaZipFile file(&zip);
+        QuaZipFile file(&zip);
 
-		if (zip.setCurrentFile("mcmod.info"))
-		{
-			if (!file.open(QIODevice::ReadOnly))
-			{
-				zip.close();
-				return;
-			}
+        if (zip.setCurrentFile("mcmod.info"))
+        {
+            if (!file.open(QIODevice::ReadOnly))
+            {
+                zip.close();
+                return;
+            }
 
-			ReadMCModInfo(file.readAll());
-			file.close();
-			zip.close();
-			return;
-		}
-		else if (zip.setCurrentFile("forgeversion.properties"))
-		{
-			if (!file.open(QIODevice::ReadOnly))
-			{
-				zip.close();
-				return;
-			}
+            ReadMCModInfo(file.readAll());
+            file.close();
+            zip.close();
+            return;
+        }
+        else if (zip.setCurrentFile("forgeversion.properties"))
+        {
+            if (!file.open(QIODevice::ReadOnly))
+            {
+                zip.close();
+                return;
+            }
 
-			ReadForgeInfo(file.readAll());
-			file.close();
-			zip.close();
-			return;
-		}
+            ReadForgeInfo(file.readAll());
+            file.close();
+            zip.close();
+            return;
+        }
 
-		zip.close();
-	}
-	else if (m_type == MOD_FOLDER)
-	{
-		QFileInfo mcmod_info(FS::PathCombine(m_file.filePath(), "mcmod.info"));
-		if (mcmod_info.isFile())
-		{
-			QFile mcmod(mcmod_info.filePath());
-			if (!mcmod.open(QIODevice::ReadOnly))
-				return;
-			auto data = mcmod.readAll();
-			if (data.isEmpty() || data.isNull())
-				return;
-			ReadMCModInfo(data);
-		}
-	}
-	else if (m_type == MOD_LITEMOD)
-	{
-		QuaZip zip(m_file.filePath());
-		if (!zip.open(QuaZip::mdUnzip))
-			return;
+        zip.close();
+    }
+    else if (m_type == MOD_FOLDER)
+    {
+        QFileInfo mcmod_info(FS::PathCombine(m_file.filePath(), "mcmod.info"));
+        if (mcmod_info.isFile())
+        {
+            QFile mcmod(mcmod_info.filePath());
+            if (!mcmod.open(QIODevice::ReadOnly))
+                return;
+            auto data = mcmod.readAll();
+            if (data.isEmpty() || data.isNull())
+                return;
+            ReadMCModInfo(data);
+        }
+    }
+    else if (m_type == MOD_LITEMOD)
+    {
+        QuaZip zip(m_file.filePath());
+        if (!zip.open(QuaZip::mdUnzip))
+            return;
 
-		QuaZipFile file(&zip);
+        QuaZipFile file(&zip);
 
-		if (zip.setCurrentFile("litemod.json"))
-		{
-			if (!file.open(QIODevice::ReadOnly))
-			{
-				zip.close();
-				return;
-			}
+        if (zip.setCurrentFile("litemod.json"))
+        {
+            if (!file.open(QIODevice::ReadOnly))
+            {
+                zip.close();
+                return;
+            }
 
-			ReadLiteModInfo(file.readAll());
-			file.close();
-		}
-		zip.close();
-	}
+            ReadLiteModInfo(file.readAll());
+            file.close();
+        }
+        zip.close();
+    }
 }
 
 // NEW format
@@ -156,223 +156,223 @@ void Mod::repath(const QFileInfo &file)
 // https://github.com/MinecraftForge/FML/wiki/FML-mod-information-file/5bf6a2d05145ec79387acc0d45c958642fb049fc
 void Mod::ReadMCModInfo(QByteArray contents)
 {
-	auto getInfoFromArray = [&](QJsonArray arr)->void
-	{
-		if (!arr.at(0).isObject())
-			return;
-		auto firstObj = arr.at(0).toObject();
-		m_mod_id = firstObj.value("modid").toString();
-		m_name = firstObj.value("name").toString();
-		m_version = firstObj.value("version").toString();
-		m_homeurl = firstObj.value("url").toString();
-		m_updateurl = firstObj.value("updateUrl").toString();
-		m_homeurl = m_homeurl.trimmed();
-		if(!m_homeurl.isEmpty())
-		{
-			// fix up url.
-			if (!m_homeurl.startsWith("http://") && !m_homeurl.startsWith("https://") &&
-				!m_homeurl.startsWith("ftp://"))
-			{
-				m_homeurl.prepend("http://");
-			}
-		}
-		m_description = firstObj.value("description").toString();
-		QJsonArray authors = firstObj.value("authorList").toArray();
-		if (authors.size() == 0)
-			authors = firstObj.value("authors").toArray();
+    auto getInfoFromArray = [&](QJsonArray arr)->void
+    {
+        if (!arr.at(0).isObject())
+            return;
+        auto firstObj = arr.at(0).toObject();
+        m_mod_id = firstObj.value("modid").toString();
+        m_name = firstObj.value("name").toString();
+        m_version = firstObj.value("version").toString();
+        m_homeurl = firstObj.value("url").toString();
+        m_updateurl = firstObj.value("updateUrl").toString();
+        m_homeurl = m_homeurl.trimmed();
+        if(!m_homeurl.isEmpty())
+        {
+            // fix up url.
+            if (!m_homeurl.startsWith("http://") && !m_homeurl.startsWith("https://") &&
+                !m_homeurl.startsWith("ftp://"))
+            {
+                m_homeurl.prepend("http://");
+            }
+        }
+        m_description = firstObj.value("description").toString();
+        QJsonArray authors = firstObj.value("authorList").toArray();
+        if (authors.size() == 0)
+            authors = firstObj.value("authors").toArray();
 
-		if (authors.size() == 0)
-			m_authors = "";
-		else if (authors.size() >= 1)
-		{
-			m_authors = authors.at(0).toString();
-			for (int i = 1; i < authors.size(); i++)
-			{
-				m_authors += ", " + authors.at(i).toString();
-			}
-		}
-		m_credits = firstObj.value("credits").toString();
-		return;
-	}
-	;
-	QJsonParseError jsonError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
-	// this is the very old format that had just the array
-	if (jsonDoc.isArray())
-	{
-		getInfoFromArray(jsonDoc.array());
-	}
-	else if (jsonDoc.isObject())
-	{
-		auto val = jsonDoc.object().value("modinfoversion");
-		if(val.isUndefined())
-			val = jsonDoc.object().value("modListVersion");
-		int version = val.toDouble();
-		if (version != 2)
-		{
-			qCritical() << "BAD stuff happened to mod json:";
-			qCritical() << contents;
-			return;
-		}
-		auto arrVal = jsonDoc.object().value("modlist");
-		if(arrVal.isUndefined())
-			arrVal = jsonDoc.object().value("modList");
-		if (arrVal.isArray())
-		{
-			getInfoFromArray(arrVal.toArray());
-		}
-	}
+        if (authors.size() == 0)
+            m_authors = "";
+        else if (authors.size() >= 1)
+        {
+            m_authors = authors.at(0).toString();
+            for (int i = 1; i < authors.size(); i++)
+            {
+                m_authors += ", " + authors.at(i).toString();
+            }
+        }
+        m_credits = firstObj.value("credits").toString();
+        return;
+    }
+    ;
+    QJsonParseError jsonError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
+    // this is the very old format that had just the array
+    if (jsonDoc.isArray())
+    {
+        getInfoFromArray(jsonDoc.array());
+    }
+    else if (jsonDoc.isObject())
+    {
+        auto val = jsonDoc.object().value("modinfoversion");
+        if(val.isUndefined())
+            val = jsonDoc.object().value("modListVersion");
+        int version = val.toDouble();
+        if (version != 2)
+        {
+            qCritical() << "BAD stuff happened to mod json:";
+            qCritical() << contents;
+            return;
+        }
+        auto arrVal = jsonDoc.object().value("modlist");
+        if(arrVal.isUndefined())
+            arrVal = jsonDoc.object().value("modList");
+        if (arrVal.isArray())
+        {
+            getInfoFromArray(arrVal.toArray());
+        }
+    }
 }
 
 void Mod::ReadForgeInfo(QByteArray contents)
 {
-	// Read the data
-	m_name = "Minecraft Forge";
-	m_mod_id = "Forge";
-	m_homeurl = "http://www.minecraftforge.net/forum/";
-	INIFile ini;
-	if (!ini.loadFile(contents))
-		return;
+    // Read the data
+    m_name = "Minecraft Forge";
+    m_mod_id = "Forge";
+    m_homeurl = "http://www.minecraftforge.net/forum/";
+    INIFile ini;
+    if (!ini.loadFile(contents))
+        return;
 
-	QString major = ini.get("forge.major.number", "0").toString();
-	QString minor = ini.get("forge.minor.number", "0").toString();
-	QString revision = ini.get("forge.revision.number", "0").toString();
-	QString build = ini.get("forge.build.number", "0").toString();
+    QString major = ini.get("forge.major.number", "0").toString();
+    QString minor = ini.get("forge.minor.number", "0").toString();
+    QString revision = ini.get("forge.revision.number", "0").toString();
+    QString build = ini.get("forge.build.number", "0").toString();
 
-	m_version = major + "." + minor + "." + revision + "." + build;
+    m_version = major + "." + minor + "." + revision + "." + build;
 }
 
 void Mod::ReadLiteModInfo(QByteArray contents)
 {
-	QJsonParseError jsonError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
-	auto object = jsonDoc.object();
-	if (object.contains("name"))
-	{
-		m_mod_id = m_name = object.value("name").toString();
-	}
-	if (object.contains("version"))
-	{
-		m_version = object.value("version").toString("");
-	}
-	else
-	{
-		m_version = object.value("revision").toString("");
-	}
-	m_mcversion = object.value("mcversion").toString();
-	m_authors = object.value("author").toString();
-	m_description = object.value("description").toString();
-	m_homeurl = object.value("url").toString();
+    QJsonParseError jsonError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
+    auto object = jsonDoc.object();
+    if (object.contains("name"))
+    {
+        m_mod_id = m_name = object.value("name").toString();
+    }
+    if (object.contains("version"))
+    {
+        m_version = object.value("version").toString("");
+    }
+    else
+    {
+        m_version = object.value("revision").toString("");
+    }
+    m_mcversion = object.value("mcversion").toString();
+    m_authors = object.value("author").toString();
+    m_description = object.value("description").toString();
+    m_homeurl = object.value("url").toString();
 }
 
 bool Mod::replace(Mod &with)
 {
-	if (!destroy())
-		return false;
-	bool success = false;
-	auto t = with.type();
+    if (!destroy())
+        return false;
+    bool success = false;
+    auto t = with.type();
 
-	if (t == MOD_ZIPFILE || t == MOD_SINGLEFILE || t == MOD_LITEMOD)
-	{
-		qDebug() << "Copy: " << with.m_file.filePath() << " to " << m_file.filePath();
-		success = QFile::copy(with.m_file.filePath(), m_file.filePath());
-	}
-	if (t == MOD_FOLDER)
-	{
-		success = FS::copy(with.m_file.filePath(), m_file.path())();
-	}
-	if (success)
-	{
-		m_name = with.m_name;
-		m_mmc_id = with.m_mmc_id;
-		m_mod_id = with.m_mod_id;
-		m_version = with.m_version;
-		m_mcversion = with.m_mcversion;
-		m_description = with.m_description;
-		m_authors = with.m_authors;
-		m_credits = with.m_credits;
-		m_homeurl = with.m_homeurl;
-		m_type = with.m_type;
-		m_file.refresh();
-	}
-	return success;
+    if (t == MOD_ZIPFILE || t == MOD_SINGLEFILE || t == MOD_LITEMOD)
+    {
+        qDebug() << "Copy: " << with.m_file.filePath() << " to " << m_file.filePath();
+        success = QFile::copy(with.m_file.filePath(), m_file.filePath());
+    }
+    if (t == MOD_FOLDER)
+    {
+        success = FS::copy(with.m_file.filePath(), m_file.path())();
+    }
+    if (success)
+    {
+        m_name = with.m_name;
+        m_mmc_id = with.m_mmc_id;
+        m_mod_id = with.m_mod_id;
+        m_version = with.m_version;
+        m_mcversion = with.m_mcversion;
+        m_description = with.m_description;
+        m_authors = with.m_authors;
+        m_credits = with.m_credits;
+        m_homeurl = with.m_homeurl;
+        m_type = with.m_type;
+        m_file.refresh();
+    }
+    return success;
 }
 
 bool Mod::destroy()
 {
-	if (m_type == MOD_FOLDER)
-	{
-		QDir d(m_file.filePath());
-		if (d.removeRecursively())
-		{
-			m_type = MOD_UNKNOWN;
-			return true;
-		}
-		return false;
-	}
-	else if (m_type == MOD_SINGLEFILE || m_type == MOD_ZIPFILE || m_type == MOD_LITEMOD)
-	{
-		QFile f(m_file.filePath());
-		if (f.remove())
-		{
-			m_type = MOD_UNKNOWN;
-			return true;
-		}
-		return false;
-	}
-	return true;
+    if (m_type == MOD_FOLDER)
+    {
+        QDir d(m_file.filePath());
+        if (d.removeRecursively())
+        {
+            m_type = MOD_UNKNOWN;
+            return true;
+        }
+        return false;
+    }
+    else if (m_type == MOD_SINGLEFILE || m_type == MOD_ZIPFILE || m_type == MOD_LITEMOD)
+    {
+        QFile f(m_file.filePath());
+        if (f.remove())
+        {
+            m_type = MOD_UNKNOWN;
+            return true;
+        }
+        return false;
+    }
+    return true;
 }
 
 QString Mod::version() const
 {
-	switch (type())
-	{
-	case MOD_ZIPFILE:
-	case MOD_LITEMOD:
-		return m_version;
-	case MOD_FOLDER:
-		return "Folder";
-	case MOD_SINGLEFILE:
-		return "File";
-	default:
-		return "VOID";
-	}
+    switch (type())
+    {
+    case MOD_ZIPFILE:
+    case MOD_LITEMOD:
+        return m_version;
+    case MOD_FOLDER:
+        return "Folder";
+    case MOD_SINGLEFILE:
+        return "File";
+    default:
+        return "VOID";
+    }
 }
 
 bool Mod::enable(bool value)
 {
-	if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER)
-		return false;
+    if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER)
+        return false;
 
-	if (m_enabled == value)
-		return false;
+    if (m_enabled == value)
+        return false;
 
-	QString path = m_file.absoluteFilePath();
-	if (value)
-	{
-		QFile foo(path);
-		if (!path.endsWith(".disabled"))
-			return false;
-		path.chop(9);
-		if (!foo.rename(path))
-			return false;
-	}
-	else
-	{
-		QFile foo(path);
-		path += ".disabled";
-		if (!foo.rename(path))
-			return false;
-	}
-	m_file = QFileInfo(path);
-	m_enabled = value;
-	return true;
+    QString path = m_file.absoluteFilePath();
+    if (value)
+    {
+        QFile foo(path);
+        if (!path.endsWith(".disabled"))
+            return false;
+        path.chop(9);
+        if (!foo.rename(path))
+            return false;
+    }
+    else
+    {
+        QFile foo(path);
+        path += ".disabled";
+        if (!foo.rename(path))
+            return false;
+    }
+    m_file = QFileInfo(path);
+    m_enabled = value;
+    return true;
 }
 bool Mod::operator==(const Mod &other) const
 {
-	return mmc_id() == other.mmc_id();
+    return mmc_id() == other.mmc_id();
 }
 bool Mod::strongCompare(const Mod &other) const
 {
-	return mmc_id() == other.mmc_id() && version() == other.version() && type() == other.type();
+    return mmc_id() == other.mmc_id() && version() == other.version() && type() == other.type();
 }
diff --git a/api/logic/minecraft/Mod.h b/api/logic/minecraft/Mod.h
index ccab1867..0c1adf24 100644
--- a/api/logic/minecraft/Mod.h
+++ b/api/logic/minecraft/Mod.h
@@ -20,123 +20,123 @@
 class Mod
 {
 public:
-	enum ModType
-	{
-		MOD_UNKNOWN,	//!< Indicates an unspecified mod type.
-		MOD_ZIPFILE,	//!< The mod is a zip file containing the mod's class files.
-		MOD_SINGLEFILE, //!< The mod is a single file (not a zip file).
-		MOD_FOLDER,	 //!< The mod is in a folder on the filesystem.
-		MOD_LITEMOD, //!< The mod is a litemod
-	};
-
-	Mod(const QFileInfo &file);
-
-	QFileInfo filename() const
-	{
-		return m_file;
-	}
-	QString mmc_id() const
-	{
-		return m_mmc_id;
-	}
-	QString mod_id() const
-	{
-		return m_mod_id;
-	}
-	ModType type() const
-	{
-		return m_type;
-	}
-	QString mcversion() const
-	{
-		return m_mcversion;
-	}
-	;
-	bool valid()
-	{
-		return m_type != MOD_UNKNOWN;
-	}
-	QString name() const
-	{
-		QString name = m_name.trimmed();
-		if(name.isEmpty() || name == "Example Mod")
-		{
-			return m_mmc_id;
-		}
-		return m_name;
-	}
-
-	QString version() const;
-
-	QString homeurl() const
-	{
-		return m_homeurl;
-	}
-
-	QString description() const
-	{
-		return m_description;
-	}
-
-	QString authors() const
-	{
-		return m_authors;
-	}
-
-	QString credits() const
-	{
-		return m_credits;
-	}
-
-	QDateTime dateTimeChanged() const
-	{
-		return m_changedDateTime;
-	}
-
-	bool enabled() const
-	{
-		return m_enabled;
-	}
-
-	bool enable(bool value);
-
-	// delete all the files of this mod
-	bool destroy();
-	// replace this mod with a copy of the other
-	bool replace(Mod &with);
-	// change the mod's filesystem path (used by mod lists for *MAGIC* purposes)
-	void repath(const QFileInfo &file);
-
-	// WEAK compare operator - used for replacing mods
-	bool operator==(const Mod &other) const;
-	bool strongCompare(const Mod &other) const;
+    enum ModType
+    {
+        MOD_UNKNOWN,    //!< Indicates an unspecified mod type.
+        MOD_ZIPFILE,    //!< The mod is a zip file containing the mod's class files.
+        MOD_SINGLEFILE, //!< The mod is a single file (not a zip file).
+        MOD_FOLDER,     //!< The mod is in a folder on the filesystem.
+        MOD_LITEMOD, //!< The mod is a litemod
+    };
+
+    Mod(const QFileInfo &file);
+
+    QFileInfo filename() const
+    {
+        return m_file;
+    }
+    QString mmc_id() const
+    {
+        return m_mmc_id;
+    }
+    QString mod_id() const
+    {
+        return m_mod_id;
+    }
+    ModType type() const
+    {
+        return m_type;
+    }
+    QString mcversion() const
+    {
+        return m_mcversion;
+    }
+    ;
+    bool valid()
+    {
+        return m_type != MOD_UNKNOWN;
+    }
+    QString name() const
+    {
+        QString name = m_name.trimmed();
+        if(name.isEmpty() || name == "Example Mod")
+        {
+            return m_mmc_id;
+        }
+        return m_name;
+    }
+
+    QString version() const;
+
+    QString homeurl() const
+    {
+        return m_homeurl;
+    }
+
+    QString description() const
+    {
+        return m_description;
+    }
+
+    QString authors() const
+    {
+        return m_authors;
+    }
+
+    QString credits() const
+    {
+        return m_credits;
+    }
+
+    QDateTime dateTimeChanged() const
+    {
+        return m_changedDateTime;
+    }
+
+    bool enabled() const
+    {
+        return m_enabled;
+    }
+
+    bool enable(bool value);
+
+    // delete all the files of this mod
+    bool destroy();
+    // replace this mod with a copy of the other
+    bool replace(Mod &with);
+    // change the mod's filesystem path (used by mod lists for *MAGIC* purposes)
+    void repath(const QFileInfo &file);
+
+    // WEAK compare operator - used for replacing mods
+    bool operator==(const Mod &other) const;
+    bool strongCompare(const Mod &other) const;
 
 private:
-	void ReadMCModInfo(QByteArray contents);
-	void ReadForgeInfo(QByteArray contents);
-	void ReadLiteModInfo(QByteArray contents);
+    void ReadMCModInfo(QByteArray contents);
+    void ReadForgeInfo(QByteArray contents);
+    void ReadLiteModInfo(QByteArray contents);
 
 protected:
 
-	// FIXME: what do do with those? HMM...
-	/*
-	void ReadModInfoData(QString info);
-	void ReadForgeInfoData(QString infoFileData);
-	*/
-
-	QFileInfo m_file;
-	QDateTime m_changedDateTime;
-	QString m_mmc_id;
-	QString m_mod_id;
-	bool m_enabled = true;
-	QString m_name;
-	QString m_version;
-	QString m_mcversion;
-	QString m_homeurl;
-	QString m_updateurl;
-	QString m_description;
-	QString m_authors;
-	QString m_credits;
-
-	ModType m_type;
+    // FIXME: what do do with those? HMM...
+    /*
+    void ReadModInfoData(QString info);
+    void ReadForgeInfoData(QString infoFileData);
+    */
+
+    QFileInfo m_file;
+    QDateTime m_changedDateTime;
+    QString m_mmc_id;
+    QString m_mod_id;
+    bool m_enabled = true;
+    QString m_name;
+    QString m_version;
+    QString m_mcversion;
+    QString m_homeurl;
+    QString m_updateurl;
+    QString m_description;
+    QString m_authors;
+    QString m_credits;
+
+    ModType m_type;
 };
diff --git a/api/logic/minecraft/ModsModel.cpp b/api/logic/minecraft/ModsModel.cpp
index ff99ad4a..e401618a 100644
--- a/api/logic/minecraft/ModsModel.cpp
+++ b/api/logic/minecraft/ModsModel.cpp
@@ -25,350 +25,350 @@
 ModsModel::ModsModel(const QString &mainDir, const QString &coreDir, const QString &cacheLocation)
     :QAbstractListModel(), m_mainDir(mainDir), m_coreDir(coreDir)
 {
-	FS::ensureFolderPathExists(m_mainDir.absolutePath());
-	m_mainDir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
+    FS::ensureFolderPathExists(m_mainDir.absolutePath());
+    m_mainDir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
                         QDir::NoSymLinks);
-	m_mainDir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
-	m_watcher = new QFileSystemWatcher(this);
-	connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
+    m_mainDir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
+    m_watcher = new QFileSystemWatcher(this);
+    connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
 }
 
 void ModsModel::startWatching()
 {
-	if(is_watching)
-		return;
-
-	update();
-
-	is_watching = m_watcher->addPath(m_mainDir.absolutePath());
-	if (is_watching)
-	{
-		qDebug() << "Started watching " << m_mainDir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to start watching " << m_mainDir.absolutePath();
-	}
+    if(is_watching)
+        return;
+
+    update();
+
+    is_watching = m_watcher->addPath(m_mainDir.absolutePath());
+    if (is_watching)
+    {
+        qDebug() << "Started watching " << m_mainDir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to start watching " << m_mainDir.absolutePath();
+    }
 }
 
 void ModsModel::stopWatching()
 {
-	if(!is_watching)
-		return;
-
-	is_watching = !m_watcher->removePath(m_mainDir.absolutePath());
-	if (!is_watching)
-	{
-		qDebug() << "Stopped watching " << m_mainDir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to stop watching " << m_mainDir.absolutePath();
-	}
+    if(!is_watching)
+        return;
+
+    is_watching = !m_watcher->removePath(m_mainDir.absolutePath());
+    if (!is_watching)
+    {
+        qDebug() << "Stopped watching " << m_mainDir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to stop watching " << m_mainDir.absolutePath();
+    }
 }
 
 bool ModsModel::update()
 {
-	if (!isValid())
-		return false;
-
-	QList<Mod> orderedMods;
-	QList<Mod> newMods;
-	m_mainDir.refresh();
-	auto folderContents = m_mainDir.entryInfoList();
-	bool orderOrStateChanged = false;
-
-	// if there are any untracked files...
-	if (folderContents.size())
-	{
-		// the order surely changed!
-		for (auto entry : folderContents)
-		{
-			newMods.append(Mod(entry));
-		}
-		orderedMods.append(newMods);
-		orderOrStateChanged = true;
-	}
-	// otherwise, if we were already tracking some mods
-	else if (mods.size())
-	{
-		// if the number doesn't match, order changed.
-		if (mods.size() != orderedMods.size())
-			orderOrStateChanged = true;
-		// if it does match, compare the mods themselves
-		else
-			for (int i = 0; i < mods.size(); i++)
-			{
-				if (!mods[i].strongCompare(orderedMods[i]))
-				{
-					orderOrStateChanged = true;
-					break;
-				}
-			}
-	}
-	beginResetModel();
-	mods.swap(orderedMods);
-	endResetModel();
-	if (orderOrStateChanged)
-	{
-		emit changed();
-	}
-	return true;
+    if (!isValid())
+        return false;
+
+    QList<Mod> orderedMods;
+    QList<Mod> newMods;
+    m_mainDir.refresh();
+    auto folderContents = m_mainDir.entryInfoList();
+    bool orderOrStateChanged = false;
+
+    // if there are any untracked files...
+    if (folderContents.size())
+    {
+        // the order surely changed!
+        for (auto entry : folderContents)
+        {
+            newMods.append(Mod(entry));
+        }
+        orderedMods.append(newMods);
+        orderOrStateChanged = true;
+    }
+    // otherwise, if we were already tracking some mods
+    else if (mods.size())
+    {
+        // if the number doesn't match, order changed.
+        if (mods.size() != orderedMods.size())
+            orderOrStateChanged = true;
+        // if it does match, compare the mods themselves
+        else
+            for (int i = 0; i < mods.size(); i++)
+            {
+                if (!mods[i].strongCompare(orderedMods[i]))
+                {
+                    orderOrStateChanged = true;
+                    break;
+                }
+            }
+    }
+    beginResetModel();
+    mods.swap(orderedMods);
+    endResetModel();
+    if (orderOrStateChanged)
+    {
+        emit changed();
+    }
+    return true;
 }
 
 void ModsModel::directoryChanged(QString path)
 {
-	update();
+    update();
 }
 
 bool ModsModel::isValid()
 {
-	return m_mainDir.exists() && m_mainDir.isReadable();
+    return m_mainDir.exists() && m_mainDir.isReadable();
 }
 
 bool ModsModel::installMod(const QString &filename)
 {
-	// NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName
-	QFileInfo fileinfo(FS::NormalizePath(filename));
-
-	qDebug() << "installing: " << fileinfo.absoluteFilePath();
-
-	if (!fileinfo.exists() || !fileinfo.isReadable())
-	{
-		return false;
-	}
-	Mod m(fileinfo);
-	if (!m.valid())
-		return false;
-
-	auto type = m.type();
-	if (type == Mod::MOD_UNKNOWN)
-		return false;
-	if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD)
-	{
-		QString newpath = FS::PathCombine(m_mainDir.path(), fileinfo.fileName());
-		if (!QFile::copy(fileinfo.filePath(), newpath))
-			return false;
-		FS::updateTimestamp(newpath);
-		m.repath(newpath);
-		update();
-		return true;
-	}
-	else if (type == Mod::MOD_FOLDER)
-	{
-		QString from = fileinfo.filePath();
-		QString to = FS::PathCombine(m_mainDir.path(), fileinfo.fileName());
-		if (!FS::copy(from, to)())
-			return false;
-		m.repath(to);
-		update();
-		return true;
-	}
-	return false;
+    // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName
+    QFileInfo fileinfo(FS::NormalizePath(filename));
+
+    qDebug() << "installing: " << fileinfo.absoluteFilePath();
+
+    if (!fileinfo.exists() || !fileinfo.isReadable())
+    {
+        return false;
+    }
+    Mod m(fileinfo);
+    if (!m.valid())
+        return false;
+
+    auto type = m.type();
+    if (type == Mod::MOD_UNKNOWN)
+        return false;
+    if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD)
+    {
+        QString newpath = FS::PathCombine(m_mainDir.path(), fileinfo.fileName());
+        if (!QFile::copy(fileinfo.filePath(), newpath))
+            return false;
+        FS::updateTimestamp(newpath);
+        m.repath(newpath);
+        update();
+        return true;
+    }
+    else if (type == Mod::MOD_FOLDER)
+    {
+        QString from = fileinfo.filePath();
+        QString to = FS::PathCombine(m_mainDir.path(), fileinfo.fileName());
+        if (!FS::copy(from, to)())
+            return false;
+        m.repath(to);
+        update();
+        return true;
+    }
+    return false;
 }
 
 bool ModsModel::enableMods(const QModelIndexList& indexes, bool enable)
 {
-	if(indexes.isEmpty())
-		return true;
-
-	for (auto i: indexes)
-	{
-		Mod &m = mods[i.row()];
-		m.enable(enable);
-		emit dataChanged(i, i);
-	}
-	emit changed();
-	return true;
+    if(indexes.isEmpty())
+        return true;
+
+    for (auto i: indexes)
+    {
+        Mod &m = mods[i.row()];
+        m.enable(enable);
+        emit dataChanged(i, i);
+    }
+    emit changed();
+    return true;
 }
 
 bool ModsModel::deleteMods(const QModelIndexList& indexes)
 {
-	if(indexes.isEmpty())
-		return true;
-
-	for (auto i: indexes)
-	{
-		Mod &m = mods[i.row()];
-		m.destroy();
-	}
-	emit changed();
-	return true;
+    if(indexes.isEmpty())
+        return true;
+
+    for (auto i: indexes)
+    {
+        Mod &m = mods[i.row()];
+        m.destroy();
+    }
+    emit changed();
+    return true;
 }
 
 int ModsModel::columnCount(const QModelIndex &parent) const
 {
-	return NUM_COLUMNS;
+    return NUM_COLUMNS;
 }
 
 QVariant ModsModel::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	int row = index.row();
-	int column = index.column();
-
-	if (row < 0 || row >= mods.size())
-		return QVariant();
-
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (column)
-		{
-		case NameColumn:
-			return mods[row].name();
-		case VersionColumn:
-			return mods[row].version();
-		case DateColumn:
-			return mods[row].dateTimeChanged();
+    if (!index.isValid())
+        return QVariant();
+
+    int row = index.row();
+    int column = index.column();
+
+    if (row < 0 || row >= mods.size())
+        return QVariant();
+
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (column)
+        {
+        case NameColumn:
+            return mods[row].name();
+        case VersionColumn:
+            return mods[row].version();
+        case DateColumn:
+            return mods[row].dateTimeChanged();
         case LocationColumn:
             return "Unknown";
 
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		return mods[row].mmc_id();
-
-	case Qt::CheckStateRole:
-		switch (column)
-		{
-		case ActiveColumn:
-			return mods[row].enabled() ? Qt::Checked : Qt::Unchecked;
-		default:
-			return QVariant();
-		}
-	default:
-		return QVariant();
-	}
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        return mods[row].mmc_id();
+
+    case Qt::CheckStateRole:
+        switch (column)
+        {
+        case ActiveColumn:
+            return mods[row].enabled() ? Qt::Checked : Qt::Unchecked;
+        default:
+            return QVariant();
+        }
+    default:
+        return QVariant();
+    }
 }
 
 bool ModsModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-	if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
-	{
-		return false;
-	}
-
-	if (role == Qt::CheckStateRole)
-	{
-		auto &mod = mods[index.row()];
-		if (mod.enable(!mod.enabled()))
-		{
-			emit dataChanged(index, index);
-			return true;
-		}
-	}
-	return false;
+    if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
+    {
+        return false;
+    }
+
+    if (role == Qt::CheckStateRole)
+    {
+        auto &mod = mods[index.row()];
+        if (mod.enable(!mod.enabled()))
+        {
+            emit dataChanged(index, index);
+            return true;
+        }
+    }
+    return false;
 }
 
 QVariant ModsModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (section)
-		{
-		case ActiveColumn:
-			return QString();
-		case NameColumn:
-			return tr("Name");
-		case VersionColumn:
-			return tr("Version");
-		case DateColumn:
-			return tr("Last changed");
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (section)
+        {
+        case ActiveColumn:
+            return QString();
+        case NameColumn:
+            return tr("Name");
+        case VersionColumn:
+            return tr("Version");
+        case DateColumn:
+            return tr("Last changed");
         case LocationColumn:
             return tr("Location");
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		switch (section)
-		{
-		case ActiveColumn:
-			return tr("Is the mod enabled?");
-		case NameColumn:
-			return tr("The name of the mod.");
-		case VersionColumn:
-			return tr("The version of the mod.");
-		case DateColumn:
-			return tr("The date and time this mod was last changed (or added).");
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        switch (section)
+        {
+        case ActiveColumn:
+            return tr("Is the mod enabled?");
+        case NameColumn:
+            return tr("The name of the mod.");
+        case VersionColumn:
+            return tr("The version of the mod.");
+        case DateColumn:
+            return tr("The date and time this mod was last changed (or added).");
         case LocationColumn:
             return tr("Where the mod is located (inside or outside the instance).");
-		default:
-			return QVariant();
-		}
-	default:
-		return QVariant();
-	}
-	return QVariant();
+        default:
+            return QVariant();
+        }
+    default:
+        return QVariant();
+    }
+    return QVariant();
 }
 
 Qt::ItemFlags ModsModel::flags(const QModelIndex &index) const
 {
-	Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
-	if (index.isValid())
-		return Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled |
-			   defaultFlags;
-	else
-		return Qt::ItemIsDropEnabled | defaultFlags;
+    Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
+    if (index.isValid())
+        return Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled |
+               defaultFlags;
+    else
+        return Qt::ItemIsDropEnabled | defaultFlags;
 }
 
 Qt::DropActions ModsModel::supportedDropActions() const
 {
-	// copy from outside, move from within and other mod lists
-	return Qt::CopyAction | Qt::MoveAction;
+    // copy from outside, move from within and other mod lists
+    return Qt::CopyAction | Qt::MoveAction;
 }
 
 QStringList ModsModel::mimeTypes() const
 {
-	QStringList types;
-	types << "text/uri-list";
-	return types;
+    QStringList types;
+    types << "text/uri-list";
+    return types;
 }
 
 bool ModsModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int, int, const QModelIndex&)
 {
-	if (action == Qt::IgnoreAction)
-	{
-		return true;
-	}
-
-	// check if the action is supported
-	if (!data || !(action & supportedDropActions()))
-	{
-		return false;
-	}
-
-	// files dropped from outside?
-	if (data->hasUrls())
-	{
-		bool was_watching = is_watching;
-		if (was_watching)
-		{
-			stopWatching();
-		}
-		auto urls = data->urls();
-		for (auto url : urls)
-		{
-			// only local files may be dropped...
-			if (!url.isLocalFile())
-			{
-				continue;
-			}
-			// TODO: implement not only copy, but also move
-			// FIXME: handle errors here
-			installMod(url.toLocalFile());
-		}
-		if (was_watching)
-		{
-			startWatching();
-		}
-		return true;
-	}
-	return false;
+    if (action == Qt::IgnoreAction)
+    {
+        return true;
+    }
+
+    // check if the action is supported
+    if (!data || !(action & supportedDropActions()))
+    {
+        return false;
+    }
+
+    // files dropped from outside?
+    if (data->hasUrls())
+    {
+        bool was_watching = is_watching;
+        if (was_watching)
+        {
+            stopWatching();
+        }
+        auto urls = data->urls();
+        for (auto url : urls)
+        {
+            // only local files may be dropped...
+            if (!url.isLocalFile())
+            {
+                continue;
+            }
+            // TODO: implement not only copy, but also move
+            // FIXME: handle errors here
+            installMod(url.toLocalFile());
+        }
+        if (was_watching)
+        {
+            startWatching();
+        }
+        return true;
+    }
+    return false;
 }
diff --git a/api/logic/minecraft/ModsModel.h b/api/logic/minecraft/ModsModel.h
index 3c8f66fd..b8980ac4 100644
--- a/api/logic/minecraft/ModsModel.h
+++ b/api/logic/minecraft/ModsModel.h
@@ -34,90 +34,90 @@ class QFileSystemWatcher;
  */
 class MULTIMC_LOGIC_EXPORT ModsModel : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum Columns
-	{
-		ActiveColumn = 0,
-		NameColumn,
-		DateColumn,
-		VersionColumn,
+    enum Columns
+    {
+        ActiveColumn = 0,
+        NameColumn,
+        DateColumn,
+        VersionColumn,
         LocationColumn,
-		NUM_COLUMNS
-	};
-	ModsModel(const QString &mainDir, const QString &coreDir, const QString &cacheFile);
-
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-	virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
-	Qt::DropActions supportedDropActions() const override;
-
-	/// flags, mostly to support drag&drop
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
-	QStringList mimeTypes() const override;
-	bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
-
-	virtual int rowCount(const QModelIndex &) const override
-	{
-		return size();
-	}
-	;
-	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
-	virtual int columnCount(const QModelIndex &parent) const override;
-
-	size_t size() const
-	{
-		return mods.size();
-	}
-	;
-	bool empty() const
-	{
-		return size() == 0;
-	}
-	Mod &operator[](size_t index)
-	{
-		return mods[index];
-	}
-
-	/// Reloads the mod list and returns true if the list changed.
-	virtual bool update();
-
-	/**
-	 * Adds the given mod to the list at the given index - if the list supports custom ordering
-	 */
-	bool installMod(const QString& filename);
-
-	/// Deletes all the selected mods
-	virtual bool deleteMods(const QModelIndexList &indexes);
-
-	/// Enable or disable listed mods
-	virtual bool enableMods(const QModelIndexList &indexes, bool enable = true);
-
-	void startWatching();
-	void stopWatching();
-
-	virtual bool isValid();
-
-	QDir dir()
-	{
-		return m_mainDir;
-	}
-
-	const QList<Mod> & allMods()
-	{
-		return mods;
-	}
+        NUM_COLUMNS
+    };
+    ModsModel(const QString &mainDir, const QString &coreDir, const QString &cacheFile);
+
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+    Qt::DropActions supportedDropActions() const override;
+
+    /// flags, mostly to support drag&drop
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
+    QStringList mimeTypes() const override;
+    bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
+
+    virtual int rowCount(const QModelIndex &) const override
+    {
+        return size();
+    }
+    ;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+    virtual int columnCount(const QModelIndex &parent) const override;
+
+    size_t size() const
+    {
+        return mods.size();
+    }
+    ;
+    bool empty() const
+    {
+        return size() == 0;
+    }
+    Mod &operator[](size_t index)
+    {
+        return mods[index];
+    }
+
+    /// Reloads the mod list and returns true if the list changed.
+    virtual bool update();
+
+    /**
+     * Adds the given mod to the list at the given index - if the list supports custom ordering
+     */
+    bool installMod(const QString& filename);
+
+    /// Deletes all the selected mods
+    virtual bool deleteMods(const QModelIndexList &indexes);
+
+    /// Enable or disable listed mods
+    virtual bool enableMods(const QModelIndexList &indexes, bool enable = true);
+
+    void startWatching();
+    void stopWatching();
+
+    virtual bool isValid();
+
+    QDir dir()
+    {
+        return m_mainDir;
+    }
+
+    const QList<Mod> & allMods()
+    {
+        return mods;
+    }
 
 private
 slots:
-	void directoryChanged(QString path);
+    void directoryChanged(QString path);
 
 signals:
-	void changed();
+    void changed();
 
 protected:
-	QFileSystemWatcher *m_watcher;
-	bool is_watching = false;
-	QDir m_mainDir;
+    QFileSystemWatcher *m_watcher;
+    bool is_watching = false;
+    QDir m_mainDir;
     QDir m_coreDir;
-	QList<Mod> mods;
+    QList<Mod> mods;
 };
diff --git a/api/logic/minecraft/MojangDownloadInfo.h b/api/logic/minecraft/MojangDownloadInfo.h
index 7399a56b..88f87287 100644
--- a/api/logic/minecraft/MojangDownloadInfo.h
+++ b/api/logic/minecraft/MojangDownloadInfo.h
@@ -5,78 +5,78 @@
 
 struct MojangDownloadInfo
 {
-	// types
-	typedef std::shared_ptr<MojangDownloadInfo> Ptr;
+    // types
+    typedef std::shared_ptr<MojangDownloadInfo> Ptr;
 
-	// data
-	/// Local filesystem path. WARNING: not used, only here so we can pass through mojang files unmolested!
-	QString path;
-	/// absolute URL of this file
-	QString url;
-	/// sha-1 checksum of the file
-	QString sha1;
-	/// size of the file in bytes
-	int size;
+    // data
+    /// Local filesystem path. WARNING: not used, only here so we can pass through mojang files unmolested!
+    QString path;
+    /// absolute URL of this file
+    QString url;
+    /// sha-1 checksum of the file
+    QString sha1;
+    /// size of the file in bytes
+    int size;
 };
 
 
 
 struct MojangLibraryDownloadInfo
 {
-	MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {};
-	MojangLibraryDownloadInfo() {};
+    MojangLibraryDownloadInfo(MojangDownloadInfo::Ptr artifact): artifact(artifact) {};
+    MojangLibraryDownloadInfo() {};
 
-	// types
-	typedef std::shared_ptr<MojangLibraryDownloadInfo> Ptr;
+    // types
+    typedef std::shared_ptr<MojangLibraryDownloadInfo> Ptr;
 
-	// methods
-	MojangDownloadInfo *getDownloadInfo(QString classifier)
-	{
-		if (classifier.isNull())
-		{
-			return artifact.get();
-		}
-		
-		return classifiers[classifier].get();
-	}
+    // methods
+    MojangDownloadInfo *getDownloadInfo(QString classifier)
+    {
+        if (classifier.isNull())
+        {
+            return artifact.get();
+        }
+        
+        return classifiers[classifier].get();
+    }
 
-	// data
-	MojangDownloadInfo::Ptr artifact;
-	QMap<QString, MojangDownloadInfo::Ptr> classifiers;
+    // data
+    MojangDownloadInfo::Ptr artifact;
+    QMap<QString, MojangDownloadInfo::Ptr> classifiers;
 };
 
 
 
 struct MojangAssetIndexInfo : public MojangDownloadInfo
 {
-	// types
-	typedef std::shared_ptr<MojangAssetIndexInfo> Ptr;
+    // types
+    typedef std::shared_ptr<MojangAssetIndexInfo> Ptr;
 
-	// methods
-	MojangAssetIndexInfo()
-	{
-	}
+    // methods
+    MojangAssetIndexInfo()
+    {
+    }
 
-	MojangAssetIndexInfo(QString id)
-	{
-		this->id = id;
-		// HACK: ignore assets from other version files than Minecraft
-		// workaround for stupid assets issue caused by amazon:
-		// https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
-		if(id == "legacy")
-		{
-			url = "https://launchermeta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json";
-		}
-		// HACK
-		else
-		{
-			url = "https://s3.amazonaws.com/Minecraft.Download/indexes/" + id + ".json";
-		}
-		known = false;
-	}
+    MojangAssetIndexInfo(QString id)
+    {
+        this->id = id;
+        // HACK: ignore assets from other version files than Minecraft
+        // workaround for stupid assets issue caused by amazon:
+        // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
+        if(id == "legacy")
+        {
+            url = "https://launchermeta.mojang.com/mc/assets/legacy/c0fd82e8ce9fbc93119e40d96d5a4e62cfa3f729/legacy.json";
+        }
+        // HACK
+        else
+        {
+            url = "https://s3.amazonaws.com/Minecraft.Download/indexes/" + id + ".json";
+        }
+        known = false;
+    }
 
-	// data
-	int totalSize;
-	QString id;
-	bool known = true;
+    // data
+    int totalSize;
+    QString id;
+    bool known = true;
 };
diff --git a/api/logic/minecraft/MojangVersionFormat.cpp b/api/logic/minecraft/MojangVersionFormat.cpp
index a0aa2894..33d3c54c 100644
--- a/api/logic/minecraft/MojangVersionFormat.cpp
+++ b/api/logic/minecraft/MojangVersionFormat.cpp
@@ -19,361 +19,361 @@ namespace Bits
 {
 static void readString(const QJsonObject &root, const QString &key, QString &variable)
 {
-	if (root.contains(key))
-	{
-		variable = requireString(root.value(key));
-	}
+    if (root.contains(key))
+    {
+        variable = requireString(root.value(key));
+    }
 }
 
 static void readDownloadInfo(MojangDownloadInfo::Ptr out, const QJsonObject &obj)
 {
-	// optional, not used
-	readString(obj, "path", out->path);
-	// required!
-	out->sha1 = requireString(obj, "sha1");
-	out->url = requireString(obj, "url");
-	out->size = requireInteger(obj, "size");
+    // optional, not used
+    readString(obj, "path", out->path);
+    // required!
+    out->sha1 = requireString(obj, "sha1");
+    out->url = requireString(obj, "url");
+    out->size = requireInteger(obj, "size");
 }
 
 static void readAssetIndex(MojangAssetIndexInfo::Ptr out, const QJsonObject &obj)
 {
-	out->totalSize = requireInteger(obj, "totalSize");
-	out->id = requireString(obj, "id");
-	// out->known = true;
+    out->totalSize = requireInteger(obj, "totalSize");
+    out->id = requireString(obj, "id");
+    // out->known = true;
 }
 }
 
 MojangDownloadInfo::Ptr downloadInfoFromJson(const QJsonObject &obj)
 {
-	auto out = std::make_shared<MojangDownloadInfo>();
-	Bits::readDownloadInfo(out, obj);
-	return out;
+    auto out = std::make_shared<MojangDownloadInfo>();
+    Bits::readDownloadInfo(out, obj);
+    return out;
 }
 
 MojangAssetIndexInfo::Ptr assetIndexFromJson(const QJsonObject &obj)
 {
-	auto out = std::make_shared<MojangAssetIndexInfo>();
-	Bits::readDownloadInfo(out, obj);
-	Bits::readAssetIndex(out, obj);
-	return out;
+    auto out = std::make_shared<MojangAssetIndexInfo>();
+    Bits::readDownloadInfo(out, obj);
+    Bits::readAssetIndex(out, obj);
+    return out;
 }
 
 QJsonObject downloadInfoToJson(MojangDownloadInfo::Ptr info)
 {
-	QJsonObject out;
-	if(!info->path.isNull())
-	{
-		out.insert("path", info->path);
-	}
-	out.insert("sha1", info->sha1);
-	out.insert("size", info->size);
-	out.insert("url", info->url);
-	return out;
+    QJsonObject out;
+    if(!info->path.isNull())
+    {
+        out.insert("path", info->path);
+    }
+    out.insert("sha1", info->sha1);
+    out.insert("size", info->size);
+    out.insert("url", info->url);
+    return out;
 }
 
 MojangLibraryDownloadInfo::Ptr libDownloadInfoFromJson(const QJsonObject &libObj)
 {
-	auto out = std::make_shared<MojangLibraryDownloadInfo>();
-	auto dlObj = requireObject(libObj.value("downloads"));
-	if(dlObj.contains("artifact"))
-	{
-		out->artifact = downloadInfoFromJson(requireObject(dlObj, "artifact"));
-	}
-	if(dlObj.contains("classifiers"))
-	{
-		auto classifiersObj = requireObject(dlObj, "classifiers");
-		for(auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++)
-		{
-			auto classifier = iter.key();
-			auto classifierObj = requireObject(iter.value());
-			out->classifiers[classifier] = downloadInfoFromJson(classifierObj);
-		}
-	}
-	return out;
+    auto out = std::make_shared<MojangLibraryDownloadInfo>();
+    auto dlObj = requireObject(libObj.value("downloads"));
+    if(dlObj.contains("artifact"))
+    {
+        out->artifact = downloadInfoFromJson(requireObject(dlObj, "artifact"));
+    }
+    if(dlObj.contains("classifiers"))
+    {
+        auto classifiersObj = requireObject(dlObj, "classifiers");
+        for(auto iter = classifiersObj.begin(); iter != classifiersObj.end(); iter++)
+        {
+            auto classifier = iter.key();
+            auto classifierObj = requireObject(iter.value());
+            out->classifiers[classifier] = downloadInfoFromJson(classifierObj);
+        }
+    }
+    return out;
 }
 
 QJsonObject libDownloadInfoToJson(MojangLibraryDownloadInfo::Ptr libinfo)
 {
-	QJsonObject out;
-	if(libinfo->artifact)
-	{
-		out.insert("artifact", downloadInfoToJson(libinfo->artifact));
-	}
-	if(libinfo->classifiers.size())
-	{
-		QJsonObject classifiersOut;
-		for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
-		{
-			classifiersOut.insert(iter.key(), downloadInfoToJson(iter.value()));
-		}
-		out.insert("classifiers", classifiersOut);
-	}
-	return out;
+    QJsonObject out;
+    if(libinfo->artifact)
+    {
+        out.insert("artifact", downloadInfoToJson(libinfo->artifact));
+    }
+    if(libinfo->classifiers.size())
+    {
+        QJsonObject classifiersOut;
+        for(auto iter = libinfo->classifiers.begin(); iter != libinfo->classifiers.end(); iter++)
+        {
+            classifiersOut.insert(iter.key(), downloadInfoToJson(iter.value()));
+        }
+        out.insert("classifiers", classifiersOut);
+    }
+    return out;
 }
 
 QJsonObject assetIndexToJson(MojangAssetIndexInfo::Ptr info)
 {
-	QJsonObject out;
-	if(!info->path.isNull())
-	{
-		out.insert("path", info->path);
-	}
-	out.insert("sha1", info->sha1);
-	out.insert("size", info->size);
-	out.insert("url", info->url);
-	out.insert("totalSize", info->totalSize);
-	out.insert("id", info->id);
-	return out;
+    QJsonObject out;
+    if(!info->path.isNull())
+    {
+        out.insert("path", info->path);
+    }
+    out.insert("sha1", info->sha1);
+    out.insert("size", info->size);
+    out.insert("url", info->url);
+    out.insert("totalSize", info->totalSize);
+    out.insert("id", info->id);
+    return out;
 }
 
 void MojangVersionFormat::readVersionProperties(const QJsonObject &in, VersionFile *out)
 {
-	Bits::readString(in, "id", out->minecraftVersion);
-	Bits::readString(in, "mainClass", out->mainClass);
-	Bits::readString(in, "minecraftArguments", out->minecraftArguments);
-	if(out->minecraftArguments.isEmpty())
-	{
-		QString processArguments;
-		Bits::readString(in, "processArguments", processArguments);
-		QString toCompare = processArguments.toLower();
-		if (toCompare == "legacy")
-		{
-			out->minecraftArguments = " ${auth_player_name} ${auth_session}";
-		}
-		else if (toCompare == "username_session")
-		{
-			out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
-		}
-		else if (toCompare == "username_session_version")
-		{
-			out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
-		}
-		else if (!toCompare.isEmpty())
-		{
-			out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
-		}
-	}
-	Bits::readString(in, "type", out->type);
+    Bits::readString(in, "id", out->minecraftVersion);
+    Bits::readString(in, "mainClass", out->mainClass);
+    Bits::readString(in, "minecraftArguments", out->minecraftArguments);
+    if(out->minecraftArguments.isEmpty())
+    {
+        QString processArguments;
+        Bits::readString(in, "processArguments", processArguments);
+        QString toCompare = processArguments.toLower();
+        if (toCompare == "legacy")
+        {
+            out->minecraftArguments = " ${auth_player_name} ${auth_session}";
+        }
+        else if (toCompare == "username_session")
+        {
+            out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
+        }
+        else if (toCompare == "username_session_version")
+        {
+            out->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
+        }
+        else if (!toCompare.isEmpty())
+        {
+            out->addProblem(ProblemSeverity::Error, QObject::tr("processArguments is set to unknown value '%1'").arg(processArguments));
+        }
+    }
+    Bits::readString(in, "type", out->type);
 
-	Bits::readString(in, "assets", out->assets);
-	if(in.contains("assetIndex"))
-	{
-		out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex"));
-	}
-	else if (!out->assets.isNull())
-	{
-		out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets);
-	}
+    Bits::readString(in, "assets", out->assets);
+    if(in.contains("assetIndex"))
+    {
+        out->mojangAssetIndex = assetIndexFromJson(requireObject(in, "assetIndex"));
+    }
+    else if (!out->assets.isNull())
+    {
+        out->mojangAssetIndex = std::make_shared<MojangAssetIndexInfo>(out->assets);
+    }
 
-	out->releaseTime = timeFromS3Time(in.value("releaseTime").toString(""));
-	out->updateTime = timeFromS3Time(in.value("time").toString(""));
+    out->releaseTime = timeFromS3Time(in.value("releaseTime").toString(""));
+    out->updateTime = timeFromS3Time(in.value("time").toString(""));
 
-	if (in.contains("minimumLauncherVersion"))
-	{
-		out->minimumLauncherVersion = requireInteger(in.value("minimumLauncherVersion"));
-		if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
-		{
-			out->addProblem(
-				ProblemSeverity::Warning,
-				QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!")
-					.arg(out->minimumLauncherVersion)
-					.arg(CURRENT_MINIMUM_LAUNCHER_VERSION));
-		}
-	}
-	if(in.contains("downloads"))
-	{
-		auto downloadsObj = requireObject(in, "downloads");
-		for(auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++)
-		{
-			auto classifier = iter.key();
-			auto classifierObj = requireObject(iter.value());
-			out->mojangDownloads[classifier] = downloadInfoFromJson(classifierObj);
-		}
-	}
+    if (in.contains("minimumLauncherVersion"))
+    {
+        out->minimumLauncherVersion = requireInteger(in.value("minimumLauncherVersion"));
+        if (out->minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
+        {
+            out->addProblem(
+                ProblemSeverity::Warning,
+                QObject::tr("The 'minimumLauncherVersion' value of this version (%1) is higher than supported by MultiMC (%2). It might not work properly!")
+                    .arg(out->minimumLauncherVersion)
+                    .arg(CURRENT_MINIMUM_LAUNCHER_VERSION));
+        }
+    }
+    if(in.contains("downloads"))
+    {
+        auto downloadsObj = requireObject(in, "downloads");
+        for(auto iter = downloadsObj.begin(); iter != downloadsObj.end(); iter++)
+        {
+            auto classifier = iter.key();
+            auto classifierObj = requireObject(iter.value());
+            out->mojangDownloads[classifier] = downloadInfoFromJson(classifierObj);
+        }
+    }
 }
 
 VersionFilePtr MojangVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename)
 {
-	VersionFilePtr out(new VersionFile());
-	if (doc.isEmpty() || doc.isNull())
-	{
-		throw JSONValidationError(filename + " is empty or null");
-	}
-	if (!doc.isObject())
-	{
-		throw JSONValidationError(filename + " is not an object");
-	}
+    VersionFilePtr out(new VersionFile());
+    if (doc.isEmpty() || doc.isNull())
+    {
+        throw JSONValidationError(filename + " is empty or null");
+    }
+    if (!doc.isObject())
+    {
+        throw JSONValidationError(filename + " is not an object");
+    }
 
-	QJsonObject root = doc.object();
+    QJsonObject root = doc.object();
 
-	readVersionProperties(root, out.get());
+    readVersionProperties(root, out.get());
 
-	out->name = "Minecraft";
-	out->uid = "net.minecraft";
-	out->version = out->minecraftVersion;
-	// out->filename = filename;
+    out->name = "Minecraft";
+    out->uid = "net.minecraft";
+    out->version = out->minecraftVersion;
+    // out->filename = filename;
 
 
-	if (root.contains("libraries"))
-	{
-		for (auto libVal : requireArray(root.value("libraries")))
-		{
-			auto libObj = requireObject(libVal);
+    if (root.contains("libraries"))
+    {
+        for (auto libVal : requireArray(root.value("libraries")))
+        {
+            auto libObj = requireObject(libVal);
 
-			auto lib = MojangVersionFormat::libraryFromJson(libObj, filename);
-			out->libraries.append(lib);
-		}
-	}
-	return out;
+            auto lib = MojangVersionFormat::libraryFromJson(libObj, filename);
+            out->libraries.append(lib);
+        }
+    }
+    return out;
 }
 
 void MojangVersionFormat::writeVersionProperties(const VersionFile* in, QJsonObject& out)
 {
-	writeString(out, "id", in->minecraftVersion);
-	writeString(out, "mainClass", in->mainClass);
-	writeString(out, "minecraftArguments", in->minecraftArguments);
-	writeString(out, "type", in->type);
-	if(!in->releaseTime.isNull())
-	{
-		writeString(out, "releaseTime", timeToS3Time(in->releaseTime));
-	}
-	if(!in->updateTime.isNull())
-	{
-		writeString(out, "time", timeToS3Time(in->updateTime));
-	}
-	if(in->minimumLauncherVersion != -1)
-	{
-		out.insert("minimumLauncherVersion", in->minimumLauncherVersion);
-	}
-	writeString(out, "assets", in->assets);
-	if(in->mojangAssetIndex && in->mojangAssetIndex->known)
-	{
-		out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
-	}
-	if(in->mojangDownloads.size())
-	{
-		QJsonObject downloadsOut;
-		for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
-		{
-			downloadsOut.insert(iter.key(), downloadInfoToJson(iter.value()));
-		}
-		out.insert("downloads", downloadsOut);
-	}
+    writeString(out, "id", in->minecraftVersion);
+    writeString(out, "mainClass", in->mainClass);
+    writeString(out, "minecraftArguments", in->minecraftArguments);
+    writeString(out, "type", in->type);
+    if(!in->releaseTime.isNull())
+    {
+        writeString(out, "releaseTime", timeToS3Time(in->releaseTime));
+    }
+    if(!in->updateTime.isNull())
+    {
+        writeString(out, "time", timeToS3Time(in->updateTime));
+    }
+    if(in->minimumLauncherVersion != -1)
+    {
+        out.insert("minimumLauncherVersion", in->minimumLauncherVersion);
+    }
+    writeString(out, "assets", in->assets);
+    if(in->mojangAssetIndex && in->mojangAssetIndex->known)
+    {
+        out.insert("assetIndex", assetIndexToJson(in->mojangAssetIndex));
+    }
+    if(in->mojangDownloads.size())
+    {
+        QJsonObject downloadsOut;
+        for(auto iter = in->mojangDownloads.begin(); iter != in->mojangDownloads.end(); iter++)
+        {
+            downloadsOut.insert(iter.key(), downloadInfoToJson(iter.value()));
+        }
+        out.insert("downloads", downloadsOut);
+    }
 }
 
 QJsonDocument MojangVersionFormat::versionFileToJson(const VersionFilePtr &patch)
 {
-	QJsonObject root;
-	writeVersionProperties(patch.get(), root);
-	if (!patch->libraries.isEmpty())
-	{
-		QJsonArray array;
-		for (auto value: patch->libraries)
-		{
-			array.append(MojangVersionFormat::libraryToJson(value.get()));
-		}
-		root.insert("libraries", array);
-	}
+    QJsonObject root;
+    writeVersionProperties(patch.get(), root);
+    if (!patch->libraries.isEmpty())
+    {
+        QJsonArray array;
+        for (auto value: patch->libraries)
+        {
+            array.append(MojangVersionFormat::libraryToJson(value.get()));
+        }
+        root.insert("libraries", array);
+    }
 
-	// write the contents to a json document.
-	{
-		QJsonDocument out;
-		out.setObject(root);
-		return out;
-	}
+    // write the contents to a json document.
+    {
+        QJsonDocument out;
+        out.setObject(root);
+        return out;
+    }
 }
 
 LibraryPtr MojangVersionFormat::libraryFromJson(const QJsonObject &libObj, const QString &filename)
 {
-	LibraryPtr out(new Library());
-	if (!libObj.contains("name"))
-	{
-		throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field");
-	}
-	out->m_name = libObj.value("name").toString();
+    LibraryPtr out(new Library());
+    if (!libObj.contains("name"))
+    {
+        throw JSONValidationError(filename + "contains a library that doesn't have a 'name' field");
+    }
+    out->m_name = libObj.value("name").toString();
 
-	Bits::readString(libObj, "url", out->m_repositoryURL);
-	if (libObj.contains("extract"))
-	{
-		out->m_hasExcludes = true;
-		auto extractObj = requireObject(libObj.value("extract"));
-		for (auto excludeVal : requireArray(extractObj.value("exclude")))
-		{
-			out->m_extractExcludes.append(requireString(excludeVal));
-		}
-	}
-	if (libObj.contains("natives"))
-	{
-		QJsonObject nativesObj = requireObject(libObj.value("natives"));
-		for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
-		{
-			if (!it.value().isString())
-			{
-				qWarning() << filename << "contains an invalid native (skipping)";
-			}
-			OpSys opSys = OpSys_fromString(it.key());
-			if (opSys != Os_Other)
-			{
-				out->m_nativeClassifiers[opSys] = it.value().toString();
-			}
-		}
-	}
-	if (libObj.contains("rules"))
-	{
-		out->applyRules = true;
-		out->m_rules = rulesFromJsonV4(libObj);
-	}
-	if (libObj.contains("downloads"))
-	{
-		out->m_mojangDownloads = libDownloadInfoFromJson(libObj);
-	}
-	return out;
+    Bits::readString(libObj, "url", out->m_repositoryURL);
+    if (libObj.contains("extract"))
+    {
+        out->m_hasExcludes = true;
+        auto extractObj = requireObject(libObj.value("extract"));
+        for (auto excludeVal : requireArray(extractObj.value("exclude")))
+        {
+            out->m_extractExcludes.append(requireString(excludeVal));
+        }
+    }
+    if (libObj.contains("natives"))
+    {
+        QJsonObject nativesObj = requireObject(libObj.value("natives"));
+        for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
+        {
+            if (!it.value().isString())
+            {
+                qWarning() << filename << "contains an invalid native (skipping)";
+            }
+            OpSys opSys = OpSys_fromString(it.key());
+            if (opSys != Os_Other)
+            {
+                out->m_nativeClassifiers[opSys] = it.value().toString();
+            }
+        }
+    }
+    if (libObj.contains("rules"))
+    {
+        out->applyRules = true;
+        out->m_rules = rulesFromJsonV4(libObj);
+    }
+    if (libObj.contains("downloads"))
+    {
+        out->m_mojangDownloads = libDownloadInfoFromJson(libObj);
+    }
+    return out;
 }
 
 QJsonObject MojangVersionFormat::libraryToJson(Library *library)
 {
-	QJsonObject libRoot;
-	libRoot.insert("name", (QString)library->m_name);
-	if (!library->m_repositoryURL.isEmpty())
-	{
-		libRoot.insert("url", library->m_repositoryURL);
-	}
-	if (library->isNative())
-	{
-		QJsonObject nativeList;
-		auto iter = library->m_nativeClassifiers.begin();
-		while (iter != library->m_nativeClassifiers.end())
-		{
-			nativeList.insert(OpSys_toString(iter.key()), iter.value());
-			iter++;
-		}
-		libRoot.insert("natives", nativeList);
-		if (library->m_extractExcludes.size())
-		{
-			QJsonArray excludes;
-			QJsonObject extract;
-			for (auto exclude : library->m_extractExcludes)
-			{
-				excludes.append(exclude);
-			}
-			extract.insert("exclude", excludes);
-			libRoot.insert("extract", extract);
-		}
-	}
-	if (library->m_rules.size())
-	{
-		QJsonArray allRules;
-		for (auto &rule : library->m_rules)
-		{
-			QJsonObject ruleObj = rule->toJson();
-			allRules.append(ruleObj);
-		}
-		libRoot.insert("rules", allRules);
-	}
-	if(library->m_mojangDownloads)
-	{
-		auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads);
-		libRoot.insert("downloads", downloadsObj);
-	}
-	return libRoot;
+    QJsonObject libRoot;
+    libRoot.insert("name", (QString)library->m_name);
+    if (!library->m_repositoryURL.isEmpty())
+    {
+        libRoot.insert("url", library->m_repositoryURL);
+    }
+    if (library->isNative())
+    {
+        QJsonObject nativeList;
+        auto iter = library->m_nativeClassifiers.begin();
+        while (iter != library->m_nativeClassifiers.end())
+        {
+            nativeList.insert(OpSys_toString(iter.key()), iter.value());
+            iter++;
+        }
+        libRoot.insert("natives", nativeList);
+        if (library->m_extractExcludes.size())
+        {
+            QJsonArray excludes;
+            QJsonObject extract;
+            for (auto exclude : library->m_extractExcludes)
+            {
+                excludes.append(exclude);
+            }
+            extract.insert("exclude", excludes);
+            libRoot.insert("extract", extract);
+        }
+    }
+    if (library->m_rules.size())
+    {
+        QJsonArray allRules;
+        for (auto &rule : library->m_rules)
+        {
+            QJsonObject ruleObj = rule->toJson();
+            allRules.append(ruleObj);
+        }
+        libRoot.insert("rules", allRules);
+    }
+    if(library->m_mojangDownloads)
+    {
+        auto downloadsObj = libDownloadInfoToJson(library->m_mojangDownloads);
+        libRoot.insert("downloads", downloadsObj);
+    }
+    return libRoot;
 }
diff --git a/api/logic/minecraft/MojangVersionFormat.h b/api/logic/minecraft/MojangVersionFormat.h
index 4e141088..76c529e9 100644
--- a/api/logic/minecraft/MojangVersionFormat.h
+++ b/api/logic/minecraft/MojangVersionFormat.h
@@ -10,16 +10,16 @@ class MULTIMC_LOGIC_EXPORT MojangVersionFormat
 {
 friend class OneSixVersionFormat;
 protected:
-	// does not include libraries
-	static void readVersionProperties(const QJsonObject& in, VersionFile* out);
-	// does not include libraries
-	static void writeVersionProperties(const VersionFile* in, QJsonObject& out);
+    // does not include libraries
+    static void readVersionProperties(const QJsonObject& in, VersionFile* out);
+    // does not include libraries
+    static void writeVersionProperties(const VersionFile* in, QJsonObject& out);
 public:
-	// version files / profile patches
-	static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename);
-	static QJsonDocument versionFileToJson(const VersionFilePtr &patch);
+    // version files / profile patches
+    static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename);
+    static QJsonDocument versionFileToJson(const VersionFilePtr &patch);
 
-	// libraries
-	static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
-	static QJsonObject libraryToJson(Library *library);
+    // libraries
+    static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
+    static QJsonObject libraryToJson(Library *library);
 };
diff --git a/api/logic/minecraft/MojangVersionFormat_test.cpp b/api/logic/minecraft/MojangVersionFormat_test.cpp
index 9c8482ce..9d095340 100644
--- a/api/logic/minecraft/MojangVersionFormat_test.cpp
+++ b/api/logic/minecraft/MojangVersionFormat_test.cpp
@@ -6,47 +6,47 @@
 
 class MojangVersionFormatTest : public QObject
 {
-	Q_OBJECT
-
-	static QJsonDocument readJson(const char *file)
-	{
-		auto path = QFINDTESTDATA(file);
-		QFile jsonFile(path);
-		jsonFile.open(QIODevice::ReadOnly);
-		auto data = jsonFile.readAll();
-		jsonFile.close();
-		return QJsonDocument::fromJson(data);
-	}
-	static void writeJson(const char *file, QJsonDocument doc)
-	{
-		QFile jsonFile(file);
-		jsonFile.open(QIODevice::WriteOnly | QIODevice::Text);
-		auto data = doc.toJson(QJsonDocument::Indented);
-		qDebug() << QString::fromUtf8(data);
-		jsonFile.write(data);
-		jsonFile.close();
-	}
+    Q_OBJECT
+
+    static QJsonDocument readJson(const char *file)
+    {
+        auto path = QFINDTESTDATA(file);
+        QFile jsonFile(path);
+        jsonFile.open(QIODevice::ReadOnly);
+        auto data = jsonFile.readAll();
+        jsonFile.close();
+        return QJsonDocument::fromJson(data);
+    }
+    static void writeJson(const char *file, QJsonDocument doc)
+    {
+        QFile jsonFile(file);
+        jsonFile.open(QIODevice::WriteOnly | QIODevice::Text);
+        auto data = doc.toJson(QJsonDocument::Indented);
+        qDebug() << QString::fromUtf8(data);
+        jsonFile.write(data);
+        jsonFile.close();
+    }
 
 private
 slots:
-	void test_Through_Simple()
-	{
-		QJsonDocument doc = readJson("data/1.9-simple.json");
-		auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9-simple.json");
-		auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
-		writeJson("1.9-simple-passthorugh.json", doc2);
-
-		QCOMPARE(doc.toJson(), doc2.toJson());
-	}
-
-	void test_Through()
-	{
-		QJsonDocument doc = readJson("data/1.9.json");
-		auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9.json");
-		auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
-		writeJson("1.9-passthorugh.json", doc2);
-		QCOMPARE(doc.toJson(), doc2.toJson());
-	}
+    void test_Through_Simple()
+    {
+        QJsonDocument doc = readJson("data/1.9-simple.json");
+        auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9-simple.json");
+        auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
+        writeJson("1.9-simple-passthorugh.json", doc2);
+
+        QCOMPARE(doc.toJson(), doc2.toJson());
+    }
+
+    void test_Through()
+    {
+        QJsonDocument doc = readJson("data/1.9.json");
+        auto vfile = MojangVersionFormat::versionFileFromJson(doc, "1.9.json");
+        auto doc2 = MojangVersionFormat::versionFileToJson(vfile);
+        writeJson("1.9-passthorugh.json", doc2);
+        QCOMPARE(doc.toJson(), doc2.toJson());
+    }
 };
 
 QTEST_GUILESS_MAIN(MojangVersionFormatTest)
diff --git a/api/logic/minecraft/OneSixVersionFormat.cpp b/api/logic/minecraft/OneSixVersionFormat.cpp
index f7ab25b3..6f3b926b 100644
--- a/api/logic/minecraft/OneSixVersionFormat.cpp
+++ b/api/logic/minecraft/OneSixVersionFormat.cpp
@@ -7,366 +7,366 @@ using namespace Json;
 
 static void readString(const QJsonObject &root, const QString &key, QString &variable)
 {
-	if (root.contains(key))
-	{
-		variable = requireString(root.value(key));
-	}
+    if (root.contains(key))
+    {
+        variable = requireString(root.value(key));
+    }
 }
 
 LibraryPtr OneSixVersionFormat::libraryFromJson(const QJsonObject &libObj, const QString &filename)
 {
-	LibraryPtr out = MojangVersionFormat::libraryFromJson(libObj, filename);
-	readString(libObj, "MMC-hint", out->m_hint);
-	readString(libObj, "MMC-absulute_url", out->m_absoluteURL);
-	readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL);
-	readString(libObj, "MMC-filename", out->m_filename);
-	readString(libObj, "MMC-displayname", out->m_displayname);
-	return out;
+    LibraryPtr out = MojangVersionFormat::libraryFromJson(libObj, filename);
+    readString(libObj, "MMC-hint", out->m_hint);
+    readString(libObj, "MMC-absulute_url", out->m_absoluteURL);
+    readString(libObj, "MMC-absoluteUrl", out->m_absoluteURL);
+    readString(libObj, "MMC-filename", out->m_filename);
+    readString(libObj, "MMC-displayname", out->m_displayname);
+    return out;
 }
 
 QJsonObject OneSixVersionFormat::libraryToJson(Library *library)
 {
-	QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
-	if (library->m_absoluteURL.size())
-		libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
-	if (library->m_hint.size())
-		libRoot.insert("MMC-hint", library->m_hint);
-	if (library->m_filename.size())
-		libRoot.insert("MMC-filename", library->m_filename);
-	if (library->m_displayname.size())
-		libRoot.insert("MMC-displayname", library->m_displayname);
-	return libRoot;
+    QJsonObject libRoot = MojangVersionFormat::libraryToJson(library);
+    if (library->m_absoluteURL.size())
+        libRoot.insert("MMC-absoluteUrl", library->m_absoluteURL);
+    if (library->m_hint.size())
+        libRoot.insert("MMC-hint", library->m_hint);
+    if (library->m_filename.size())
+        libRoot.insert("MMC-filename", library->m_filename);
+    if (library->m_displayname.size())
+        libRoot.insert("MMC-displayname", library->m_displayname);
+    return libRoot;
 }
 
 VersionFilePtr OneSixVersionFormat::versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder)
 {
-	VersionFilePtr out(new VersionFile());
-	if (doc.isEmpty() || doc.isNull())
-	{
-		throw JSONValidationError(filename + " is empty or null");
-	}
-	if (!doc.isObject())
-	{
-		throw JSONValidationError(filename + " is not an object");
-	}
-
-	QJsonObject root = doc.object();
-
-	Meta::MetadataVersion formatVersion = Meta::parseFormatVersion(root, false);
-	switch(formatVersion)
-	{
-		case Meta::MetadataVersion::InitialRelease:
-			break;
-		case Meta::MetadataVersion::Invalid:
-			throw JSONValidationError(filename + " does not contain a recognizable version of the metadata format.");
-	}
-
-	if (requireOrder)
-	{
-		if (root.contains("order"))
-		{
-			out->order = requireInteger(root.value("order"));
-		}
-		else
-		{
-			// FIXME: evaluate if we don't want to throw exceptions here instead
-			qCritical() << filename << "doesn't contain an order field";
-		}
-	}
-
-	out->name = root.value("name").toString();
-
-	if(root.contains("uid"))
-	{
-		out->uid = root.value("uid").toString();
-	}
-	else
-	{
-		out->uid = root.value("fileId").toString();
-	}
-
-	out->version = root.value("version").toString();
-
-	MojangVersionFormat::readVersionProperties(root, out.get());
-
-	// added for legacy Minecraft window embedding, TODO: remove
-	readString(root, "appletClass", out->appletClass);
-
-	if (root.contains("+tweakers"))
-	{
-		for (auto tweakerVal : requireArray(root.value("+tweakers")))
-		{
-			out->addTweakers.append(requireString(tweakerVal));
-		}
-	}
-
-	if (root.contains("+traits"))
-	{
-		for (auto tweakerVal : requireArray(root.value("+traits")))
-		{
-			out->traits.insert(requireString(tweakerVal));
-		}
-	}
-
-
-	if (root.contains("jarMods"))
-	{
-		for (auto libVal : requireArray(root.value("jarMods")))
-		{
-			QJsonObject libObj = requireObject(libVal);
-			// parse the jarmod
-			auto lib = OneSixVersionFormat::jarModFromJson(libObj, filename);
-			// and add to jar mods
-			out->jarMods.append(lib);
-		}
-	}
-	else if (root.contains("+jarMods")) // DEPRECATED: old style '+jarMods' are only here for backwards compatibility
-	{
-		for (auto libVal : requireArray(root.value("+jarMods")))
-		{
-			QJsonObject libObj = requireObject(libVal);
-			// parse the jarmod
-			auto lib = OneSixVersionFormat::plusJarModFromJson(libObj, filename, out->name);
-			// and add to jar mods
-			out->jarMods.append(lib);
-		}
-	}
-
-	if (root.contains("mods"))
-	{
-		for (auto libVal : requireArray(root.value("mods")))
-		{
-			QJsonObject libObj = requireObject(libVal);
-			// parse the jarmod
-			auto lib = OneSixVersionFormat::modFromJson(libObj, filename);
-			// and add to jar mods
-			out->mods.append(lib);
-		}
-	}
-
-	auto readLibs = [&](const char * which)
-	{
-		for (auto libVal : requireArray(root.value(which)))
-		{
-			QJsonObject libObj = requireObject(libVal);
-			// parse the library
-			auto lib = libraryFromJson(libObj, filename);
-			out->libraries.append(lib);
-		}
-	};
-	bool hasPlusLibs = root.contains("+libraries");
-	bool hasLibs = root.contains("libraries");
-	if (hasPlusLibs && hasLibs)
-	{
-		out->addProblem(ProblemSeverity::Warning,
-						QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
-		readLibs("libraries");
-		readLibs("+libraries");
-	}
-	else if (hasLibs)
-	{
-		readLibs("libraries");
-	}
-	else if(hasPlusLibs)
-	{
-		readLibs("+libraries");
-	}
-
-	// if we have mainJar, just use it
-	if(root.contains("mainJar"))
-	{
-		QJsonObject libObj = requireObject(root, "mainJar");
-		out->mainJar = libraryFromJson(libObj, filename);
-	}
-	// else reconstruct it from downloads and id ... if that's available
-	else if(!out->minecraftVersion.isEmpty())
-	{
-		auto lib = std::make_shared<Library>();
-		lib->setRawName(GradleSpecifier(QString("com.mojang:minecraft:%1:client").arg(out->minecraftVersion)));
-		// we have a reliable client download, use it.
-		if(out->mojangDownloads.contains("client"))
-		{
-			auto LibDLInfo = std::make_shared<MojangLibraryDownloadInfo>();
-			LibDLInfo->artifact = out->mojangDownloads["client"];
-			lib->setMojangDownloadInfo(LibDLInfo);
-		}
-		// we got nothing... guess based on ancient hardcoded Mojang behaviour
-		// FIXME: this will eventually break...
-		else
-		{
-			lib->setAbsoluteUrl(URLConstants::getLegacyJarUrl(out->minecraftVersion));
-		}
-		out->mainJar = lib;
-	}
-
-	if (root.contains("requires"))
-	{
-		Meta::parseRequires(root, &out->requires);
-	}
-	QString dependsOnMinecraftVersion = root.value("mcVersion").toString();
-	if(!dependsOnMinecraftVersion.isEmpty())
-	{
-		Meta::Require mcReq;
-		mcReq.uid = "net.minecraft";
-		mcReq.equalsVersion = dependsOnMinecraftVersion;
-		if (out->requires.count(mcReq) == 0)
-		{
-			out->requires.insert(mcReq);
-		}
-	}
-	if (root.contains("conflicts"))
-	{
-		Meta::parseRequires(root, &out->conflicts);
-	}
-	if (root.contains("volatile"))
-	{
-		out->m_volatile = requireBoolean(root, "volatile");
-	}
-
-	/* removed features that shouldn't be used */
-	if (root.contains("tweakers"))
-	{
-		out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'"));
-	}
-	if (root.contains("-libraries"))
-	{
-		out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-libraries'"));
-	}
-	if (root.contains("-tweakers"))
-	{
-		out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-tweakers'"));
-	}
-	if (root.contains("-minecraftArguments"))
-	{
-		out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-minecraftArguments'"));
-	}
-	if (root.contains("+minecraftArguments"))
-	{
-		out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '+minecraftArguments'"));
-	}
-	return out;
+    VersionFilePtr out(new VersionFile());
+    if (doc.isEmpty() || doc.isNull())
+    {
+        throw JSONValidationError(filename + " is empty or null");
+    }
+    if (!doc.isObject())
+    {
+        throw JSONValidationError(filename + " is not an object");
+    }
+
+    QJsonObject root = doc.object();
+
+    Meta::MetadataVersion formatVersion = Meta::parseFormatVersion(root, false);
+    switch(formatVersion)
+    {
+        case Meta::MetadataVersion::InitialRelease:
+            break;
+        case Meta::MetadataVersion::Invalid:
+            throw JSONValidationError(filename + " does not contain a recognizable version of the metadata format.");
+    }
+
+    if (requireOrder)
+    {
+        if (root.contains("order"))
+        {
+            out->order = requireInteger(root.value("order"));
+        }
+        else
+        {
+            // FIXME: evaluate if we don't want to throw exceptions here instead
+            qCritical() << filename << "doesn't contain an order field";
+        }
+    }
+
+    out->name = root.value("name").toString();
+
+    if(root.contains("uid"))
+    {
+        out->uid = root.value("uid").toString();
+    }
+    else
+    {
+        out->uid = root.value("fileId").toString();
+    }
+
+    out->version = root.value("version").toString();
+
+    MojangVersionFormat::readVersionProperties(root, out.get());
+
+    // added for legacy Minecraft window embedding, TODO: remove
+    readString(root, "appletClass", out->appletClass);
+
+    if (root.contains("+tweakers"))
+    {
+        for (auto tweakerVal : requireArray(root.value("+tweakers")))
+        {
+            out->addTweakers.append(requireString(tweakerVal));
+        }
+    }
+
+    if (root.contains("+traits"))
+    {
+        for (auto tweakerVal : requireArray(root.value("+traits")))
+        {
+            out->traits.insert(requireString(tweakerVal));
+        }
+    }
+
+
+    if (root.contains("jarMods"))
+    {
+        for (auto libVal : requireArray(root.value("jarMods")))
+        {
+            QJsonObject libObj = requireObject(libVal);
+            // parse the jarmod
+            auto lib = OneSixVersionFormat::jarModFromJson(libObj, filename);
+            // and add to jar mods
+            out->jarMods.append(lib);
+        }
+    }
+    else if (root.contains("+jarMods")) // DEPRECATED: old style '+jarMods' are only here for backwards compatibility
+    {
+        for (auto libVal : requireArray(root.value("+jarMods")))
+        {
+            QJsonObject libObj = requireObject(libVal);
+            // parse the jarmod
+            auto lib = OneSixVersionFormat::plusJarModFromJson(libObj, filename, out->name);
+            // and add to jar mods
+            out->jarMods.append(lib);
+        }
+    }
+
+    if (root.contains("mods"))
+    {
+        for (auto libVal : requireArray(root.value("mods")))
+        {
+            QJsonObject libObj = requireObject(libVal);
+            // parse the jarmod
+            auto lib = OneSixVersionFormat::modFromJson(libObj, filename);
+            // and add to jar mods
+            out->mods.append(lib);
+        }
+    }
+
+    auto readLibs = [&](const char * which)
+    {
+        for (auto libVal : requireArray(root.value(which)))
+        {
+            QJsonObject libObj = requireObject(libVal);
+            // parse the library
+            auto lib = libraryFromJson(libObj, filename);
+            out->libraries.append(lib);
+        }
+    };
+    bool hasPlusLibs = root.contains("+libraries");
+    bool hasLibs = root.contains("libraries");
+    if (hasPlusLibs && hasLibs)
+    {
+        out->addProblem(ProblemSeverity::Warning,
+                        QObject::tr("Version file has both '+libraries' and 'libraries'. This is no longer supported."));
+        readLibs("libraries");
+        readLibs("+libraries");
+    }
+    else if (hasLibs)
+    {
+        readLibs("libraries");
+    }
+    else if(hasPlusLibs)
+    {
+        readLibs("+libraries");
+    }
+
+    // if we have mainJar, just use it
+    if(root.contains("mainJar"))
+    {
+        QJsonObject libObj = requireObject(root, "mainJar");
+        out->mainJar = libraryFromJson(libObj, filename);
+    }
+    // else reconstruct it from downloads and id ... if that's available
+    else if(!out->minecraftVersion.isEmpty())
+    {
+        auto lib = std::make_shared<Library>();
+        lib->setRawName(GradleSpecifier(QString("com.mojang:minecraft:%1:client").arg(out->minecraftVersion)));
+        // we have a reliable client download, use it.
+        if(out->mojangDownloads.contains("client"))
+        {
+            auto LibDLInfo = std::make_shared<MojangLibraryDownloadInfo>();
+            LibDLInfo->artifact = out->mojangDownloads["client"];
+            lib->setMojangDownloadInfo(LibDLInfo);
+        }
+        // we got nothing... guess based on ancient hardcoded Mojang behaviour
+        // FIXME: this will eventually break...
+        else
+        {
+            lib->setAbsoluteUrl(URLConstants::getLegacyJarUrl(out->minecraftVersion));
+        }
+        out->mainJar = lib;
+    }
+
+    if (root.contains("requires"))
+    {
+        Meta::parseRequires(root, &out->requires);
+    }
+    QString dependsOnMinecraftVersion = root.value("mcVersion").toString();
+    if(!dependsOnMinecraftVersion.isEmpty())
+    {
+        Meta::Require mcReq;
+        mcReq.uid = "net.minecraft";
+        mcReq.equalsVersion = dependsOnMinecraftVersion;
+        if (out->requires.count(mcReq) == 0)
+        {
+            out->requires.insert(mcReq);
+        }
+    }
+    if (root.contains("conflicts"))
+    {
+        Meta::parseRequires(root, &out->conflicts);
+    }
+    if (root.contains("volatile"))
+    {
+        out->m_volatile = requireBoolean(root, "volatile");
+    }
+
+    /* removed features that shouldn't be used */
+    if (root.contains("tweakers"))
+    {
+        out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element 'tweakers'"));
+    }
+    if (root.contains("-libraries"))
+    {
+        out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-libraries'"));
+    }
+    if (root.contains("-tweakers"))
+    {
+        out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-tweakers'"));
+    }
+    if (root.contains("-minecraftArguments"))
+    {
+        out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '-minecraftArguments'"));
+    }
+    if (root.contains("+minecraftArguments"))
+    {
+        out->addProblem(ProblemSeverity::Error, QObject::tr("Version file contains unsupported element '+minecraftArguments'"));
+    }
+    return out;
 }
 
 QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch)
 {
-	QJsonObject root;
-	writeString(root, "name", patch->name);
-
-	writeString(root, "uid", patch->uid);
-
-	writeString(root, "version", patch->version);
-
-	Meta::serializeFormatVersion(root, Meta::MetadataVersion::InitialRelease);
-
-	MojangVersionFormat::writeVersionProperties(patch.get(), root);
-
-	if(patch->mainJar)
-	{
-		root.insert("mainJar", libraryToJson(patch->mainJar.get()));
-	}
-	writeString(root, "appletClass", patch->appletClass);
-	writeStringList(root, "+tweakers", patch->addTweakers);
-	writeStringList(root, "+traits", patch->traits.toList());
-	if (!patch->libraries.isEmpty())
-	{
-		QJsonArray array;
-		for (auto value: patch->libraries)
-		{
-			array.append(OneSixVersionFormat::libraryToJson(value.get()));
-		}
-		root.insert("libraries", array);
-	}
-	if (!patch->jarMods.isEmpty())
-	{
-		QJsonArray array;
-		for (auto value: patch->jarMods)
-		{
-			array.append(OneSixVersionFormat::jarModtoJson(value.get()));
-		}
-		root.insert("jarMods", array);
-	}
-	if (!patch->mods.isEmpty())
-	{
-		QJsonArray array;
-		for (auto value: patch->jarMods)
-		{
-			array.append(OneSixVersionFormat::modtoJson(value.get()));
-		}
-		root.insert("mods", array);
-	}
-	if(!patch->requires.empty())
-	{
-		Meta::serializeRequires(root, &patch->requires, "requires");
-	}
-	if(!patch->conflicts.empty())
-	{
-		Meta::serializeRequires(root, &patch->conflicts, "conflicts");
-	}
-	if(patch->m_volatile)
-	{
-		root.insert("volatile", true);
-	}
-	// write the contents to a json document.
-	{
-		QJsonDocument out;
-		out.setObject(root);
-		return out;
-	}
+    QJsonObject root;
+    writeString(root, "name", patch->name);
+
+    writeString(root, "uid", patch->uid);
+
+    writeString(root, "version", patch->version);
+
+    Meta::serializeFormatVersion(root, Meta::MetadataVersion::InitialRelease);
+
+    MojangVersionFormat::writeVersionProperties(patch.get(), root);
+
+    if(patch->mainJar)
+    {
+        root.insert("mainJar", libraryToJson(patch->mainJar.get()));
+    }
+    writeString(root, "appletClass", patch->appletClass);
+    writeStringList(root, "+tweakers", patch->addTweakers);
+    writeStringList(root, "+traits", patch->traits.toList());
+    if (!patch->libraries.isEmpty())
+    {
+        QJsonArray array;
+        for (auto value: patch->libraries)
+        {
+            array.append(OneSixVersionFormat::libraryToJson(value.get()));
+        }
+        root.insert("libraries", array);
+    }
+    if (!patch->jarMods.isEmpty())
+    {
+        QJsonArray array;
+        for (auto value: patch->jarMods)
+        {
+            array.append(OneSixVersionFormat::jarModtoJson(value.get()));
+        }
+        root.insert("jarMods", array);
+    }
+    if (!patch->mods.isEmpty())
+    {
+        QJsonArray array;
+        for (auto value: patch->jarMods)
+        {
+            array.append(OneSixVersionFormat::modtoJson(value.get()));
+        }
+        root.insert("mods", array);
+    }
+    if(!patch->requires.empty())
+    {
+        Meta::serializeRequires(root, &patch->requires, "requires");
+    }
+    if(!patch->conflicts.empty())
+    {
+        Meta::serializeRequires(root, &patch->conflicts, "conflicts");
+    }
+    if(patch->m_volatile)
+    {
+        root.insert("volatile", true);
+    }
+    // write the contents to a json document.
+    {
+        QJsonDocument out;
+        out.setObject(root);
+        return out;
+    }
 }
 
 LibraryPtr OneSixVersionFormat::plusJarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName)
 {
-	LibraryPtr out(new Library());
-	if (!libObj.contains("name"))
-	{
-		throw JSONValidationError(filename +
-								  "contains a jarmod that doesn't have a 'name' field");
-	}
-
-	// just make up something unique on the spot for the library name.
-	auto uuid = QUuid::createUuid();
-	QString id = uuid.toString().remove('{').remove('}');
-	out->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1"));
-
-	// filename override is the old name
-	out->setFilename(libObj.value("name").toString());
-
-	// it needs to be local, it is stored in the instance jarmods folder
-	out->setHint("local");
-
-	// read the original name if present - some versions did not set it
-	// it is the original jar mod filename before it got renamed at the point of addition
-	auto displayName = libObj.value("originalName").toString();
-	if(displayName.isEmpty())
-	{
-		auto fixed = originalName;
-		fixed.remove(" (jar mod)");
-		out->setDisplayName(fixed);
-	}
-	else
-	{
-		out->setDisplayName(displayName);
-	}
-	return out;
+    LibraryPtr out(new Library());
+    if (!libObj.contains("name"))
+    {
+        throw JSONValidationError(filename +
+                                  "contains a jarmod that doesn't have a 'name' field");
+    }
+
+    // just make up something unique on the spot for the library name.
+    auto uuid = QUuid::createUuid();
+    QString id = uuid.toString().remove('{').remove('}');
+    out->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1"));
+
+    // filename override is the old name
+    out->setFilename(libObj.value("name").toString());
+
+    // it needs to be local, it is stored in the instance jarmods folder
+    out->setHint("local");
+
+    // read the original name if present - some versions did not set it
+    // it is the original jar mod filename before it got renamed at the point of addition
+    auto displayName = libObj.value("originalName").toString();
+    if(displayName.isEmpty())
+    {
+        auto fixed = originalName;
+        fixed.remove(" (jar mod)");
+        out->setDisplayName(fixed);
+    }
+    else
+    {
+        out->setDisplayName(displayName);
+    }
+    return out;
 }
 
 LibraryPtr OneSixVersionFormat::jarModFromJson(const QJsonObject& libObj, const QString& filename)
 {
-	return libraryFromJson(libObj, filename);
+    return libraryFromJson(libObj, filename);
 }
 
 
 QJsonObject OneSixVersionFormat::jarModtoJson(Library *jarmod)
 {
-	return libraryToJson(jarmod);
+    return libraryToJson(jarmod);
 }
 
 LibraryPtr OneSixVersionFormat::modFromJson(const QJsonObject& libObj, const QString& filename)
 {
-	return  libraryFromJson(libObj, filename);
+    return  libraryFromJson(libObj, filename);
 }
 
 QJsonObject OneSixVersionFormat::modtoJson(Library *jarmod)
 {
-	return libraryToJson(jarmod);
+    return libraryToJson(jarmod);
 }
diff --git a/api/logic/minecraft/OneSixVersionFormat.h b/api/logic/minecraft/OneSixVersionFormat.h
index 8b782db0..6bbebca0 100644
--- a/api/logic/minecraft/OneSixVersionFormat.h
+++ b/api/logic/minecraft/OneSixVersionFormat.h
@@ -8,22 +8,22 @@
 class OneSixVersionFormat
 {
 public:
-	// version files / profile patches
-	static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder);
-	static QJsonDocument versionFileToJson(const VersionFilePtr &patch);
+    // version files / profile patches
+    static VersionFilePtr versionFileFromJson(const QJsonDocument &doc, const QString &filename, const bool requireOrder);
+    static QJsonDocument versionFileToJson(const VersionFilePtr &patch);
 
-	// libraries
-	static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
-	static QJsonObject libraryToJson(Library *library);
+    // libraries
+    static LibraryPtr libraryFromJson(const QJsonObject &libObj, const QString &filename);
+    static QJsonObject libraryToJson(Library *library);
 
-	// DEPRECATED: old 'plus' jar mods generated by the application
-	static LibraryPtr plusJarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName);
+    // DEPRECATED: old 'plus' jar mods generated by the application
+    static LibraryPtr plusJarModFromJson(const QJsonObject &libObj, const QString &filename, const QString &originalName);
 
-	// new jar mods derived from libraries
-	static LibraryPtr jarModFromJson(const QJsonObject &libObj, const QString &filename);
-	static QJsonObject jarModtoJson(Library * jarmod);
+    // new jar mods derived from libraries
+    static LibraryPtr jarModFromJson(const QJsonObject &libObj, const QString &filename);
+    static QJsonObject jarModtoJson(Library * jarmod);
 
-	// mods, also derived from libraries
-	static LibraryPtr modFromJson(const QJsonObject &libObj, const QString &filename);
-	static QJsonObject modtoJson(Library * jarmod);
+    // mods, also derived from libraries
+    static LibraryPtr modFromJson(const QJsonObject &libObj, const QString &filename);
+    static QJsonObject modtoJson(Library * jarmod);
 };
diff --git a/api/logic/minecraft/OpSys.cpp b/api/logic/minecraft/OpSys.cpp
index 2165fa7f..2e18634b 100644
--- a/api/logic/minecraft/OpSys.cpp
+++ b/api/logic/minecraft/OpSys.cpp
@@ -17,26 +17,26 @@
 
 OpSys OpSys_fromString(QString name)
 {
-	if (name == "linux")
-		return Os_Linux;
-	if (name == "windows")
-		return Os_Windows;
-	if (name == "osx")
-		return Os_OSX;
-	return Os_Other;
+    if (name == "linux")
+        return Os_Linux;
+    if (name == "windows")
+        return Os_Windows;
+    if (name == "osx")
+        return Os_OSX;
+    return Os_Other;
 }
 
 QString OpSys_toString(OpSys name)
 {
-	switch (name)
-	{
-	case Os_Linux:
-		return "linux";
-	case Os_OSX:
-		return "osx";
-	case Os_Windows:
-		return "windows";
-	default:
-		return "other";
-	}
+    switch (name)
+    {
+    case Os_Linux:
+        return "linux";
+    case Os_OSX:
+        return "osx";
+    case Os_Windows:
+        return "windows";
+    default:
+        return "other";
+    }
 }
\ No newline at end of file
diff --git a/api/logic/minecraft/OpSys.h b/api/logic/minecraft/OpSys.h
index e44b1e07..8ea84587 100644
--- a/api/logic/minecraft/OpSys.h
+++ b/api/logic/minecraft/OpSys.h
@@ -17,10 +17,10 @@
 #include <QString>
 enum OpSys
 {
-	Os_Windows,
-	Os_Linux,
-	Os_OSX,
-	Os_Other
+    Os_Windows,
+    Os_Linux,
+    Os_OSX,
+    Os_Other
 };
 
 OpSys OpSys_fromString(QString);
diff --git a/api/logic/minecraft/ParseUtils.cpp b/api/logic/minecraft/ParseUtils.cpp
index ca188432..c9640e77 100644
--- a/api/logic/minecraft/ParseUtils.cpp
+++ b/api/logic/minecraft/ParseUtils.cpp
@@ -6,29 +6,29 @@
 
 QDateTime timeFromS3Time(QString str)
 {
-	return QDateTime::fromString(str, Qt::ISODate);
+    return QDateTime::fromString(str, Qt::ISODate);
 }
 
 QString timeToS3Time(QDateTime time)
 {
-	// this all because Qt can't format timestamps right.
-	int offsetRaw = time.offsetFromUtc();
-	bool negative = offsetRaw < 0;
-	int offsetAbs = std::abs(offsetRaw);
+    // this all because Qt can't format timestamps right.
+    int offsetRaw = time.offsetFromUtc();
+    bool negative = offsetRaw < 0;
+    int offsetAbs = std::abs(offsetRaw);
 
-	int offsetSeconds = offsetAbs % 60;
-	offsetAbs -= offsetSeconds;
+    int offsetSeconds = offsetAbs % 60;
+    offsetAbs -= offsetSeconds;
 
-	int offsetMinutes = offsetAbs % 3600;
-	offsetAbs -= offsetMinutes;
-	offsetMinutes /= 60;
-	
-	int offsetHours = offsetAbs / 3600;
+    int offsetMinutes = offsetAbs % 3600;
+    offsetAbs -= offsetMinutes;
+    offsetMinutes /= 60;
+    
+    int offsetHours = offsetAbs / 3600;
 
-	QString raw = time.toString("yyyy-MM-ddTHH:mm:ss");
-	raw += (negative ? QChar('-') : QChar('+'));
-	raw += QString("%1").arg(offsetHours, 2, 10, QChar('0'));
-	raw += ":";
-	raw += QString("%1").arg(offsetMinutes, 2, 10, QChar('0'));
-	return raw;
+    QString raw = time.toString("yyyy-MM-ddTHH:mm:ss");
+    raw += (negative ? QChar('-') : QChar('+'));
+    raw += QString("%1").arg(offsetHours, 2, 10, QChar('0'));
+    raw += ":";
+    raw += QString("%1").arg(offsetMinutes, 2, 10, QChar('0'));
+    return raw;
 }
diff --git a/api/logic/minecraft/ParseUtils_test.cpp b/api/logic/minecraft/ParseUtils_test.cpp
index 1ce96248..fde9cdbf 100644
--- a/api/logic/minecraft/ParseUtils_test.cpp
+++ b/api/logic/minecraft/ParseUtils_test.cpp
@@ -5,37 +5,37 @@
 
 class ParseUtilsTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void test_Through_data()
-	{
-		QTest::addColumn<QString>("timestamp");
-		const char * timestamps[] =
-		{
-			"2016-02-29T13:49:54+01:00",
-			"2016-02-26T15:21:11+00:01",
-			"2016-02-24T15:52:36+01:13",
-			"2016-02-18T17:41:00+00:00",
-			"2016-02-17T15:23:19+00:00",
-			"2016-02-16T15:22:39+09:22",
-			"2016-02-10T15:06:41+00:00",
-			"2016-02-04T15:28:02-05:33"
-		};
-		for(unsigned i = 0; i < (sizeof(timestamps) / sizeof(const char *)); i++)
-		{
-			QTest::newRow(timestamps[i]) << QString(timestamps[i]);
-		}
-	}
-	void test_Through()
-	{
-		QFETCH(QString, timestamp);
+    void test_Through_data()
+    {
+        QTest::addColumn<QString>("timestamp");
+        const char * timestamps[] =
+        {
+            "2016-02-29T13:49:54+01:00",
+            "2016-02-26T15:21:11+00:01",
+            "2016-02-24T15:52:36+01:13",
+            "2016-02-18T17:41:00+00:00",
+            "2016-02-17T15:23:19+00:00",
+            "2016-02-16T15:22:39+09:22",
+            "2016-02-10T15:06:41+00:00",
+            "2016-02-04T15:28:02-05:33"
+        };
+        for(unsigned i = 0; i < (sizeof(timestamps) / sizeof(const char *)); i++)
+        {
+            QTest::newRow(timestamps[i]) << QString(timestamps[i]);
+        }
+    }
+    void test_Through()
+    {
+        QFETCH(QString, timestamp);
 
-		auto time_parsed = timeFromS3Time(timestamp);
-		auto time_serialized = timeToS3Time(time_parsed);
-		
-		QCOMPARE(time_serialized, timestamp);
-	}
+        auto time_parsed = timeFromS3Time(timestamp);
+        auto time_serialized = timeToS3Time(time_parsed);
+        
+        QCOMPARE(time_serialized, timestamp);
+    }
 
 };
 
diff --git a/api/logic/minecraft/ProfileUtils.cpp b/api/logic/minecraft/ProfileUtils.cpp
index 2227e438..8ca24cc8 100644
--- a/api/logic/minecraft/ProfileUtils.cpp
+++ b/api/logic/minecraft/ProfileUtils.cpp
@@ -16,163 +16,163 @@ static const int currentOrderFileVersion = 1;
 
 bool readOverrideOrders(QString path, PatchOrder &order)
 {
-	QFile orderFile(path);
-	if (!orderFile.exists())
-	{
-		qWarning() << "Order file doesn't exist. Ignoring.";
-		return false;
-	}
-	if (!orderFile.open(QFile::ReadOnly))
-	{
-		qCritical() << "Couldn't open" << orderFile.fileName()
-					 << " for reading:" << orderFile.errorString();
-		qWarning() << "Ignoring overriden order";
-		return false;
-	}
+    QFile orderFile(path);
+    if (!orderFile.exists())
+    {
+        qWarning() << "Order file doesn't exist. Ignoring.";
+        return false;
+    }
+    if (!orderFile.open(QFile::ReadOnly))
+    {
+        qCritical() << "Couldn't open" << orderFile.fileName()
+                     << " for reading:" << orderFile.errorString();
+        qWarning() << "Ignoring overriden order";
+        return false;
+    }
 
-	// and it's valid JSON
-	QJsonParseError error;
-	QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
-	if (error.error != QJsonParseError::NoError)
-	{
-		qCritical() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
-		qWarning() << "Ignoring overriden order";
-		return false;
-	}
+    // and it's valid JSON
+    QJsonParseError error;
+    QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
+    if (error.error != QJsonParseError::NoError)
+    {
+        qCritical() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
+        qWarning() << "Ignoring overriden order";
+        return false;
+    }
 
-	// and then read it and process it if all above is true.
-	try
-	{
-		auto obj = Json::requireObject(doc);
-		// check order file version.
-		auto version = Json::requireInteger(obj.value("version"));
-		if (version != currentOrderFileVersion)
-		{
-			throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
-										  .arg(currentOrderFileVersion));
-		}
-		auto orderArray = Json::requireArray(obj.value("order"));
-		for(auto item: orderArray)
-		{
-			order.append(Json::requireString(item));
-		}
-	}
-	catch (const JSONValidationError &err)
-	{
-		qCritical() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
-		qWarning() << "Ignoring overriden order";
-		order.clear();
-		return false;
-	}
-	return true;
+    // and then read it and process it if all above is true.
+    try
+    {
+        auto obj = Json::requireObject(doc);
+        // check order file version.
+        auto version = Json::requireInteger(obj.value("version"));
+        if (version != currentOrderFileVersion)
+        {
+            throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
+                                          .arg(currentOrderFileVersion));
+        }
+        auto orderArray = Json::requireArray(obj.value("order"));
+        for(auto item: orderArray)
+        {
+            order.append(Json::requireString(item));
+        }
+    }
+    catch (const JSONValidationError &err)
+    {
+        qCritical() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
+        qWarning() << "Ignoring overriden order";
+        order.clear();
+        return false;
+    }
+    return true;
 }
 
 static VersionFilePtr createErrorVersionFile(QString fileId, QString filepath, QString error)
 {
-	auto outError = std::make_shared<VersionFile>();
-	outError->uid = outError->name = fileId;
-	// outError->filename = filepath;
-	outError->addProblem(ProblemSeverity::Error, error);
-	return outError;
+    auto outError = std::make_shared<VersionFile>();
+    outError->uid = outError->name = fileId;
+    // outError->filename = filepath;
+    outError->addProblem(ProblemSeverity::Error, error);
+    return outError;
 }
 
 static VersionFilePtr guardedParseJson(const QJsonDocument & doc,const QString &fileId,const QString &filepath,const bool &requireOrder)
 {
-	try
-	{
-		return OneSixVersionFormat::versionFileFromJson(doc, filepath, requireOrder);
-	}
-	catch (const Exception &e)
-	{
-		return createErrorVersionFile(fileId, filepath, e.cause());
-	}
+    try
+    {
+        return OneSixVersionFormat::versionFileFromJson(doc, filepath, requireOrder);
+    }
+    catch (const Exception &e)
+    {
+        return createErrorVersionFile(fileId, filepath, e.cause());
+    }
 }
 
 VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder)
 {
-	QFile file(fileInfo.absoluteFilePath());
-	if (!file.open(QFile::ReadOnly))
-	{
-		auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString());
-		return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
-	}
-	QJsonParseError error;
-	auto data = file.readAll();
-	QJsonDocument doc = QJsonDocument::fromJson(data, &error);
-	file.close();
-	if (error.error != QJsonParseError::NoError)
-	{
-		int line = 1;
-		int column = 0;
-		for(int i = 0; i < error.offset; i++)
-		{
-			if(data[i] == '\n')
-			{
-				line++;
-				column = 0;
-				continue;
-			}
-			column++;
-		}
-		auto errorStr = QObject::tr("Unable to process the version file %1: %2 at line %3 column %4.")
-				.arg(fileInfo.fileName(), error.errorString())
-				.arg(line).arg(column);
-		return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
-	}
-	return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), requireOrder);
+    QFile file(fileInfo.absoluteFilePath());
+    if (!file.open(QFile::ReadOnly))
+    {
+        auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString());
+        return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
+    }
+    QJsonParseError error;
+    auto data = file.readAll();
+    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
+    file.close();
+    if (error.error != QJsonParseError::NoError)
+    {
+        int line = 1;
+        int column = 0;
+        for(int i = 0; i < error.offset; i++)
+        {
+            if(data[i] == '\n')
+            {
+                line++;
+                column = 0;
+                continue;
+            }
+            column++;
+        }
+        auto errorStr = QObject::tr("Unable to process the version file %1: %2 at line %3 column %4.")
+                .arg(fileInfo.fileName(), error.errorString())
+                .arg(line).arg(column);
+        return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
+    }
+    return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), requireOrder);
 }
 
 bool saveJsonFile(const QJsonDocument doc, const QString & filename)
 {
-	auto data = doc.toJson();
-	QSaveFile jsonFile(filename);
-	if(!jsonFile.open(QIODevice::WriteOnly))
-	{
-		jsonFile.cancelWriting();
-		qWarning() << "Couldn't open" << filename << "for writing";
-		return false;
-	}
-	jsonFile.write(data);
-	if(!jsonFile.commit())
-	{
-		qWarning() << "Couldn't save" << filename;
-		return false;
-	}
-	return true;
+    auto data = doc.toJson();
+    QSaveFile jsonFile(filename);
+    if(!jsonFile.open(QIODevice::WriteOnly))
+    {
+        jsonFile.cancelWriting();
+        qWarning() << "Couldn't open" << filename << "for writing";
+        return false;
+    }
+    jsonFile.write(data);
+    if(!jsonFile.commit())
+    {
+        qWarning() << "Couldn't save" << filename;
+        return false;
+    }
+    return true;
 }
 
 VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
 {
-	QFile file(fileInfo.absoluteFilePath());
-	if (!file.open(QFile::ReadOnly))
-	{
-		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());
-	file.close();
-	if (doc.isNull())
-	{
-		file.remove();
-		throw JSONValidationError(QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
-	}
-	return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), false);
+    QFile file(fileInfo.absoluteFilePath());
+    if (!file.open(QFile::ReadOnly))
+    {
+        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());
+    file.close();
+    if (doc.isNull())
+    {
+        file.remove();
+        throw JSONValidationError(QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
+    }
+    return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), false);
 }
 
 void removeLwjglFromPatch(VersionFilePtr patch)
 {
-	auto filter = [](QList<LibraryPtr>& libs)
-	{
-		QList<LibraryPtr> filteredLibs;
-		for (auto lib : libs)
-		{
-			if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
-			{
-				filteredLibs.append(lib);
-			}
-		}
-		libs = filteredLibs;
-	};
-	filter(patch->libraries);
+    auto filter = [](QList<LibraryPtr>& libs)
+    {
+        QList<LibraryPtr> filteredLibs;
+        for (auto lib : libs)
+        {
+            if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
+            {
+                filteredLibs.append(lib);
+            }
+        }
+        libs = filteredLibs;
+    };
+    filter(patch->libraries);
 }
 }
diff --git a/api/logic/minecraft/Rule.cpp b/api/logic/minecraft/Rule.cpp
index 43d673c2..a7640635 100644
--- a/api/logic/minecraft/Rule.cpp
+++ b/api/logic/minecraft/Rule.cpp
@@ -20,74 +20,74 @@
 
 RuleAction RuleAction_fromString(QString name)
 {
-	if (name == "allow")
-		return Allow;
-	if (name == "disallow")
-		return Disallow;
-	return Defer;
+    if (name == "allow")
+        return Allow;
+    if (name == "disallow")
+        return Disallow;
+    return Defer;
 }
 
 QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules)
 {
-	QList<std::shared_ptr<Rule>> rules;
-	auto rulesVal = objectWithRules.value("rules");
-	if (!rulesVal.isArray())
-		return rules;
+    QList<std::shared_ptr<Rule>> rules;
+    auto rulesVal = objectWithRules.value("rules");
+    if (!rulesVal.isArray())
+        return rules;
 
-	QJsonArray ruleList = rulesVal.toArray();
-	for (auto ruleVal : ruleList)
-	{
-		std::shared_ptr<Rule> rule;
-		if (!ruleVal.isObject())
-			continue;
-		auto ruleObj = ruleVal.toObject();
-		auto actionVal = ruleObj.value("action");
-		if (!actionVal.isString())
-			continue;
-		auto action = RuleAction_fromString(actionVal.toString());
-		if (action == Defer)
-			continue;
+    QJsonArray ruleList = rulesVal.toArray();
+    for (auto ruleVal : ruleList)
+    {
+        std::shared_ptr<Rule> rule;
+        if (!ruleVal.isObject())
+            continue;
+        auto ruleObj = ruleVal.toObject();
+        auto actionVal = ruleObj.value("action");
+        if (!actionVal.isString())
+            continue;
+        auto action = RuleAction_fromString(actionVal.toString());
+        if (action == Defer)
+            continue;
 
-		auto osVal = ruleObj.value("os");
-		if (!osVal.isObject())
-		{
-			// add a new implicit action rule
-			rules.append(ImplicitRule::create(action));
-			continue;
-		}
+        auto osVal = ruleObj.value("os");
+        if (!osVal.isObject())
+        {
+            // add a new implicit action rule
+            rules.append(ImplicitRule::create(action));
+            continue;
+        }
 
-		auto osObj = osVal.toObject();
-		auto osNameVal = osObj.value("name");
-		if (!osNameVal.isString())
-			continue;
-		OpSys requiredOs = OpSys_fromString(osNameVal.toString());
-		QString versionRegex = osObj.value("version").toString();
-		// add a new OS rule
-		rules.append(OsRule::create(action, requiredOs, versionRegex));
-	}
+        auto osObj = osVal.toObject();
+        auto osNameVal = osObj.value("name");
+        if (!osNameVal.isString())
+            continue;
+        OpSys requiredOs = OpSys_fromString(osNameVal.toString());
+        QString versionRegex = osObj.value("version").toString();
+        // add a new OS rule
+        rules.append(OsRule::create(action, requiredOs, versionRegex));
+    }
     return rules;
 }
 
 QJsonObject ImplicitRule::toJson()
 {
-	QJsonObject ruleObj;
-	ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow"));
-	return ruleObj;
+    QJsonObject ruleObj;
+    ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow"));
+    return ruleObj;
 }
 
 QJsonObject OsRule::toJson()
 {
-	QJsonObject ruleObj;
-	ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow"));
-	QJsonObject osObj;
-	{
-		osObj.insert("name", OpSys_toString(m_system));
-		if(!m_version_regexp.isEmpty())
-		{
-			osObj.insert("version", m_version_regexp);
-		}
-	}
-	ruleObj.insert("os", osObj);
-	return ruleObj;
+    QJsonObject ruleObj;
+    ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow"));
+    QJsonObject osObj;
+    {
+        osObj.insert("name", OpSys_toString(m_system));
+        if(!m_version_regexp.isEmpty())
+        {
+            osObj.insert("version", m_version_regexp);
+        }
+    }
+    ruleObj.insert("os", osObj);
+    return ruleObj;
 }
 
diff --git a/api/logic/minecraft/Rule.h b/api/logic/minecraft/Rule.h
index dc1eee0b..ec9b26bd 100644
--- a/api/logic/minecraft/Rule.h
+++ b/api/logic/minecraft/Rule.h
@@ -26,9 +26,9 @@ class Rule;
 
 enum RuleAction
 {
-	Allow,
-	Disallow,
-	Defer
+    Allow,
+    Disallow,
+    Defer
 };
 
 QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules);
@@ -36,66 +36,66 @@ QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules)
 class Rule
 {
 protected:
-	RuleAction m_result;
-	virtual bool applies(const Library *parent) = 0;
+    RuleAction m_result;
+    virtual bool applies(const Library *parent) = 0;
 
 public:
-	Rule(RuleAction result) : m_result(result)
-	{
-	}
-	virtual ~Rule() {};
-	virtual QJsonObject toJson() = 0;
-	RuleAction apply(const Library *parent)
-	{
-		if (applies(parent))
-			return m_result;
-		else
-			return Defer;
-	}
+    Rule(RuleAction result) : m_result(result)
+    {
+    }
+    virtual ~Rule() {};
+    virtual QJsonObject toJson() = 0;
+    RuleAction apply(const Library *parent)
+    {
+        if (applies(parent))
+            return m_result;
+        else
+            return Defer;
+    }
 };
 
 class OsRule : public Rule
 {
 private:
-	// the OS
-	OpSys m_system;
-	// the OS version regexp
-	QString m_version_regexp;
+    // the OS
+    OpSys m_system;
+    // the OS version regexp
+    QString m_version_regexp;
 
 protected:
-	virtual bool applies(const Library *)
-	{
-		return (m_system == currentSystem);
-	}
-	OsRule(RuleAction result, OpSys system, QString version_regexp)
-		: Rule(result), m_system(system), m_version_regexp(version_regexp)
-	{
-	}
+    virtual bool applies(const Library *)
+    {
+        return (m_system == currentSystem);
+    }
+    OsRule(RuleAction result, OpSys system, QString version_regexp)
+        : Rule(result), m_system(system), m_version_regexp(version_regexp)
+    {
+    }
 
 public:
-	virtual QJsonObject toJson();
-	static std::shared_ptr<OsRule> create(RuleAction result, OpSys system,
-										  QString version_regexp)
-	{
-		return std::shared_ptr<OsRule>(new OsRule(result, system, version_regexp));
-	}
+    virtual QJsonObject toJson();
+    static std::shared_ptr<OsRule> create(RuleAction result, OpSys system,
+                                          QString version_regexp)
+    {
+        return std::shared_ptr<OsRule>(new OsRule(result, system, version_regexp));
+    }
 };
 
 class ImplicitRule : public Rule
 {
 protected:
-	virtual bool applies(const Library *)
-	{
-		return true;
-	}
-	ImplicitRule(RuleAction result) : Rule(result)
-	{
-	}
+    virtual bool applies(const Library *)
+    {
+        return true;
+    }
+    ImplicitRule(RuleAction result) : Rule(result)
+    {
+    }
 
 public:
-	virtual QJsonObject toJson();
-	static std::shared_ptr<ImplicitRule> create(RuleAction result)
-	{
-		return std::shared_ptr<ImplicitRule>(new ImplicitRule(result));
-	}
+    virtual QJsonObject toJson();
+    static std::shared_ptr<ImplicitRule> create(RuleAction result)
+    {
+        return std::shared_ptr<ImplicitRule>(new ImplicitRule(result));
+    }
 };
diff --git a/api/logic/minecraft/SimpleModList.cpp b/api/logic/minecraft/SimpleModList.cpp
index ca923226..a9fb42eb 100644
--- a/api/logic/minecraft/SimpleModList.cpp
+++ b/api/logic/minecraft/SimpleModList.cpp
@@ -24,344 +24,344 @@
 
 SimpleModList::SimpleModList(const QString &dir) : QAbstractListModel(), m_dir(dir)
 {
-	FS::ensureFolderPathExists(m_dir.absolutePath());
-	m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
-					QDir::NoSymLinks);
-	m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
-	m_watcher = new QFileSystemWatcher(this);
-	connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
+    FS::ensureFolderPathExists(m_dir.absolutePath());
+    m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
+                    QDir::NoSymLinks);
+    m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
+    m_watcher = new QFileSystemWatcher(this);
+    connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
 }
 
 void SimpleModList::startWatching()
 {
-	if(is_watching)
-		return;
-
-	update();
-
-	is_watching = m_watcher->addPath(m_dir.absolutePath());
-	if (is_watching)
-	{
-		qDebug() << "Started watching " << m_dir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to start watching " << m_dir.absolutePath();
-	}
+    if(is_watching)
+        return;
+
+    update();
+
+    is_watching = m_watcher->addPath(m_dir.absolutePath());
+    if (is_watching)
+    {
+        qDebug() << "Started watching " << m_dir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to start watching " << m_dir.absolutePath();
+    }
 }
 
 void SimpleModList::stopWatching()
 {
-	if(!is_watching)
-		return;
-
-	is_watching = !m_watcher->removePath(m_dir.absolutePath());
-	if (!is_watching)
-	{
-		qDebug() << "Stopped watching " << m_dir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to stop watching " << m_dir.absolutePath();
-	}
+    if(!is_watching)
+        return;
+
+    is_watching = !m_watcher->removePath(m_dir.absolutePath());
+    if (!is_watching)
+    {
+        qDebug() << "Stopped watching " << m_dir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to stop watching " << m_dir.absolutePath();
+    }
 }
 
 bool SimpleModList::update()
 {
-	if (!isValid())
-		return false;
-
-	QList<Mod> orderedMods;
-	QList<Mod> newMods;
-	m_dir.refresh();
-	auto folderContents = m_dir.entryInfoList();
-	bool orderOrStateChanged = false;
-
-	// if there are any untracked files...
-	if (folderContents.size())
-	{
-		// the order surely changed!
-		for (auto entry : folderContents)
-		{
-			newMods.append(Mod(entry));
-		}
-		orderedMods.append(newMods);
-		orderOrStateChanged = true;
-	}
-	// otherwise, if we were already tracking some mods
-	else if (mods.size())
-	{
-		// if the number doesn't match, order changed.
-		if (mods.size() != orderedMods.size())
-			orderOrStateChanged = true;
-		// if it does match, compare the mods themselves
-		else
-			for (int i = 0; i < mods.size(); i++)
-			{
-				if (!mods[i].strongCompare(orderedMods[i]))
-				{
-					orderOrStateChanged = true;
-					break;
-				}
-			}
-	}
-	beginResetModel();
-	mods.swap(orderedMods);
-	endResetModel();
-	if (orderOrStateChanged)
-	{
-		emit changed();
-	}
-	return true;
+    if (!isValid())
+        return false;
+
+    QList<Mod> orderedMods;
+    QList<Mod> newMods;
+    m_dir.refresh();
+    auto folderContents = m_dir.entryInfoList();
+    bool orderOrStateChanged = false;
+
+    // if there are any untracked files...
+    if (folderContents.size())
+    {
+        // the order surely changed!
+        for (auto entry : folderContents)
+        {
+            newMods.append(Mod(entry));
+        }
+        orderedMods.append(newMods);
+        orderOrStateChanged = true;
+    }
+    // otherwise, if we were already tracking some mods
+    else if (mods.size())
+    {
+        // if the number doesn't match, order changed.
+        if (mods.size() != orderedMods.size())
+            orderOrStateChanged = true;
+        // if it does match, compare the mods themselves
+        else
+            for (int i = 0; i < mods.size(); i++)
+            {
+                if (!mods[i].strongCompare(orderedMods[i]))
+                {
+                    orderOrStateChanged = true;
+                    break;
+                }
+            }
+    }
+    beginResetModel();
+    mods.swap(orderedMods);
+    endResetModel();
+    if (orderOrStateChanged)
+    {
+        emit changed();
+    }
+    return true;
 }
 
 void SimpleModList::directoryChanged(QString path)
 {
-	update();
+    update();
 }
 
 bool SimpleModList::isValid()
 {
-	return m_dir.exists() && m_dir.isReadable();
+    return m_dir.exists() && m_dir.isReadable();
 }
 
 bool SimpleModList::installMod(const QString &filename)
 {
-	// NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName
-	QFileInfo fileinfo(FS::NormalizePath(filename));
-
-	qDebug() << "installing: " << fileinfo.absoluteFilePath();
-
-	if (!fileinfo.exists() || !fileinfo.isReadable())
-	{
-		return false;
-	}
-	Mod m(fileinfo);
-	if (!m.valid())
-		return false;
-
-	auto type = m.type();
-	if (type == Mod::MOD_UNKNOWN)
-		return false;
-	if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD)
-	{
-		QString newpath = FS::PathCombine(m_dir.path(), fileinfo.fileName());
-		if (!QFile::copy(fileinfo.filePath(), newpath))
-			return false;
-		FS::updateTimestamp(newpath);
-		m.repath(newpath);
-		update();
-		return true;
-	}
-	else if (type == Mod::MOD_FOLDER)
-	{
-		QString from = fileinfo.filePath();
-		QString to = FS::PathCombine(m_dir.path(), fileinfo.fileName());
-		if (!FS::copy(from, to)())
-			return false;
-		m.repath(to);
-		update();
-		return true;
-	}
-	return false;
+    // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName
+    QFileInfo fileinfo(FS::NormalizePath(filename));
+
+    qDebug() << "installing: " << fileinfo.absoluteFilePath();
+
+    if (!fileinfo.exists() || !fileinfo.isReadable())
+    {
+        return false;
+    }
+    Mod m(fileinfo);
+    if (!m.valid())
+        return false;
+
+    auto type = m.type();
+    if (type == Mod::MOD_UNKNOWN)
+        return false;
+    if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD)
+    {
+        QString newpath = FS::PathCombine(m_dir.path(), fileinfo.fileName());
+        if (!QFile::copy(fileinfo.filePath(), newpath))
+            return false;
+        FS::updateTimestamp(newpath);
+        m.repath(newpath);
+        update();
+        return true;
+    }
+    else if (type == Mod::MOD_FOLDER)
+    {
+        QString from = fileinfo.filePath();
+        QString to = FS::PathCombine(m_dir.path(), fileinfo.fileName());
+        if (!FS::copy(from, to)())
+            return false;
+        m.repath(to);
+        update();
+        return true;
+    }
+    return false;
 }
 
 bool SimpleModList::enableMods(const QModelIndexList& indexes, bool enable)
 {
-	if(indexes.isEmpty())
-		return true;
-
-	for (auto i: indexes)
-	{
-		Mod &m = mods[i.row()];
-		m.enable(enable);
-		emit dataChanged(i, i);
-	}
-	emit changed();
-	return true;
+    if(indexes.isEmpty())
+        return true;
+
+    for (auto i: indexes)
+    {
+        Mod &m = mods[i.row()];
+        m.enable(enable);
+        emit dataChanged(i, i);
+    }
+    emit changed();
+    return true;
 }
 
 bool SimpleModList::deleteMods(const QModelIndexList& indexes)
 {
-	if(indexes.isEmpty())
-		return true;
-
-	for (auto i: indexes)
-	{
-		Mod &m = mods[i.row()];
-		m.destroy();
-	}
-	emit changed();
-	return true;
+    if(indexes.isEmpty())
+        return true;
+
+    for (auto i: indexes)
+    {
+        Mod &m = mods[i.row()];
+        m.destroy();
+    }
+    emit changed();
+    return true;
 }
 
 int SimpleModList::columnCount(const QModelIndex &parent) const
 {
-	return NUM_COLUMNS;
+    return NUM_COLUMNS;
 }
 
 QVariant SimpleModList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	int row = index.row();
-	int column = index.column();
-
-	if (row < 0 || row >= mods.size())
-		return QVariant();
-
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (column)
-		{
-		case NameColumn:
-			return mods[row].name();
-		case VersionColumn:
-			return mods[row].version();
-		case DateColumn:
-			return mods[row].dateTimeChanged();
-
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		return mods[row].mmc_id();
-
-	case Qt::CheckStateRole:
-		switch (column)
-		{
-		case ActiveColumn:
-			return mods[row].enabled() ? Qt::Checked : Qt::Unchecked;
-		default:
-			return QVariant();
-		}
-	default:
-		return QVariant();
-	}
+    if (!index.isValid())
+        return QVariant();
+
+    int row = index.row();
+    int column = index.column();
+
+    if (row < 0 || row >= mods.size())
+        return QVariant();
+
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (column)
+        {
+        case NameColumn:
+            return mods[row].name();
+        case VersionColumn:
+            return mods[row].version();
+        case DateColumn:
+            return mods[row].dateTimeChanged();
+
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        return mods[row].mmc_id();
+
+    case Qt::CheckStateRole:
+        switch (column)
+        {
+        case ActiveColumn:
+            return mods[row].enabled() ? Qt::Checked : Qt::Unchecked;
+        default:
+            return QVariant();
+        }
+    default:
+        return QVariant();
+    }
 }
 
 bool SimpleModList::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-	if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
-	{
-		return false;
-	}
-
-	if (role == Qt::CheckStateRole)
-	{
-		auto &mod = mods[index.row()];
-		if (mod.enable(!mod.enabled()))
-		{
-			emit dataChanged(index, index);
-			return true;
-		}
-	}
-	return false;
+    if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
+    {
+        return false;
+    }
+
+    if (role == Qt::CheckStateRole)
+    {
+        auto &mod = mods[index.row()];
+        if (mod.enable(!mod.enabled()))
+        {
+            emit dataChanged(index, index);
+            return true;
+        }
+    }
+    return false;
 }
 
 QVariant SimpleModList::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (section)
-		{
-		case ActiveColumn:
-			return QString();
-		case NameColumn:
-			return tr("Name");
-		case VersionColumn:
-			return tr("Version");
-		case DateColumn:
-			return tr("Last changed");
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		switch (section)
-		{
-		case ActiveColumn:
-			return tr("Is the mod enabled?");
-		case NameColumn:
-			return tr("The name of the mod.");
-		case VersionColumn:
-			return tr("The version of the mod.");
-		case DateColumn:
-			return tr("The date and time this mod was last changed (or added).");
-		default:
-			return QVariant();
-		}
-	default:
-		return QVariant();
-	}
-	return QVariant();
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (section)
+        {
+        case ActiveColumn:
+            return QString();
+        case NameColumn:
+            return tr("Name");
+        case VersionColumn:
+            return tr("Version");
+        case DateColumn:
+            return tr("Last changed");
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        switch (section)
+        {
+        case ActiveColumn:
+            return tr("Is the mod enabled?");
+        case NameColumn:
+            return tr("The name of the mod.");
+        case VersionColumn:
+            return tr("The version of the mod.");
+        case DateColumn:
+            return tr("The date and time this mod was last changed (or added).");
+        default:
+            return QVariant();
+        }
+    default:
+        return QVariant();
+    }
+    return QVariant();
 }
 
 Qt::ItemFlags SimpleModList::flags(const QModelIndex &index) const
 {
-	Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
-	if (index.isValid())
-		return Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled |
-			   defaultFlags;
-	else
-		return Qt::ItemIsDropEnabled | defaultFlags;
+    Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
+    if (index.isValid())
+        return Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled |
+               defaultFlags;
+    else
+        return Qt::ItemIsDropEnabled | defaultFlags;
 }
 
 Qt::DropActions SimpleModList::supportedDropActions() const
 {
-	// copy from outside, move from within and other mod lists
-	return Qt::CopyAction | Qt::MoveAction;
+    // copy from outside, move from within and other mod lists
+    return Qt::CopyAction | Qt::MoveAction;
 }
 
 QStringList SimpleModList::mimeTypes() const
 {
-	QStringList types;
-	types << "text/uri-list";
-	return types;
+    QStringList types;
+    types << "text/uri-list";
+    return types;
 }
 
 bool SimpleModList::dropMimeData(const QMimeData* data, Qt::DropAction action, int, int, const QModelIndex&)
 {
-	if (action == Qt::IgnoreAction)
-	{
-		return true;
-	}
-
-	// check if the action is supported
-	if (!data || !(action & supportedDropActions()))
-	{
-		return false;
-	}
-
-	// files dropped from outside?
-	if (data->hasUrls())
-	{
-		bool was_watching = is_watching;
-		if (was_watching)
-		{
-			stopWatching();
-		}
-		auto urls = data->urls();
-		for (auto url : urls)
-		{
-			// only local files may be dropped...
-			if (!url.isLocalFile())
-			{
-				continue;
-			}
-			// TODO: implement not only copy, but also move
-			// FIXME: handle errors here
-			installMod(url.toLocalFile());
-		}
-		if (was_watching)
-		{
-			startWatching();
-		}
-		return true;
-	}
-	return false;
+    if (action == Qt::IgnoreAction)
+    {
+        return true;
+    }
+
+    // check if the action is supported
+    if (!data || !(action & supportedDropActions()))
+    {
+        return false;
+    }
+
+    // files dropped from outside?
+    if (data->hasUrls())
+    {
+        bool was_watching = is_watching;
+        if (was_watching)
+        {
+            stopWatching();
+        }
+        auto urls = data->urls();
+        for (auto url : urls)
+        {
+            // only local files may be dropped...
+            if (!url.isLocalFile())
+            {
+                continue;
+            }
+            // TODO: implement not only copy, but also move
+            // FIXME: handle errors here
+            installMod(url.toLocalFile());
+        }
+        if (was_watching)
+        {
+            startWatching();
+        }
+        return true;
+    }
+    return false;
 }
diff --git a/api/logic/minecraft/SimpleModList.h b/api/logic/minecraft/SimpleModList.h
index 3257edbe..d623a295 100644
--- a/api/logic/minecraft/SimpleModList.h
+++ b/api/logic/minecraft/SimpleModList.h
@@ -34,88 +34,88 @@ class QFileSystemWatcher;
  */
 class MULTIMC_LOGIC_EXPORT SimpleModList : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum Columns
-	{
-		ActiveColumn = 0,
-		NameColumn,
-		DateColumn,
-		VersionColumn,
-		NUM_COLUMNS
-	};
-	SimpleModList(const QString &dir);
-
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-	virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
-	Qt::DropActions supportedDropActions() const override;
-
-	/// flags, mostly to support drag&drop
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
-	QStringList mimeTypes() const override;
-	bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
-
-	virtual int rowCount(const QModelIndex &) const override
-	{
-		return size();
-	}
-	;
-	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
-	virtual int columnCount(const QModelIndex &parent) const override;
-
-	size_t size() const
-	{
-		return mods.size();
-	}
-	;
-	bool empty() const
-	{
-		return size() == 0;
-	}
-	Mod &operator[](size_t index)
-	{
-		return mods[index];
-	}
-
-	/// Reloads the mod list and returns true if the list changed.
-	virtual bool update();
-
-	/**
-	 * Adds the given mod to the list at the given index - if the list supports custom ordering
-	 */
-	bool installMod(const QString& filename);
-
-	/// Deletes all the selected mods
-	virtual bool deleteMods(const QModelIndexList &indexes);
-
-	/// Enable or disable listed mods
-	virtual bool enableMods(const QModelIndexList &indexes, bool enable = true);
-
-	void startWatching();
-	void stopWatching();
-
-	virtual bool isValid();
-
-	QDir dir()
-	{
-		return m_dir;
-	}
-
-	const QList<Mod> & allMods()
-	{
-		return mods;
-	}
+    enum Columns
+    {
+        ActiveColumn = 0,
+        NameColumn,
+        DateColumn,
+        VersionColumn,
+        NUM_COLUMNS
+    };
+    SimpleModList(const QString &dir);
+
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+    Qt::DropActions supportedDropActions() const override;
+
+    /// flags, mostly to support drag&drop
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
+    QStringList mimeTypes() const override;
+    bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override;
+
+    virtual int rowCount(const QModelIndex &) const override
+    {
+        return size();
+    }
+    ;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+    virtual int columnCount(const QModelIndex &parent) const override;
+
+    size_t size() const
+    {
+        return mods.size();
+    }
+    ;
+    bool empty() const
+    {
+        return size() == 0;
+    }
+    Mod &operator[](size_t index)
+    {
+        return mods[index];
+    }
+
+    /// Reloads the mod list and returns true if the list changed.
+    virtual bool update();
+
+    /**
+     * Adds the given mod to the list at the given index - if the list supports custom ordering
+     */
+    bool installMod(const QString& filename);
+
+    /// Deletes all the selected mods
+    virtual bool deleteMods(const QModelIndexList &indexes);
+
+    /// Enable or disable listed mods
+    virtual bool enableMods(const QModelIndexList &indexes, bool enable = true);
+
+    void startWatching();
+    void stopWatching();
+
+    virtual bool isValid();
+
+    QDir dir()
+    {
+        return m_dir;
+    }
+
+    const QList<Mod> & allMods()
+    {
+        return mods;
+    }
 
 private
 slots:
-	void directoryChanged(QString path);
+    void directoryChanged(QString path);
 
 signals:
-	void changed();
+    void changed();
 
 protected:
-	QFileSystemWatcher *m_watcher;
-	bool is_watching = false;
-	QDir m_dir;
-	QList<Mod> mods;
+    QFileSystemWatcher *m_watcher;
+    bool is_watching = false;
+    QDir m_dir;
+    QList<Mod> mods;
 };
diff --git a/api/logic/minecraft/SimpleModList_test.cpp b/api/logic/minecraft/SimpleModList_test.cpp
index 28ce8471..a100b539 100644
--- a/api/logic/minecraft/SimpleModList_test.cpp
+++ b/api/logic/minecraft/SimpleModList_test.cpp
@@ -8,44 +8,44 @@
 
 class SimpleModListTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 
 private
 slots:
-	// test for GH-1178 - install a folder with files to a mod list
-	void test_1178()
-	{
-		// source
-		QString source = QFINDTESTDATA("data/test_folder");
-
-		// sanity check
-		QVERIFY(!source.endsWith('/'));
-
-		auto verify = [](QString path)
-		{
-			QDir target_dir(FS::PathCombine(path, "test_folder"));
-			QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
-			QVERIFY(target_dir.entryList().contains("assets"));
-		};
-
-		// 1. test with no trailing /
-		{
-			QString folder = source;
-			QTemporaryDir tempDir;
-			SimpleModList m(tempDir.path());
-			m.installMod(folder);
-			verify(tempDir.path());
-		}
-
-		// 2. test with trailing /
-		{
-			QString folder = source + '/';
-			QTemporaryDir tempDir;
-			SimpleModList m(tempDir.path());
-			m.installMod(folder);
-			verify(tempDir.path());
-		}
-	}
+    // test for GH-1178 - install a folder with files to a mod list
+    void test_1178()
+    {
+        // source
+        QString source = QFINDTESTDATA("data/test_folder");
+
+        // sanity check
+        QVERIFY(!source.endsWith('/'));
+
+        auto verify = [](QString path)
+        {
+            QDir target_dir(FS::PathCombine(path, "test_folder"));
+            QVERIFY(target_dir.entryList().contains("pack.mcmeta"));
+            QVERIFY(target_dir.entryList().contains("assets"));
+        };
+
+        // 1. test with no trailing /
+        {
+            QString folder = source;
+            QTemporaryDir tempDir;
+            SimpleModList m(tempDir.path());
+            m.installMod(folder);
+            verify(tempDir.path());
+        }
+
+        // 2. test with trailing /
+        {
+            QString folder = source + '/';
+            QTemporaryDir tempDir;
+            SimpleModList m(tempDir.path());
+            m.installMod(folder);
+            verify(tempDir.path());
+        }
+    }
 };
 
 QTEST_GUILESS_MAIN(SimpleModListTest)
diff --git a/api/logic/minecraft/SkinUpload.cpp b/api/logic/minecraft/SkinUpload.cpp
index bd246139..83bdf592 100644
--- a/api/logic/minecraft/SkinUpload.cpp
+++ b/api/logic/minecraft/SkinUpload.cpp
@@ -4,66 +4,66 @@
 #include <Env.h>
 
 QByteArray getModelString(SkinUpload::Model model) {
-	switch (model) {
-		case SkinUpload::STEVE:
-			return "";
-		case SkinUpload::ALEX:
-			return "slim";
-		default:
-			qDebug() << "Unknown skin type!";
-			return "";
-	}
+    switch (model) {
+        case SkinUpload::STEVE:
+            return "";
+        case SkinUpload::ALEX:
+            return "slim";
+        default:
+            qDebug() << "Unknown skin type!";
+            return "";
+    }
 }
 
 SkinUpload::SkinUpload(QObject *parent, AuthSessionPtr session, QByteArray skin, SkinUpload::Model model)
-	: Task(parent), m_model(model), m_skin(skin), m_session(session)
+    : Task(parent), m_model(model), m_skin(skin), m_session(session)
 {
 }
 
 void SkinUpload::executeTask()
 {
-	QNetworkRequest request(QUrl(QString("https://api.mojang.com/user/profile/%1/skin").arg(m_session->uuid)));
-	request.setRawHeader("Authorization", QString("Bearer: %1").arg(m_session->access_token).toLocal8Bit());
+    QNetworkRequest request(QUrl(QString("https://api.mojang.com/user/profile/%1/skin").arg(m_session->uuid)));
+    request.setRawHeader("Authorization", QString("Bearer: %1").arg(m_session->access_token).toLocal8Bit());
 
-	QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
+    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
 
-	QHttpPart model;
-	model.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model\""));
-	model.setBody(getModelString(m_model));
+    QHttpPart model;
+    model.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model\""));
+    model.setBody(getModelString(m_model));
 
-	QHttpPart skin;
-	skin.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
-	skin.setHeader(QNetworkRequest::ContentDispositionHeader,
-				QVariant("form-data; name=\"file\"; filename=\"skin.png\""));
-	skin.setBody(m_skin);
+    QHttpPart skin;
+    skin.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
+    skin.setHeader(QNetworkRequest::ContentDispositionHeader,
+                QVariant("form-data; name=\"file\"; filename=\"skin.png\""));
+    skin.setBody(m_skin);
 
-	multiPart->append(model);
-	multiPart->append(skin);
+    multiPart->append(model);
+    multiPart->append(skin);
 
-	QNetworkReply *rep = ENV.qnam().put(request, multiPart);
-	m_reply = std::shared_ptr<QNetworkReply>(rep);
+    QNetworkReply *rep = ENV.qnam().put(request, multiPart);
+    m_reply = std::shared_ptr<QNetworkReply>(rep);
 
-	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(finished()), this, SLOT(downloadFinished()));
+    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(finished()), this, SLOT(downloadFinished()));
 }
 
 void SkinUpload::downloadError(QNetworkReply::NetworkError error)
 {
-	// error happened during download.
-	qCritical() << "Network error: " << error;
-	emitFailed(m_reply->errorString());
+    // error happened during download.
+    qCritical() << "Network error: " << error;
+    emitFailed(m_reply->errorString());
 }
 
 void SkinUpload::downloadFinished()
 {
-	// if the download failed
-	if (m_reply->error() != QNetworkReply::NetworkError::NoError)
-	{
-		emitFailed(QString("Network error: %1").arg(m_reply->errorString()));
-		m_reply.reset();
-		return;
-	}
-	emitSucceeded();
+    // if the download failed
+    if (m_reply->error() != QNetworkReply::NetworkError::NoError)
+    {
+        emitFailed(QString("Network error: %1").arg(m_reply->errorString()));
+        m_reply.reset();
+        return;
+    }
+    emitSucceeded();
 }
diff --git a/api/logic/minecraft/SkinUpload.h b/api/logic/minecraft/SkinUpload.h
index c47283b1..c77abb03 100644
--- a/api/logic/minecraft/SkinUpload.h
+++ b/api/logic/minecraft/SkinUpload.h
@@ -11,29 +11,29 @@ typedef std::shared_ptr<class SkinUpload> SkinUploadPtr;
 
 class MULTIMC_LOGIC_EXPORT SkinUpload : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum Model
-	{
-		STEVE,
-		ALEX
-	};
+    enum Model
+    {
+        STEVE,
+        ALEX
+    };
 
-	// Note this class takes ownership of the file.
-	SkinUpload(QObject *parent, AuthSessionPtr session, QByteArray skin, Model model = STEVE);
-	virtual ~SkinUpload() {}
+    // Note this class takes ownership of the file.
+    SkinUpload(QObject *parent, AuthSessionPtr session, QByteArray skin, Model model = STEVE);
+    virtual ~SkinUpload() {}
 
 private:
-	Model m_model;
-	QByteArray m_skin;
-	AuthSessionPtr m_session;
-	std::shared_ptr<QNetworkReply> m_reply;
+    Model m_model;
+    QByteArray m_skin;
+    AuthSessionPtr m_session;
+    std::shared_ptr<QNetworkReply> m_reply;
 protected:
-	virtual void executeTask();
+    virtual void executeTask();
 
 public slots:
 
-	void downloadError(QNetworkReply::NetworkError);
+    void downloadError(QNetworkReply::NetworkError);
 
-	void downloadFinished();
+    void downloadFinished();
 };
diff --git a/api/logic/minecraft/VersionFile.cpp b/api/logic/minecraft/VersionFile.cpp
index 9f485c55..cfb9e504 100644
--- a/api/logic/minecraft/VersionFile.cpp
+++ b/api/logic/minecraft/VersionFile.cpp
@@ -12,45 +12,45 @@
 
 static bool isMinecraftVersion(const QString &uid)
 {
-	return uid == "net.minecraft";
+    return uid == "net.minecraft";
 }
 
 void VersionFile::applyTo(LaunchProfile *profile)
 {
-	// Only real Minecraft can set those. Don't let anything override them.
-	if (isMinecraftVersion(uid))
-	{
-		profile->applyMinecraftVersion(minecraftVersion);
-		profile->applyMinecraftVersionType(type);
-		// HACK: ignore assets from other version files than Minecraft
-		// workaround for stupid assets issue caused by amazon:
-		// https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
-		profile->applyMinecraftAssets(mojangAssetIndex);
-	}
-
-	profile->applyMainJar(mainJar);
-	profile->applyMainClass(mainClass);
-	profile->applyAppletClass(appletClass);
-	profile->applyMinecraftArguments(minecraftArguments);
-	profile->applyTweakers(addTweakers);
-	profile->applyJarMods(jarMods);
-	profile->applyMods(mods);
-	profile->applyTraits(traits);
-
-	for (auto library : libraries)
-	{
-		profile->applyLibrary(library);
-	}
-	profile->applyProblemSeverity(getProblemSeverity());
+    // Only real Minecraft can set those. Don't let anything override them.
+    if (isMinecraftVersion(uid))
+    {
+        profile->applyMinecraftVersion(minecraftVersion);
+        profile->applyMinecraftVersionType(type);
+        // HACK: ignore assets from other version files than Minecraft
+        // workaround for stupid assets issue caused by amazon:
+        // https://www.theregister.co.uk/2017/02/28/aws_is_awol_as_s3_goes_haywire/
+        profile->applyMinecraftAssets(mojangAssetIndex);
+    }
+
+    profile->applyMainJar(mainJar);
+    profile->applyMainClass(mainClass);
+    profile->applyAppletClass(appletClass);
+    profile->applyMinecraftArguments(minecraftArguments);
+    profile->applyTweakers(addTweakers);
+    profile->applyJarMods(jarMods);
+    profile->applyMods(mods);
+    profile->applyTraits(traits);
+
+    for (auto library : libraries)
+    {
+        profile->applyLibrary(library);
+    }
+    profile->applyProblemSeverity(getProblemSeverity());
 }
 
 /*
-	auto theirVersion = profile->getMinecraftVersion();
-	if (!theirVersion.isNull() && !dependsOnMinecraftVersion.isNull())
-	{
-		if (QRegExp(dependsOnMinecraftVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1)
-		{
-			throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion);
-		}
-	}
+    auto theirVersion = profile->getMinecraftVersion();
+    if (!theirVersion.isNull() && !dependsOnMinecraftVersion.isNull())
+    {
+        if (QRegExp(dependsOnMinecraftVersion, Qt::CaseInsensitive, QRegExp::Wildcard).indexIn(theirVersion) == -1)
+        {
+            throw MinecraftVersionMismatch(uid, dependsOnMinecraftVersion, theirVersion);
+        }
+    }
 */
\ No newline at end of file
diff --git a/api/logic/minecraft/VersionFile.h b/api/logic/minecraft/VersionFile.h
index 5aea7a7a..3dc9db96 100644
--- a/api/logic/minecraft/VersionFile.h
+++ b/api/logic/minecraft/VersionFile.h
@@ -21,91 +21,91 @@ struct MojangAssetIndexInfo;
 using VersionFilePtr = std::shared_ptr<VersionFile>;
 class VersionFile : public ProblemContainer
 {
-	friend class MojangVersionFormat;
-	friend class OneSixVersionFormat;
+    friend class MojangVersionFormat;
+    friend class OneSixVersionFormat;
 public: /* methods */
-	void applyTo(LaunchProfile* profile);
+    void applyTo(LaunchProfile* profile);
 
 public: /* data */
-	/// MultiMC: order hint for this version file if no explicit order is set
-	int order = 0;
+    /// MultiMC: order hint for this version file if no explicit order is set
+    int order = 0;
 
-	/// MultiMC: human readable name of this package
-	QString name;
+    /// MultiMC: human readable name of this package
+    QString name;
 
-	/// MultiMC: package ID of this package
-	QString uid;
+    /// MultiMC: package ID of this package
+    QString uid;
 
-	/// MultiMC: version of this package
-	QString version;
+    /// MultiMC: version of this package
+    QString version;
 
-	/// MultiMC: DEPRECATED dependency on a Minecraft version
-	QString dependsOnMinecraftVersion;
+    /// MultiMC: DEPRECATED dependency on a Minecraft version
+    QString dependsOnMinecraftVersion;
 
-	/// Mojang: DEPRECATED used to version the Mojang version format
-	int minimumLauncherVersion = -1;
+    /// Mojang: DEPRECATED used to version the Mojang version format
+    int minimumLauncherVersion = -1;
 
-	/// Mojang: DEPRECATED version of Minecraft this is
-	QString minecraftVersion;
+    /// Mojang: DEPRECATED version of Minecraft this is
+    QString minecraftVersion;
 
-	/// Mojang: class to launch Minecraft with
-	QString mainClass;
+    /// Mojang: class to launch Minecraft with
+    QString mainClass;
 
-	/// MultiMC: class to launch legacy Minecraft with (embed in a custom window)
-	QString appletClass;
+    /// MultiMC: class to launch legacy Minecraft with (embed in a custom window)
+    QString appletClass;
 
-	/// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
-	QString minecraftArguments;
+    /// Mojang: Minecraft launch arguments (may contain placeholders for variable substitution)
+    QString minecraftArguments;
 
-	/// Mojang: type of the Minecraft version
-	QString type;
+    /// Mojang: type of the Minecraft version
+    QString type;
 
-	/// Mojang: the time this version was actually released by Mojang
-	QDateTime releaseTime;
+    /// Mojang: the time this version was actually released by Mojang
+    QDateTime releaseTime;
 
-	/// Mojang: DEPRECATED the time this version was last updated by Mojang
-	QDateTime updateTime;
+    /// Mojang: DEPRECATED the time this version was last updated by Mojang
+    QDateTime updateTime;
 
-	/// Mojang: DEPRECATED asset group to be used with Minecraft
-	QString assets;
+    /// Mojang: DEPRECATED asset group to be used with Minecraft
+    QString assets;
 
-	/// MultiMC: list of tweaker mod arguments for launchwrapper
-	QStringList addTweakers;
+    /// MultiMC: list of tweaker mod arguments for launchwrapper
+    QStringList addTweakers;
 
-	/// Mojang: list of libraries to add to the version
-	QList<LibraryPtr> libraries;
+    /// Mojang: list of libraries to add to the version
+    QList<LibraryPtr> libraries;
 
-	/// The main jar (Minecraft version library, normally)
-	LibraryPtr mainJar;
+    /// The main jar (Minecraft version library, normally)
+    LibraryPtr mainJar;
 
-	/// MultiMC: list of attached traits of this version file - used to enable features
-	QSet<QString> traits;
+    /// MultiMC: list of attached traits of this version file - used to enable features
+    QSet<QString> traits;
 
-	/// MultiMC: list of jar mods added to this version
-	QList<LibraryPtr> jarMods;
+    /// MultiMC: list of jar mods added to this version
+    QList<LibraryPtr> jarMods;
 
-	/// MultiMC: list of mods added to this version
-	QList<LibraryPtr> mods;
+    /// MultiMC: list of mods added to this version
+    QList<LibraryPtr> mods;
 
-	/**
-	 * MultiMC: set of packages this depends on
-	 * NOTE: this is shared with the meta format!!!
-	 */
-	Meta::RequireSet requires;
+    /**
+     * MultiMC: set of packages this depends on
+     * NOTE: this is shared with the meta format!!!
+     */
+    Meta::RequireSet requires;
 
-	/**
-	 * MultiMC: set of packages this conflicts with
-	 * NOTE: this is shared with the meta format!!!
-	 */
-	Meta::RequireSet conflicts;
+    /**
+     * MultiMC: set of packages this conflicts with
+     * NOTE: this is shared with the meta format!!!
+     */
+    Meta::RequireSet conflicts;
 
-	/// is volatile -- may be removed as soon as it is no longer needed by something else
-	bool m_volatile = false;
+    /// is volatile -- may be removed as soon as it is no longer needed by something else
+    bool m_volatile = false;
 
 public:
-	// Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more.
-	QMap <QString, std::shared_ptr<MojangDownloadInfo>> mojangDownloads;
+    // Mojang: DEPRECATED list of 'downloads' - client jar, server jar, windows server exe, maybe more.
+    QMap <QString, std::shared_ptr<MojangDownloadInfo>> mojangDownloads;
 
-	// Mojang: extended asset index download information
-	std::shared_ptr<MojangAssetIndexInfo> mojangAssetIndex;
+    // Mojang: extended asset index download information
+    std::shared_ptr<MojangAssetIndexInfo> mojangAssetIndex;
 };
diff --git a/api/logic/minecraft/VersionFilterData.cpp b/api/logic/minecraft/VersionFilterData.cpp
index 5f4ceee6..11f7eea9 100644
--- a/api/logic/minecraft/VersionFilterData.cpp
+++ b/api/logic/minecraft/VersionFilterData.cpp
@@ -5,64 +5,64 @@ VersionFilterData g_VersionFilterData = VersionFilterData();
 
 VersionFilterData::VersionFilterData()
 {
-	// 1.3.*
-	auto libs13 =
-		QList<FMLlib>{{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
-					  {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
-					  {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}};
+    // 1.3.*
+    auto libs13 =
+        QList<FMLlib>{{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
+                      {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
+                      {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}};
 
-	fmlLibsMapping["1.3.2"] = libs13;
+    fmlLibsMapping["1.3.2"] = libs13;
 
-	// 1.4.*
-	auto libs14 = QList<FMLlib>{
-		{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
-		{"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
-		{"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false},
-		{"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb", false}};
+    // 1.4.*
+    auto libs14 = QList<FMLlib>{
+        {"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
+        {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
+        {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false},
+        {"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb", false}};
 
-	fmlLibsMapping["1.4"] = libs14;
-	fmlLibsMapping["1.4.1"] = libs14;
-	fmlLibsMapping["1.4.2"] = libs14;
-	fmlLibsMapping["1.4.3"] = libs14;
-	fmlLibsMapping["1.4.4"] = libs14;
-	fmlLibsMapping["1.4.5"] = libs14;
-	fmlLibsMapping["1.4.6"] = libs14;
-	fmlLibsMapping["1.4.7"] = libs14;
+    fmlLibsMapping["1.4"] = libs14;
+    fmlLibsMapping["1.4.1"] = libs14;
+    fmlLibsMapping["1.4.2"] = libs14;
+    fmlLibsMapping["1.4.3"] = libs14;
+    fmlLibsMapping["1.4.4"] = libs14;
+    fmlLibsMapping["1.4.5"] = libs14;
+    fmlLibsMapping["1.4.6"] = libs14;
+    fmlLibsMapping["1.4.7"] = libs14;
 
-	// 1.5
-	fmlLibsMapping["1.5"] = QList<FMLlib>{
-		{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
-		{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
-		{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
-		{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
-		{"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8", false},
-		{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
+    // 1.5
+    fmlLibsMapping["1.5"] = QList<FMLlib>{
+        {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
+        {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
+        {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
+        {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
+        {"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8", false},
+        {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
 
-	// 1.5.1
-	fmlLibsMapping["1.5.1"] = QList<FMLlib>{
-		{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
-		{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
-		{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
-		{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
-		{"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6", false},
-		{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
+    // 1.5.1
+    fmlLibsMapping["1.5.1"] = QList<FMLlib>{
+        {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
+        {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
+        {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
+        {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
+        {"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6", false},
+        {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
 
-	// 1.5.2
-	fmlLibsMapping["1.5.2"] = QList<FMLlib>{
-		{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
-		{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
-		{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
-		{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
-		{"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9", false},
-		{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
+    // 1.5.2
+    fmlLibsMapping["1.5.2"] = QList<FMLlib>{
+        {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
+        {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
+        {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
+        {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
+        {"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9", false},
+        {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
 
-	// don't use installers for those.
-	forgeInstallerBlacklist = QSet<QString>({"1.5.2"});
+    // don't use installers for those.
+    forgeInstallerBlacklist = QSet<QString>({"1.5.2"});
 
-	// FIXME: remove, used for deciding when core mods should display
-	legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00");
-	lwjglWhitelist =
-		QSet<QString>{"net.java.jinput:jinput",	 "net.java.jinput:jinput-platform",
-					  "net.java.jutils:jutils",	 "org.lwjgl.lwjgl:lwjgl",
-					  "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
+    // FIXME: remove, used for deciding when core mods should display
+    legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00");
+    lwjglWhitelist =
+        QSet<QString>{"net.java.jinput:jinput",     "net.java.jinput:jinput-platform",
+                      "net.java.jutils:jutils",     "org.lwjgl.lwjgl:lwjgl",
+                      "org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
 }
diff --git a/api/logic/minecraft/VersionFilterData.h b/api/logic/minecraft/VersionFilterData.h
index 2408e704..88e91f11 100644
--- a/api/logic/minecraft/VersionFilterData.h
+++ b/api/logic/minecraft/VersionFilterData.h
@@ -8,21 +8,21 @@
 
 struct FMLlib
 {
-	QString filename;
-	QString checksum;
-	bool ours;
+    QString filename;
+    QString checksum;
+    bool ours;
 };
 
 struct VersionFilterData
 {
-	VersionFilterData();
-	// mapping between minecraft versions and FML libraries required
-	QMap<QString, QList<FMLlib>> fmlLibsMapping;
-	// set of minecraft versions for which using forge installers is blacklisted
-	QSet<QString> forgeInstallerBlacklist;
-	// no new versions below this date will be accepted from Mojang servers
-	QDateTime legacyCutoffDate;
-	// Libraries that belong to LWJGL
-	QSet<QString> lwjglWhitelist;
+    VersionFilterData();
+    // mapping between minecraft versions and FML libraries required
+    QMap<QString, QList<FMLlib>> fmlLibsMapping;
+    // set of minecraft versions for which using forge installers is blacklisted
+    QSet<QString> forgeInstallerBlacklist;
+    // no new versions below this date will be accepted from Mojang servers
+    QDateTime legacyCutoffDate;
+    // Libraries that belong to LWJGL
+    QSet<QString> lwjglWhitelist;
 };
 extern VersionFilterData MULTIMC_LOGIC_EXPORT g_VersionFilterData;
diff --git a/api/logic/minecraft/World.cpp b/api/logic/minecraft/World.cpp
index d7bc4553..b39f940e 100644
--- a/api/logic/minecraft/World.cpp
+++ b/api/logic/minecraft/World.cpp
@@ -32,354 +32,354 @@
 
 std::unique_ptr <nbt::tag_compound> parseLevelDat(QByteArray data)
 {
-	QByteArray output;
-	if(!GZip::unzip(data, output))
-	{
-		return nullptr;
-	}
-	std::istringstream foo(std::string(output.constData(), output.size()));
-	auto pair = nbt::io::read_compound(foo);
+    QByteArray output;
+    if(!GZip::unzip(data, output))
+    {
+        return nullptr;
+    }
+    std::istringstream foo(std::string(output.constData(), output.size()));
+    auto pair = nbt::io::read_compound(foo);
 
-	if(pair.first != "")
-		return nullptr;
+    if(pair.first != "")
+        return nullptr;
 
-	if(pair.second == nullptr)
-		return nullptr;
+    if(pair.second == nullptr)
+        return nullptr;
 
-	return std::move(pair.second);
+    return std::move(pair.second);
 }
 
 QByteArray serializeLevelDat(nbt::tag_compound * levelInfo)
 {
-	std::ostringstream s;
-	nbt::io::write_tag("", *levelInfo, s);
-	QByteArray val( s.str().data(), (int) s.str().size() );
-	return val;
+    std::ostringstream s;
+    nbt::io::write_tag("", *levelInfo, s);
+    QByteArray val( s.str().data(), (int) s.str().size() );
+    return val;
 }
 
 QString getLevelDatFromFS(const QFileInfo &file)
 {
-	QDir worldDir(file.filePath());
-	if(!file.isDir() || !worldDir.exists("level.dat"))
-	{
-		return QString();
-	}
-	return worldDir.absoluteFilePath("level.dat");
+    QDir worldDir(file.filePath());
+    if(!file.isDir() || !worldDir.exists("level.dat"))
+    {
+        return QString();
+    }
+    return worldDir.absoluteFilePath("level.dat");
 }
 
 QByteArray getLevelDatDataFromFS(const QFileInfo &file)
 {
-	auto fullFilePath = getLevelDatFromFS(file);
-	if(fullFilePath.isNull())
-	{
-		return QByteArray();
-	}
-	QFile f(fullFilePath);
-	if(!f.open(QIODevice::ReadOnly))
-	{
-		return QByteArray();
-	}
-	return f.readAll();
+    auto fullFilePath = getLevelDatFromFS(file);
+    if(fullFilePath.isNull())
+    {
+        return QByteArray();
+    }
+    QFile f(fullFilePath);
+    if(!f.open(QIODevice::ReadOnly))
+    {
+        return QByteArray();
+    }
+    return f.readAll();
 }
 
 bool putLevelDatDataToFS(const QFileInfo &file, QByteArray & data)
 {
-	auto fullFilePath =  getLevelDatFromFS(file);
-	if(fullFilePath.isNull())
-	{
-		return false;
-	}
-	QSaveFile f(fullFilePath);
-	if(!f.open(QIODevice::WriteOnly))
-	{
-		return false;
-	}
-	QByteArray compressed;
-	if(!GZip::zip(data, compressed))
-	{
-		return false;
-	}
-	if(f.write(compressed) != compressed.size())
-	{
-		f.cancelWriting();
-		return false;
-	}
-	return f.commit();
+    auto fullFilePath =  getLevelDatFromFS(file);
+    if(fullFilePath.isNull())
+    {
+        return false;
+    }
+    QSaveFile f(fullFilePath);
+    if(!f.open(QIODevice::WriteOnly))
+    {
+        return false;
+    }
+    QByteArray compressed;
+    if(!GZip::zip(data, compressed))
+    {
+        return false;
+    }
+    if(f.write(compressed) != compressed.size())
+    {
+        f.cancelWriting();
+        return false;
+    }
+    return f.commit();
 }
 
 World::World(const QFileInfo &file)
 {
-	repath(file);
+    repath(file);
 }
 
 void World::repath(const QFileInfo &file)
 {
-	m_containerFile = file;
-	m_folderName = file.fileName();
-	if(file.isFile() && file.suffix() == "zip")
-	{
-		readFromZip(file);
-	}
-	else if(file.isDir())
-	{
-		readFromFS(file);
-	}
+    m_containerFile = file;
+    m_folderName = file.fileName();
+    if(file.isFile() && file.suffix() == "zip")
+    {
+        readFromZip(file);
+    }
+    else if(file.isDir())
+    {
+        readFromFS(file);
+    }
 }
 
 void World::readFromFS(const QFileInfo &file)
 {
-	auto bytes = getLevelDatDataFromFS(file);
-	if(bytes.isEmpty())
-	{
-		is_valid = false;
-		return;
-	}
-	loadFromLevelDat(bytes);
-	levelDatTime = file.lastModified();
+    auto bytes = getLevelDatDataFromFS(file);
+    if(bytes.isEmpty())
+    {
+        is_valid = false;
+        return;
+    }
+    loadFromLevelDat(bytes);
+    levelDatTime = file.lastModified();
 }
 
 void World::readFromZip(const QFileInfo &file)
 {
-	QuaZip zip(file.absoluteFilePath());
-	is_valid = zip.open(QuaZip::mdUnzip);
-	if (!is_valid)
-	{
-		return;
-	}
-	auto location = MMCZip::findFolderOfFileInZip(&zip, "level.dat");
-	is_valid = !location.isEmpty();
-	if (!is_valid)
-	{
-		return;
-	}
-	m_containerOffsetPath = location;
-	QuaZipFile zippedFile(&zip);
-	// read the install profile
-	is_valid = zip.setCurrentFile(location + "level.dat");
-	if (!is_valid)
-	{
-		return;
-	}
-	is_valid = zippedFile.open(QIODevice::ReadOnly);
-	QuaZipFileInfo64 levelDatInfo;
-	zippedFile.getFileInfo(&levelDatInfo);
-	auto modTime = levelDatInfo.getNTFSmTime();
-	if(!modTime.isValid())
-	{
-		modTime = levelDatInfo.dateTime;
-	}
-	levelDatTime = modTime;
-	if (!is_valid)
-	{
-		return;
-	}
-	loadFromLevelDat(zippedFile.readAll());
-	zippedFile.close();
+    QuaZip zip(file.absoluteFilePath());
+    is_valid = zip.open(QuaZip::mdUnzip);
+    if (!is_valid)
+    {
+        return;
+    }
+    auto location = MMCZip::findFolderOfFileInZip(&zip, "level.dat");
+    is_valid = !location.isEmpty();
+    if (!is_valid)
+    {
+        return;
+    }
+    m_containerOffsetPath = location;
+    QuaZipFile zippedFile(&zip);
+    // read the install profile
+    is_valid = zip.setCurrentFile(location + "level.dat");
+    if (!is_valid)
+    {
+        return;
+    }
+    is_valid = zippedFile.open(QIODevice::ReadOnly);
+    QuaZipFileInfo64 levelDatInfo;
+    zippedFile.getFileInfo(&levelDatInfo);
+    auto modTime = levelDatInfo.getNTFSmTime();
+    if(!modTime.isValid())
+    {
+        modTime = levelDatInfo.dateTime;
+    }
+    levelDatTime = modTime;
+    if (!is_valid)
+    {
+        return;
+    }
+    loadFromLevelDat(zippedFile.readAll());
+    zippedFile.close();
 }
 
 bool World::install(const QString &to, const QString &name)
 {
-	auto finalPath = FS::PathCombine(to, FS::DirNameFromString(m_actualName, to));
-	if(!FS::ensureFolderPathExists(finalPath))
-	{
-		return false;
-	}
-	bool ok = false;
-	if(m_containerFile.isFile())
-	{
-		QuaZip zip(m_containerFile.absoluteFilePath());
-		if (!zip.open(QuaZip::mdUnzip))
-		{
-			return false;
-		}
-		ok = !MMCZip::extractSubDir(&zip, m_containerOffsetPath, finalPath).isEmpty();
-	}
-	else if(m_containerFile.isDir())
-	{
-		QString from = m_containerFile.filePath();
-		ok = FS::copy(from, finalPath)();
-	}
-
-	if(ok && !name.isEmpty() && m_actualName != name)
-	{
-		World newWorld(finalPath);
-		if(newWorld.isValid())
-		{
-			newWorld.rename(name);
-		}
-	}
-	return ok;
+    auto finalPath = FS::PathCombine(to, FS::DirNameFromString(m_actualName, to));
+    if(!FS::ensureFolderPathExists(finalPath))
+    {
+        return false;
+    }
+    bool ok = false;
+    if(m_containerFile.isFile())
+    {
+        QuaZip zip(m_containerFile.absoluteFilePath());
+        if (!zip.open(QuaZip::mdUnzip))
+        {
+            return false;
+        }
+        ok = !MMCZip::extractSubDir(&zip, m_containerOffsetPath, finalPath).isEmpty();
+    }
+    else if(m_containerFile.isDir())
+    {
+        QString from = m_containerFile.filePath();
+        ok = FS::copy(from, finalPath)();
+    }
+
+    if(ok && !name.isEmpty() && m_actualName != name)
+    {
+        World newWorld(finalPath);
+        if(newWorld.isValid())
+        {
+            newWorld.rename(name);
+        }
+    }
+    return ok;
 }
 
 bool World::rename(const QString &newName)
 {
-	if(m_containerFile.isFile())
-	{
-		return false;
-	}
-
-	auto data = getLevelDatDataFromFS(m_containerFile);
-	if(data.isEmpty())
-	{
-		return false;
-	}
-
-	auto worldData = parseLevelDat(data);
-	if(!worldData)
-	{
-		return false;
-	}
-	auto &val = worldData->at("Data");
-	if(val.get_type() != nbt::tag_type::Compound)
-	{
-		return false;
-	}
-	auto &dataCompound = val.as<nbt::tag_compound>();
-	dataCompound.put("LevelName", nbt::value_initializer(newName.toUtf8().data()));
-	data = serializeLevelDat(worldData.get());
-
-	putLevelDatDataToFS(m_containerFile, data);
-
-	m_actualName = newName;
-
-	QDir parentDir(m_containerFile.absoluteFilePath());
-	parentDir.cdUp();
-	QFile container(m_containerFile.absoluteFilePath());
-	auto dirName = FS::DirNameFromString(m_actualName, parentDir.absolutePath());
-	container.rename(parentDir.absoluteFilePath(dirName));
-
-	return true;
+    if(m_containerFile.isFile())
+    {
+        return false;
+    }
+
+    auto data = getLevelDatDataFromFS(m_containerFile);
+    if(data.isEmpty())
+    {
+        return false;
+    }
+
+    auto worldData = parseLevelDat(data);
+    if(!worldData)
+    {
+        return false;
+    }
+    auto &val = worldData->at("Data");
+    if(val.get_type() != nbt::tag_type::Compound)
+    {
+        return false;
+    }
+    auto &dataCompound = val.as<nbt::tag_compound>();
+    dataCompound.put("LevelName", nbt::value_initializer(newName.toUtf8().data()));
+    data = serializeLevelDat(worldData.get());
+
+    putLevelDatDataToFS(m_containerFile, data);
+
+    m_actualName = newName;
+
+    QDir parentDir(m_containerFile.absoluteFilePath());
+    parentDir.cdUp();
+    QFile container(m_containerFile.absoluteFilePath());
+    auto dirName = FS::DirNameFromString(m_actualName, parentDir.absolutePath());
+    container.rename(parentDir.absoluteFilePath(dirName));
+
+    return true;
 }
 
 static QString read_string (nbt::value& parent, const char * name, const QString & fallback = QString())
 {
-	try
-	{
-		auto &namedValue = parent.at(name);
-		if(namedValue.get_type() != nbt::tag_type::String)
-		{
-			return fallback;
-		}
-		auto & tag_str = namedValue.as<nbt::tag_string>();
-		return QString::fromStdString(tag_str.get());
-	}
-	catch (const std::out_of_range &e)
-	{
-		// fallback for old world formats
-		qWarning() << "String NBT tag" << name << "could not be found. Defaulting to" << fallback;
-		return fallback;
-	}
-	catch (const std::bad_cast &e)
-	{
-		// type mismatch
-		qWarning() << "NBT tag" << name << "could not be converted to string. Defaulting to" << fallback;
-		return fallback;
-	}
+    try
+    {
+        auto &namedValue = parent.at(name);
+        if(namedValue.get_type() != nbt::tag_type::String)
+        {
+            return fallback;
+        }
+        auto & tag_str = namedValue.as<nbt::tag_string>();
+        return QString::fromStdString(tag_str.get());
+    }
+    catch (const std::out_of_range &e)
+    {
+        // fallback for old world formats
+        qWarning() << "String NBT tag" << name << "could not be found. Defaulting to" << fallback;
+        return fallback;
+    }
+    catch (const std::bad_cast &e)
+    {
+        // type mismatch
+        qWarning() << "NBT tag" << name << "could not be converted to string. Defaulting to" << fallback;
+        return fallback;
+    }
 }
 
 static int64_t read_long (nbt::value& parent, const char * name, const int64_t & fallback = 0)
 {
-	try
-	{
-		auto &namedValue = parent.at(name);
-		if(namedValue.get_type() != nbt::tag_type::Long)
-		{
-			return fallback;
-		}
-		auto & tag_str = namedValue.as<nbt::tag_long>();
-		return tag_str.get();
-	}
-	catch (const std::out_of_range &e)
-	{
-		// fallback for old world formats
-		qWarning() << "Long NBT tag" << name << "could not be found. Defaulting to" << fallback;
-		return fallback;
-	}
-	catch (const std::bad_cast &e)
-	{
-		// type mismatch
-		qWarning() << "NBT tag" << name << "could not be converted to long. Defaulting to" << fallback;
-		return fallback;
-	}
+    try
+    {
+        auto &namedValue = parent.at(name);
+        if(namedValue.get_type() != nbt::tag_type::Long)
+        {
+            return fallback;
+        }
+        auto & tag_str = namedValue.as<nbt::tag_long>();
+        return tag_str.get();
+    }
+    catch (const std::out_of_range &e)
+    {
+        // fallback for old world formats
+        qWarning() << "Long NBT tag" << name << "could not be found. Defaulting to" << fallback;
+        return fallback;
+    }
+    catch (const std::bad_cast &e)
+    {
+        // type mismatch
+        qWarning() << "NBT tag" << name << "could not be converted to long. Defaulting to" << fallback;
+        return fallback;
+    }
 }
 
 void World::loadFromLevelDat(QByteArray data)
 {
-	try
-	{
-		auto levelData = parseLevelDat(data);
-		if(!levelData)
-		{
-			is_valid = false;
-			return;
-		}
-
-		auto &val = levelData->at("Data");
-		is_valid = val.get_type() == nbt::tag_type::Compound;
-		if(!is_valid)
-			return;
-
-		m_actualName = read_string(val, "LevelName", m_folderName);
-
-
-		int64_t temp = read_long(val, "LastPlayed", 0);
-		if(temp == 0)
-		{
-			m_lastPlayed = levelDatTime;
-		}
-		else
-		{
-			m_lastPlayed = QDateTime::fromMSecsSinceEpoch(temp);
-		}
-
-		m_randomSeed = read_long(val, "RandomSeed", 0);
-
-		qDebug() << "World Name:" << m_actualName;
-		qDebug() << "Last Played:" << m_lastPlayed.toString();
-		qDebug() << "Seed:" << m_randomSeed;
-	}
-	catch (const nbt::io::input_error &e)
-	{
-		qWarning() << "Unable to load" << m_folderName << ":" << e.what();
-		is_valid = false;
-		return;
-	}
+    try
+    {
+        auto levelData = parseLevelDat(data);
+        if(!levelData)
+        {
+            is_valid = false;
+            return;
+        }
+
+        auto &val = levelData->at("Data");
+        is_valid = val.get_type() == nbt::tag_type::Compound;
+        if(!is_valid)
+            return;
+
+        m_actualName = read_string(val, "LevelName", m_folderName);
+
+
+        int64_t temp = read_long(val, "LastPlayed", 0);
+        if(temp == 0)
+        {
+            m_lastPlayed = levelDatTime;
+        }
+        else
+        {
+            m_lastPlayed = QDateTime::fromMSecsSinceEpoch(temp);
+        }
+
+        m_randomSeed = read_long(val, "RandomSeed", 0);
+
+        qDebug() << "World Name:" << m_actualName;
+        qDebug() << "Last Played:" << m_lastPlayed.toString();
+        qDebug() << "Seed:" << m_randomSeed;
+    }
+    catch (const nbt::io::input_error &e)
+    {
+        qWarning() << "Unable to load" << m_folderName << ":" << e.what();
+        is_valid = false;
+        return;
+    }
 }
 
 bool World::replace(World &with)
 {
-	if (!destroy())
-		return false;
-	bool success = FS::copy(with.m_containerFile.filePath(), m_containerFile.path())();
-	if (success)
-	{
-		m_folderName = with.m_folderName;
-		m_containerFile.refresh();
-	}
-	return success;
+    if (!destroy())
+        return false;
+    bool success = FS::copy(with.m_containerFile.filePath(), m_containerFile.path())();
+    if (success)
+    {
+        m_folderName = with.m_folderName;
+        m_containerFile.refresh();
+    }
+    return success;
 }
 
 bool World::destroy()
 {
-	if(!is_valid) return false;
-	if (m_containerFile.isDir())
-	{
-		QDir d(m_containerFile.filePath());
-		return d.removeRecursively();
-	}
-	else if(m_containerFile.isFile())
-	{
-		QFile file(m_containerFile.absoluteFilePath());
-		return file.remove();
-	}
-	return true;
+    if(!is_valid) return false;
+    if (m_containerFile.isDir())
+    {
+        QDir d(m_containerFile.filePath());
+        return d.removeRecursively();
+    }
+    else if(m_containerFile.isFile())
+    {
+        QFile file(m_containerFile.absoluteFilePath());
+        return file.remove();
+    }
+    return true;
 }
 
 bool World::operator==(const World &other) const
 {
-	return is_valid == other.is_valid && folderName() == other.folderName();
+    return is_valid == other.is_valid && folderName() == other.folderName();
 }
 bool World::strongCompare(const World &other) const
 {
-	return is_valid == other.is_valid && folderName() == other.folderName();
+    return is_valid == other.is_valid && folderName() == other.folderName();
 }
diff --git a/api/logic/minecraft/World.h b/api/logic/minecraft/World.h
index 7087bf48..2cce85a2 100644
--- a/api/logic/minecraft/World.h
+++ b/api/logic/minecraft/World.h
@@ -22,62 +22,62 @@
 class MULTIMC_LOGIC_EXPORT World
 {
 public:
-	World(const QFileInfo &file);
-	QString folderName() const
-	{
-		return m_folderName;
-	}
-	QString name() const
-	{
-		return m_actualName;
-	}
-	QDateTime lastPlayed() const
-	{
-		return m_lastPlayed;
-	}
-	int64_t seed() const
-	{
-		return m_randomSeed;
-	}
-	bool isValid() const
-	{
-		return is_valid;
-	}
-	bool isOnFS() const
-	{
-		return m_containerFile.isDir();
-	}
-	QFileInfo container() const
-	{
-		return m_containerFile;
-	}
-	// delete all the files of this world
-	bool destroy();
-	// replace this world with a copy of the other
-	bool replace(World &with);
-	// change the world's filesystem path (used by world lists for *MAGIC* purposes)
-	void repath(const QFileInfo &file);
+    World(const QFileInfo &file);
+    QString folderName() const
+    {
+        return m_folderName;
+    }
+    QString name() const
+    {
+        return m_actualName;
+    }
+    QDateTime lastPlayed() const
+    {
+        return m_lastPlayed;
+    }
+    int64_t seed() const
+    {
+        return m_randomSeed;
+    }
+    bool isValid() const
+    {
+        return is_valid;
+    }
+    bool isOnFS() const
+    {
+        return m_containerFile.isDir();
+    }
+    QFileInfo container() const
+    {
+        return m_containerFile;
+    }
+    // delete all the files of this world
+    bool destroy();
+    // replace this world with a copy of the other
+    bool replace(World &with);
+    // change the world's filesystem path (used by world lists for *MAGIC* purposes)
+    void repath(const QFileInfo &file);
 
-	bool rename(const QString &to);
-	bool install(const QString &to, const QString &name= QString());
+    bool rename(const QString &to);
+    bool install(const QString &to, const QString &name= QString());
 
-	// WEAK compare operator - used for replacing worlds
-	bool operator==(const World &other) const;
-	bool strongCompare(const World &other) const;
+    // WEAK compare operator - used for replacing worlds
+    bool operator==(const World &other) const;
+    bool strongCompare(const World &other) const;
 
 private:
-	void readFromZip(const QFileInfo &file);
-	void readFromFS(const QFileInfo &file);
-	void loadFromLevelDat(QByteArray data);
+    void readFromZip(const QFileInfo &file);
+    void readFromFS(const QFileInfo &file);
+    void loadFromLevelDat(QByteArray data);
 
 protected:
 
-	QFileInfo m_containerFile;
-	QString m_containerOffsetPath;
-	QString m_folderName;
-	QString m_actualName;
-	QDateTime levelDatTime;
-	QDateTime m_lastPlayed;
-	int64_t m_randomSeed = 0;
-	bool is_valid = false;
+    QFileInfo m_containerFile;
+    QString m_containerOffsetPath;
+    QString m_folderName;
+    QString m_actualName;
+    QDateTime levelDatTime;
+    QDateTime m_lastPlayed;
+    int64_t m_randomSeed = 0;
+    bool is_valid = false;
 };
diff --git a/api/logic/minecraft/WorldList.cpp b/api/logic/minecraft/WorldList.cpp
index 4278c2f7..79a5bf38 100644
--- a/api/logic/minecraft/WorldList.cpp
+++ b/api/logic/minecraft/WorldList.cpp
@@ -23,216 +23,216 @@
 #include <QDebug>
 
 WorldList::WorldList(const QString &dir)
-	: QAbstractListModel(), m_dir(dir)
+    : QAbstractListModel(), m_dir(dir)
 {
-	FS::ensureFolderPathExists(m_dir.absolutePath());
-	m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
-					QDir::NoSymLinks);
-	m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
-	m_watcher = new QFileSystemWatcher(this);
-	is_watching = false;
-	connect(m_watcher, SIGNAL(directoryChanged(QString)), this,
-			SLOT(directoryChanged(QString)));
+    FS::ensureFolderPathExists(m_dir.absolutePath());
+    m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
+                    QDir::NoSymLinks);
+    m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
+    m_watcher = new QFileSystemWatcher(this);
+    is_watching = false;
+    connect(m_watcher, SIGNAL(directoryChanged(QString)), this,
+            SLOT(directoryChanged(QString)));
 }
 
 void WorldList::startWatching()
 {
-	if(is_watching)
-	{
-		return;
-	}
-	update();
-	is_watching = m_watcher->addPath(m_dir.absolutePath());
-	if (is_watching)
-	{
-		qDebug() << "Started watching " << m_dir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to start watching " << m_dir.absolutePath();
-	}
+    if(is_watching)
+    {
+        return;
+    }
+    update();
+    is_watching = m_watcher->addPath(m_dir.absolutePath());
+    if (is_watching)
+    {
+        qDebug() << "Started watching " << m_dir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to start watching " << m_dir.absolutePath();
+    }
 }
 
 void WorldList::stopWatching()
 {
-	if(!is_watching)
-	{
-		return;
-	}
-	is_watching = !m_watcher->removePath(m_dir.absolutePath());
-	if (!is_watching)
-	{
-		qDebug() << "Stopped watching " << m_dir.absolutePath();
-	}
-	else
-	{
-		qDebug() << "Failed to stop watching " << m_dir.absolutePath();
-	}
+    if(!is_watching)
+    {
+        return;
+    }
+    is_watching = !m_watcher->removePath(m_dir.absolutePath());
+    if (!is_watching)
+    {
+        qDebug() << "Stopped watching " << m_dir.absolutePath();
+    }
+    else
+    {
+        qDebug() << "Failed to stop watching " << m_dir.absolutePath();
+    }
 }
 
 bool WorldList::update()
 {
-	if (!isValid())
-		return false;
-
-	QList<World> newWorlds;
-	m_dir.refresh();
-	auto folderContents = m_dir.entryInfoList();
-	// if there are any untracked files...
-	for (QFileInfo entry : folderContents)
-	{
-		if(!entry.isDir())
-			continue;
-
-		World w(entry);
-		if(w.isValid())
-		{
-			newWorlds.append(w);
-		}
-	}
-	beginResetModel();
-	worlds.swap(newWorlds);
-	endResetModel();
-	return true;
+    if (!isValid())
+        return false;
+
+    QList<World> newWorlds;
+    m_dir.refresh();
+    auto folderContents = m_dir.entryInfoList();
+    // if there are any untracked files...
+    for (QFileInfo entry : folderContents)
+    {
+        if(!entry.isDir())
+            continue;
+
+        World w(entry);
+        if(w.isValid())
+        {
+            newWorlds.append(w);
+        }
+    }
+    beginResetModel();
+    worlds.swap(newWorlds);
+    endResetModel();
+    return true;
 }
 
 void WorldList::directoryChanged(QString path)
 {
-	update();
+    update();
 }
 
 bool WorldList::isValid()
 {
-	return m_dir.exists() && m_dir.isReadable();
+    return m_dir.exists() && m_dir.isReadable();
 }
 
 bool WorldList::deleteWorld(int index)
 {
-	if (index >= worlds.size() || index < 0)
-		return false;
-	World &m = worlds[index];
-	if (m.destroy())
-	{
-		beginRemoveRows(QModelIndex(), index, index);
-		worlds.removeAt(index);
-		endRemoveRows();
-		emit changed();
-		return true;
-	}
-	return false;
+    if (index >= worlds.size() || index < 0)
+        return false;
+    World &m = worlds[index];
+    if (m.destroy())
+    {
+        beginRemoveRows(QModelIndex(), index, index);
+        worlds.removeAt(index);
+        endRemoveRows();
+        emit changed();
+        return true;
+    }
+    return false;
 }
 
 bool WorldList::deleteWorlds(int first, int last)
 {
-	for (int i = first; i <= last; i++)
-	{
-		World &m = worlds[i];
-		m.destroy();
-	}
-	beginRemoveRows(QModelIndex(), first, last);
-	worlds.erase(worlds.begin() + first, worlds.begin() + last + 1);
-	endRemoveRows();
-	emit changed();
-	return true;
+    for (int i = first; i <= last; i++)
+    {
+        World &m = worlds[i];
+        m.destroy();
+    }
+    beginRemoveRows(QModelIndex(), first, last);
+    worlds.erase(worlds.begin() + first, worlds.begin() + last + 1);
+    endRemoveRows();
+    emit changed();
+    return true;
 }
 
 int WorldList::columnCount(const QModelIndex &parent) const
 {
-	return 2;
+    return 2;
 }
 
 QVariant WorldList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	int row = index.row();
-	int column = index.column();
-
-	if (row < 0 || row >= worlds.size())
-		return QVariant();
-
-	auto & world = worlds[row];
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (column)
-		{
-		case NameColumn:
-			return world.name();
-
-		case LastPlayedColumn:
-			return world.lastPlayed();
-
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-	{
-		return world.folderName();
-	}
-	case ObjectRole:
-	{
-		return QVariant::fromValue<void *>((void *)&world);
-	}
-	case FolderRole:
-	{
-		return QDir::toNativeSeparators(dir().absoluteFilePath(world.folderName()));
-	}
-	case SeedRole:
-	{
-		return qVariantFromValue<qlonglong>(world.seed());
-	}
-	case NameRole:
-	{
-		return world.name();
-	}
-	case LastPlayedRole:
-	{
-		return world.lastPlayed();
-	}
-	default:
-		return QVariant();
-	}
+    if (!index.isValid())
+        return QVariant();
+
+    int row = index.row();
+    int column = index.column();
+
+    if (row < 0 || row >= worlds.size())
+        return QVariant();
+
+    auto & world = worlds[row];
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (column)
+        {
+        case NameColumn:
+            return world.name();
+
+        case LastPlayedColumn:
+            return world.lastPlayed();
+
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+    {
+        return world.folderName();
+    }
+    case ObjectRole:
+    {
+        return QVariant::fromValue<void *>((void *)&world);
+    }
+    case FolderRole:
+    {
+        return QDir::toNativeSeparators(dir().absoluteFilePath(world.folderName()));
+    }
+    case SeedRole:
+    {
+        return qVariantFromValue<qlonglong>(world.seed());
+    }
+    case NameRole:
+    {
+        return world.name();
+    }
+    case LastPlayedRole:
+    {
+        return world.lastPlayed();
+    }
+    default:
+        return QVariant();
+    }
 }
 
 QVariant WorldList::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (section)
-		{
-		case NameColumn:
-			return tr("Name");
-		case LastPlayedColumn:
-			return tr("Last Played");
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		switch (section)
-		{
-		case NameColumn:
-			return tr("The name of the world.");
-		case LastPlayedColumn:
-			return tr("Date and time the world was last played.");
-		default:
-			return QVariant();
-		}
-	default:
-		return QVariant();
-	}
-	return QVariant();
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (section)
+        {
+        case NameColumn:
+            return tr("Name");
+        case LastPlayedColumn:
+            return tr("Last Played");
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        switch (section)
+        {
+        case NameColumn:
+            return tr("The name of the world.");
+        case LastPlayedColumn:
+            return tr("Date and time the world was last played.");
+        default:
+            return QVariant();
+        }
+    default:
+        return QVariant();
+    }
+    return QVariant();
 }
 
 QStringList WorldList::mimeTypes() const
 {
-	QStringList types;
-	types << "text/uri-list";
-	return types;
+    QStringList types;
+    types << "text/uri-list";
+    return types;
 }
 
 class WorldMimeData : public QMimeData
@@ -240,124 +240,124 @@ class WorldMimeData : public QMimeData
 Q_OBJECT
 
 public:
-	WorldMimeData(QList<World> worlds)
-	{
-		m_worlds = worlds;
+    WorldMimeData(QList<World> worlds)
+    {
+        m_worlds = worlds;
 
-	}
-	QStringList formats() const
-	{
-		return QMimeData::formats() << "text/uri-list";
-	}
+    }
+    QStringList formats() const
+    {
+        return QMimeData::formats() << "text/uri-list";
+    }
 
 protected:
-	QVariant retrieveData(const QString &mimetype, QVariant::Type type) const
-	{
-		QList<QUrl> urls;
-		for(auto &world: m_worlds)
-		{
-			if(!world.isValid() || !world.isOnFS())
-				continue;
-			QString worldPath = world.container().absoluteFilePath();
-			qDebug() << worldPath;
-			urls.append(QUrl::fromLocalFile(worldPath));
-		}
-		const_cast<WorldMimeData*>(this)->setUrls(urls);
-		return QMimeData::retrieveData(mimetype, type);
-	}
+    QVariant retrieveData(const QString &mimetype, QVariant::Type type) const
+    {
+        QList<QUrl> urls;
+        for(auto &world: m_worlds)
+        {
+            if(!world.isValid() || !world.isOnFS())
+                continue;
+            QString worldPath = world.container().absoluteFilePath();
+            qDebug() << worldPath;
+            urls.append(QUrl::fromLocalFile(worldPath));
+        }
+        const_cast<WorldMimeData*>(this)->setUrls(urls);
+        return QMimeData::retrieveData(mimetype, type);
+    }
 private:
-	QList<World> m_worlds;
+    QList<World> m_worlds;
 };
 
 QMimeData *WorldList::mimeData(const QModelIndexList &indexes) const
 {
-	if (indexes.size() == 0)
-		return new QMimeData();
-
-	QList<World> worlds;
-	for(auto idx : indexes)
-	{
-		if(idx.column() != 0)
-			continue;
-		int row = idx.row();
-		if (row < 0 || row >= this->worlds.size())
-			continue;
-		worlds.append(this->worlds[row]);
-	}
-	if(!worlds.size())
-	{
-		return new QMimeData();
-	}
-	return new WorldMimeData(worlds);
+    if (indexes.size() == 0)
+        return new QMimeData();
+
+    QList<World> worlds;
+    for(auto idx : indexes)
+    {
+        if(idx.column() != 0)
+            continue;
+        int row = idx.row();
+        if (row < 0 || row >= this->worlds.size())
+            continue;
+        worlds.append(this->worlds[row]);
+    }
+    if(!worlds.size())
+    {
+        return new QMimeData();
+    }
+    return new WorldMimeData(worlds);
 }
 
 Qt::ItemFlags WorldList::flags(const QModelIndex &index) const
 {
-	Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
-	if (index.isValid())
-		return Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled |
-			   defaultFlags;
-	else
-		return Qt::ItemIsDropEnabled | defaultFlags;
+    Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
+    if (index.isValid())
+        return Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled |
+               defaultFlags;
+    else
+        return Qt::ItemIsDropEnabled | defaultFlags;
 }
 
 Qt::DropActions WorldList::supportedDragActions() const
 {
-	// move to other mod lists or VOID
-	return Qt::MoveAction;
+    // move to other mod lists or VOID
+    return Qt::MoveAction;
 }
 
 Qt::DropActions WorldList::supportedDropActions() const
 {
-	// copy from outside, move from within and other mod lists
-	return Qt::CopyAction | Qt::MoveAction;
+    // copy from outside, move from within and other mod lists
+    return Qt::CopyAction | Qt::MoveAction;
 }
 
 void WorldList::installWorld(QFileInfo filename)
 {
-	qDebug() << "installing: " << filename.absoluteFilePath();
-	World w(filename);
-	if(!w.isValid())
-	{
-		return;
-	}
-	w.install(m_dir.absolutePath());
+    qDebug() << "installing: " << filename.absoluteFilePath();
+    World w(filename);
+    if(!w.isValid())
+    {
+        return;
+    }
+    w.install(m_dir.absolutePath());
 }
 
 bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
-							 const QModelIndex &parent)
+                             const QModelIndex &parent)
 {
-	if (action == Qt::IgnoreAction)
-		return true;
-	// check if the action is supported
-	if (!data || !(action & supportedDropActions()))
-		return false;
-	// files dropped from outside?
-	if (data->hasUrls())
-	{
-		bool was_watching = is_watching;
-		if (was_watching)
-			stopWatching();
-		auto urls = data->urls();
-		for (auto url : urls)
-		{
-			// only local files may be dropped...
-			if (!url.isLocalFile())
-				continue;
-			QString filename = url.toLocalFile();
-
-			QFileInfo worldInfo(filename);
-
-			if(!m_dir.entryInfoList().contains(worldInfo))
-			{
-				installWorld(worldInfo);
-			}
-		}
-		if (was_watching)
-			startWatching();
-		return true;
-	}
-	return false;
+    if (action == Qt::IgnoreAction)
+        return true;
+    // check if the action is supported
+    if (!data || !(action & supportedDropActions()))
+        return false;
+    // files dropped from outside?
+    if (data->hasUrls())
+    {
+        bool was_watching = is_watching;
+        if (was_watching)
+            stopWatching();
+        auto urls = data->urls();
+        for (auto url : urls)
+        {
+            // only local files may be dropped...
+            if (!url.isLocalFile())
+                continue;
+            QString filename = url.toLocalFile();
+
+            QFileInfo worldInfo(filename);
+
+            if(!m_dir.entryInfoList().contains(worldInfo))
+            {
+                installWorld(worldInfo);
+            }
+        }
+        if (was_watching)
+            startWatching();
+        return true;
+    }
+    return false;
 }
 
 #include "WorldList.moc"
diff --git a/api/logic/minecraft/WorldList.h b/api/logic/minecraft/WorldList.h
index 811393cd..a1cd8f51 100644
--- a/api/logic/minecraft/WorldList.h
+++ b/api/logic/minecraft/WorldList.h
@@ -28,98 +28,98 @@ class QFileSystemWatcher;
 
 class MULTIMC_LOGIC_EXPORT WorldList : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum Columns
-	{
-		NameColumn,
-		LastPlayedColumn
-	};
-
-	enum Roles
-	{
-		ObjectRole = Qt::UserRole + 1,
-		FolderRole,
-		SeedRole,
-		NameRole,
-		LastPlayedRole
-	};
-
-	WorldList(const QString &dir);
-
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
-
-	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
-	{
-		return size();
-	};
-	virtual QVariant headerData(int section, Qt::Orientation orientation,
-								int role = Qt::DisplayRole) const;
-	virtual int columnCount(const QModelIndex &parent) const;
-
-	size_t size() const
-	{
-		return worlds.size();
-	};
-	bool empty() const
-	{
-		return size() == 0;
-	}
-	World &operator[](size_t index)
-	{
-		return worlds[index];
-	}
-
-	/// Reloads the mod list and returns true if the list changed.
-	virtual bool update();
-
-	/// Install a world from location
-	void installWorld(QFileInfo filename);
-
-	/// Deletes the mod at the given index.
-	virtual bool deleteWorld(int index);
-
-	/// Deletes all the selected mods
-	virtual bool deleteWorlds(int first, int last);
-
-	/// flags, mostly to support drag&drop
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const;
-	/// get data for drag action
-	virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
-	/// get the supported mime types
-	virtual QStringList mimeTypes() const;
-	/// process data from drop action
-	virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
-	/// what drag actions do we support?
-	virtual Qt::DropActions supportedDragActions() const;
-
-	/// what drop actions do we support?
-	virtual Qt::DropActions supportedDropActions() const;
-
-	void startWatching();
-	void stopWatching();
-
-	virtual bool isValid();
-
-	QDir dir() const
-	{
-		return m_dir;
-	}
-
-	const QList<World> &allWorlds() const
-	{
-		return worlds;
-	}
+    enum Columns
+    {
+        NameColumn,
+        LastPlayedColumn
+    };
+
+    enum Roles
+    {
+        ObjectRole = Qt::UserRole + 1,
+        FolderRole,
+        SeedRole,
+        NameRole,
+        LastPlayedRole
+    };
+
+    WorldList(const QString &dir);
+
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
+    {
+        return size();
+    };
+    virtual QVariant headerData(int section, Qt::Orientation orientation,
+                                int role = Qt::DisplayRole) const;
+    virtual int columnCount(const QModelIndex &parent) const;
+
+    size_t size() const
+    {
+        return worlds.size();
+    };
+    bool empty() const
+    {
+        return size() == 0;
+    }
+    World &operator[](size_t index)
+    {
+        return worlds[index];
+    }
+
+    /// Reloads the mod list and returns true if the list changed.
+    virtual bool update();
+
+    /// Install a world from location
+    void installWorld(QFileInfo filename);
+
+    /// Deletes the mod at the given index.
+    virtual bool deleteWorld(int index);
+
+    /// Deletes all the selected mods
+    virtual bool deleteWorlds(int first, int last);
+
+    /// flags, mostly to support drag&drop
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+    /// get data for drag action
+    virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
+    /// get the supported mime types
+    virtual QStringList mimeTypes() const;
+    /// process data from drop action
+    virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
+    /// what drag actions do we support?
+    virtual Qt::DropActions supportedDragActions() const;
+
+    /// what drop actions do we support?
+    virtual Qt::DropActions supportedDropActions() const;
+
+    void startWatching();
+    void stopWatching();
+
+    virtual bool isValid();
+
+    QDir dir() const
+    {
+        return m_dir;
+    }
+
+    const QList<World> &allWorlds() const
+    {
+        return worlds;
+    }
 
 private slots:
-	void directoryChanged(QString path);
+    void directoryChanged(QString path);
 
 signals:
-	void changed();
+    void changed();
 
 protected:
-	QFileSystemWatcher *m_watcher;
-	bool is_watching;
-	QDir m_dir;
-	QList<World> worlds;
+    QFileSystemWatcher *m_watcher;
+    bool is_watching;
+    QDir m_dir;
+    QList<World> worlds;
 };
diff --git a/api/logic/minecraft/auth/AuthSession.cpp b/api/logic/minecraft/auth/AuthSession.cpp
index 8758bfbd..4e858796 100644
--- a/api/logic/minecraft/auth/AuthSession.cpp
+++ b/api/logic/minecraft/auth/AuthSession.cpp
@@ -6,25 +6,25 @@
 
 QString AuthSession::serializeUserProperties()
 {
-	QJsonObject userAttrs;
-	for (auto key : u.properties.keys())
-	{
-		auto array = QJsonArray::fromStringList(u.properties.values(key));
-		userAttrs.insert(key, array);
-	}
-	QJsonDocument value(userAttrs);
-	return value.toJson(QJsonDocument::Compact);
+    QJsonObject userAttrs;
+    for (auto key : u.properties.keys())
+    {
+        auto array = QJsonArray::fromStringList(u.properties.values(key));
+        userAttrs.insert(key, array);
+    }
+    QJsonDocument value(userAttrs);
+    return value.toJson(QJsonDocument::Compact);
 
 }
 
 bool AuthSession::MakeOffline(QString offline_playername)
 {
-	if (status != PlayableOffline && status != PlayableOnline)
-	{
-		return false;
-	}
-	session = "-";
-	player_name = offline_playername;
-	status = PlayableOffline;
-	return true;
+    if (status != PlayableOffline && status != PlayableOnline)
+    {
+        return false;
+    }
+    session = "-";
+    player_name = offline_playername;
+    status = PlayableOffline;
+    return true;
 }
diff --git a/api/logic/minecraft/auth/AuthSession.h b/api/logic/minecraft/auth/AuthSession.h
index d2f66db8..b397d9a1 100644
--- a/api/logic/minecraft/auth/AuthSession.h
+++ b/api/logic/minecraft/auth/AuthSession.h
@@ -10,45 +10,45 @@ class MojangAccount;
 
 struct User
 {
-	QString id;
-	QMultiMap<QString, QString> properties;
+    QString id;
+    QMultiMap<QString, QString> properties;
 };
 
 struct MULTIMC_LOGIC_EXPORT AuthSession
 {
-	bool MakeOffline(QString offline_playername);
-
-	QString serializeUserProperties();
-
-	enum Status
-	{
-		Undetermined,
-		RequiresPassword,
-		PlayableOffline,
-		PlayableOnline
-	} status = Undetermined;
-
-	User u;
-
-	// client token
-	QString client_token;
-	// account user name
-	QString username;
-	// combined session ID
-	QString session;
-	// volatile auth token
-	QString access_token;
-	// profile name
-	QString player_name;
-	// profile ID
-	QString uuid;
-	// 'legacy' or 'mojang', depending on account type
-	QString user_type;
-	// Did the auth server reply?
-	bool auth_server_online = false;
-	// Did the user request online mode?
-	bool wants_online = true;
-	std::shared_ptr<MojangAccount> m_accountPtr;
+    bool MakeOffline(QString offline_playername);
+
+    QString serializeUserProperties();
+
+    enum Status
+    {
+        Undetermined,
+        RequiresPassword,
+        PlayableOffline,
+        PlayableOnline
+    } status = Undetermined;
+
+    User u;
+
+    // client token
+    QString client_token;
+    // account user name
+    QString username;
+    // combined session ID
+    QString session;
+    // volatile auth token
+    QString access_token;
+    // profile name
+    QString player_name;
+    // profile ID
+    QString uuid;
+    // 'legacy' or 'mojang', depending on account type
+    QString user_type;
+    // Did the auth server reply?
+    bool auth_server_online = false;
+    // Did the user request online mode?
+    bool wants_online = true;
+    std::shared_ptr<MojangAccount> m_accountPtr;
 };
 
 typedef std::shared_ptr<AuthSession> AuthSessionPtr;
diff --git a/api/logic/minecraft/auth/MojangAccount.cpp b/api/logic/minecraft/auth/MojangAccount.cpp
index edad4344..edf1e4e3 100644
--- a/api/logic/minecraft/auth/MojangAccount.cpp
+++ b/api/logic/minecraft/auth/MojangAccount.cpp
@@ -30,286 +30,286 @@
 
 MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
 {
-	// The JSON object must at least have a username for it to be valid.
-	if (!object.value("username").isString())
-	{
-		qCritical() << "Can't load Mojang account info from JSON object. Username field is "
-						"missing or of the wrong type.";
-		return nullptr;
-	}
+    // The JSON object must at least have a username for it to be valid.
+    if (!object.value("username").isString())
+    {
+        qCritical() << "Can't load Mojang account info from JSON object. Username field is "
+                        "missing or of the wrong type.";
+        return nullptr;
+    }
 
-	QString username = object.value("username").toString("");
-	QString clientToken = object.value("clientToken").toString("");
-	QString accessToken = object.value("accessToken").toString("");
+    QString username = object.value("username").toString("");
+    QString clientToken = object.value("clientToken").toString("");
+    QString accessToken = object.value("accessToken").toString("");
 
-	QJsonArray profileArray = object.value("profiles").toArray();
-	if (profileArray.size() < 1)
-	{
-		qCritical() << "Can't load Mojang account with username \"" << username
-					 << "\". No profiles found.";
-		return nullptr;
-	}
+    QJsonArray profileArray = object.value("profiles").toArray();
+    if (profileArray.size() < 1)
+    {
+        qCritical() << "Can't load Mojang account with username \"" << username
+                     << "\". No profiles found.";
+        return nullptr;
+    }
 
-	QList<AccountProfile> profiles;
-	for (QJsonValue profileVal : profileArray)
-	{
-		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 because it was missing an ID or a name.";
-			continue;
-		}
-		profiles.append({id, name, legacy});
-	}
+    QList<AccountProfile> profiles;
+    for (QJsonValue profileVal : profileArray)
+    {
+        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 because it was missing an ID or a name.";
+            continue;
+        }
+        profiles.append({id, name, legacy});
+    }
 
-	MojangAccountPtr account(new MojangAccount());
-	if (object.value("user").isObject())
-	{
-		User u;
-		QJsonObject userStructure = object.value("user").toObject();
-		u.id = userStructure.value("id").toString();
-		/*
-		QJsonObject propMap = userStructure.value("properties").toObject();
-		for(auto key: propMap.keys())
-		{
-			auto values = propMap.operator[](key).toArray();
-			for(auto value: values)
-				u.properties.insert(key, value.toString());
-		}
-		*/
-		account->m_user = u;
-	}
-	account->m_username = username;
-	account->m_clientToken = clientToken;
-	account->m_accessToken = accessToken;
-	account->m_profiles = profiles;
+    MojangAccountPtr account(new MojangAccount());
+    if (object.value("user").isObject())
+    {
+        User u;
+        QJsonObject userStructure = object.value("user").toObject();
+        u.id = userStructure.value("id").toString();
+        /*
+        QJsonObject propMap = userStructure.value("properties").toObject();
+        for(auto key: propMap.keys())
+        {
+            auto values = propMap.operator[](key).toArray();
+            for(auto value: values)
+                u.properties.insert(key, value.toString());
+        }
+        */
+        account->m_user = u;
+    }
+    account->m_username = username;
+    account->m_clientToken = clientToken;
+    account->m_accessToken = accessToken;
+    account->m_profiles = profiles;
 
-	// Get the currently selected profile.
-	QString currentProfile = object.value("activeProfile").toString("");
-	if (!currentProfile.isEmpty())
-		account->setCurrentProfile(currentProfile);
+    // Get the currently selected profile.
+    QString currentProfile = object.value("activeProfile").toString("");
+    if (!currentProfile.isEmpty())
+        account->setCurrentProfile(currentProfile);
 
-	return account;
+    return account;
 }
 
 MojangAccountPtr MojangAccount::createFromUsername(const QString &username)
 {
-	MojangAccountPtr account(new MojangAccount());
-	account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
-	account->m_username = username;
-	return account;
+    MojangAccountPtr account(new MojangAccount());
+    account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+    account->m_username = username;
+    return account;
 }
 
 QJsonObject MojangAccount::saveToJson() const
 {
-	QJsonObject json;
-	json.insert("username", m_username);
-	json.insert("clientToken", m_clientToken);
-	json.insert("accessToken", m_accessToken);
+    QJsonObject json;
+    json.insert("username", m_username);
+    json.insert("clientToken", m_clientToken);
+    json.insert("accessToken", m_accessToken);
 
-	QJsonArray profileArray;
-	for (AccountProfile profile : m_profiles)
-	{
-		QJsonObject profileObj;
-		profileObj.insert("id", profile.id);
-		profileObj.insert("name", profile.name);
-		profileObj.insert("legacy", profile.legacy);
-		profileArray.append(profileObj);
-	}
-	json.insert("profiles", profileArray);
+    QJsonArray profileArray;
+    for (AccountProfile profile : m_profiles)
+    {
+        QJsonObject profileObj;
+        profileObj.insert("id", profile.id);
+        profileObj.insert("name", profile.name);
+        profileObj.insert("legacy", profile.legacy);
+        profileArray.append(profileObj);
+    }
+    json.insert("profiles", profileArray);
 
-	QJsonObject userStructure;
-	{
-		userStructure.insert("id", m_user.id);
-		/*
-		QJsonObject userAttrs;
-		for(auto key: m_user.properties.keys())
-		{
-			auto array = QJsonArray::fromStringList(m_user.properties.values(key));
-			userAttrs.insert(key, array);
-		}
-		userStructure.insert("properties", userAttrs);
-		*/
-	}
-	json.insert("user", userStructure);
+    QJsonObject userStructure;
+    {
+        userStructure.insert("id", m_user.id);
+        /*
+        QJsonObject userAttrs;
+        for(auto key: m_user.properties.keys())
+        {
+            auto array = QJsonArray::fromStringList(m_user.properties.values(key));
+            userAttrs.insert(key, array);
+        }
+        userStructure.insert("properties", userAttrs);
+        */
+    }
+    json.insert("user", userStructure);
 
-	if (m_currentProfile != -1)
-		json.insert("activeProfile", currentProfile()->id);
+    if (m_currentProfile != -1)
+        json.insert("activeProfile", currentProfile()->id);
 
-	return json;
+    return json;
 }
 
 bool MojangAccount::setCurrentProfile(const QString &profileId)
 {
-	for (int i = 0; i < m_profiles.length(); i++)
-	{
-		if (m_profiles[i].id == profileId)
-		{
-			m_currentProfile = i;
-			return true;
-		}
-	}
-	return false;
+    for (int i = 0; i < m_profiles.length(); i++)
+    {
+        if (m_profiles[i].id == profileId)
+        {
+            m_currentProfile = i;
+            return true;
+        }
+    }
+    return false;
 }
 
 const AccountProfile *MojangAccount::currentProfile() const
 {
-	if (m_currentProfile == -1)
-		return nullptr;
-	return &m_profiles[m_currentProfile];
+    if (m_currentProfile == -1)
+        return nullptr;
+    return &m_profiles[m_currentProfile];
 }
 
 AccountStatus MojangAccount::accountStatus() const
 {
-	if (m_accessToken.isEmpty())
-		return NotVerified;
-	else
-		return Verified;
+    if (m_accessToken.isEmpty())
+        return NotVerified;
+    else
+        return Verified;
 }
 
 std::shared_ptr<YggdrasilTask> MojangAccount::login(AuthSessionPtr session, QString password)
 {
-	Q_ASSERT(m_currentTask.get() == nullptr);
+    Q_ASSERT(m_currentTask.get() == nullptr);
 
-	// take care of the true offline status
-	if (accountStatus() == NotVerified && password.isEmpty())
-	{
-		if (session)
-		{
-			session->status = AuthSession::RequiresPassword;
-			fillSession(session);
-		}
-		return nullptr;
-	}
+    // take care of the true offline status
+    if (accountStatus() == NotVerified && password.isEmpty())
+    {
+        if (session)
+        {
+            session->status = AuthSession::RequiresPassword;
+            fillSession(session);
+        }
+        return nullptr;
+    }
 
-	if(accountStatus() == Verified && !session->wants_online)
-	{
-		session->status = AuthSession::PlayableOffline;
-		session->auth_server_online = false;
-		fillSession(session);
-		return nullptr;
-	}
-	else
-	{
-		if (password.isEmpty())
-		{
-			m_currentTask.reset(new RefreshTask(this));
-		}
-		else
-		{
-			m_currentTask.reset(new AuthenticateTask(this, password));
-		}
-		m_currentTask->assignSession(session);
+    if(accountStatus() == Verified && !session->wants_online)
+    {
+        session->status = AuthSession::PlayableOffline;
+        session->auth_server_online = false;
+        fillSession(session);
+        return nullptr;
+    }
+    else
+    {
+        if (password.isEmpty())
+        {
+            m_currentTask.reset(new RefreshTask(this));
+        }
+        else
+        {
+            m_currentTask.reset(new AuthenticateTask(this, password));
+        }
+        m_currentTask->assignSession(session);
 
-		connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
-		connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
-	}
-	return m_currentTask;
+        connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
+        connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
+    }
+    return m_currentTask;
 }
 
 void MojangAccount::authSucceeded()
 {
-	auto session = m_currentTask->getAssignedSession();
-	if (session)
-	{
-		session->status =
-			session->wants_online ? AuthSession::PlayableOnline : AuthSession::PlayableOffline;
-		fillSession(session);
-		session->auth_server_online = true;
-	}
-	m_currentTask.reset();
-	emit changed();
+    auto session = m_currentTask->getAssignedSession();
+    if (session)
+    {
+        session->status =
+            session->wants_online ? AuthSession::PlayableOnline : AuthSession::PlayableOffline;
+        fillSession(session);
+        session->auth_server_online = true;
+    }
+    m_currentTask.reset();
+    emit changed();
 }
 
 void MojangAccount::authFailed(QString reason)
 {
-	auto session = m_currentTask->getAssignedSession();
-	// This is emitted when the yggdrasil tasks time out or are cancelled.
-	// -> we treat the error as no-op
-	if (m_currentTask->state() == YggdrasilTask::STATE_FAILED_SOFT)
-	{
-		if (session)
-		{
-			session->status = accountStatus() == Verified ? AuthSession::PlayableOffline
-														  : AuthSession::RequiresPassword;
-			session->auth_server_online = false;
-			fillSession(session);
-		}
-	}
-	else
-	{
-		m_accessToken = QString();
-		emit changed();
-		if (session)
-		{
-			session->status = AuthSession::RequiresPassword;
-			session->auth_server_online = true;
-			fillSession(session);
-		}
-	}
-	m_currentTask.reset();
+    auto session = m_currentTask->getAssignedSession();
+    // This is emitted when the yggdrasil tasks time out or are cancelled.
+    // -> we treat the error as no-op
+    if (m_currentTask->state() == YggdrasilTask::STATE_FAILED_SOFT)
+    {
+        if (session)
+        {
+            session->status = accountStatus() == Verified ? AuthSession::PlayableOffline
+                                                          : AuthSession::RequiresPassword;
+            session->auth_server_online = false;
+            fillSession(session);
+        }
+    }
+    else
+    {
+        m_accessToken = QString();
+        emit changed();
+        if (session)
+        {
+            session->status = AuthSession::RequiresPassword;
+            session->auth_server_online = true;
+            fillSession(session);
+        }
+    }
+    m_currentTask.reset();
 }
 
 void MojangAccount::fillSession(AuthSessionPtr session)
 {
-	// the user name. you have to have an user name
-	session->username = m_username;
-	// volatile auth token
-	session->access_token = m_accessToken;
-	// the semi-permanent client token
-	session->client_token = m_clientToken;
-	if (currentProfile())
-	{
-		// profile name
-		session->player_name = currentProfile()->name;
-		// profile ID
-		session->uuid = currentProfile()->id;
-		// 'legacy' or 'mojang', depending on account type
-		session->user_type = currentProfile()->legacy ? "legacy" : "mojang";
-		if (!session->access_token.isEmpty())
-		{
-			session->session = "token:" + m_accessToken + ":" + m_profiles[m_currentProfile].id;
-		}
-		else
-		{
-			session->session = "-";
-		}
-	}
-	else
-	{
-		session->player_name = "Player";
-		session->session = "-";
-	}
-	session->u = user();
-	session->m_accountPtr = shared_from_this();
+    // the user name. you have to have an user name
+    session->username = m_username;
+    // volatile auth token
+    session->access_token = m_accessToken;
+    // the semi-permanent client token
+    session->client_token = m_clientToken;
+    if (currentProfile())
+    {
+        // profile name
+        session->player_name = currentProfile()->name;
+        // profile ID
+        session->uuid = currentProfile()->id;
+        // 'legacy' or 'mojang', depending on account type
+        session->user_type = currentProfile()->legacy ? "legacy" : "mojang";
+        if (!session->access_token.isEmpty())
+        {
+            session->session = "token:" + m_accessToken + ":" + m_profiles[m_currentProfile].id;
+        }
+        else
+        {
+            session->session = "-";
+        }
+    }
+    else
+    {
+        session->player_name = "Player";
+        session->session = "-";
+    }
+    session->u = user();
+    session->m_accountPtr = shared_from_this();
 }
 
 void MojangAccount::decrementUses()
 {
-	Usable::decrementUses();
-	if(!isInUse())
-	{
-		emit changed();
-		qWarning() << "Account" << m_username << "is no longer in use.";
-	}
+    Usable::decrementUses();
+    if(!isInUse())
+    {
+        emit changed();
+        qWarning() << "Account" << m_username << "is no longer in use.";
+    }
 }
 
 void MojangAccount::incrementUses()
 {
-	bool wasInUse = isInUse();
-	Usable::incrementUses();
-	if(!wasInUse)
-	{
-		emit changed();
-		qWarning() << "Account" << m_username << "is now in use.";
-	}
+    bool wasInUse = isInUse();
+    Usable::incrementUses();
+    if(!wasInUse)
+    {
+        emit changed();
+        qWarning() << "Account" << m_username << "is now in use.";
+    }
 }
 
 void MojangAccount::invalidateClientToken()
 {
-	m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
-	emit changed();
+    m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+    emit changed();
 }
diff --git a/api/logic/minecraft/auth/MojangAccount.h b/api/logic/minecraft/auth/MojangAccount.h
index b2bbc357..8f9bec95 100644
--- a/api/logic/minecraft/auth/MojangAccount.h
+++ b/api/logic/minecraft/auth/MojangAccount.h
@@ -44,15 +44,15 @@ Q_DECLARE_METATYPE(MojangAccountPtr)
  */
 struct AccountProfile
 {
-	QString id;
-	QString name;
-	bool legacy;
+    QString id;
+    QString name;
+    bool legacy;
 };
 
 enum AccountStatus
 {
-	NotVerified,
-	Verified
+    NotVerified,
+    Verified
 };
 
 /**
@@ -62,121 +62,121 @@ enum AccountStatus
  * token if the user chose to stay logged in.
  */
 class MULTIMC_LOGIC_EXPORT MojangAccount :
-	public QObject,
-	public Usable,
-	public std::enable_shared_from_this<MojangAccount>
+    public QObject,
+    public Usable,
+    public std::enable_shared_from_this<MojangAccount>
 {
-	Q_OBJECT
+    Q_OBJECT
 public: /* construction */
-	//! Do not copy accounts. ever.
-	explicit MojangAccount(const MojangAccount &other, QObject *parent) = delete;
+    //! Do not copy accounts. ever.
+    explicit MojangAccount(const MojangAccount &other, QObject *parent) = delete;
 
-	//! Default constructor
-	explicit MojangAccount(QObject *parent = 0) : QObject(parent) {};
+    //! Default constructor
+    explicit MojangAccount(QObject *parent = 0) : QObject(parent) {};
 
-	//! Creates an empty account for the specified user name.
-	static MojangAccountPtr createFromUsername(const QString &username);
+    //! Creates an empty account for the specified user name.
+    static MojangAccountPtr createFromUsername(const QString &username);
 
-	//! Loads a MojangAccount from the given JSON object.
-	static MojangAccountPtr loadFromJson(const QJsonObject &json);
+    //! Loads a MojangAccount from the given JSON object.
+    static MojangAccountPtr loadFromJson(const QJsonObject &json);
 
-	//! Saves a MojangAccount to a JSON object and returns it.
-	QJsonObject saveToJson() const;
+    //! Saves a MojangAccount to a JSON object and returns it.
+    QJsonObject saveToJson() const;
 
 public: /* manipulation */
-		/**
-	 * Sets the currently selected profile to the profile with the given ID string.
-	 * If profileId is not in the list of available profiles, the function will simply return
-	 * false.
-	 */
-	bool setCurrentProfile(const QString &profileId);
-
-	/**
-	 * Attempt to login. Empty password means we use the token.
-	 * If the attempt fails because we already are performing some task, it returns false.
-	 */
-	std::shared_ptr<YggdrasilTask> login(AuthSessionPtr session, QString password = QString());
-	void invalidateClientToken();
+        /**
+     * Sets the currently selected profile to the profile with the given ID string.
+     * If profileId is not in the list of available profiles, the function will simply return
+     * false.
+     */
+    bool setCurrentProfile(const QString &profileId);
+
+    /**
+     * Attempt to login. Empty password means we use the token.
+     * If the attempt fails because we already are performing some task, it returns false.
+     */
+    std::shared_ptr<YggdrasilTask> login(AuthSessionPtr session, QString password = QString());
+    void invalidateClientToken();
 
 public: /* queries */
-	const QString &username() const
-	{
-		return m_username;
-	}
+    const QString &username() const
+    {
+        return m_username;
+    }
 
-	const QString &clientToken() const
-	{
-		return m_clientToken;
-	}
+    const QString &clientToken() const
+    {
+        return m_clientToken;
+    }
 
-	const QString &accessToken() const
-	{
-		return m_accessToken;
-	}
+    const QString &accessToken() const
+    {
+        return m_accessToken;
+    }
 
-	const QList<AccountProfile> &profiles() const
-	{
-		return m_profiles;
-	}
+    const QList<AccountProfile> &profiles() const
+    {
+        return m_profiles;
+    }
 
-	const User &user()
-	{
-		return m_user;
-	}
+    const User &user()
+    {
+        return m_user;
+    }
 
-	//! Returns the currently selected profile (if none, returns nullptr)
-	const AccountProfile *currentProfile() const;
+    //! Returns the currently selected profile (if none, returns nullptr)
+    const AccountProfile *currentProfile() const;
 
-	//! Returns whether the account is NotVerified, Verified or Online
-	AccountStatus accountStatus() const;
+    //! Returns whether the account is NotVerified, Verified or Online
+    AccountStatus accountStatus() const;
 
 signals:
-	/**
-	 * This signal is emitted when the account changes
-	 */
-	void changed();
+    /**
+     * This signal is emitted when the account changes
+     */
+    void changed();
 
-	// TODO: better signalling for the various possible state changes - especially errors
+    // TODO: better signalling for the various possible state changes - especially errors
 
 protected: /* variables */
-	QString m_username;
+    QString m_username;
 
-	// Used to identify the client - the user can have multiple clients for the same account
-	// Think: different launchers, all connecting to the same account/profile
-	QString m_clientToken;
+    // Used to identify the client - the user can have multiple clients for the same account
+    // Think: different launchers, all connecting to the same account/profile
+    QString m_clientToken;
 
-	// Blank if not logged in.
-	QString m_accessToken;
+    // Blank if not logged in.
+    QString m_accessToken;
 
-	// Index of the selected profile within the list of available
-	// profiles. -1 if nothing is selected.
-	int m_currentProfile = -1;
+    // Index of the selected profile within the list of available
+    // profiles. -1 if nothing is selected.
+    int m_currentProfile = -1;
 
-	// List of available profiles.
-	QList<AccountProfile> m_profiles;
+    // List of available profiles.
+    QList<AccountProfile> m_profiles;
 
-	// the user structure, whatever it is.
-	User m_user;
+    // the user structure, whatever it is.
+    User m_user;
 
-	// current task we are executing here
-	std::shared_ptr<YggdrasilTask> m_currentTask;
+    // current task we are executing here
+    std::shared_ptr<YggdrasilTask> m_currentTask;
 
 protected: /* methods */
 
-	void incrementUses() override;
-	void decrementUses() override;
+    void incrementUses() override;
+    void decrementUses() override;
 
 private
 slots:
-	void authSucceeded();
-	void authFailed(QString reason);
+    void authSucceeded();
+    void authFailed(QString reason);
 
 private:
-	void fillSession(AuthSessionPtr session);
+    void fillSession(AuthSessionPtr session);
 
 public:
-	friend class YggdrasilTask;
-	friend class AuthenticateTask;
-	friend class ValidateTask;
-	friend class RefreshTask;
+    friend class YggdrasilTask;
+    friend class AuthenticateTask;
+    friend class ValidateTask;
+    friend class RefreshTask;
 };
diff --git a/api/logic/minecraft/auth/MojangAccountList.cpp b/api/logic/minecraft/auth/MojangAccountList.cpp
index 21ae188a..de671add 100644
--- a/api/logic/minecraft/auth/MojangAccountList.cpp
+++ b/api/logic/minecraft/auth/MojangAccountList.cpp
@@ -37,432 +37,432 @@ MojangAccountList::MojangAccountList(QObject *parent) : QAbstractListModel(paren
 
 MojangAccountPtr MojangAccountList::findAccount(const QString &username) const
 {
-	for (int i = 0; i < count(); i++)
-	{
-		MojangAccountPtr account = at(i);
-		if (account->username() == username)
-			return account;
-	}
-	return nullptr;
+    for (int i = 0; i < count(); i++)
+    {
+        MojangAccountPtr account = at(i);
+        if (account->username() == username)
+            return account;
+    }
+    return nullptr;
 }
 
 const MojangAccountPtr MojangAccountList::at(int i) const
 {
-	return MojangAccountPtr(m_accounts.at(i));
+    return MojangAccountPtr(m_accounts.at(i));
 }
 
 void MojangAccountList::addAccount(const MojangAccountPtr account)
 {
-	int row = m_accounts.count();
-	beginInsertRows(QModelIndex(), row, row);
-	connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
-	m_accounts.append(account);
-	endInsertRows();
-	onListChanged();
+    int row = m_accounts.count();
+    beginInsertRows(QModelIndex(), row, row);
+    connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
+    m_accounts.append(account);
+    endInsertRows();
+    onListChanged();
 }
 
 void MojangAccountList::removeAccount(const QString &username)
 {
-	int idx = 0;
-	for (auto account : m_accounts)
-	{
-		if (account->username() == username)
-		{
-			beginRemoveRows(QModelIndex(), idx, idx);
-			m_accounts.removeOne(account);
-			endRemoveRows();
-			return;
-		}
-		idx++;
-	}
-	onListChanged();
+    int idx = 0;
+    for (auto account : m_accounts)
+    {
+        if (account->username() == username)
+        {
+            beginRemoveRows(QModelIndex(), idx, idx);
+            m_accounts.removeOne(account);
+            endRemoveRows();
+            return;
+        }
+        idx++;
+    }
+    onListChanged();
 }
 
 void MojangAccountList::removeAccount(QModelIndex index)
 {
-	int row = index.row();
-	if(index.isValid() && row >= 0 && row < m_accounts.size())
-	{
-		auto & account = m_accounts[row];
-		if(account == m_activeAccount)
-		{
-			m_activeAccount = nullptr;
-			onActiveChanged();
-		}
-		beginRemoveRows(QModelIndex(), row, row);
-		m_accounts.removeAt(index.row());
-		endRemoveRows();
-		onListChanged();
-	}
+    int row = index.row();
+    if(index.isValid() && row >= 0 && row < m_accounts.size())
+    {
+        auto & account = m_accounts[row];
+        if(account == m_activeAccount)
+        {
+            m_activeAccount = nullptr;
+            onActiveChanged();
+        }
+        beginRemoveRows(QModelIndex(), row, row);
+        m_accounts.removeAt(index.row());
+        endRemoveRows();
+        onListChanged();
+    }
 }
 
 MojangAccountPtr MojangAccountList::activeAccount() const
 {
-	return m_activeAccount;
+    return m_activeAccount;
 }
 
 void MojangAccountList::setActiveAccount(const QString &username)
 {
-	if (username.isEmpty() && m_activeAccount)
-	{
-		int idx = 0;
-		auto prevActiveAcc = m_activeAccount;
-		m_activeAccount = nullptr;
-		for (MojangAccountPtr account : m_accounts)
-		{
-			if (account == prevActiveAcc)
-			{
-				emit dataChanged(index(idx), index(idx));
-			}
-			idx ++;
-		}
-		onActiveChanged();
-	}
-	else
-	{
-		auto currentActiveAccount = m_activeAccount;
-		int currentActiveAccountIdx = -1;
-		auto newActiveAccount = m_activeAccount;
-		int newActiveAccountIdx = -1;
-		int idx = 0;
-		for (MojangAccountPtr account : m_accounts)
-		{
-			if (account->username() == username)
-			{
-				newActiveAccount = account;
-				newActiveAccountIdx = idx;
-			}
-			if(currentActiveAccount == account)
-			{
-				currentActiveAccountIdx = idx;
-			}
-			idx++;
-		}
-		if(currentActiveAccount != newActiveAccount)
-		{
-			emit dataChanged(index(currentActiveAccountIdx), index(currentActiveAccountIdx));
-			emit dataChanged(index(newActiveAccountIdx), index(newActiveAccountIdx));
-			m_activeAccount = newActiveAccount;
-			onActiveChanged();
-		}
-	}
+    if (username.isEmpty() && m_activeAccount)
+    {
+        int idx = 0;
+        auto prevActiveAcc = m_activeAccount;
+        m_activeAccount = nullptr;
+        for (MojangAccountPtr account : m_accounts)
+        {
+            if (account == prevActiveAcc)
+            {
+                emit dataChanged(index(idx), index(idx));
+            }
+            idx ++;
+        }
+        onActiveChanged();
+    }
+    else
+    {
+        auto currentActiveAccount = m_activeAccount;
+        int currentActiveAccountIdx = -1;
+        auto newActiveAccount = m_activeAccount;
+        int newActiveAccountIdx = -1;
+        int idx = 0;
+        for (MojangAccountPtr account : m_accounts)
+        {
+            if (account->username() == username)
+            {
+                newActiveAccount = account;
+                newActiveAccountIdx = idx;
+            }
+            if(currentActiveAccount == account)
+            {
+                currentActiveAccountIdx = idx;
+            }
+            idx++;
+        }
+        if(currentActiveAccount != newActiveAccount)
+        {
+            emit dataChanged(index(currentActiveAccountIdx), index(currentActiveAccountIdx));
+            emit dataChanged(index(newActiveAccountIdx), index(newActiveAccountIdx));
+            m_activeAccount = newActiveAccount;
+            onActiveChanged();
+        }
+    }
 }
 
 void MojangAccountList::accountChanged()
 {
-	// the list changed. there is no doubt.
-	onListChanged();
+    // the list changed. there is no doubt.
+    onListChanged();
 }
 
 void MojangAccountList::onListChanged()
 {
-	if (m_autosave)
-		// TODO: Alert the user if this fails.
-		saveList();
+    if (m_autosave)
+        // TODO: Alert the user if this fails.
+        saveList();
 
-	emit listChanged();
+    emit listChanged();
 }
 
 void MojangAccountList::onActiveChanged()
 {
-	if (m_autosave)
-		saveList();
+    if (m_autosave)
+        saveList();
 
-	emit activeAccountChanged();
+    emit activeAccountChanged();
 }
 
 int MojangAccountList::count() const
 {
-	return m_accounts.count();
+    return m_accounts.count();
 }
 
 QVariant MojangAccountList::data(const QModelIndex &index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	if (index.row() > count())
-		return QVariant();
-
-	MojangAccountPtr account = at(index.row());
-
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (index.column())
-		{
-		case NameColumn:
-			return account->username();
-
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		return account->username();
-
-	case PointerRole:
-		return qVariantFromValue(account);
-
-	case Qt::CheckStateRole:
-		switch (index.column())
-		{
-		case ActiveColumn:
-			return account == m_activeAccount ? Qt::Checked : Qt::Unchecked;
-		}
-
-	default:
-		return QVariant();
-	}
+    if (!index.isValid())
+        return QVariant();
+
+    if (index.row() > count())
+        return QVariant();
+
+    MojangAccountPtr account = at(index.row());
+
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (index.column())
+        {
+        case NameColumn:
+            return account->username();
+
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        return account->username();
+
+    case PointerRole:
+        return qVariantFromValue(account);
+
+    case Qt::CheckStateRole:
+        switch (index.column())
+        {
+        case ActiveColumn:
+            return account == m_activeAccount ? Qt::Checked : Qt::Unchecked;
+        }
+
+    default:
+        return QVariant();
+    }
 }
 
 QVariant MojangAccountList::headerData(int section, Qt::Orientation orientation, int role) const
 {
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		switch (section)
-		{
-		case ActiveColumn:
-			return tr("Active?");
-
-		case NameColumn:
-			return tr("Name");
-
-		default:
-			return QVariant();
-		}
-
-	case Qt::ToolTipRole:
-		switch (section)
-		{
-		case NameColumn:
-			return tr("The name of the version.");
-
-		default:
-			return QVariant();
-		}
-
-	default:
-		return QVariant();
-	}
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (section)
+        {
+        case ActiveColumn:
+            return tr("Active?");
+
+        case NameColumn:
+            return tr("Name");
+
+        default:
+            return QVariant();
+        }
+
+    case Qt::ToolTipRole:
+        switch (section)
+        {
+        case NameColumn:
+            return tr("The name of the version.");
+
+        default:
+            return QVariant();
+        }
+
+    default:
+        return QVariant();
+    }
 }
 
 int MojangAccountList::rowCount(const QModelIndex &) const
 {
-	// Return count
-	return count();
+    // Return count
+    return count();
 }
 
 int MojangAccountList::columnCount(const QModelIndex &) const
 {
-	return 2;
+    return 2;
 }
 
 Qt::ItemFlags MojangAccountList::flags(const QModelIndex &index) const
 {
-	if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
-	{
-		return Qt::NoItemFlags;
-	}
+    if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
+    {
+        return Qt::NoItemFlags;
+    }
 
-	return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+    return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 }
 
 bool MojangAccountList::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-	if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
-	{
-		return false;
-	}
-
-	if(role == Qt::CheckStateRole)
-	{
-		if(value == Qt::Checked)
-		{
-			MojangAccountPtr account = this->at(index.row());
-			this->setActiveAccount(account->username());
-		}
-	}
-
-	emit dataChanged(index, index);
-	return true;
+    if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
+    {
+        return false;
+    }
+
+    if(role == Qt::CheckStateRole)
+    {
+        if(value == Qt::Checked)
+        {
+            MojangAccountPtr account = this->at(index.row());
+            this->setActiveAccount(account->username());
+        }
+    }
+
+    emit dataChanged(index, index);
+    return true;
 }
 
 void MojangAccountList::updateListData(QList<MojangAccountPtr> versions)
 {
-	beginResetModel();
-	m_accounts = versions;
-	endResetModel();
+    beginResetModel();
+    m_accounts = versions;
+    endResetModel();
 }
 
 bool MojangAccountList::loadList(const QString &filePath)
 {
-	QString path = filePath;
-	if (path.isEmpty())
-		path = m_listFilePath;
-	if (path.isEmpty())
-	{
-		qCritical() << "Can't load Mojang account list. No file path given and no default set.";
-		return false;
-	}
-
-	QFile file(path);
-
-	// Try to open the file and fail if we can't.
-	// TODO: We should probably report this error to the user.
-	if (!file.open(QIODevice::ReadOnly))
-	{
-		qCritical() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
-		return false;
-	}
-
-	// Read the file and close it.
-	QByteArray jsonData = file.readAll();
-	file.close();
-
-	QJsonParseError parseError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
-
-	// Fail if the JSON is invalid.
-	if (parseError.error != QJsonParseError::NoError)
-	{
-		qCritical() << QString("Failed to parse account list file: %1 at offset %2")
-							.arg(parseError.errorString(), QString::number(parseError.offset))
-							.toUtf8();
-		return false;
-	}
-
-	// Make sure the root is an object.
-	if (!jsonDoc.isObject())
-	{
-		qCritical() << "Invalid account list JSON: Root should be an array.";
-		return false;
-	}
-
-	QJsonObject root = jsonDoc.object();
-
-	// Make sure the format version matches.
-	if (root.value("formatVersion").toVariant().toInt() != ACCOUNT_LIST_FORMAT_VERSION)
-	{
-		QString newName = "accounts-old.json";
-		qWarning() << "Format version mismatch when loading account list. Existing one will be renamed to"
-					<< newName;
-
-		// Attempt to rename the old version.
-		file.rename(newName);
-		return false;
-	}
-
-	// Now, load the accounts array.
-	beginResetModel();
-	QJsonArray accounts = root.value("accounts").toArray();
-	for (QJsonValue accountVal : accounts)
-	{
-		QJsonObject accountObj = accountVal.toObject();
-		MojangAccountPtr account = MojangAccount::loadFromJson(accountObj);
-		if (account.get() != nullptr)
-		{
-			connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
-			m_accounts.append(account);
-		}
-		else
-		{
-			qWarning() << "Failed to load an account.";
-		}
-	}
-	// Load the active account.
-	m_activeAccount = findAccount(root.value("activeAccount").toString(""));
-	endResetModel();
-	return true;
+    QString path = filePath;
+    if (path.isEmpty())
+        path = m_listFilePath;
+    if (path.isEmpty())
+    {
+        qCritical() << "Can't load Mojang account list. No file path given and no default set.";
+        return false;
+    }
+
+    QFile file(path);
+
+    // Try to open the file and fail if we can't.
+    // TODO: We should probably report this error to the user.
+    if (!file.open(QIODevice::ReadOnly))
+    {
+        qCritical() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
+        return false;
+    }
+
+    // Read the file and close it.
+    QByteArray jsonData = file.readAll();
+    file.close();
+
+    QJsonParseError parseError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);
+
+    // Fail if the JSON is invalid.
+    if (parseError.error != QJsonParseError::NoError)
+    {
+        qCritical() << QString("Failed to parse account list file: %1 at offset %2")
+                            .arg(parseError.errorString(), QString::number(parseError.offset))
+                            .toUtf8();
+        return false;
+    }
+
+    // Make sure the root is an object.
+    if (!jsonDoc.isObject())
+    {
+        qCritical() << "Invalid account list JSON: Root should be an array.";
+        return false;
+    }
+
+    QJsonObject root = jsonDoc.object();
+
+    // Make sure the format version matches.
+    if (root.value("formatVersion").toVariant().toInt() != ACCOUNT_LIST_FORMAT_VERSION)
+    {
+        QString newName = "accounts-old.json";
+        qWarning() << "Format version mismatch when loading account list. Existing one will be renamed to"
+                    << newName;
+
+        // Attempt to rename the old version.
+        file.rename(newName);
+        return false;
+    }
+
+    // Now, load the accounts array.
+    beginResetModel();
+    QJsonArray accounts = root.value("accounts").toArray();
+    for (QJsonValue accountVal : accounts)
+    {
+        QJsonObject accountObj = accountVal.toObject();
+        MojangAccountPtr account = MojangAccount::loadFromJson(accountObj);
+        if (account.get() != nullptr)
+        {
+            connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
+            m_accounts.append(account);
+        }
+        else
+        {
+            qWarning() << "Failed to load an account.";
+        }
+    }
+    // Load the active account.
+    m_activeAccount = findAccount(root.value("activeAccount").toString(""));
+    endResetModel();
+    return true;
 }
 
 bool MojangAccountList::saveList(const QString &filePath)
 {
-	QString path(filePath);
-	if (path.isEmpty())
-		path = m_listFilePath;
-	if (path.isEmpty())
-	{
-		qCritical() << "Can't save Mojang account list. No file path given and no default set.";
-		return false;
-	}
-
-	// make sure the parent folder exists
-	if(!FS::ensureFilePathExists(path))
-		return false;
-
-	// make sure the file wasn't overwritten with a folder before (fixes a bug)
-	QFileInfo finfo(path);
-	if(finfo.isDir())
-	{
-		QDir badDir(path);
-		badDir.removeRecursively();
-	}
-
-	qDebug() << "Writing account list to" << path;
-
-	qDebug() << "Building JSON data structure.";
-	// Build the JSON document to write to the list file.
-	QJsonObject root;
-
-	root.insert("formatVersion", ACCOUNT_LIST_FORMAT_VERSION);
-
-	// Build a list of accounts.
-	qDebug() << "Building account array.";
-	QJsonArray accounts;
-	for (MojangAccountPtr account : m_accounts)
-	{
-		QJsonObject accountObj = account->saveToJson();
-		accounts.append(accountObj);
-	}
-
-	// Insert the account list into the root object.
-	root.insert("accounts", accounts);
-
-	if(m_activeAccount)
-	{
-		// Save the active account.
-		root.insert("activeAccount", m_activeAccount->username());
-	}
-
-	// Create a JSON document object to convert our JSON to bytes.
-	QJsonDocument doc(root);
-
-	// Now that we're done building the JSON object, we can write it to the file.
-	qDebug() << "Writing account list to file.";
-	QFile file(path);
-
-	// Try to open the file and fail if we can't.
-	// TODO: We should probably report this error to the user.
-	if (!file.open(QIODevice::WriteOnly))
-	{
-		qCritical() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
-		return false;
-	}
-
-	// Write the JSON to the file.
-	file.write(doc.toJson());
-	file.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
-	file.close();
-
-	qDebug() << "Saved account list to" << path;
-
-	return true;
+    QString path(filePath);
+    if (path.isEmpty())
+        path = m_listFilePath;
+    if (path.isEmpty())
+    {
+        qCritical() << "Can't save Mojang account list. No file path given and no default set.";
+        return false;
+    }
+
+    // make sure the parent folder exists
+    if(!FS::ensureFilePathExists(path))
+        return false;
+
+    // make sure the file wasn't overwritten with a folder before (fixes a bug)
+    QFileInfo finfo(path);
+    if(finfo.isDir())
+    {
+        QDir badDir(path);
+        badDir.removeRecursively();
+    }
+
+    qDebug() << "Writing account list to" << path;
+
+    qDebug() << "Building JSON data structure.";
+    // Build the JSON document to write to the list file.
+    QJsonObject root;
+
+    root.insert("formatVersion", ACCOUNT_LIST_FORMAT_VERSION);
+
+    // Build a list of accounts.
+    qDebug() << "Building account array.";
+    QJsonArray accounts;
+    for (MojangAccountPtr account : m_accounts)
+    {
+        QJsonObject accountObj = account->saveToJson();
+        accounts.append(accountObj);
+    }
+
+    // Insert the account list into the root object.
+    root.insert("accounts", accounts);
+
+    if(m_activeAccount)
+    {
+        // Save the active account.
+        root.insert("activeAccount", m_activeAccount->username());
+    }
+
+    // Create a JSON document object to convert our JSON to bytes.
+    QJsonDocument doc(root);
+
+    // Now that we're done building the JSON object, we can write it to the file.
+    qDebug() << "Writing account list to file.";
+    QFile file(path);
+
+    // Try to open the file and fail if we can't.
+    // TODO: We should probably report this error to the user.
+    if (!file.open(QIODevice::WriteOnly))
+    {
+        qCritical() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
+        return false;
+    }
+
+    // Write the JSON to the file.
+    file.write(doc.toJson());
+    file.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser);
+    file.close();
+
+    qDebug() << "Saved account list to" << path;
+
+    return true;
 }
 
 void MojangAccountList::setListFilePath(QString path, bool autosave)
 {
-	m_listFilePath = path;
-	m_autosave = autosave;
+    m_listFilePath = path;
+    m_autosave = autosave;
 }
 
 bool MojangAccountList::anyAccountIsValid()
 {
-	for(auto account:m_accounts)
-	{
-		if(account->accountStatus() != NotVerified)
-			return true;
-	}
-	return false;
+    for(auto account:m_accounts)
+    {
+        if(account->accountStatus() != NotVerified)
+            return true;
+    }
+    return false;
 }
diff --git a/api/logic/minecraft/auth/MojangAccountList.h b/api/logic/minecraft/auth/MojangAccountList.h
index dd6c07e8..33018636 100644
--- a/api/logic/minecraft/auth/MojangAccountList.h
+++ b/api/logic/minecraft/auth/MojangAccountList.h
@@ -35,167 +35,167 @@
  */
 class MULTIMC_LOGIC_EXPORT MojangAccountList : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	enum ModelRoles
-	{
-		PointerRole = 0x34B1CB48
-	};
-
-	enum VListColumns
-	{
-		// TODO: Add icon column.
-
-		// First column - Active?
-		ActiveColumn = 0,
-
-		// Second column - Name
-		NameColumn,
-	};
-
-	explicit MojangAccountList(QObject *parent = 0);
-
-	//! Gets the account at the given index.
-	virtual const MojangAccountPtr at(int i) const;
-
-	//! Returns the number of accounts in the list.
-	virtual int count() const;
-
-	//////// List Model Functions ////////
-	virtual QVariant data(const QModelIndex &index, int role) const;
-	virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-	virtual int rowCount(const QModelIndex &parent) const;
-	virtual int columnCount(const QModelIndex &parent) const;
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const;
-	virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
-
-	/*!
-	 * Adds a the given Mojang account to the account list.
-	 */
-	virtual void addAccount(const MojangAccountPtr account);
-
-	/*!
-	 * Removes the mojang account with the given username from the account list.
-	 */
-	virtual void removeAccount(const QString &username);
-
-	/*!
-	 * Removes the account at the given QModelIndex.
-	 */
-	virtual void removeAccount(QModelIndex index);
-
-	/*!
-	 * \brief Finds an account by its username.
-	 * \param The username of the account to find.
-	 * \return A const pointer to the account with the given username. NULL if
-	 * one doesn't exist.
-	 */
-	virtual MojangAccountPtr findAccount(const QString &username) const;
-
-	/*!
-	 * Sets the default path to save the list file to.
-	 * If autosave is true, this list will automatically save to the given path whenever it changes.
-	 * THIS FUNCTION DOES NOT LOAD THE LIST. If you set autosave, be sure to call loadList() immediately
-	 * after calling this function to ensure an autosaved change doesn't overwrite the list you intended
-	 * to load.
-	 */
-	virtual void setListFilePath(QString path, bool autosave = false);
-
-	/*!
-	 * \brief Loads the account list from the given file path.
-	 * If the given file is an empty string (default), will load from the default account list file.
-	 * \return True if successful, otherwise false.
-	 */
-	virtual bool loadList(const QString &file = "");
-
-	/*!
-	 * \brief Saves the account list to the given file.
-	 * If the given file is an empty string (default), will save from the default account list file.
-	 * \return True if successful, otherwise false.
-	 */
-	virtual bool saveList(const QString &file = "");
-
-	/*!
-	 * \brief Gets a pointer to the account that the user has selected as their "active" account.
-	 * Which account is active can be overridden on a per-instance basis, but this will return the one that
-	 * is set as active globally.
-	 * \return The currently active MojangAccount. If there isn't an active account, returns a null pointer.
-	 */
-	virtual MojangAccountPtr activeAccount() const;
-
-	/*!
-	 * Sets the given account as the current active account.
-	 * If the username given is an empty string, sets the active account to nothing.
-	 */
-	virtual void setActiveAccount(const QString &username);
-
-	/*!
-	 * Returns true if any of the account is at least Validated
-	 */
-	bool anyAccountIsValid();
+    enum ModelRoles
+    {
+        PointerRole = 0x34B1CB48
+    };
+
+    enum VListColumns
+    {
+        // TODO: Add icon column.
+
+        // First column - Active?
+        ActiveColumn = 0,
+
+        // Second column - Name
+        NameColumn,
+    };
+
+    explicit MojangAccountList(QObject *parent = 0);
+
+    //! Gets the account at the given index.
+    virtual const MojangAccountPtr at(int i) const;
+
+    //! Returns the number of accounts in the list.
+    virtual int count() const;
+
+    //////// List Model Functions ////////
+    virtual QVariant data(const QModelIndex &index, int role) const;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+    virtual int rowCount(const QModelIndex &parent) const;
+    virtual int columnCount(const QModelIndex &parent) const;
+    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+    /*!
+     * Adds a the given Mojang account to the account list.
+     */
+    virtual void addAccount(const MojangAccountPtr account);
+
+    /*!
+     * Removes the mojang account with the given username from the account list.
+     */
+    virtual void removeAccount(const QString &username);
+
+    /*!
+     * Removes the account at the given QModelIndex.
+     */
+    virtual void removeAccount(QModelIndex index);
+
+    /*!
+     * \brief Finds an account by its username.
+     * \param The username of the account to find.
+     * \return A const pointer to the account with the given username. NULL if
+     * one doesn't exist.
+     */
+    virtual MojangAccountPtr findAccount(const QString &username) const;
+
+    /*!
+     * Sets the default path to save the list file to.
+     * If autosave is true, this list will automatically save to the given path whenever it changes.
+     * THIS FUNCTION DOES NOT LOAD THE LIST. If you set autosave, be sure to call loadList() immediately
+     * after calling this function to ensure an autosaved change doesn't overwrite the list you intended
+     * to load.
+     */
+    virtual void setListFilePath(QString path, bool autosave = false);
+
+    /*!
+     * \brief Loads the account list from the given file path.
+     * If the given file is an empty string (default), will load from the default account list file.
+     * \return True if successful, otherwise false.
+     */
+    virtual bool loadList(const QString &file = "");
+
+    /*!
+     * \brief Saves the account list to the given file.
+     * If the given file is an empty string (default), will save from the default account list file.
+     * \return True if successful, otherwise false.
+     */
+    virtual bool saveList(const QString &file = "");
+
+    /*!
+     * \brief Gets a pointer to the account that the user has selected as their "active" account.
+     * Which account is active can be overridden on a per-instance basis, but this will return the one that
+     * is set as active globally.
+     * \return The currently active MojangAccount. If there isn't an active account, returns a null pointer.
+     */
+    virtual MojangAccountPtr activeAccount() const;
+
+    /*!
+     * Sets the given account as the current active account.
+     * If the username given is an empty string, sets the active account to nothing.
+     */
+    virtual void setActiveAccount(const QString &username);
+
+    /*!
+     * Returns true if any of the account is at least Validated
+     */
+    bool anyAccountIsValid();
 
 signals:
-	/*!
-	 * Signal emitted to indicate that the account list has changed.
-	 * This will also fire if the value of an element in the list changes (will be implemented
-	 * later).
-	 */
-	void listChanged();
-
-	/*!
-	 * Signal emitted to indicate that the active account has changed.
-	 */
-	void activeAccountChanged();
+    /*!
+     * Signal emitted to indicate that the account list has changed.
+     * This will also fire if the value of an element in the list changes (will be implemented
+     * later).
+     */
+    void listChanged();
+
+    /*!
+     * Signal emitted to indicate that the active account has changed.
+     */
+    void activeAccountChanged();
 
 public
 slots:
-	/**
-	 * This is called when one of the accounts changes and the list needs to be updated
-	 */
-	void accountChanged();
+    /**
+     * This is called when one of the accounts changes and the list needs to be updated
+     */
+    void accountChanged();
 
 protected:
-	/*!
-	 * Called whenever the list changes.
-	 * This emits the listChanged() signal and autosaves the list (if autosave is enabled).
-	 */
-	void onListChanged();
-
-	/*!
-	 * Called whenever the active account changes.
-	 * Emits the activeAccountChanged() signal and autosaves the list if enabled.
-	 */
-	void onActiveChanged();
-
-	QList<MojangAccountPtr> m_accounts;
-
-	/*!
-	 * Account that is currently active.
-	 */
-	MojangAccountPtr m_activeAccount;
-
-	//! Path to the account list file. Empty string if there isn't one.
-	QString m_listFilePath;
-
-	/*!
-	 * If true, the account list will automatically save to the account list path when it changes.
-	 * Ignored if m_listFilePath is blank.
-	 */
-	bool m_autosave = false;
+    /*!
+     * Called whenever the list changes.
+     * This emits the listChanged() signal and autosaves the list (if autosave is enabled).
+     */
+    void onListChanged();
+
+    /*!
+     * Called whenever the active account changes.
+     * Emits the activeAccountChanged() signal and autosaves the list if enabled.
+     */
+    void onActiveChanged();
+
+    QList<MojangAccountPtr> m_accounts;
+
+    /*!
+     * Account that is currently active.
+     */
+    MojangAccountPtr m_activeAccount;
+
+    //! Path to the account list file. Empty string if there isn't one.
+    QString m_listFilePath;
+
+    /*!
+     * If true, the account list will automatically save to the account list path when it changes.
+     * Ignored if m_listFilePath is blank.
+     */
+    bool m_autosave = false;
 
 protected
 slots:
-	/*!
-	 * Updates this list with the given list of accounts.
-	 * This is done by copying each account in the given list and inserting it
-	 * into this one.
-	 * We need to do this so that we can set the parents of the accounts are set to this
-	 * account list. This can't be done in the load task, because the accounts the load
-	 * task creates are on the load task's thread and Qt won't allow their parents
-	 * to be set to something created on another thread.
-	 * To get around that problem, we invoke this method on the GUI thread, which
-	 * then copies the accounts and sets their parents correctly.
-	 * \param accounts List of accounts whose parents should be set.
-	 */
-	virtual void updateListData(QList<MojangAccountPtr> versions);
+    /*!
+     * Updates this list with the given list of accounts.
+     * This is done by copying each account in the given list and inserting it
+     * into this one.
+     * We need to do this so that we can set the parents of the accounts are set to this
+     * account list. This can't be done in the load task, because the accounts the load
+     * task creates are on the load task's thread and Qt won't allow their parents
+     * to be set to something created on another thread.
+     * To get around that problem, we invoke this method on the GUI thread, which
+     * then copies the accounts and sets their parents correctly.
+     * \param accounts List of accounts whose parents should be set.
+     */
+    virtual void updateListData(QList<MojangAccountPtr> versions);
 };
diff --git a/api/logic/minecraft/auth/YggdrasilTask.cpp b/api/logic/minecraft/auth/YggdrasilTask.cpp
index f17d803f..666e57d6 100644
--- a/api/logic/minecraft/auth/YggdrasilTask.cpp
+++ b/api/logic/minecraft/auth/YggdrasilTask.cpp
@@ -30,226 +30,226 @@
 #include <QDebug>
 
 YggdrasilTask::YggdrasilTask(MojangAccount *account, QObject *parent)
-	: Task(parent), m_account(account)
+    : Task(parent), m_account(account)
 {
-	changeState(STATE_CREATED);
+    changeState(STATE_CREATED);
 }
 
 void YggdrasilTask::executeTask()
 {
-	changeState(STATE_SENDING_REQUEST);
-
-	// Get the content of the request we're going to send to the server.
-	QJsonDocument doc(getRequestContent());
-
-	QUrl reqUrl("https://" + URLConstants::AUTH_BASE + getEndpoint());
-	QNetworkRequest netRequest(reqUrl);
-	netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
-
-	QByteArray requestData = doc.toJson();
-	m_netReply = ENV.qnam().post(netRequest, requestData);
-	connect(m_netReply, &QNetworkReply::finished, this, &YggdrasilTask::processReply);
-	connect(m_netReply, &QNetworkReply::uploadProgress, this, &YggdrasilTask::refreshTimers);
-	connect(m_netReply, &QNetworkReply::downloadProgress, this, &YggdrasilTask::refreshTimers);
-	connect(m_netReply, &QNetworkReply::sslErrors, this, &YggdrasilTask::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, &YggdrasilTask::abortByTimeout);
-	connect(&counter, &QTimer::timeout, this, &YggdrasilTask::heartbeat);
+    changeState(STATE_SENDING_REQUEST);
+
+    // Get the content of the request we're going to send to the server.
+    QJsonDocument doc(getRequestContent());
+
+    QUrl reqUrl("https://" + URLConstants::AUTH_BASE + getEndpoint());
+    QNetworkRequest netRequest(reqUrl);
+    netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+
+    QByteArray requestData = doc.toJson();
+    m_netReply = ENV.qnam().post(netRequest, requestData);
+    connect(m_netReply, &QNetworkReply::finished, this, &YggdrasilTask::processReply);
+    connect(m_netReply, &QNetworkReply::uploadProgress, this, &YggdrasilTask::refreshTimers);
+    connect(m_netReply, &QNetworkReply::downloadProgress, this, &YggdrasilTask::refreshTimers);
+    connect(m_netReply, &QNetworkReply::sslErrors, this, &YggdrasilTask::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, &YggdrasilTask::abortByTimeout);
+    connect(&counter, &QTimer::timeout, this, &YggdrasilTask::heartbeat);
 }
 
 void YggdrasilTask::refreshTimers(qint64, qint64)
 {
-	timeout_keeper.stop();
-	timeout_keeper.start(timeout_max);
-	progress(count = 0, timeout_max);
+    timeout_keeper.stop();
+    timeout_keeper.start(timeout_max);
+    progress(count = 0, timeout_max);
 }
 void YggdrasilTask::heartbeat()
 {
-	count += time_step;
-	progress(count, timeout_max);
+    count += time_step;
+    progress(count, timeout_max);
 }
 
 bool YggdrasilTask::abort()
 {
-	progress(timeout_max, timeout_max);
-	// TODO: actually use this in a meaningful way
-	m_aborted = YggdrasilTask::BY_USER;
-	m_netReply->abort();
-	return true;
+    progress(timeout_max, timeout_max);
+    // TODO: actually use this in a meaningful way
+    m_aborted = YggdrasilTask::BY_USER;
+    m_netReply->abort();
+    return true;
 }
 
 void YggdrasilTask::abortByTimeout()
 {
-	progress(timeout_max, timeout_max);
-	// TODO: actually use this in a meaningful way
-	m_aborted = YggdrasilTask::BY_TIMEOUT;
-	m_netReply->abort();
+    progress(timeout_max, timeout_max);
+    // TODO: actually use this in a meaningful way
+    m_aborted = YggdrasilTask::BY_TIMEOUT;
+    m_netReply->abort();
 }
 
 void YggdrasilTask::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++;
-	}
+    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 YggdrasilTask::processReply()
 {
-	changeState(STATE_PROCESSING_RESPONSE);
-
-	switch (m_netReply->error())
-	{
-	case QNetworkReply::NoError:
-		break;
-	case QNetworkReply::TimeoutError:
-		changeState(STATE_FAILED_SOFT, tr("Authentication operation timed out."));
-		return;
-	case QNetworkReply::OperationCanceledError:
-		changeState(STATE_FAILED_SOFT, tr("Authentication operation cancelled."));
-		return;
-	case QNetworkReply::SslHandshakeFailedError:
-		changeState(
-			STATE_FAILED_SOFT,
-			tr("<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>"
-			   "<ul>"
-			   "<li>You use Windows XP and need to <a "
-			   "href=\"http://www.microsoft.com/en-us/download/details.aspx?id=38918\">update "
-			   "your root certificates</a></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 MultiMC log file for details</li>"
-			   "</ul>"));
-		return;
-	// used for invalid credentials and similar errors. Fall through.
-	case QNetworkReply::ContentAccessDenied:
-	case QNetworkReply::ContentOperationNotPermittedError:
-		break;
-	default:
-		changeState(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(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(STATE_FAILED_SOFT,
-					tr("An unknown error occurred when trying to communicate with the "
-					   "authentication server: %1").arg(m_netReply->errorString()));
-	}
+    changeState(STATE_PROCESSING_RESPONSE);
+
+    switch (m_netReply->error())
+    {
+    case QNetworkReply::NoError:
+        break;
+    case QNetworkReply::TimeoutError:
+        changeState(STATE_FAILED_SOFT, tr("Authentication operation timed out."));
+        return;
+    case QNetworkReply::OperationCanceledError:
+        changeState(STATE_FAILED_SOFT, tr("Authentication operation cancelled."));
+        return;
+    case QNetworkReply::SslHandshakeFailedError:
+        changeState(
+            STATE_FAILED_SOFT,
+            tr("<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>"
+               "<ul>"
+               "<li>You use Windows XP and need to <a "
+               "href=\"http://www.microsoft.com/en-us/download/details.aspx?id=38918\">update "
+               "your root certificates</a></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 MultiMC log file for details</li>"
+               "</ul>"));
+        return;
+    // used for invalid credentials and similar errors. Fall through.
+    case QNetworkReply::ContentAccessDenied:
+    case QNetworkReply::ContentOperationNotPermittedError:
+        break;
+    default:
+        changeState(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(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(STATE_FAILED_SOFT,
+                    tr("An unknown error occurred when trying to communicate with the "
+                       "authentication server: %1").arg(m_netReply->errorString()));
+    }
 }
 
 void YggdrasilTask::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(STATE_FAILED_HARD, m_error->m_errorMessageVerbose);
-	}
-	else
-	{
-		// Error is not in standard format. Don't set m_error and return unknown error.
-		changeState(STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred."));
-	}
+    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(STATE_FAILED_HARD, m_error->m_errorMessageVerbose);
+    }
+    else
+    {
+        // Error is not in standard format. Don't set m_error and return unknown error.
+        changeState(STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred."));
+    }
 }
 
 QString YggdrasilTask::getStateMessage() const
 {
-	switch (m_state)
-	{
-	case STATE_CREATED:
-		return "Waiting...";
-	case STATE_SENDING_REQUEST:
-		return tr("Sending request to auth servers...");
-	case STATE_PROCESSING_RESPONSE:
-		return tr("Processing response from servers...");
-	case STATE_SUCCEEDED:
-		return tr("Authentication task succeeded.");
-	case STATE_FAILED_SOFT:
-		return tr("Failed to contact the authentication server.");
-	case STATE_FAILED_HARD:
-		return tr("Failed to authenticate.");
-	default:
-		return tr("...");
-	}
+    switch (m_state)
+    {
+    case STATE_CREATED:
+        return "Waiting...";
+    case STATE_SENDING_REQUEST:
+        return tr("Sending request to auth servers...");
+    case STATE_PROCESSING_RESPONSE:
+        return tr("Processing response from servers...");
+    case STATE_SUCCEEDED:
+        return tr("Authentication task succeeded.");
+    case STATE_FAILED_SOFT:
+        return tr("Failed to contact the authentication server.");
+    case STATE_FAILED_HARD:
+        return tr("Failed to authenticate.");
+    default:
+        return tr("...");
+    }
 }
 
 void YggdrasilTask::changeState(YggdrasilTask::State newState, QString reason)
 {
-	m_state = newState;
-	setStatus(getStateMessage());
-	if (newState == STATE_SUCCEEDED)
-	{
-		emitSucceeded();
-	}
-	else if (newState == STATE_FAILED_HARD || newState == STATE_FAILED_SOFT)
-	{
-		emitFailed(reason);
-	}
+    m_state = newState;
+    setStatus(getStateMessage());
+    if (newState == STATE_SUCCEEDED)
+    {
+        emitSucceeded();
+    }
+    else if (newState == STATE_FAILED_HARD || newState == STATE_FAILED_SOFT)
+    {
+        emitFailed(reason);
+    }
 }
 
 YggdrasilTask::State YggdrasilTask::state()
 {
-	return m_state;
+    return m_state;
 }
diff --git a/api/logic/minecraft/auth/YggdrasilTask.h b/api/logic/minecraft/auth/YggdrasilTask.h
index b5d6af13..4e302195 100644
--- a/api/logic/minecraft/auth/YggdrasilTask.h
+++ b/api/logic/minecraft/auth/YggdrasilTask.h
@@ -31,121 +31,121 @@ class QNetworkReply;
  */
 class YggdrasilTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit YggdrasilTask(MojangAccount * account, QObject *parent = 0);
-	virtual ~YggdrasilTask() {};
-
-	/**
-	 * assign a session to this task. the session will be filled with required infomration
-	 * upon completion
-	 */
-	void assignSession(AuthSessionPtr session)
-	{
-		m_session = session;
-	}
-
-	/// get the assigned session for filling with information.
-	AuthSessionPtr getAssignedSession()
-	{
-		return m_session;
-	}
-
-	/**
-	 * Class describing a Yggdrasil error response.
-	 */
-	struct Error
-	{
-		QString m_errorMessageShort;
-		QString m_errorMessageVerbose;
-		QString m_cause;
-	};
-
-	enum AbortedBy
-	{
-		BY_NOTHING,
-		BY_USER,
-		BY_TIMEOUT
-	} m_aborted = BY_NOTHING;
-
-	/**
-	 * Enum for describing the state of the current task.
-	 * Used by the getStateMessage function to determine what the status message should be.
-	 */
-	enum State
-	{
-		STATE_CREATED,
-		STATE_SENDING_REQUEST,
-		STATE_PROCESSING_RESPONSE,
-		STATE_FAILED_SOFT, //!< soft failure. this generally means the user auth details haven't been invalidated
-		STATE_FAILED_HARD, //!< hard failure. auth is invalid
-		STATE_SUCCEEDED
-	} m_state = STATE_CREATED;
+    explicit YggdrasilTask(MojangAccount * account, QObject *parent = 0);
+    virtual ~YggdrasilTask() {};
+
+    /**
+     * assign a session to this task. the session will be filled with required infomration
+     * upon completion
+     */
+    void assignSession(AuthSessionPtr session)
+    {
+        m_session = session;
+    }
+
+    /// get the assigned session for filling with information.
+    AuthSessionPtr getAssignedSession()
+    {
+        return m_session;
+    }
+
+    /**
+     * Class describing a Yggdrasil error response.
+     */
+    struct Error
+    {
+        QString m_errorMessageShort;
+        QString m_errorMessageVerbose;
+        QString m_cause;
+    };
+
+    enum AbortedBy
+    {
+        BY_NOTHING,
+        BY_USER,
+        BY_TIMEOUT
+    } m_aborted = BY_NOTHING;
+
+    /**
+     * Enum for describing the state of the current task.
+     * Used by the getStateMessage function to determine what the status message should be.
+     */
+    enum State
+    {
+        STATE_CREATED,
+        STATE_SENDING_REQUEST,
+        STATE_PROCESSING_RESPONSE,
+        STATE_FAILED_SOFT, //!< soft failure. this generally means the user auth details haven't been invalidated
+        STATE_FAILED_HARD, //!< hard failure. auth is invalid
+        STATE_SUCCEEDED
+    } m_state = STATE_CREATED;
 
 protected:
 
-	virtual void executeTask() override;
-
-	/**
-	 * Gets the JSON object that will be sent to the authentication server.
-	 * Should be overridden by subclasses.
-	 */
-	virtual QJsonObject getRequestContent() const = 0;
-
-	/**
-	 * Gets the endpoint to POST to.
-	 * No leading slash.
-	 */
-	virtual QString getEndpoint() const = 0;
-
-	/**
-	 * Processes the response received from the server.
-	 * If an error occurred, this should emit a failed signal and return false.
-	 * 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.
-	 */
-	virtual void processResponse(QJsonObject responseData) = 0;
-
-	/**
-	 * 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);
-
-	/**
-	 * Returns the state message for the given state.
-	 * Used to set the status message for the task.
-	 * Should be overridden by subclasses that want to change messages for a given state.
-	 */
-	virtual QString getStateMessage() const;
+    virtual void executeTask() override;
+
+    /**
+     * Gets the JSON object that will be sent to the authentication server.
+     * Should be overridden by subclasses.
+     */
+    virtual QJsonObject getRequestContent() const = 0;
+
+    /**
+     * Gets the endpoint to POST to.
+     * No leading slash.
+     */
+    virtual QString getEndpoint() const = 0;
+
+    /**
+     * Processes the response received from the server.
+     * If an error occurred, this should emit a failed signal and return false.
+     * 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.
+     */
+    virtual void processResponse(QJsonObject responseData) = 0;
+
+    /**
+     * 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);
+
+    /**
+     * Returns the state message for the given state.
+     * Used to set the status message for the task.
+     * Should be overridden by subclasses that want to change messages for a given state.
+     */
+    virtual QString getStateMessage() const;
 
 protected
 slots:
-	void processReply();
-	void refreshTimers(qint64, qint64);
-	void heartbeat();
-	void sslErrors(QList<QSslError>);
+    void processReply();
+    void refreshTimers(qint64, qint64);
+    void heartbeat();
+    void sslErrors(QList<QSslError>);
 
-	void changeState(State newState, QString reason=QString());
+    void changeState(State newState, QString reason=QString());
 public
 slots:
-	virtual bool abort() override;
-	void abortByTimeout();
-	State state();
+    virtual bool abort() override;
+    void abortByTimeout();
+    State state();
 protected:
-	// FIXME: segfault disaster waiting to happen
-	MojangAccount *m_account = nullptr;
-	QNetworkReply *m_netReply = nullptr;
-	std::shared_ptr<Error> m_error;
-	QTimer timeout_keeper;
-	QTimer counter;
-	int count = 0; // num msec since time reset
-
-	const int timeout_max = 30000;
-	const int time_step = 50;
-
-	AuthSessionPtr m_session;
+    // FIXME: segfault disaster waiting to happen
+    MojangAccount *m_account = nullptr;
+    QNetworkReply *m_netReply = nullptr;
+    std::shared_ptr<Error> m_error;
+    QTimer timeout_keeper;
+    QTimer counter;
+    int count = 0; // num msec since time reset
+
+    const int timeout_max = 30000;
+    const int time_step = 50;
+
+    AuthSessionPtr m_session;
 };
diff --git a/api/logic/minecraft/auth/flows/AuthenticateTask.cpp b/api/logic/minecraft/auth/flows/AuthenticateTask.cpp
index ff4e7d47..5e37f0ca 100644
--- a/api/logic/minecraft/auth/flows/AuthenticateTask.cpp
+++ b/api/logic/minecraft/auth/flows/AuthenticateTask.cpp
@@ -26,177 +26,177 @@
 #include <QUuid>
 
 AuthenticateTask::AuthenticateTask(MojangAccount * account, const QString &password,
-								   QObject *parent)
-	: YggdrasilTask(account, parent), m_password(password)
+                                   QObject *parent)
+    : YggdrasilTask(account, parent), m_password(password)
 {
 }
 
 QJsonObject AuthenticateTask::getRequestContent() const
 {
-	/*
-	 * {
-	 *   "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_account->username());
-	req.insert("password", m_password);
-	req.insert("requestUser", true);
-
-	// If we already have a client token, give it to the server.
-	// Otherwise, let the server give us one.
-
-	if(m_account->m_clientToken.isEmpty())
-	{
-		auto uuid = QUuid::createUuid();
-		auto uuidString = uuid.toString().remove('{').remove('-').remove('}');
-		m_account->m_clientToken = uuidString;
-	}
-	req.insert("clientToken", m_account->m_clientToken);
-
-	return req;
+    /*
+     * {
+     *   "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_account->username());
+    req.insert("password", m_password);
+    req.insert("requestUser", true);
+
+    // If we already have a client token, give it to the server.
+    // Otherwise, let the server give us one.
+
+    if(m_account->m_clientToken.isEmpty())
+    {
+        auto uuid = QUuid::createUuid();
+        auto uuidString = uuid.toString().remove('{').remove('-').remove('}');
+        m_account->m_clientToken = uuidString;
+    }
+    req.insert("clientToken", m_account->m_clientToken);
+
+    return req;
 }
 
 void AuthenticateTask::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.
-	qDebug() << "Getting client token.";
-	QString clientToken = responseData.value("clientToken").toString("");
-	if (clientToken.isEmpty())
-	{
-		// Fail if the server gave us an empty client token
-		changeState(STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
-		return;
-	}
-	if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken)
-	{
-		changeState(STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported."));
-		return;
-	}
-	// Set the client token.
-	m_account->m_clientToken = clientToken;
-
-	// 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(STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
-		return;
-	}
-	// Set the access token.
-	m_account->m_accessToken = accessToken;
-
-	// Now we load the list of available profiles.
-	// Mojang hasn't yet implemented the profile system,
-	// but we might as well support what's there so we
-	// don't have trouble implementing it later.
-	qDebug() << "Loading profile list.";
-	QJsonArray availableProfiles = responseData.value("availableProfiles").toArray();
-	QList<AccountProfile> loadedProfiles;
-	for (auto iter : availableProfiles)
-	{
-		QJsonObject profile = iter.toObject();
-		// Profiles are easy, we just need their ID and name.
-		QString id = profile.value("id").toString("");
-		QString name = profile.value("name").toString("");
-		bool legacy = profile.value("legacy").toBool(false);
-
-		if (id.isEmpty() || name.isEmpty())
-		{
-			// This should never happen, but we might as well
-			// warn about it if it does so we can debug it easily.
-			// You never know when Mojang might do something truly derpy.
-			qWarning() << "Found entry in available profiles list with missing ID or name "
-						   "field. Ignoring it.";
-		}
-
-		// Now, add a new AccountProfile entry to the list.
-		loadedProfiles.append({id, name, legacy});
-	}
-	// Put the list of profiles we loaded into the MojangAccount object.
-	m_account->m_profiles = loadedProfiles;
-
-	// Finally, we set the current profile to the correct value. This is pretty simple.
-	// We do need to make sure that the current profile that the server gave us
-	// is actually in the available profiles list.
-	// If it isn't, we'll just fail horribly (*shouldn't* ever happen, but you never know).
-	qDebug() << "Setting current profile.";
-	QJsonObject currentProfile = responseData.value("selectedProfile").toObject();
-	QString currentProfileId = currentProfile.value("id").toString("");
-	if (currentProfileId.isEmpty())
-	{
-		changeState(STATE_FAILED_HARD, tr("Authentication server didn't specify a currently selected profile. The account exists, but likely isn't premium."));
-		return;
-	}
-	if (!m_account->setCurrentProfile(currentProfileId))
-	{
-		changeState(STATE_FAILED_HARD, tr("Authentication server specified a selected profile that wasn't in the available profiles list."));
-		return;
-	}
-
-	// this is what the vanilla launcher passes to the userProperties launch param
-	if (responseData.contains("user"))
-	{
-		User u;
-		auto obj = responseData.value("user").toObject();
-		u.id = obj.value("id").toString();
-		auto propArray = obj.value("properties").toArray();
-		for (auto prop : propArray)
-		{
-			auto propTuple = prop.toObject();
-			auto name = propTuple.value("name").toString();
-			auto value = propTuple.value("value").toString();
-			u.properties.insert(name, value);
-		}
-		m_account->m_user = u;
-	}
-
-	// We've made it through the minefield of possible errors. Return true to indicate that
-	// we've succeeded.
-	qDebug() << "Finished reading authentication response.";
-	changeState(STATE_SUCCEEDED);
+    // 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.
+    qDebug() << "Getting client token.";
+    QString clientToken = responseData.value("clientToken").toString("");
+    if (clientToken.isEmpty())
+    {
+        // Fail if the server gave us an empty client token
+        changeState(STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
+        return;
+    }
+    if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken)
+    {
+        changeState(STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported."));
+        return;
+    }
+    // Set the client token.
+    m_account->m_clientToken = clientToken;
+
+    // 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(STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
+        return;
+    }
+    // Set the access token.
+    m_account->m_accessToken = accessToken;
+
+    // Now we load the list of available profiles.
+    // Mojang hasn't yet implemented the profile system,
+    // but we might as well support what's there so we
+    // don't have trouble implementing it later.
+    qDebug() << "Loading profile list.";
+    QJsonArray availableProfiles = responseData.value("availableProfiles").toArray();
+    QList<AccountProfile> loadedProfiles;
+    for (auto iter : availableProfiles)
+    {
+        QJsonObject profile = iter.toObject();
+        // Profiles are easy, we just need their ID and name.
+        QString id = profile.value("id").toString("");
+        QString name = profile.value("name").toString("");
+        bool legacy = profile.value("legacy").toBool(false);
+
+        if (id.isEmpty() || name.isEmpty())
+        {
+            // This should never happen, but we might as well
+            // warn about it if it does so we can debug it easily.
+            // You never know when Mojang might do something truly derpy.
+            qWarning() << "Found entry in available profiles list with missing ID or name "
+                           "field. Ignoring it.";
+        }
+
+        // Now, add a new AccountProfile entry to the list.
+        loadedProfiles.append({id, name, legacy});
+    }
+    // Put the list of profiles we loaded into the MojangAccount object.
+    m_account->m_profiles = loadedProfiles;
+
+    // Finally, we set the current profile to the correct value. This is pretty simple.
+    // We do need to make sure that the current profile that the server gave us
+    // is actually in the available profiles list.
+    // If it isn't, we'll just fail horribly (*shouldn't* ever happen, but you never know).
+    qDebug() << "Setting current profile.";
+    QJsonObject currentProfile = responseData.value("selectedProfile").toObject();
+    QString currentProfileId = currentProfile.value("id").toString("");
+    if (currentProfileId.isEmpty())
+    {
+        changeState(STATE_FAILED_HARD, tr("Authentication server didn't specify a currently selected profile. The account exists, but likely isn't premium."));
+        return;
+    }
+    if (!m_account->setCurrentProfile(currentProfileId))
+    {
+        changeState(STATE_FAILED_HARD, tr("Authentication server specified a selected profile that wasn't in the available profiles list."));
+        return;
+    }
+
+    // this is what the vanilla launcher passes to the userProperties launch param
+    if (responseData.contains("user"))
+    {
+        User u;
+        auto obj = responseData.value("user").toObject();
+        u.id = obj.value("id").toString();
+        auto propArray = obj.value("properties").toArray();
+        for (auto prop : propArray)
+        {
+            auto propTuple = prop.toObject();
+            auto name = propTuple.value("name").toString();
+            auto value = propTuple.value("value").toString();
+            u.properties.insert(name, value);
+        }
+        m_account->m_user = u;
+    }
+
+    // We've made it through the minefield of possible errors. Return true to indicate that
+    // we've succeeded.
+    qDebug() << "Finished reading authentication response.";
+    changeState(STATE_SUCCEEDED);
 }
 
 QString AuthenticateTask::getEndpoint() const
 {
-	return "authenticate";
+    return "authenticate";
 }
 
 QString AuthenticateTask::getStateMessage() const
 {
-	switch (m_state)
-	{
-	case STATE_SENDING_REQUEST:
-		return tr("Authenticating: Sending request...");
-	case STATE_PROCESSING_RESPONSE:
-		return tr("Authenticating: Processing response...");
-	default:
-		return YggdrasilTask::getStateMessage();
-	}
+    switch (m_state)
+    {
+    case STATE_SENDING_REQUEST:
+        return tr("Authenticating: Sending request...");
+    case STATE_PROCESSING_RESPONSE:
+        return tr("Authenticating: Processing response...");
+    default:
+        return YggdrasilTask::getStateMessage();
+    }
 }
diff --git a/api/logic/minecraft/auth/flows/AuthenticateTask.h b/api/logic/minecraft/auth/flows/AuthenticateTask.h
index ab7a6e64..71f0eab7 100644
--- a/api/logic/minecraft/auth/flows/AuthenticateTask.h
+++ b/api/logic/minecraft/auth/flows/AuthenticateTask.h
@@ -28,19 +28,19 @@
  */
 class AuthenticateTask : public YggdrasilTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	AuthenticateTask(MojangAccount *account, const QString &password, QObject *parent = 0);
+    AuthenticateTask(MojangAccount *account, const QString &password, QObject *parent = 0);
 
 protected:
-	virtual QJsonObject getRequestContent() const override;
+    virtual QJsonObject getRequestContent() const override;
 
-	virtual QString getEndpoint() const override;
+    virtual QString getEndpoint() const override;
 
-	virtual void processResponse(QJsonObject responseData) override;
+    virtual void processResponse(QJsonObject responseData) override;
 
-	virtual QString getStateMessage() const override;
+    virtual QString getStateMessage() const override;
 
 private:
-	QString m_password;
+    QString m_password;
 };
diff --git a/api/logic/minecraft/auth/flows/RefreshTask.cpp b/api/logic/minecraft/auth/flows/RefreshTask.cpp
index 73050907..f6fe4757 100644
--- a/api/logic/minecraft/auth/flows/RefreshTask.cpp
+++ b/api/logic/minecraft/auth/flows/RefreshTask.cpp
@@ -29,116 +29,116 @@ RefreshTask::RefreshTask(MojangAccount *account) : YggdrasilTask(account)
 
 QJsonObject RefreshTask::getRequestContent() const
 {
-	/*
-	 * {
-	 *  "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_account->m_clientToken);
-	req.insert("accessToken", m_account->m_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", true);
+    /*
+     * {
+     *  "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_account->m_clientToken);
+    req.insert("accessToken", m_account->m_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", true);
 
-	return req;
+    return req;
 }
 
 void RefreshTask::processResponse(QJsonObject responseData)
 {
-	// Read the response data. We need to get the client token, access token, and the selected
-	// profile.
-	qDebug() << "Processing authentication response.";
+    // 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(STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
-		return;
-	}
-	if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken)
-	{
-		changeState(STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported."));
-		return;
-	}
+    // 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(STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
+        return;
+    }
+    if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken)
+    {
+        changeState(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 new access token.";
-	QString accessToken = responseData.value("accessToken").toString("");
-	if (accessToken.isEmpty())
-	{
-		// Fail if the server didn't give us an access token.
-		changeState(STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
-		return;
-	}
+    // Now, we set the access token.
+    qDebug() << "Getting new access token.";
+    QString accessToken = responseData.value("accessToken").toString("");
+    if (accessToken.isEmpty())
+    {
+        // Fail if the server didn't give us an access token.
+        changeState(STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
+        return;
+    }
 
-	// we validate that the server responded right. (our current profile = returned current
-	// profile)
-	QJsonObject currentProfile = responseData.value("selectedProfile").toObject();
-	QString currentProfileId = currentProfile.value("id").toString("");
-	if (m_account->currentProfile()->id != currentProfileId)
-	{
-		changeState(STATE_FAILED_HARD, tr("Authentication server didn't specify the same prefile as expected."));
-		return;
-	}
+    // we validate that the server responded right. (our current profile = returned current
+    // profile)
+    QJsonObject currentProfile = responseData.value("selectedProfile").toObject();
+    QString currentProfileId = currentProfile.value("id").toString("");
+    if (m_account->currentProfile()->id != currentProfileId)
+    {
+        changeState(STATE_FAILED_HARD, tr("Authentication server didn't specify the same prefile as expected."));
+        return;
+    }
 
-	// this is what the vanilla launcher passes to the userProperties launch param
-	if (responseData.contains("user"))
-	{
-		User u;
-		auto obj = responseData.value("user").toObject();
-		u.id = obj.value("id").toString();
-		auto propArray = obj.value("properties").toArray();
-		for (auto prop : propArray)
-		{
-			auto propTuple = prop.toObject();
-			auto name = propTuple.value("name").toString();
-			auto value = propTuple.value("value").toString();
-			u.properties.insert(name, value);
-		}
-		m_account->m_user = u;
-	}
+    // this is what the vanilla launcher passes to the userProperties launch param
+    if (responseData.contains("user"))
+    {
+        User u;
+        auto obj = responseData.value("user").toObject();
+        u.id = obj.value("id").toString();
+        auto propArray = obj.value("properties").toArray();
+        for (auto prop : propArray)
+        {
+            auto propTuple = prop.toObject();
+            auto name = propTuple.value("name").toString();
+            auto value = propTuple.value("value").toString();
+            u.properties.insert(name, value);
+        }
+        m_account->m_user = u;
+    }
 
-	// We've made it through the minefield of possible errors. Return true to indicate that
-	// we've succeeded.
-	qDebug() << "Finished reading refresh response.";
-	// Reset the access token.
-	m_account->m_accessToken = accessToken;
-	changeState(STATE_SUCCEEDED);
+    // We've made it through the minefield of possible errors. Return true to indicate that
+    // we've succeeded.
+    qDebug() << "Finished reading refresh response.";
+    // Reset the access token.
+    m_account->m_accessToken = accessToken;
+    changeState(STATE_SUCCEEDED);
 }
 
 QString RefreshTask::getEndpoint() const
 {
-	return "refresh";
+    return "refresh";
 }
 
 QString RefreshTask::getStateMessage() const
 {
-	switch (m_state)
-	{
-	case STATE_SENDING_REQUEST:
-		return tr("Refreshing login token...");
-	case STATE_PROCESSING_RESPONSE:
-		return tr("Refreshing login token: Processing response...");
-	default:
-		return YggdrasilTask::getStateMessage();
-	}
+    switch (m_state)
+    {
+    case STATE_SENDING_REQUEST:
+        return tr("Refreshing login token...");
+    case STATE_PROCESSING_RESPONSE:
+        return tr("Refreshing login token: Processing response...");
+    default:
+        return YggdrasilTask::getStateMessage();
+    }
 }
diff --git a/api/logic/minecraft/auth/flows/RefreshTask.h b/api/logic/minecraft/auth/flows/RefreshTask.h
index a97b54e6..ff586396 100644
--- a/api/logic/minecraft/auth/flows/RefreshTask.h
+++ b/api/logic/minecraft/auth/flows/RefreshTask.h
@@ -28,17 +28,17 @@
  */
 class RefreshTask : public YggdrasilTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	RefreshTask(MojangAccount * account);
+    RefreshTask(MojangAccount * account);
 
 protected:
-	virtual QJsonObject getRequestContent() const override;
+    virtual QJsonObject getRequestContent() const override;
 
-	virtual QString getEndpoint() const override;
+    virtual QString getEndpoint() const override;
 
-	virtual void processResponse(QJsonObject responseData) override;
+    virtual void processResponse(QJsonObject responseData) override;
 
-	virtual QString getStateMessage() const override;
+    virtual QString getStateMessage() const override;
 };
 
diff --git a/api/logic/minecraft/auth/flows/ValidateTask.cpp b/api/logic/minecraft/auth/flows/ValidateTask.cpp
index b6d6c823..e82678c8 100644
--- a/api/logic/minecraft/auth/flows/ValidateTask.cpp
+++ b/api/logic/minecraft/auth/flows/ValidateTask.cpp
@@ -25,37 +25,37 @@
 #include <QDebug>
 
 ValidateTask::ValidateTask(MojangAccount * account, QObject *parent)
-	: YggdrasilTask(account, parent)
+    : YggdrasilTask(account, parent)
 {
 }
 
 QJsonObject ValidateTask::getRequestContent() const
 {
-	QJsonObject req;
-	req.insert("accessToken", m_account->m_accessToken);
-	return req;
+    QJsonObject req;
+    req.insert("accessToken", m_account->m_accessToken);
+    return req;
 }
 
 void ValidateTask::processResponse(QJsonObject responseData)
 {
-	// Assume that if processError wasn't called, then the request was successful.
-	changeState(YggdrasilTask::STATE_SUCCEEDED);
+    // Assume that if processError wasn't called, then the request was successful.
+    changeState(YggdrasilTask::STATE_SUCCEEDED);
 }
 
 QString ValidateTask::getEndpoint() const
 {
-	return "validate";
+    return "validate";
 }
 
 QString ValidateTask::getStateMessage() const
 {
-	switch (m_state)
-	{
-	case YggdrasilTask::STATE_SENDING_REQUEST:
-		return tr("Validating access token: Sending request...");
-	case YggdrasilTask::STATE_PROCESSING_RESPONSE:
-		return tr("Validating access token: Processing response...");
-	default:
-		return YggdrasilTask::getStateMessage();
-	}
+    switch (m_state)
+    {
+    case YggdrasilTask::STATE_SENDING_REQUEST:
+        return tr("Validating access token: Sending request...");
+    case YggdrasilTask::STATE_PROCESSING_RESPONSE:
+        return tr("Validating access token: Processing response...");
+    default:
+        return YggdrasilTask::getStateMessage();
+    }
 }
diff --git a/api/logic/minecraft/auth/flows/ValidateTask.h b/api/logic/minecraft/auth/flows/ValidateTask.h
index 77de24c7..87876fb8 100644
--- a/api/logic/minecraft/auth/flows/ValidateTask.h
+++ b/api/logic/minecraft/auth/flows/ValidateTask.h
@@ -30,18 +30,18 @@
  */
 class ValidateTask : public YggdrasilTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	ValidateTask(MojangAccount *account, QObject *parent = 0);
+    ValidateTask(MojangAccount *account, QObject *parent = 0);
 
 protected:
-	virtual QJsonObject getRequestContent() const override;
+    virtual QJsonObject getRequestContent() const override;
 
-	virtual QString getEndpoint() const override;
+    virtual QString getEndpoint() const override;
 
-	virtual void processResponse(QJsonObject responseData) override;
+    virtual void processResponse(QJsonObject responseData) override;
 
-	virtual QString getStateMessage() const override;
+    virtual QString getStateMessage() const override;
 
 private:
 };
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.cpp b/api/logic/minecraft/forge/ForgeXzDownload.cpp
index 4d82a58a..4083bdea 100644
--- a/api/logic/minecraft/forge/ForgeXzDownload.cpp
+++ b/api/logic/minecraft/forge/ForgeXzDownload.cpp
@@ -25,138 +25,138 @@
 
 ForgeXzDownload::ForgeXzDownload(QString relative_path, MetaEntryPtr entry) : NetAction()
 {
-	m_entry = entry;
-	m_target_path = entry->getFullPath();
-	m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
-	m_status = Job_NotStarted;
-	m_url_path = relative_path;
-	m_url = "http://files.minecraftforge.net/maven/" + m_url_path + ".pack.xz";
+    m_entry = entry;
+    m_target_path = entry->getFullPath();
+    m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
+    m_status = Job_NotStarted;
+    m_url_path = relative_path;
+    m_url = "http://files.minecraftforge.net/maven/" + m_url_path + ".pack.xz";
 }
 
 void ForgeXzDownload::start()
 {
-	if(m_status == Job_Aborted)
-	{
-		qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
-		emit aborted(m_index_within_job);
-		return;
-	}
-	m_status = Job_InProgress;
-	if (!m_entry->isStale())
-	{
-		m_status = Job_Finished;
-		emit succeeded(m_index_within_job);
-		return;
-	}
-	// can we actually create the real, final file?
-	if (!FS::ensureFilePathExists(m_target_path))
-	{
-		m_status = Job_Failed;
-		emit failed(m_index_within_job);
-		return;
-	}
-
-	qDebug() << "Downloading " << m_url.toString();
-	QNetworkRequest request(m_url);
-	request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
-
-	QNetworkReply *rep = ENV.qnam().get(request);
-
-	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(readyRead()), SLOT(downloadReadyRead()));
+    if(m_status == Job_Aborted)
+    {
+        qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
+        emit aborted(m_index_within_job);
+        return;
+    }
+    m_status = Job_InProgress;
+    if (!m_entry->isStale())
+    {
+        m_status = Job_Finished;
+        emit succeeded(m_index_within_job);
+        return;
+    }
+    // can we actually create the real, final file?
+    if (!FS::ensureFilePathExists(m_target_path))
+    {
+        m_status = Job_Failed;
+        emit failed(m_index_within_job);
+        return;
+    }
+
+    qDebug() << "Downloading " << m_url.toString();
+    QNetworkRequest request(m_url);
+    request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
+    request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
+
+    QNetworkReply *rep = ENV.qnam().get(request);
+
+    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(readyRead()), SLOT(downloadReadyRead()));
 }
 
 void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	m_total_progress = bytesTotal;
-	m_progress = bytesReceived;
-	emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
+    m_total_progress = bytesTotal;
+    m_progress = bytesReceived;
+    emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
 {
-	if(error == QNetworkReply::OperationCanceledError)
-	{
-		qCritical() << "Aborted " << m_url.toString();
-		m_status = Job_Aborted;
-	}
-	else
-	{
-		// error happened during download.
-		qCritical() << "Failed " << m_url.toString() << " with reason " << error;
-		m_status = Job_Failed;
-	}
+    if(error == QNetworkReply::OperationCanceledError)
+    {
+        qCritical() << "Aborted " << m_url.toString();
+        m_status = Job_Aborted;
+    }
+    else
+    {
+        // error happened during download.
+        qCritical() << "Failed " << m_url.toString() << " with reason " << error;
+        m_status = Job_Failed;
+    }
 }
 
 void ForgeXzDownload::failAndTryNextMirror()
 {
-	m_status = Job_Failed;
-	emit failed(m_index_within_job);
+    m_status = Job_Failed;
+    emit failed(m_index_within_job);
 }
 
 void ForgeXzDownload::downloadFinished()
 {
-	// if the download succeeded
-	if (m_status != Job_Failed && m_status != Job_Aborted)
-	{
-		// nothing went wrong...
-		m_status = Job_Finished;
-		if (m_pack200_xz_file.isOpen())
-		{
-			// we actually downloaded something! process and isntall it
-			decompressAndInstall();
-			return;
-		}
-		else
-		{
-			// something bad happened -- on the local machine!
-			m_status = Job_Failed;
-			m_pack200_xz_file.remove();
-			m_reply.reset();
-			emit failed(m_index_within_job);
-			return;
-		}
-	}
-	else if(m_status == Job_Aborted)
-	{
-		m_pack200_xz_file.remove();
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		emit aborted(m_index_within_job);
-		return;
-	}
-	// else the download failed
-	else
-	{
-		m_status = Job_Failed;
-		m_pack200_xz_file.close();
-		m_pack200_xz_file.remove();
-		m_reply.reset();
-		failAndTryNextMirror();
-		return;
-	}
+    // if the download succeeded
+    if (m_status != Job_Failed && m_status != Job_Aborted)
+    {
+        // nothing went wrong...
+        m_status = Job_Finished;
+        if (m_pack200_xz_file.isOpen())
+        {
+            // we actually downloaded something! process and isntall it
+            decompressAndInstall();
+            return;
+        }
+        else
+        {
+            // something bad happened -- on the local machine!
+            m_status = Job_Failed;
+            m_pack200_xz_file.remove();
+            m_reply.reset();
+            emit failed(m_index_within_job);
+            return;
+        }
+    }
+    else if(m_status == Job_Aborted)
+    {
+        m_pack200_xz_file.remove();
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        emit aborted(m_index_within_job);
+        return;
+    }
+    // else the download failed
+    else
+    {
+        m_status = Job_Failed;
+        m_pack200_xz_file.close();
+        m_pack200_xz_file.remove();
+        m_reply.reset();
+        failAndTryNextMirror();
+        return;
+    }
 }
 
 void ForgeXzDownload::downloadReadyRead()
 {
 
-	if (!m_pack200_xz_file.isOpen())
-	{
-		if (!m_pack200_xz_file.open())
-		{
-			/*
-			* Can't open the file... the job failed
-			*/
-			m_reply->abort();
-			emit failed(m_index_within_job);
-			return;
-		}
-	}
-	m_pack200_xz_file.write(m_reply->readAll());
+    if (!m_pack200_xz_file.isOpen())
+    {
+        if (!m_pack200_xz_file.open())
+        {
+            /*
+            * Can't open the file... the job failed
+            */
+            m_reply->abort();
+            emit failed(m_index_within_job);
+            return;
+        }
+    }
+    m_pack200_xz_file.write(m_reply->readAll());
 }
 
 #include "xz.h"
@@ -169,225 +169,225 @@ const size_t buffer_size = 8196;
 // NOTE: once this gets here, it can't be aborted anymore. we don't care.
 void ForgeXzDownload::decompressAndInstall()
 {
-	// rewind the downloaded temp file
-	m_pack200_xz_file.seek(0);
-	// de-xz'd file
-	QTemporaryFile pack200_file("./dl_temp.XXXXXX");
-	pack200_file.open();
-
-	bool xz_success = false;
-	// first, de-xz
-	{
-		uint8_t in[buffer_size];
-		uint8_t out[buffer_size];
-		struct xz_buf b;
-		struct xz_dec *s;
-		enum xz_ret ret;
-		xz_crc32_init();
-		xz_crc64_init();
-		s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
-		if (s == nullptr)
-		{
-			xz_dec_end(s);
-			failAndTryNextMirror();
-			return;
-		}
-		b.in = in;
-		b.in_pos = 0;
-		b.in_size = 0;
-		b.out = out;
-		b.out_pos = 0;
-		b.out_size = buffer_size;
-		while (!xz_success)
-		{
-			if (b.in_pos == b.in_size)
-			{
-				b.in_size = m_pack200_xz_file.read((char *)in, sizeof(in));
-				b.in_pos = 0;
-			}
-
-			ret = xz_dec_run(s, &b);
-
-			if (b.out_pos == sizeof(out))
-			{
-				auto wresult = pack200_file.write((char *)out, b.out_pos);
-				if (wresult < 0 || size_t(wresult) != b.out_pos)
-				{
-					// msg = "Write error\n";
-					xz_dec_end(s);
-					failAndTryNextMirror();
-					return;
-				}
-
-				b.out_pos = 0;
-			}
-
-			if (ret == XZ_OK)
-				continue;
-
-			if (ret == XZ_UNSUPPORTED_CHECK)
-			{
-				// unsupported check. this is OK, but we should log this
-				continue;
-			}
-
-			auto wresult = pack200_file.write((char *)out, b.out_pos);
-			if (wresult < 0 || size_t(wresult) != b.out_pos)
-			{
-				// write error
-				pack200_file.close();
-				xz_dec_end(s);
-				return;
-			}
-
-			switch (ret)
-			{
-			case XZ_STREAM_END:
-				xz_dec_end(s);
-				xz_success = true;
-				break;
-
-			case XZ_MEM_ERROR:
-				qCritical() << "Memory allocation failed\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-
-			case XZ_MEMLIMIT_ERROR:
-				qCritical() << "Memory usage limit reached\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-
-			case XZ_FORMAT_ERROR:
-				qCritical() << "Not a .xz file\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-
-			case XZ_OPTIONS_ERROR:
-				qCritical() << "Unsupported options in the .xz headers\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-
-			case XZ_DATA_ERROR:
-			case XZ_BUF_ERROR:
-				qCritical() << "File is corrupt\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-
-			default:
-				qCritical() << "Bug!\n";
-				xz_dec_end(s);
-				failAndTryNextMirror();
-				return;
-			}
-		}
-	}
-	m_pack200_xz_file.remove();
-
-	// revert pack200
-	pack200_file.seek(0);
-	int handle_in = pack200_file.handle();
-	// FIXME: dispose of file handles, pointers and the like. Ideally wrap in objects.
-	if(handle_in == -1)
-	{
-		qCritical() << "Error reopening " << pack200_file.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	int handle_in_dup = dup (handle_in);
-	if(handle_in_dup == -1)
-	{
-		qCritical() << "Error reopening " << pack200_file.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	FILE *file_in = fdopen (handle_in_dup, "rb");
-	if(!file_in)
-	{
-		qCritical() << "Error reopening " << pack200_file.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	QFile qfile_out(m_target_path);
-	if(!qfile_out.open(QIODevice::WriteOnly))
-	{
-		qCritical() << "Error opening " << qfile_out.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	int handle_out = qfile_out.handle();
-	if(handle_out == -1)
-	{
-		qCritical() << "Error opening " << qfile_out.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	int handle_out_dup = dup (handle_out);
-	if(handle_out_dup == -1)
-	{
-		qCritical() << "Error reopening " << qfile_out.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	FILE *file_out = fdopen (handle_out_dup, "wb");
-	if(!file_out)
-	{
-		qCritical() << "Error opening " << qfile_out.fileName();
-		failAndTryNextMirror();
-		return;
-	}
-	try
-	{
-		// NOTE: this takes ownership of both FILE pointers. That's why we duplicate them above.
-		unpack_200(file_in, file_out);
-	}
-	catch (const std::runtime_error &err)
-	{
-		m_status = Job_Failed;
-		qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
-		QFile f(m_target_path);
-		if (f.exists())
-			f.remove();
-		failAndTryNextMirror();
-		return;
-	}
-	pack200_file.remove();
-
-	QFile jar_file(m_target_path);
-
-	if (!jar_file.open(QIODevice::ReadOnly))
-	{
-		jar_file.remove();
-		failAndTryNextMirror();
-		return;
-	}
-	auto hash = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5);
-	m_entry->setMD5Sum(hash.toHex().constData());
-	jar_file.close();
-
-	QFileInfo output_file_info(m_target_path);
-	m_entry->setETag(m_reply->rawHeader("ETag").constData());
-	m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
-	m_entry->setStale(false);
-	ENV.metacache()->updateEntry(m_entry);
-
-	m_reply.reset();
-	emit succeeded(m_index_within_job);
+    // rewind the downloaded temp file
+    m_pack200_xz_file.seek(0);
+    // de-xz'd file
+    QTemporaryFile pack200_file("./dl_temp.XXXXXX");
+    pack200_file.open();
+
+    bool xz_success = false;
+    // first, de-xz
+    {
+        uint8_t in[buffer_size];
+        uint8_t out[buffer_size];
+        struct xz_buf b;
+        struct xz_dec *s;
+        enum xz_ret ret;
+        xz_crc32_init();
+        xz_crc64_init();
+        s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
+        if (s == nullptr)
+        {
+            xz_dec_end(s);
+            failAndTryNextMirror();
+            return;
+        }
+        b.in = in;
+        b.in_pos = 0;
+        b.in_size = 0;
+        b.out = out;
+        b.out_pos = 0;
+        b.out_size = buffer_size;
+        while (!xz_success)
+        {
+            if (b.in_pos == b.in_size)
+            {
+                b.in_size = m_pack200_xz_file.read((char *)in, sizeof(in));
+                b.in_pos = 0;
+            }
+
+            ret = xz_dec_run(s, &b);
+
+            if (b.out_pos == sizeof(out))
+            {
+                auto wresult = pack200_file.write((char *)out, b.out_pos);
+                if (wresult < 0 || size_t(wresult) != b.out_pos)
+                {
+                    // msg = "Write error\n";
+                    xz_dec_end(s);
+                    failAndTryNextMirror();
+                    return;
+                }
+
+                b.out_pos = 0;
+            }
+
+            if (ret == XZ_OK)
+                continue;
+
+            if (ret == XZ_UNSUPPORTED_CHECK)
+            {
+                // unsupported check. this is OK, but we should log this
+                continue;
+            }
+
+            auto wresult = pack200_file.write((char *)out, b.out_pos);
+            if (wresult < 0 || size_t(wresult) != b.out_pos)
+            {
+                // write error
+                pack200_file.close();
+                xz_dec_end(s);
+                return;
+            }
+
+            switch (ret)
+            {
+            case XZ_STREAM_END:
+                xz_dec_end(s);
+                xz_success = true;
+                break;
+
+            case XZ_MEM_ERROR:
+                qCritical() << "Memory allocation failed\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+
+            case XZ_MEMLIMIT_ERROR:
+                qCritical() << "Memory usage limit reached\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+
+            case XZ_FORMAT_ERROR:
+                qCritical() << "Not a .xz file\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+
+            case XZ_OPTIONS_ERROR:
+                qCritical() << "Unsupported options in the .xz headers\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+
+            case XZ_DATA_ERROR:
+            case XZ_BUF_ERROR:
+                qCritical() << "File is corrupt\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+
+            default:
+                qCritical() << "Bug!\n";
+                xz_dec_end(s);
+                failAndTryNextMirror();
+                return;
+            }
+        }
+    }
+    m_pack200_xz_file.remove();
+
+    // revert pack200
+    pack200_file.seek(0);
+    int handle_in = pack200_file.handle();
+    // FIXME: dispose of file handles, pointers and the like. Ideally wrap in objects.
+    if(handle_in == -1)
+    {
+        qCritical() << "Error reopening " << pack200_file.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    int handle_in_dup = dup (handle_in);
+    if(handle_in_dup == -1)
+    {
+        qCritical() << "Error reopening " << pack200_file.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    FILE *file_in = fdopen (handle_in_dup, "rb");
+    if(!file_in)
+    {
+        qCritical() << "Error reopening " << pack200_file.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    QFile qfile_out(m_target_path);
+    if(!qfile_out.open(QIODevice::WriteOnly))
+    {
+        qCritical() << "Error opening " << qfile_out.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    int handle_out = qfile_out.handle();
+    if(handle_out == -1)
+    {
+        qCritical() << "Error opening " << qfile_out.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    int handle_out_dup = dup (handle_out);
+    if(handle_out_dup == -1)
+    {
+        qCritical() << "Error reopening " << qfile_out.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    FILE *file_out = fdopen (handle_out_dup, "wb");
+    if(!file_out)
+    {
+        qCritical() << "Error opening " << qfile_out.fileName();
+        failAndTryNextMirror();
+        return;
+    }
+    try
+    {
+        // NOTE: this takes ownership of both FILE pointers. That's why we duplicate them above.
+        unpack_200(file_in, file_out);
+    }
+    catch (const std::runtime_error &err)
+    {
+        m_status = Job_Failed;
+        qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
+        QFile f(m_target_path);
+        if (f.exists())
+            f.remove();
+        failAndTryNextMirror();
+        return;
+    }
+    pack200_file.remove();
+
+    QFile jar_file(m_target_path);
+
+    if (!jar_file.open(QIODevice::ReadOnly))
+    {
+        jar_file.remove();
+        failAndTryNextMirror();
+        return;
+    }
+    auto hash = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5);
+    m_entry->setMD5Sum(hash.toHex().constData());
+    jar_file.close();
+
+    QFileInfo output_file_info(m_target_path);
+    m_entry->setETag(m_reply->rawHeader("ETag").constData());
+    m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
+    m_entry->setStale(false);
+    ENV.metacache()->updateEntry(m_entry);
+
+    m_reply.reset();
+    emit succeeded(m_index_within_job);
 }
 
 bool ForgeXzDownload::abort()
 {
-	if(m_reply)
-		m_reply->abort();
-	m_status = Job_Aborted;
-	return true;
+    if(m_reply)
+        m_reply->abort();
+    m_status = Job_Aborted;
+    return true;
 }
 
 bool ForgeXzDownload::canAbort()
 {
-	return true;
+    return true;
 }
diff --git a/api/logic/minecraft/forge/ForgeXzDownload.h b/api/logic/minecraft/forge/ForgeXzDownload.h
index cee402ef..728a7f7a 100644
--- a/api/logic/minecraft/forge/ForgeXzDownload.h
+++ b/api/logic/minecraft/forge/ForgeXzDownload.h
@@ -24,38 +24,38 @@ typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
 
 class ForgeXzDownload : public NetAction
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	MetaEntryPtr m_entry;
-	/// if saving to file, use the one specified in this string
-	QString m_target_path;
-	/// this is the output file, if any
-	QTemporaryFile m_pack200_xz_file;
-	/// path relative to the mirror base
-	QString m_url_path;
+    MetaEntryPtr m_entry;
+    /// if saving to file, use the one specified in this string
+    QString m_target_path;
+    /// this is the output file, if any
+    QTemporaryFile m_pack200_xz_file;
+    /// path relative to the mirror base
+    QString m_url_path;
 
 public:
-	explicit ForgeXzDownload(QString relative_path, MetaEntryPtr entry);
-	static ForgeXzDownloadPtr make(QString relative_path, MetaEntryPtr entry)
-	{
-		return ForgeXzDownloadPtr(new ForgeXzDownload(relative_path, entry));
-	}
-	virtual ~ForgeXzDownload(){};
-	bool canAbort() override;
+    explicit ForgeXzDownload(QString relative_path, MetaEntryPtr entry);
+    static ForgeXzDownloadPtr make(QString relative_path, MetaEntryPtr entry)
+    {
+        return ForgeXzDownloadPtr(new ForgeXzDownload(relative_path, entry));
+    }
+    virtual ~ForgeXzDownload(){};
+    bool canAbort() override;
 
 protected
 slots:
-	void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
-	void downloadError(QNetworkReply::NetworkError error) override;
-	void downloadFinished() override;
-	void downloadReadyRead() override;
+    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
+    void downloadError(QNetworkReply::NetworkError error) override;
+    void downloadFinished() override;
+    void downloadReadyRead() override;
 
 public
 slots:
-	void start() override;
-	bool abort() override;
+    void start() override;
+    bool abort() override;
 
 private:
-	void decompressAndInstall();
-	void failAndTryNextMirror();
+    void decompressAndInstall();
+    void failAndTryNextMirror();
 };
diff --git a/api/logic/minecraft/launch/ClaimAccount.cpp b/api/logic/minecraft/launch/ClaimAccount.cpp
index 71670b4f..a1180f0a 100644
--- a/api/logic/minecraft/launch/ClaimAccount.cpp
+++ b/api/logic/minecraft/launch/ClaimAccount.cpp
@@ -3,22 +3,22 @@
 
 ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchStep(parent)
 {
-	if(session->status == AuthSession::Status::PlayableOnline)
-	{
-		m_account = session->m_accountPtr;
-	}
+    if(session->status == AuthSession::Status::PlayableOnline)
+    {
+        m_account = session->m_accountPtr;
+    }
 }
 
 void ClaimAccount::executeTask()
 {
-	if(m_account)
-	{
-		lock.reset(new UseLock(m_account));
-		emitSucceeded();
-	}
+    if(m_account)
+    {
+        lock.reset(new UseLock(m_account));
+        emitSucceeded();
+    }
 }
 
 void ClaimAccount::finalize()
 {
-	lock.reset();
+    lock.reset();
 }
diff --git a/api/logic/minecraft/launch/ClaimAccount.h b/api/logic/minecraft/launch/ClaimAccount.h
index c11c2128..64891406 100644
--- a/api/logic/minecraft/launch/ClaimAccount.h
+++ b/api/logic/minecraft/launch/ClaimAccount.h
@@ -20,18 +20,18 @@
 
 class ClaimAccount: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session);
-	virtual ~ClaimAccount() {};
+    explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session);
+    virtual ~ClaimAccount() {};
 
-	void executeTask() override;
-	void finalize() override;
-	bool canAbort() const override
-	{
-		return false;
-	}
+    void executeTask() override;
+    void finalize() override;
+    bool canAbort() const override
+    {
+        return false;
+    }
 private:
-	std::unique_ptr<UseLock> lock;
-	MojangAccountPtr m_account;
+    std::unique_ptr<UseLock> lock;
+    MojangAccountPtr m_account;
 };
diff --git a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp
index 5398f7d0..bbca46d5 100644
--- a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp
+++ b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.cpp
@@ -9,11 +9,11 @@ CreateServerResourcePacksFolder::CreateServerResourcePacksFolder(LaunchTask* par
 
 void CreateServerResourcePacksFolder::executeTask()
 {
-	auto instance = m_parent->instance();
-	std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
-	if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->minecraftRoot(), "server-resource-packs")))
-	{
-		emit logLine(tr("Couldn't create the 'server-resource-packs' folder"), MessageLevel::Error);
-	}
-	emitSucceeded();
+    auto instance = m_parent->instance();
+    std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
+    if(!FS::ensureFolderPathExists(FS::PathCombine(minecraftInstance->minecraftRoot(), "server-resource-packs")))
+    {
+        emit logLine(tr("Couldn't create the 'server-resource-packs' folder"), MessageLevel::Error);
+    }
+    emitSucceeded();
 }
diff --git a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h
index 1e7b6621..b29496c9 100644
--- a/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h
+++ b/api/logic/minecraft/launch/CreateServerResourcePacksFolder.h
@@ -22,16 +22,16 @@
 // HACK: this is a workaround for MCL-3732 - 'server-resource-packs' folder is created.
 class CreateServerResourcePacksFolder: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit CreateServerResourcePacksFolder(LaunchTask *parent);
-	virtual ~CreateServerResourcePacksFolder() {};
+    explicit CreateServerResourcePacksFolder(LaunchTask *parent);
+    virtual ~CreateServerResourcePacksFolder() {};
 
-	virtual void executeTask();
-	virtual bool canAbort() const
-	{
-		return false;
-	}
+    virtual void executeTask();
+    virtual bool canAbort() const
+    {
+        return false;
+    }
 };
 
 
diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.cpp b/api/logic/minecraft/launch/DirectJavaLaunch.cpp
index 4ccc5c3c..7ead8324 100644
--- a/api/logic/minecraft/launch/DirectJavaLaunch.cpp
+++ b/api/logic/minecraft/launch/DirectJavaLaunch.cpp
@@ -22,128 +22,128 @@
 
 DirectJavaLaunch::DirectJavaLaunch(LaunchTask *parent) : LaunchStep(parent)
 {
-	connect(&m_process, &LoggedProcess::log, this, &DirectJavaLaunch::logLines);
-	connect(&m_process, &LoggedProcess::stateChanged, this, &DirectJavaLaunch::on_state);
+    connect(&m_process, &LoggedProcess::log, this, &DirectJavaLaunch::logLines);
+    connect(&m_process, &LoggedProcess::stateChanged, this, &DirectJavaLaunch::on_state);
 }
 
 void DirectJavaLaunch::executeTask()
 {
-	auto instance = m_parent->instance();
-	std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
-	QStringList args = minecraftInstance->javaArguments();
+    auto instance = m_parent->instance();
+    std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
+    QStringList args = minecraftInstance->javaArguments();
 
-	args.append("-Djava.library.path=" + minecraftInstance->getNativePath());
+    args.append("-Djava.library.path=" + minecraftInstance->getNativePath());
 
-	auto classPathEntries = minecraftInstance->getClassPath();
-	args.append("-cp");
-	QString classpath;
+    auto classPathEntries = minecraftInstance->getClassPath();
+    args.append("-cp");
+    QString classpath;
 #ifdef Q_OS_WIN32
-	classpath = classPathEntries.join(';');
+    classpath = classPathEntries.join(';');
 #else
-	classpath = classPathEntries.join(':');
+    classpath = classPathEntries.join(':');
 #endif
-	args.append(classpath);
-	args.append(minecraftInstance->getMainClass());
-
-	QString allArgs = args.join(", ");
-	emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC);
-
-	auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString());
-
-	m_process.setProcessEnvironment(instance->createEnvironment());
-
-	// make detachable - this will keep the process running even if the object is destroyed
-	m_process.setDetachable(true);
-
-	auto mcArgs = minecraftInstance->processMinecraftArgs(m_session);
-	args.append(mcArgs);
-
-	QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
-	if(!wrapperCommandStr.isEmpty())
-	{
-		auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
-		auto wrapperCommand = wrapperArgs.takeFirst();
-		auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
-		if (realWrapperCommand.isEmpty())
-		{
-			QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand);
-			emit logLine(reason, MessageLevel::Fatal);
-			emitFailed(reason);
-			return;
-		}
-		emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
-		args.prepend(javaPath);
-		m_process.start(wrapperCommand, wrapperArgs + args);
-	}
-	else
-	{
-		m_process.start(javaPath, args);
-	}
+    args.append(classpath);
+    args.append(minecraftInstance->getMainClass());
+
+    QString allArgs = args.join(", ");
+    emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC);
+
+    auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString());
+
+    m_process.setProcessEnvironment(instance->createEnvironment());
+
+    // make detachable - this will keep the process running even if the object is destroyed
+    m_process.setDetachable(true);
+
+    auto mcArgs = minecraftInstance->processMinecraftArgs(m_session);
+    args.append(mcArgs);
+
+    QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
+    if(!wrapperCommandStr.isEmpty())
+    {
+        auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
+        auto wrapperCommand = wrapperArgs.takeFirst();
+        auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
+        if (realWrapperCommand.isEmpty())
+        {
+            QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand);
+            emit logLine(reason, MessageLevel::Fatal);
+            emitFailed(reason);
+            return;
+        }
+        emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
+        args.prepend(javaPath);
+        m_process.start(wrapperCommand, wrapperArgs + args);
+    }
+    else
+    {
+        m_process.start(javaPath, args);
+    }
 }
 
 void DirectJavaLaunch::on_state(LoggedProcess::State state)
 {
-	switch(state)
-	{
-		case LoggedProcess::FailedToStart:
-		{
-			//: Error message displayed if instace can't start
-			QString reason = tr("Could not launch minecraft!");
-			emit logLine(reason, MessageLevel::Fatal);
-			emitFailed(reason);
-			return;
-		}
-		case LoggedProcess::Aborted:
-		case LoggedProcess::Crashed:
-
-		{
-			m_parent->setPid(-1);
-			emitFailed("Game crashed.");
-			return;
-		}
-		case LoggedProcess::Finished:
-		{
-			m_parent->setPid(-1);
-			// if the exit code wasn't 0, report this as a crash
-			auto exitCode = m_process.exitCode();
-			if(exitCode != 0)
-			{
-				emitFailed("Game crashed.");
-				return;
-			}
-			//FIXME: make this work again
-			// m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode));
-			// run post-exit
-			emitSucceeded();
-			break;
-		}
-		case LoggedProcess::Running:
-			emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
-			m_parent->setPid(m_process.processId());
-			m_parent->instance()->setLastLaunch();
-			break;
-		default:
-			break;
-	}
+    switch(state)
+    {
+        case LoggedProcess::FailedToStart:
+        {
+            //: Error message displayed if instace can't start
+            QString reason = tr("Could not launch minecraft!");
+            emit logLine(reason, MessageLevel::Fatal);
+            emitFailed(reason);
+            return;
+        }
+        case LoggedProcess::Aborted:
+        case LoggedProcess::Crashed:
+
+        {
+            m_parent->setPid(-1);
+            emitFailed("Game crashed.");
+            return;
+        }
+        case LoggedProcess::Finished:
+        {
+            m_parent->setPid(-1);
+            // if the exit code wasn't 0, report this as a crash
+            auto exitCode = m_process.exitCode();
+            if(exitCode != 0)
+            {
+                emitFailed("Game crashed.");
+                return;
+            }
+            //FIXME: make this work again
+            // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode));
+            // run post-exit
+            emitSucceeded();
+            break;
+        }
+        case LoggedProcess::Running:
+            emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
+            m_parent->setPid(m_process.processId());
+            m_parent->instance()->setLastLaunch();
+            break;
+        default:
+            break;
+    }
 }
 
 void DirectJavaLaunch::setWorkingDirectory(const QString &wd)
 {
-	m_process.setWorkingDirectory(wd);
+    m_process.setWorkingDirectory(wd);
 }
 
 void DirectJavaLaunch::proceed()
 {
-	// nil
+    // nil
 }
 
 bool DirectJavaLaunch::abort()
 {
-	auto state = m_process.state();
-	if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
-	{
-		m_process.kill();
-	}
-	return true;
+    auto state = m_process.state();
+    if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
+    {
+        m_process.kill();
+    }
+    return true;
 }
 
diff --git a/api/logic/minecraft/launch/DirectJavaLaunch.h b/api/logic/minecraft/launch/DirectJavaLaunch.h
index 8d2cc467..fb555e3e 100644
--- a/api/logic/minecraft/launch/DirectJavaLaunch.h
+++ b/api/logic/minecraft/launch/DirectJavaLaunch.h
@@ -21,29 +21,29 @@
 
 class DirectJavaLaunch: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit DirectJavaLaunch(LaunchTask *parent);
-	virtual ~DirectJavaLaunch() {};
+    explicit DirectJavaLaunch(LaunchTask *parent);
+    virtual ~DirectJavaLaunch() {};
 
-	virtual void executeTask();
-	virtual bool abort();
-	virtual void proceed();
-	virtual bool canAbort() const
-	{
-		return true;
-	}
-	void setWorkingDirectory(const QString &wd);
-	void setAuthSession(AuthSessionPtr session)
-	{
-		m_session = session;
-	}
+    virtual void executeTask();
+    virtual bool abort();
+    virtual void proceed();
+    virtual bool canAbort() const
+    {
+        return true;
+    }
+    void setWorkingDirectory(const QString &wd);
+    void setAuthSession(AuthSessionPtr session)
+    {
+        m_session = session;
+    }
 private slots:
-	void on_state(LoggedProcess::State state);
+    void on_state(LoggedProcess::State state);
 
 private:
-	LoggedProcess m_process;
-	QString m_command;
-	AuthSessionPtr m_session;
+    LoggedProcess m_process;
+    QString m_command;
+    AuthSessionPtr m_session;
 };
 
diff --git a/api/logic/minecraft/launch/ExtractNatives.cpp b/api/logic/minecraft/launch/ExtractNatives.cpp
index 7ddde374..336eddbd 100644
--- a/api/logic/minecraft/launch/ExtractNatives.cpp
+++ b/api/logic/minecraft/launch/ExtractNatives.cpp
@@ -25,76 +25,76 @@
 
 static QString replaceSuffix (QString target, const QString &suffix, const QString &replacement)
 {
-	if (!target.endsWith(suffix))
-	{
-		return target;
-	}
-	target.resize(target.length() - suffix.length());
-	return target + replacement;
+    if (!target.endsWith(suffix))
+    {
+        return target;
+    }
+    target.resize(target.length() - suffix.length());
+    return target + replacement;
 }
 
 static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack)
 {
-	QuaZip zip(source);
-	if(!zip.open(QuaZip::mdUnzip))
-	{
-		return false;
-	}
-	QDir directory(targetFolder);
-	if (!zip.goToFirstFile())
-	{
-		return false;
-	}
-	do
-	{
-		QString name = zip.getCurrentFileName();
-		if(applyJnilibHack)
-		{
-			name = replaceSuffix(name, ".jnilib", ".dylib");
-		}
-		QString absFilePath = directory.absoluteFilePath(name);
-		if (!JlCompress::extractFile(&zip, "", absFilePath))
-		{
-			return false;
-		}
-	} while (zip.goToNextFile());
-	zip.close();
-	if(zip.getZipError()!=0)
-	{
-		return false;
-	}
-	return true;
+    QuaZip zip(source);
+    if(!zip.open(QuaZip::mdUnzip))
+    {
+        return false;
+    }
+    QDir directory(targetFolder);
+    if (!zip.goToFirstFile())
+    {
+        return false;
+    }
+    do
+    {
+        QString name = zip.getCurrentFileName();
+        if(applyJnilibHack)
+        {
+            name = replaceSuffix(name, ".jnilib", ".dylib");
+        }
+        QString absFilePath = directory.absoluteFilePath(name);
+        if (!JlCompress::extractFile(&zip, "", absFilePath))
+        {
+            return false;
+        }
+    } while (zip.goToNextFile());
+    zip.close();
+    if(zip.getZipError()!=0)
+    {
+        return false;
+    }
+    return true;
 }
 
 void ExtractNatives::executeTask()
 {
-	auto instance = m_parent->instance();
-	std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
-	auto toExtract = minecraftInstance->getNativeJars();
-	if(toExtract.isEmpty())
-	{
-		emitSucceeded();
-		return;
-	}
-	auto outputPath  = minecraftInstance->getNativePath();
-	auto javaVersion = minecraftInstance->getJavaVersion();
-	bool jniHackEnabled = javaVersion.major() >= 8;
-	for(const auto &source: toExtract)
-	{
-		if(!unzipNatives(source, outputPath, jniHackEnabled))
-		{
-			auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath);
-			emit logLine(reason, MessageLevel::Fatal);
-			emitFailed(reason);
-		}
-	}
-	emitSucceeded();
+    auto instance = m_parent->instance();
+    std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
+    auto toExtract = minecraftInstance->getNativeJars();
+    if(toExtract.isEmpty())
+    {
+        emitSucceeded();
+        return;
+    }
+    auto outputPath  = minecraftInstance->getNativePath();
+    auto javaVersion = minecraftInstance->getJavaVersion();
+    bool jniHackEnabled = javaVersion.major() >= 8;
+    for(const auto &source: toExtract)
+    {
+        if(!unzipNatives(source, outputPath, jniHackEnabled))
+        {
+            auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath);
+            emit logLine(reason, MessageLevel::Fatal);
+            emitFailed(reason);
+        }
+    }
+    emitSucceeded();
 }
 
 void ExtractNatives::finalize()
 {
-	auto instance = m_parent->instance();
-	QString target_dir = FS::PathCombine(instance->instanceRoot(), "natives/");
-	QDir dir(target_dir);
-	dir.removeRecursively();
+    auto instance = m_parent->instance();
+    QString target_dir = FS::PathCombine(instance->instanceRoot(), "natives/");
+    QDir dir(target_dir);
+    dir.removeRecursively();
 }
diff --git a/api/logic/minecraft/launch/ExtractNatives.h b/api/logic/minecraft/launch/ExtractNatives.h
index 6e1e7cd4..d9587991 100644
--- a/api/logic/minecraft/launch/ExtractNatives.h
+++ b/api/logic/minecraft/launch/ExtractNatives.h
@@ -22,17 +22,17 @@
 // FIXME: temporary wrapper for existing task.
 class ExtractNatives: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){};
-	virtual ~ExtractNatives(){};
+    explicit ExtractNatives(LaunchTask *parent) : LaunchStep(parent){};
+    virtual ~ExtractNatives(){};
 
-	void executeTask() override;
-	bool canAbort() const override
-	{
-		return false;
-	}
-	void finalize() override;
+    void executeTask() override;
+    bool canAbort() const override
+    {
+        return false;
+    }
+    void finalize() override;
 };
 
 
diff --git a/api/logic/minecraft/launch/LauncherPartLaunch.cpp b/api/logic/minecraft/launch/LauncherPartLaunch.cpp
index 1fe9c323..466c1e46 100644
--- a/api/logic/minecraft/launch/LauncherPartLaunch.cpp
+++ b/api/logic/minecraft/launch/LauncherPartLaunch.cpp
@@ -24,8 +24,8 @@
 
 LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
 {
-	connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
-	connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
+    connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
+    connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
 }
 
 #ifdef Q_OS_WIN
@@ -33,187 +33,187 @@ LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
 #include <windows.h>
 QString shortPathName(const QString & file)
 {
-	auto input = file.toStdWString();
-	std::wstring output;
-	long length = GetShortPathNameW(input.c_str(), NULL, 0);
-	// NOTE: this resizing might seem weird...
-	// when GetShortPathNameW fails, it returns length including null character
-	// when it succeeds, it returns length excluding null character
-	// See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx
-	output.resize(length);
-	GetShortPathNameW(input.c_str(),(LPWSTR)output.c_str(),length);
-	output.resize(length-1);
-	QString ret = QString::fromStdWString(output);
-	return ret;
+    auto input = file.toStdWString();
+    std::wstring output;
+    long length = GetShortPathNameW(input.c_str(), NULL, 0);
+    // NOTE: this resizing might seem weird...
+    // when GetShortPathNameW fails, it returns length including null character
+    // when it succeeds, it returns length excluding null character
+    // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989(v=vs.85).aspx
+    output.resize(length);
+    GetShortPathNameW(input.c_str(),(LPWSTR)output.c_str(),length);
+    output.resize(length-1);
+    QString ret = QString::fromStdWString(output);
+    return ret;
 }
 #endif
 
 // if the string survives roundtrip through local 8bit encoding...
 bool fitsInLocal8bit(const QString & string)
 {
-	return string == QString::fromLocal8Bit(string.toLocal8Bit());
+    return string == QString::fromLocal8Bit(string.toLocal8Bit());
 }
 
 void LauncherPartLaunch::executeTask()
 {
-	auto instance = m_parent->instance();
-	std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
+    auto instance = m_parent->instance();
+    std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
 
-	m_launchScript = minecraftInstance->createLaunchScript(m_session);
-	QStringList args = minecraftInstance->javaArguments();
-	QString allArgs = args.join(", ");
-	emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC);
+    m_launchScript = minecraftInstance->createLaunchScript(m_session);
+    QStringList args = minecraftInstance->javaArguments();
+    QString allArgs = args.join(", ");
+    emit logLine("Java Arguments:\n[" + m_parent->censorPrivateInfo(allArgs) + "]\n\n", MessageLevel::MultiMC);
 
-	auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString());
+    auto javaPath = FS::ResolveExecutable(instance->settings()->get("JavaPath").toString());
 
-	m_process.setProcessEnvironment(instance->createEnvironment());
+    m_process.setProcessEnvironment(instance->createEnvironment());
 
-	// make detachable - this will keep the process running even if the object is destroyed
-	m_process.setDetachable(true);
+    // make detachable - this will keep the process running even if the object is destroyed
+    m_process.setDetachable(true);
 
-	auto classPath = minecraftInstance->getClassPath();
-	classPath.prepend(FS::PathCombine(ENV.getJarsPath(), "NewLaunch.jar"));
+    auto classPath = minecraftInstance->getClassPath();
+    classPath.prepend(FS::PathCombine(ENV.getJarsPath(), "NewLaunch.jar"));
 
-	auto natPath = minecraftInstance->getNativePath();
+    auto natPath = minecraftInstance->getNativePath();
 #ifdef Q_OS_WIN
-	if (!fitsInLocal8bit(natPath))
-	{
-		args << "-Djava.library.path=" + shortPathName(natPath);
-	}
-	else
-	{
-		args << "-Djava.library.path=" + natPath;
-	}
+    if (!fitsInLocal8bit(natPath))
+    {
+        args << "-Djava.library.path=" + shortPathName(natPath);
+    }
+    else
+    {
+        args << "-Djava.library.path=" + natPath;
+    }
 #else
-	args << "-Djava.library.path=" + natPath;
+    args << "-Djava.library.path=" + natPath;
 #endif
 
-	args << "-cp";
+    args << "-cp";
 #ifdef Q_OS_WIN
-	QStringList processed;
-	for(auto & item: classPath)
-	{
-		if (!fitsInLocal8bit(item))
-		{
-			processed << shortPathName(item);
-		}
-		else
-		{
-			processed << item;
-		}
-	}
-	args << processed.join(';');
+    QStringList processed;
+    for(auto & item: classPath)
+    {
+        if (!fitsInLocal8bit(item))
+        {
+            processed << shortPathName(item);
+        }
+        else
+        {
+            processed << item;
+        }
+    }
+    args << processed.join(';');
 #else
-	args << classPath.join(':');
+    args << classPath.join(':');
 #endif
-	args << "org.multimc.EntryPoint";
-
-	qDebug() << args.join(' ');
-
-	QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
-	if(!wrapperCommandStr.isEmpty())
-	{
-		auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
-		auto wrapperCommand = wrapperArgs.takeFirst();
-		auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
-		if (realWrapperCommand.isEmpty())
-		{
-			QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand);
-			emit logLine(reason, MessageLevel::Fatal);
-			emitFailed(reason);
-			return;
-		}
-		emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
-		args.prepend(javaPath);
-		m_process.start(wrapperCommand, wrapperArgs + args);
-	}
-	else
-	{
-		m_process.start(javaPath, args);
-	}
+    args << "org.multimc.EntryPoint";
+
+    qDebug() << args.join(' ');
+
+    QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
+    if(!wrapperCommandStr.isEmpty())
+    {
+        auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
+        auto wrapperCommand = wrapperArgs.takeFirst();
+        auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);
+        if (realWrapperCommand.isEmpty())
+        {
+            QString reason = tr("The wrapper command \"%1\" couldn't be found.").arg(wrapperCommand);
+            emit logLine(reason, MessageLevel::Fatal);
+            emitFailed(reason);
+            return;
+        }
+        emit logLine("Wrapper command is:\n" + wrapperCommandStr + "\n\n", MessageLevel::MultiMC);
+        args.prepend(javaPath);
+        m_process.start(wrapperCommand, wrapperArgs + args);
+    }
+    else
+    {
+        m_process.start(javaPath, args);
+    }
 }
 
 void LauncherPartLaunch::on_state(LoggedProcess::State state)
 {
-	switch(state)
-	{
-		case LoggedProcess::FailedToStart:
-		{
-			//: Error message displayed if instace can't start
-			QString reason = tr("Could not launch minecraft!");
-			emit logLine(reason, MessageLevel::Fatal);
-			emitFailed(reason);
-			return;
-		}
-		case LoggedProcess::Aborted:
-		case LoggedProcess::Crashed:
-
-		{
-			m_parent->setPid(-1);
-			emitFailed("Game crashed.");
-			return;
-		}
-		case LoggedProcess::Finished:
-		{
-			m_parent->setPid(-1);
-			// if the exit code wasn't 0, report this as a crash
-			auto exitCode = m_process.exitCode();
-			if(exitCode != 0)
-			{
-				emitFailed("Game crashed.");
-				return;
-			}
-			//FIXME: make this work again
-			// m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode));
-			// run post-exit
-			emitSucceeded();
-			break;
-		}
-		case LoggedProcess::Running:
-			emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
-			m_parent->setPid(m_process.processId());
-			m_parent->instance()->setLastLaunch();
-			// send the launch script to the launcher part
-			m_process.write(m_launchScript.toUtf8());
-
-			mayProceed = true;
-			emit readyForLaunch();
-			break;
-		default:
-			break;
-	}
+    switch(state)
+    {
+        case LoggedProcess::FailedToStart:
+        {
+            //: Error message displayed if instace can't start
+            QString reason = tr("Could not launch minecraft!");
+            emit logLine(reason, MessageLevel::Fatal);
+            emitFailed(reason);
+            return;
+        }
+        case LoggedProcess::Aborted:
+        case LoggedProcess::Crashed:
+
+        {
+            m_parent->setPid(-1);
+            emitFailed("Game crashed.");
+            return;
+        }
+        case LoggedProcess::Finished:
+        {
+            m_parent->setPid(-1);
+            // if the exit code wasn't 0, report this as a crash
+            auto exitCode = m_process.exitCode();
+            if(exitCode != 0)
+            {
+                emitFailed("Game crashed.");
+                return;
+            }
+            //FIXME: make this work again
+            // m_postlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(exitCode));
+            // run post-exit
+            emitSucceeded();
+            break;
+        }
+        case LoggedProcess::Running:
+            emit logLine(tr("Minecraft process ID: %1\n\n").arg(m_process.processId()), MessageLevel::MultiMC);
+            m_parent->setPid(m_process.processId());
+            m_parent->instance()->setLastLaunch();
+            // send the launch script to the launcher part
+            m_process.write(m_launchScript.toUtf8());
+
+            mayProceed = true;
+            emit readyForLaunch();
+            break;
+        default:
+            break;
+    }
 }
 
 void LauncherPartLaunch::setWorkingDirectory(const QString &wd)
 {
-	m_process.setWorkingDirectory(wd);
+    m_process.setWorkingDirectory(wd);
 }
 
 void LauncherPartLaunch::proceed()
 {
-	if(mayProceed)
-	{
-		QString launchString("launch\n");
-		m_process.write(launchString.toUtf8());
-		mayProceed = false;
-	}
+    if(mayProceed)
+    {
+        QString launchString("launch\n");
+        m_process.write(launchString.toUtf8());
+        mayProceed = false;
+    }
 }
 
 bool LauncherPartLaunch::abort()
 {
-	if(mayProceed)
-	{
-		mayProceed = false;
-		QString launchString("abort\n");
-		m_process.write(launchString.toUtf8());
-	}
-	else
-	{
-		auto state = m_process.state();
-		if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
-		{
-			m_process.kill();
-		}
-	}
-	return true;
+    if(mayProceed)
+    {
+        mayProceed = false;
+        QString launchString("abort\n");
+        m_process.write(launchString.toUtf8());
+    }
+    else
+    {
+        auto state = m_process.state();
+        if (state == LoggedProcess::Running || state == LoggedProcess::Starting)
+        {
+            m_process.kill();
+        }
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/launch/LauncherPartLaunch.h b/api/logic/minecraft/launch/LauncherPartLaunch.h
index 6ae85a3f..7fadbd66 100644
--- a/api/logic/minecraft/launch/LauncherPartLaunch.h
+++ b/api/logic/minecraft/launch/LauncherPartLaunch.h
@@ -21,31 +21,31 @@
 
 class LauncherPartLaunch: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit LauncherPartLaunch(LaunchTask *parent);
-	virtual ~LauncherPartLaunch() {};
+    explicit LauncherPartLaunch(LaunchTask *parent);
+    virtual ~LauncherPartLaunch() {};
 
-	virtual void executeTask();
-	virtual bool abort();
-	virtual void proceed();
-	virtual bool canAbort() const
-	{
-		return true;
-	}
-	void setWorkingDirectory(const QString &wd);
-	void setAuthSession(AuthSessionPtr session)
-	{
-		m_session = session;
-	}
+    virtual void executeTask();
+    virtual bool abort();
+    virtual void proceed();
+    virtual bool canAbort() const
+    {
+        return true;
+    }
+    void setWorkingDirectory(const QString &wd);
+    void setAuthSession(AuthSessionPtr session)
+    {
+        m_session = session;
+    }
 
 private slots:
-	void on_state(LoggedProcess::State state);
+    void on_state(LoggedProcess::State state);
 
 private:
-	LoggedProcess m_process;
-	QString m_command;
-	AuthSessionPtr m_session;
-	QString m_launchScript;
-	bool mayProceed = false;
+    LoggedProcess m_process;
+    QString m_command;
+    AuthSessionPtr m_session;
+    QString m_launchScript;
+    bool mayProceed = false;
 };
diff --git a/api/logic/minecraft/launch/ModMinecraftJar.cpp b/api/logic/minecraft/launch/ModMinecraftJar.cpp
index 34825b45..34472bb3 100644
--- a/api/logic/minecraft/launch/ModMinecraftJar.cpp
+++ b/api/logic/minecraft/launch/ModMinecraftJar.cpp
@@ -23,60 +23,60 @@
 
 void ModMinecraftJar::executeTask()
 {
-	auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
+    auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
 
-	if(!m_inst->getJarMods().size())
-	{
-		emitSucceeded();
-		return;
-	}
-	// nuke obsolete stripped jar(s) if needed
-	if(!FS::ensureFolderPathExists(m_inst->binRoot()))
-	{
-		emitFailed(tr("Couldn't create the bin folder for Minecraft.jar"));
-	}
+    if(!m_inst->getJarMods().size())
+    {
+        emitSucceeded();
+        return;
+    }
+    // nuke obsolete stripped jar(s) if needed
+    if(!FS::ensureFolderPathExists(m_inst->binRoot()))
+    {
+        emitFailed(tr("Couldn't create the bin folder for Minecraft.jar"));
+    }
 
-	auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
-	if(!removeJar())
-	{
-		emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath));
-	}
+    auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
+    if(!removeJar())
+    {
+        emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath));
+    }
 
-	// create temporary modded jar, if needed
-	auto components = m_inst->getComponentList();
-	auto profile = components->getProfile();
-	auto jarMods = m_inst->getJarMods();
-	if(jarMods.size())
-	{
-		auto mainJar = profile->getMainJar();
-		QStringList jars, temp1, temp2, temp3, temp4;
-		mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath());
-		auto sourceJarPath = jars[0];
-		if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods))
-		{
-			emitFailed(tr("Failed to create the custom Minecraft jar file."));
-			return;
-		}
-	}
-	emitSucceeded();
+    // create temporary modded jar, if needed
+    auto components = m_inst->getComponentList();
+    auto profile = components->getProfile();
+    auto jarMods = m_inst->getJarMods();
+    if(jarMods.size())
+    {
+        auto mainJar = profile->getMainJar();
+        QStringList jars, temp1, temp2, temp3, temp4;
+        mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath());
+        auto sourceJarPath = jars[0];
+        if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods))
+        {
+            emitFailed(tr("Failed to create the custom Minecraft jar file."));
+            return;
+        }
+    }
+    emitSucceeded();
 }
 
 void ModMinecraftJar::finalize()
 {
-	removeJar();
+    removeJar();
 }
 
 bool ModMinecraftJar::removeJar()
 {
-	auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
-	auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
-	QFile finalJar(finalJarPath);
-	if(finalJar.exists())
-	{
-		if(!finalJar.remove())
-		{
-			return false;
-		}
-	}
-	return true;
+    auto m_inst = std::dynamic_pointer_cast<MinecraftInstance>(m_parent->instance());
+    auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar");
+    QFile finalJar(finalJarPath);
+    if(finalJar.exists())
+    {
+        if(!finalJar.remove())
+        {
+            return false;
+        }
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/launch/ModMinecraftJar.h b/api/logic/minecraft/launch/ModMinecraftJar.h
index dca484f8..48e11736 100644
--- a/api/logic/minecraft/launch/ModMinecraftJar.h
+++ b/api/logic/minecraft/launch/ModMinecraftJar.h
@@ -20,17 +20,17 @@
 
 class ModMinecraftJar: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit ModMinecraftJar(LaunchTask *parent) : LaunchStep(parent) {};
-	virtual ~ModMinecraftJar(){};
+    explicit ModMinecraftJar(LaunchTask *parent) : LaunchStep(parent) {};
+    virtual ~ModMinecraftJar(){};
 
-	virtual void executeTask() override;
-	virtual bool canAbort() const override
-	{
-		return false;
-	}
-	void finalize() override;
+    virtual void executeTask() override;
+    virtual bool canAbort() const override
+    {
+        return false;
+    }
+    void finalize() override;
 private:
-	bool removeJar();
+    bool removeJar();
 };
diff --git a/api/logic/minecraft/launch/PrintInstanceInfo.h b/api/logic/minecraft/launch/PrintInstanceInfo.h
index 61615ba1..ae0a0400 100644
--- a/api/logic/minecraft/launch/PrintInstanceInfo.h
+++ b/api/logic/minecraft/launch/PrintInstanceInfo.h
@@ -22,17 +22,17 @@
 // FIXME: temporary wrapper for existing task.
 class PrintInstanceInfo: public LaunchStep
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session) : LaunchStep(parent), m_session(session) {};
-	virtual ~PrintInstanceInfo(){};
+    explicit PrintInstanceInfo(LaunchTask *parent, AuthSessionPtr session) : LaunchStep(parent), m_session(session) {};
+    virtual ~PrintInstanceInfo(){};
 
-	virtual void executeTask();
-	virtual bool canAbort() const
-	{
-		return false;
-	}
+    virtual void executeTask();
+    virtual bool canAbort() const
+    {
+        return false;
+    }
 private:
-	AuthSessionPtr m_session;
+    AuthSessionPtr m_session;
 };
 
diff --git a/api/logic/minecraft/legacy/LegacyInstance.cpp b/api/logic/minecraft/legacy/LegacyInstance.cpp
index 1282eb4d..d22535e7 100644
--- a/api/logic/minecraft/legacy/LegacyInstance.cpp
+++ b/api/logic/minecraft/legacy/LegacyInstance.cpp
@@ -27,236 +27,236 @@
 #include <FileSystem.h>
 
 LegacyInstance::LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir)
-	: BaseInstance(globalSettings, settings, rootDir)
+    : BaseInstance(globalSettings, settings, rootDir)
 {
-	settings->registerSetting("NeedsRebuild", true);
-	settings->registerSetting("ShouldUpdate", false);
-	settings->registerSetting("JarVersion", QString());
-	settings->registerSetting("IntendedJarVersion", QString());
-	/*
-	 * custom base jar has no default. it is determined in code... see the accessor methods for
-	 *it
-	 *
-	 * for instances that DO NOT have the CustomBaseJar setting (legacy instances),
-	 * [.]minecraft/bin/mcbackup.jar is the default base jar
-	 */
-	settings->registerSetting("UseCustomBaseJar", true);
-	settings->registerSetting("CustomBaseJar", "");
+    settings->registerSetting("NeedsRebuild", true);
+    settings->registerSetting("ShouldUpdate", false);
+    settings->registerSetting("JarVersion", QString());
+    settings->registerSetting("IntendedJarVersion", QString());
+    /*
+     * custom base jar has no default. it is determined in code... see the accessor methods for
+     *it
+     *
+     * for instances that DO NOT have the CustomBaseJar setting (legacy instances),
+     * [.]minecraft/bin/mcbackup.jar is the default base jar
+     */
+    settings->registerSetting("UseCustomBaseJar", true);
+    settings->registerSetting("CustomBaseJar", "");
 }
 
 QString LegacyInstance::mainJarToPreserve() const
 {
-	bool customJar = m_settings->get("UseCustomBaseJar").toBool();
-	if(customJar)
-	{
-		auto base = baseJar();
-		if(QFile::exists(base))
-		{
-			return base;
-		}
-	}
-	auto runnable = runnableJar();
-	if(QFile::exists(runnable))
-	{
-		return runnable;
-	}
-	return QString();
+    bool customJar = m_settings->get("UseCustomBaseJar").toBool();
+    if(customJar)
+    {
+        auto base = baseJar();
+        if(QFile::exists(base))
+        {
+            return base;
+        }
+    }
+    auto runnable = runnableJar();
+    if(QFile::exists(runnable))
+    {
+        return runnable;
+    }
+    return QString();
 }
 
 
 QString LegacyInstance::baseJar() const
 {
-	bool customJar = m_settings->get("UseCustomBaseJar").toBool();
-	if (customJar)
-	{
-		return customBaseJar();
-	}
-	else
-		return defaultBaseJar();
+    bool customJar = m_settings->get("UseCustomBaseJar").toBool();
+    if (customJar)
+    {
+        return customBaseJar();
+    }
+    else
+        return defaultBaseJar();
 }
 
 QString LegacyInstance::customBaseJar() const
 {
-	QString value = m_settings->get("CustomBaseJar").toString();
-	if (value.isNull() || value.isEmpty())
-	{
-		return defaultCustomBaseJar();
-	}
-	return value;
+    QString value = m_settings->get("CustomBaseJar").toString();
+    if (value.isNull() || value.isEmpty())
+    {
+        return defaultCustomBaseJar();
+    }
+    return value;
 }
 
 bool LegacyInstance::shouldUseCustomBaseJar() const
 {
-	return m_settings->get("UseCustomBaseJar").toBool();
+    return m_settings->get("UseCustomBaseJar").toBool();
 }
 
 
 shared_qobject_ptr<Task> LegacyInstance::createUpdateTask(Net::Mode)
 {
-	return nullptr;
+    return nullptr;
 }
 
 std::shared_ptr<LegacyModList> LegacyInstance::jarModList() const
 {
-	if (!jar_mod_list)
-	{
-		auto list = new LegacyModList(jarModsDir(), modListFile());
-		jar_mod_list.reset(list);
-	}
-	jar_mod_list->update();
-	return jar_mod_list;
+    if (!jar_mod_list)
+    {
+        auto list = new LegacyModList(jarModsDir(), modListFile());
+        jar_mod_list.reset(list);
+    }
+    jar_mod_list->update();
+    return jar_mod_list;
 }
 
 QList<Mod> LegacyInstance::getJarMods() const
 {
-	return jarModList()->allMods();
+    return jarModList()->allMods();
 }
 
 QString LegacyInstance::minecraftRoot() const
 {
-	QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
-	QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
+    QFileInfo mcDir(FS::PathCombine(instanceRoot(), "minecraft"));
+    QFileInfo dotMCDir(FS::PathCombine(instanceRoot(), ".minecraft"));
 
-	if (mcDir.exists() && !dotMCDir.exists())
-		return mcDir.filePath();
-	else
-		return dotMCDir.filePath();
+    if (mcDir.exists() && !dotMCDir.exists())
+        return mcDir.filePath();
+    else
+        return dotMCDir.filePath();
 }
 
 QString LegacyInstance::binRoot() const
 {
-	return FS::PathCombine(minecraftRoot(), "bin");
+    return FS::PathCombine(minecraftRoot(), "bin");
 }
 
 QString LegacyInstance::jarModsDir() const
 {
-	return FS::PathCombine(instanceRoot(), "instMods");
+    return FS::PathCombine(instanceRoot(), "instMods");
 }
 
 QString LegacyInstance::libDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "lib");
+    return FS::PathCombine(minecraftRoot(), "lib");
 }
 
 QString LegacyInstance::savesDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "saves");
+    return FS::PathCombine(minecraftRoot(), "saves");
 }
 
 QString LegacyInstance::loaderModsDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "mods");
+    return FS::PathCombine(minecraftRoot(), "mods");
 }
 
 QString LegacyInstance::coreModsDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "coremods");
+    return FS::PathCombine(minecraftRoot(), "coremods");
 }
 
 QString LegacyInstance::resourceDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "resources");
+    return FS::PathCombine(minecraftRoot(), "resources");
 }
 QString LegacyInstance::texturePacksDir() const
 {
-	return FS::PathCombine(minecraftRoot(), "texturepacks");
+    return FS::PathCombine(minecraftRoot(), "texturepacks");
 }
 
 QString LegacyInstance::runnableJar() const
 {
-	return FS::PathCombine(binRoot(), "minecraft.jar");
+    return FS::PathCombine(binRoot(), "minecraft.jar");
 }
 
 QString LegacyInstance::modListFile() const
 {
-	return FS::PathCombine(instanceRoot(), "modlist");
+    return FS::PathCombine(instanceRoot(), "modlist");
 }
 
 QString LegacyInstance::instanceConfigFolder() const
 {
-	return FS::PathCombine(minecraftRoot(), "config");
+    return FS::PathCombine(minecraftRoot(), "config");
 }
 
 bool LegacyInstance::shouldRebuild() const
 {
-	return m_settings->get("NeedsRebuild").toBool();
+    return m_settings->get("NeedsRebuild").toBool();
 }
 
 QString LegacyInstance::currentVersionId() const
 {
-	return m_settings->get("JarVersion").toString();
+    return m_settings->get("JarVersion").toString();
 }
 
 QString LegacyInstance::intendedVersionId() const
 {
-	return m_settings->get("IntendedJarVersion").toString();
+    return m_settings->get("IntendedJarVersion").toString();
 }
 
 bool LegacyInstance::shouldUpdate() const
 {
-	QVariant var = settings()->get("ShouldUpdate");
-	if (!var.isValid() || var.toBool() == false)
-	{
-		return intendedVersionId() != currentVersionId();
-	}
-	return true;
+    QVariant var = settings()->get("ShouldUpdate");
+    if (!var.isValid() || var.toBool() == false)
+    {
+        return intendedVersionId() != currentVersionId();
+    }
+    return true;
 }
 
 QString LegacyInstance::defaultBaseJar() const
 {
-	return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
+    return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar";
 }
 
 QString LegacyInstance::defaultCustomBaseJar() const
 {
-	return FS::PathCombine(binRoot(), "mcbackup.jar");
+    return FS::PathCombine(binRoot(), "mcbackup.jar");
 }
 
 std::shared_ptr<WorldList> LegacyInstance::worldList() const
 {
-	if (!m_world_list)
-	{
-		m_world_list.reset(new WorldList(savesDir()));
-	}
-	return m_world_list;
+    if (!m_world_list)
+    {
+        m_world_list.reset(new WorldList(savesDir()));
+    }
+    return m_world_list;
 }
 
 QString LegacyInstance::typeName() const
 {
-	return tr("Legacy");
+    return tr("Legacy");
 }
 
 QString LegacyInstance::getStatusbarDescription()
 {
-	return tr("Instance from previous versions.");
+    return tr("Instance from previous versions.");
 }
 
 QStringList LegacyInstance::verboseDescription(AuthSessionPtr session)
 {
-	QStringList out;
-
-	auto alltraits = traits();
-	if(alltraits.size())
-	{
-		out << "Traits:";
-		for (auto trait : alltraits)
-		{
-			out << "  " + trait;
-		}
-		out << "";
-	}
-
-	QString windowParams;
-	if (settings()->get("LaunchMaximized").toBool())
-	{
-		out << "Window size: max (if available)";
-	}
-	else
-	{
-		auto width = settings()->get("MinecraftWinWidth").toInt();
-		auto height = settings()->get("MinecraftWinHeight").toInt();
-		out << "Window size: " + QString::number(width) + " x " + QString::number(height);
-	}
-	out << "";
-	return out;
+    QStringList out;
+
+    auto alltraits = traits();
+    if(alltraits.size())
+    {
+        out << "Traits:";
+        for (auto trait : alltraits)
+        {
+            out << "  " + trait;
+        }
+        out << "";
+    }
+
+    QString windowParams;
+    if (settings()->get("LaunchMaximized").toBool())
+    {
+        out << "Window size: max (if available)";
+    }
+    else
+    {
+        auto width = settings()->get("MinecraftWinWidth").toInt();
+        auto height = settings()->get("MinecraftWinHeight").toInt();
+        out << "Window size: " + QString::number(width) + " x " + QString::number(height);
+    }
+    out << "";
+    return out;
 }
diff --git a/api/logic/minecraft/legacy/LegacyInstance.h b/api/logic/minecraft/legacy/LegacyInstance.h
index 1b4798f6..3cf641ab 100644
--- a/api/logic/minecraft/legacy/LegacyInstance.h
+++ b/api/logic/minecraft/legacy/LegacyInstance.h
@@ -29,115 +29,115 @@ class Task;
  */
 class MULTIMC_LOGIC_EXPORT LegacyInstance : public BaseInstance
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
 
-	explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
-
-	virtual void init() override {}
-	virtual void saveNow() override {}
-
-	/// Path to the instance's minecraft.jar
-	QString runnableJar() const;
-
-	//! Path to the instance's modlist file.
-	QString modListFile() const;
-
-	////// Directories //////
-	QString libDir() const;
-	QString savesDir() const;
-	QString texturePacksDir() const;
-	QString jarModsDir() const;
-	QString loaderModsDir() const;
-	QString coreModsDir() const;
-	QString resourceDir() const;
-	virtual QString instanceConfigFolder() const override;
-	QString minecraftRoot() const; // Path to the instance's minecraft directory.
-	QString binRoot() const; // Path to the instance's minecraft bin directory.
-
-	/// Get the curent base jar of this instance. By default, it's the
-	/// versions/$version/$version.jar
-	QString baseJar() const;
-
-	/// the default base jar of this instance
-	QString defaultBaseJar() const;
-	/// the default custom base jar of this instance
-	QString defaultCustomBaseJar() const;
-
-	// the main jar that we actually want to keep when migrating the instance
-	QString mainJarToPreserve() const;
-
-	/*!
-	 * Whether or not custom base jar is used
-	 */
-	bool shouldUseCustomBaseJar() const;
-
-	/*!
-	 * The value of the custom base jar
-	 */
-	QString customBaseJar() const;
-
-	std::shared_ptr<LegacyModList> jarModList() const;
-	QList<Mod> getJarMods() const;
-	std::shared_ptr<WorldList> worldList() const;
-
-	/*!
-	 * Whether or not the instance's minecraft.jar needs to be rebuilt.
-	 * If this is true, when the instance launches, its jar mods will be
-	 * re-added to a fresh minecraft.jar file.
-	 */
-	bool shouldRebuild() const;
-
-	QString currentVersionId() const;
-	QString intendedVersionId() const;
-
-	QSet<QString> traits() const override
-	{
-		return {"legacy-instance", "texturepacks"};
-	};
-
-	virtual bool shouldUpdate() const;
-	virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override;
-
-	virtual QString typeName() const override;
-
-	bool canLaunch() const override
-	{
-		return false;
-	}
-	bool canEdit() const override
-	{
-		return true;
-	}
-	bool canExport() const override
-	{
-		return false;
-	}
-	std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override
-	{
-		return nullptr;
-	}
-	IPathMatcher::Ptr getLogFileMatcher() override
-	{
-		return nullptr;
-	}
-	QString getLogFileRoot() override
-	{
-		return minecraftRoot();
-	}
-
-	QString getStatusbarDescription() override;
-	QStringList verboseDescription(AuthSessionPtr session) override;
-
-	QProcessEnvironment createEnvironment() override
-	{
-		return QProcessEnvironment();
-	}
-	QMap<QString, QString> getVariables() const override
-	{
-		return {};
-	}
+    explicit LegacyInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr settings, const QString &rootDir);
+
+    virtual void init() override {}
+    virtual void saveNow() override {}
+
+    /// Path to the instance's minecraft.jar
+    QString runnableJar() const;
+
+    //! Path to the instance's modlist file.
+    QString modListFile() const;
+
+    ////// Directories //////
+    QString libDir() const;
+    QString savesDir() const;
+    QString texturePacksDir() const;
+    QString jarModsDir() const;
+    QString loaderModsDir() const;
+    QString coreModsDir() const;
+    QString resourceDir() const;
+    virtual QString instanceConfigFolder() const override;
+    QString minecraftRoot() const; // Path to the instance's minecraft directory.
+    QString binRoot() const; // Path to the instance's minecraft bin directory.
+
+    /// Get the curent base jar of this instance. By default, it's the
+    /// versions/$version/$version.jar
+    QString baseJar() const;
+
+    /// the default base jar of this instance
+    QString defaultBaseJar() const;
+    /// the default custom base jar of this instance
+    QString defaultCustomBaseJar() const;
+
+    // the main jar that we actually want to keep when migrating the instance
+    QString mainJarToPreserve() const;
+
+    /*!
+     * Whether or not custom base jar is used
+     */
+    bool shouldUseCustomBaseJar() const;
+
+    /*!
+     * The value of the custom base jar
+     */
+    QString customBaseJar() const;
+
+    std::shared_ptr<LegacyModList> jarModList() const;
+    QList<Mod> getJarMods() const;
+    std::shared_ptr<WorldList> worldList() const;
+
+    /*!
+     * Whether or not the instance's minecraft.jar needs to be rebuilt.
+     * If this is true, when the instance launches, its jar mods will be
+     * re-added to a fresh minecraft.jar file.
+     */
+    bool shouldRebuild() const;
+
+    QString currentVersionId() const;
+    QString intendedVersionId() const;
+
+    QSet<QString> traits() const override
+    {
+        return {"legacy-instance", "texturepacks"};
+    };
+
+    virtual bool shouldUpdate() const;
+    virtual shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override;
+
+    virtual QString typeName() const override;
+
+    bool canLaunch() const override
+    {
+        return false;
+    }
+    bool canEdit() const override
+    {
+        return true;
+    }
+    bool canExport() const override
+    {
+        return false;
+    }
+    std::shared_ptr<LaunchTask> createLaunchTask(AuthSessionPtr account) override
+    {
+        return nullptr;
+    }
+    IPathMatcher::Ptr getLogFileMatcher() override
+    {
+        return nullptr;
+    }
+    QString getLogFileRoot() override
+    {
+        return minecraftRoot();
+    }
+
+    QString getStatusbarDescription() override;
+    QStringList verboseDescription(AuthSessionPtr session) override;
+
+    QProcessEnvironment createEnvironment() override
+    {
+        return QProcessEnvironment();
+    }
+    QMap<QString, QString> getVariables() const override
+    {
+        return {};
+    }
 protected:
-	mutable std::shared_ptr<LegacyModList> jar_mod_list;
-	mutable std::shared_ptr<WorldList> m_world_list;
+    mutable std::shared_ptr<LegacyModList> jar_mod_list;
+    mutable std::shared_ptr<WorldList> m_world_list;
 };
diff --git a/api/logic/minecraft/legacy/LegacyModList.cpp b/api/logic/minecraft/legacy/LegacyModList.cpp
index 638b2e21..ca171b08 100644
--- a/api/logic/minecraft/legacy/LegacyModList.cpp
+++ b/api/logic/minecraft/legacy/LegacyModList.cpp
@@ -19,153 +19,153 @@
 #include <QDebug>
 
 LegacyModList::LegacyModList(const QString &dir, const QString &list_file)
-	: m_dir(dir), m_list_file(list_file)
+    : m_dir(dir), m_list_file(list_file)
 {
-	FS::ensureFolderPathExists(m_dir.absolutePath());
-	m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
-					QDir::NoSymLinks);
-	m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
+    FS::ensureFolderPathExists(m_dir.absolutePath());
+    m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs |
+                    QDir::NoSymLinks);
+    m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
 }
 
-	struct OrderItem
-	{
-		QString id;
-		bool enabled = false;
-	};
-	typedef QList<OrderItem> OrderList;
+    struct OrderItem
+    {
+        QString id;
+        bool enabled = false;
+    };
+    typedef QList<OrderItem> OrderList;
 
 static void internalSort(QList<Mod> &what)
 {
-	auto predicate = [](const Mod &left, const Mod &right)
-	{
-		if (left.name() == right.name())
-		{
-			return left.mmc_id().localeAwareCompare(right.mmc_id()) < 0;
-		}
-		return left.name().localeAwareCompare(right.name()) < 0;
-	};
-	std::sort(what.begin(), what.end(), predicate);
+    auto predicate = [](const Mod &left, const Mod &right)
+    {
+        if (left.name() == right.name())
+        {
+            return left.mmc_id().localeAwareCompare(right.mmc_id()) < 0;
+        }
+        return left.name().localeAwareCompare(right.name()) < 0;
+    };
+    std::sort(what.begin(), what.end(), predicate);
 }
 
 static OrderList readListFile(const QString &m_list_file)
 {
-	OrderList itemList;
-	if (m_list_file.isNull() || m_list_file.isEmpty())
-		return itemList;
+    OrderList itemList;
+    if (m_list_file.isNull() || m_list_file.isEmpty())
+        return itemList;
 
-	QFile textFile(m_list_file);
-	if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text))
-		return OrderList();
+    QFile textFile(m_list_file);
+    if (!textFile.open(QIODevice::ReadOnly | QIODevice::Text))
+        return OrderList();
 
-	QTextStream textStream;
-	textStream.setAutoDetectUnicode(true);
-	textStream.setDevice(&textFile);
-	while (true)
-	{
-		QString line = textStream.readLine();
-		if (line.isNull() || line.isEmpty())
-			break;
-		else
-		{
-			OrderItem it;
-			it.enabled = !line.endsWith(".disabled");
-			if (!it.enabled)
-			{
-				line.chop(9);
-			}
-			it.id = line;
-			itemList.append(it);
-		}
-	}
-	textFile.close();
-	return itemList;
+    QTextStream textStream;
+    textStream.setAutoDetectUnicode(true);
+    textStream.setDevice(&textFile);
+    while (true)
+    {
+        QString line = textStream.readLine();
+        if (line.isNull() || line.isEmpty())
+            break;
+        else
+        {
+            OrderItem it;
+            it.enabled = !line.endsWith(".disabled");
+            if (!it.enabled)
+            {
+                line.chop(9);
+            }
+            it.id = line;
+            itemList.append(it);
+        }
+    }
+    textFile.close();
+    return itemList;
 }
 
 bool LegacyModList::update()
 {
-	if (!m_dir.exists() || !m_dir.isReadable())
-		return false;
+    if (!m_dir.exists() || !m_dir.isReadable())
+        return false;
 
-	QList<Mod> orderedMods;
-	QList<Mod> newMods;
-	m_dir.refresh();
-	auto folderContents = m_dir.entryInfoList();
-	bool orderOrStateChanged = false;
+    QList<Mod> orderedMods;
+    QList<Mod> newMods;
+    m_dir.refresh();
+    auto folderContents = m_dir.entryInfoList();
+    bool orderOrStateChanged = false;
 
-	// first, process the ordered items (if any)
-	OrderList listOrder = readListFile(m_list_file);
-	for (auto item : listOrder)
-	{
-		QFileInfo infoEnabled(m_dir.filePath(item.id));
-		QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled"));
-		int idxEnabled = folderContents.indexOf(infoEnabled);
-		int idxDisabled = folderContents.indexOf(infoDisabled);
-		bool isEnabled;
-		// if both enabled and disabled versions are present, it's a special case...
-		if (idxEnabled >= 0 && idxDisabled >= 0)
-		{
-			// we only process the one we actually have in the order file.
-			// and exactly as we have it.
-			// THIS IS A CORNER CASE
-			isEnabled = item.enabled;
-		}
-		else
-		{
-			// only one is present.
-			// we pick the one that we found.
-			// we assume the mod was enabled/disabled by external means
-			isEnabled = idxEnabled >= 0;
-		}
-		int idx = isEnabled ? idxEnabled : idxDisabled;
-		QFileInfo &info = isEnabled ? infoEnabled : infoDisabled;
-		// if the file from the index file exists
-		if (idx != -1)
-		{
-			// remove from the actual folder contents list
-			folderContents.takeAt(idx);
-			// append the new mod
-			orderedMods.append(Mod(info));
-			if (isEnabled != item.enabled)
-				orderOrStateChanged = true;
-		}
-		else
-		{
-			orderOrStateChanged = true;
-		}
-	}
-	// if there are any untracked files...
-	if (folderContents.size())
-	{
-		// the order surely changed!
-		for (auto entry : folderContents)
-		{
-			newMods.append(Mod(entry));
-		}
-		internalSort(newMods);
-		orderedMods.append(newMods);
-		orderOrStateChanged = true;
-	}
-	// otherwise, if we were already tracking some mods
-	else if (mods.size())
-	{
-		// if the number doesn't match, order changed.
-		if (mods.size() != orderedMods.size())
-			orderOrStateChanged = true;
-		// if it does match, compare the mods themselves
-		else
-			for (int i = 0; i < mods.size(); i++)
-			{
-				if (!mods[i].strongCompare(orderedMods[i]))
-				{
-					orderOrStateChanged = true;
-					break;
-				}
-			}
-	}
-	mods.swap(orderedMods);
-	if (orderOrStateChanged && !m_list_file.isEmpty())
-	{
-		qDebug() << "Mod list " << m_list_file << " changed!";
-	}
-	return true;
+    // first, process the ordered items (if any)
+    OrderList listOrder = readListFile(m_list_file);
+    for (auto item : listOrder)
+    {
+        QFileInfo infoEnabled(m_dir.filePath(item.id));
+        QFileInfo infoDisabled(m_dir.filePath(item.id + ".disabled"));
+        int idxEnabled = folderContents.indexOf(infoEnabled);
+        int idxDisabled = folderContents.indexOf(infoDisabled);
+        bool isEnabled;
+        // if both enabled and disabled versions are present, it's a special case...
+        if (idxEnabled >= 0 && idxDisabled >= 0)
+        {
+            // we only process the one we actually have in the order file.
+            // and exactly as we have it.
+            // THIS IS A CORNER CASE
+            isEnabled = item.enabled;
+        }
+        else
+        {
+            // only one is present.
+            // we pick the one that we found.
+            // we assume the mod was enabled/disabled by external means
+            isEnabled = idxEnabled >= 0;
+        }
+        int idx = isEnabled ? idxEnabled : idxDisabled;
+        QFileInfo &info = isEnabled ? infoEnabled : infoDisabled;
+        // if the file from the index file exists
+        if (idx != -1)
+        {
+            // remove from the actual folder contents list
+            folderContents.takeAt(idx);
+            // append the new mod
+            orderedMods.append(Mod(info));
+            if (isEnabled != item.enabled)
+                orderOrStateChanged = true;
+        }
+        else
+        {
+            orderOrStateChanged = true;
+        }
+    }
+    // if there are any untracked files...
+    if (folderContents.size())
+    {
+        // the order surely changed!
+        for (auto entry : folderContents)
+        {
+            newMods.append(Mod(entry));
+        }
+        internalSort(newMods);
+        orderedMods.append(newMods);
+        orderOrStateChanged = true;
+    }
+    // otherwise, if we were already tracking some mods
+    else if (mods.size())
+    {
+        // if the number doesn't match, order changed.
+        if (mods.size() != orderedMods.size())
+            orderOrStateChanged = true;
+        // if it does match, compare the mods themselves
+        else
+            for (int i = 0; i < mods.size(); i++)
+            {
+                if (!mods[i].strongCompare(orderedMods[i]))
+                {
+                    orderOrStateChanged = true;
+                    break;
+                }
+            }
+    }
+    mods.swap(orderedMods);
+    if (orderOrStateChanged && !m_list_file.isEmpty())
+    {
+        qDebug() << "Mod list " << m_list_file << " changed!";
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/legacy/LegacyModList.h b/api/logic/minecraft/legacy/LegacyModList.h
index 19b191a7..8bc68b87 100644
--- a/api/logic/minecraft/legacy/LegacyModList.h
+++ b/api/logic/minecraft/legacy/LegacyModList.h
@@ -34,23 +34,23 @@ class MULTIMC_LOGIC_EXPORT LegacyModList
 {
 public:
 
-	LegacyModList(const QString &dir, const QString &list_file = QString());
+    LegacyModList(const QString &dir, const QString &list_file = QString());
 
-	/// Reloads the mod list and returns true if the list changed.
-	bool update();
+    /// Reloads the mod list and returns true if the list changed.
+    bool update();
 
-	QDir dir()
-	{
-		return m_dir;
-	}
+    QDir dir()
+    {
+        return m_dir;
+    }
 
-	const QList<Mod> & allMods()
-	{
-		return mods;
-	}
+    const QList<Mod> & allMods()
+    {
+        return mods;
+    }
 
 protected:
-	QDir m_dir;
-	QString m_list_file;
-	QList<Mod> mods;
+    QDir m_dir;
+    QString m_list_file;
+    QList<Mod> mods;
 };
diff --git a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp
index 5cc3b5d9..b274f061 100644
--- a/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp
+++ b/api/logic/minecraft/legacy/LegacyUpgradeTask.cpp
@@ -12,128 +12,128 @@
 
 LegacyUpgradeTask::LegacyUpgradeTask(InstancePtr origInstance)
 {
-	m_origInstance = origInstance;
+    m_origInstance = origInstance;
 }
 
 void LegacyUpgradeTask::executeTask()
 {
-	setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
+    setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
 
-	FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
-	folderCopy.followSymlinks(true);
+    FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
+    folderCopy.followSymlinks(true);
 
-	m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
-	connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &LegacyUpgradeTask::copyFinished);
-	connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &LegacyUpgradeTask::copyAborted);
-	m_copyFutureWatcher.setFuture(m_copyFuture);
+    m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy);
+    connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &LegacyUpgradeTask::copyFinished);
+    connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &LegacyUpgradeTask::copyAborted);
+    m_copyFutureWatcher.setFuture(m_copyFuture);
 }
 
 static QString decideVersion(const QString& currentVersion, const QString& intendedVersion)
 {
-	if(intendedVersion != currentVersion)
-	{
-		if(!intendedVersion.isEmpty())
-		{
-			return intendedVersion;
-		}
-		else if(!currentVersion.isEmpty())
-		{
-			return currentVersion;
-		}
-	}
-	else
-	{
-		if(!intendedVersion.isEmpty())
-		{
-			return intendedVersion;
-		}
-	}
-	return QString();
+    if(intendedVersion != currentVersion)
+    {
+        if(!intendedVersion.isEmpty())
+        {
+            return intendedVersion;
+        }
+        else if(!currentVersion.isEmpty())
+        {
+            return currentVersion;
+        }
+    }
+    else
+    {
+        if(!intendedVersion.isEmpty())
+        {
+            return intendedVersion;
+        }
+    }
+    return QString();
 }
 
 void LegacyUpgradeTask::copyFinished()
 {
-	auto successful = m_copyFuture.result();
-	if(!successful)
-	{
-		emitFailed(tr("Instance folder copy failed."));
-		return;
-	}
-	auto legacyInst = std::dynamic_pointer_cast<LegacyInstance>(m_origInstance);
+    auto successful = m_copyFuture.result();
+    if(!successful)
+    {
+        emitFailed(tr("Instance folder copy failed."));
+        return;
+    }
+    auto legacyInst = std::dynamic_pointer_cast<LegacyInstance>(m_origInstance);
 
-	auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
-	instanceSettings->registerSetting("InstanceType", "Legacy");
-	instanceSettings->set("InstanceType", "OneSix");
-	// NOTE: this scope ensures the instance is fully saved before we emitSucceeded
-	{
-		MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
-		inst.setName(m_instName);
-		inst.init();
+    auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg"));
+    instanceSettings->registerSetting("InstanceType", "Legacy");
+    instanceSettings->set("InstanceType", "OneSix");
+    // NOTE: this scope ensures the instance is fully saved before we emitSucceeded
+    {
+        MinecraftInstance inst(m_globalSettings, instanceSettings, m_stagingPath);
+        inst.setName(m_instName);
+        inst.init();
 
-		QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId());
-		if(preferredVersionNumber.isNull())
-		{
-			// try to decide version based on the jar(s?)
-			preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar());
-			if(preferredVersionNumber.isNull())
-			{
-				preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar());
-				if(preferredVersionNumber.isNull())
-				{
-					emitFailed(tr("Could not decide Minecraft version."));
-					return;
-				}
-			}
-		}
-		auto components = inst.getComponentList();
-		components->buildingFromScratch();
-		components->setComponentVersion("net.minecraft", preferredVersionNumber, true);
+        QString preferredVersionNumber = decideVersion(legacyInst->currentVersionId(), legacyInst->intendedVersionId());
+        if(preferredVersionNumber.isNull())
+        {
+            // try to decide version based on the jar(s?)
+            preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->baseJar());
+            if(preferredVersionNumber.isNull())
+            {
+                preferredVersionNumber = classparser::GetMinecraftJarVersion(legacyInst->runnableJar());
+                if(preferredVersionNumber.isNull())
+                {
+                    emitFailed(tr("Could not decide Minecraft version."));
+                    return;
+                }
+            }
+        }
+        auto components = inst.getComponentList();
+        components->buildingFromScratch();
+        components->setComponentVersion("net.minecraft", preferredVersionNumber, true);
 
-		QString jarPath = legacyInst->mainJarToPreserve();
-		if(!jarPath.isNull())
-		{
-			qDebug() << "Preserving base jar! : " << jarPath;
-			// FIXME: handle case when the jar is unreadable?
-			// TODO: check the hash, if it's the same as the upstream jar, do not do this
-			components->installCustomJar(jarPath);
-		}
+        QString jarPath = legacyInst->mainJarToPreserve();
+        if(!jarPath.isNull())
+        {
+            qDebug() << "Preserving base jar! : " << jarPath;
+            // FIXME: handle case when the jar is unreadable?
+            // TODO: check the hash, if it's the same as the upstream jar, do not do this
+            components->installCustomJar(jarPath);
+        }
 
-		auto jarMods = legacyInst->getJarMods();
-		for(auto & jarMod: jarMods)
-		{
-			QString modPath = jarMod.filename().absoluteFilePath();
-			qDebug() << "jarMod: " << modPath;
-			components->installJarMods({modPath});
-		}
+        auto jarMods = legacyInst->getJarMods();
+        for(auto & jarMod: jarMods)
+        {
+            QString modPath = jarMod.filename().absoluteFilePath();
+            qDebug() << "jarMod: " << modPath;
+            components->installJarMods({modPath});
+        }
 
-		// remove all the extra garbage we no longer need
-		auto removeAll = [&](const QString &root, const QStringList &things)
-		{
-			for(auto &thing : things)
-			{
-				auto removePath = FS::PathCombine(root, thing);
-				QFileInfo stat(removePath);
-				if(stat.isDir())
-				{
-					FS::deletePath(removePath);
-				}
-				else
-				{
-					QFile::remove(removePath);
-				}
-			}
-		};
-		QStringList rootRemovables = {"modlist", "version", "instMods"};
-		QStringList mcRemovables = {"bin", "MultiMCLauncher.jar", "icon.png"};
-		removeAll(inst.instanceRoot(), rootRemovables);
-		removeAll(inst.minecraftRoot(), mcRemovables);
-	}
-	emitSucceeded();
+        // remove all the extra garbage we no longer need
+        auto removeAll = [&](const QString &root, const QStringList &things)
+        {
+            for(auto &thing : things)
+            {
+                auto removePath = FS::PathCombine(root, thing);
+                QFileInfo stat(removePath);
+                if(stat.isDir())
+                {
+                    FS::deletePath(removePath);
+                }
+                else
+                {
+                    QFile::remove(removePath);
+                }
+            }
+        };
+        QStringList rootRemovables = {"modlist", "version", "instMods"};
+        QStringList mcRemovables = {"bin", "MultiMCLauncher.jar", "icon.png"};
+        removeAll(inst.instanceRoot(), rootRemovables);
+        removeAll(inst.minecraftRoot(), mcRemovables);
+    }
+    emitSucceeded();
 }
 
 void LegacyUpgradeTask::copyAborted()
 {
-	emitFailed(tr("Instance folder copy has been aborted."));
-	return;
+    emitFailed(tr("Instance folder copy has been aborted."));
+    return;
 }
 
diff --git a/api/logic/minecraft/legacy/LegacyUpgradeTask.h b/api/logic/minecraft/legacy/LegacyUpgradeTask.h
index a93dd0d9..5606eb87 100644
--- a/api/logic/minecraft/legacy/LegacyUpgradeTask.h
+++ b/api/logic/minecraft/legacy/LegacyUpgradeTask.h
@@ -15,18 +15,18 @@ class BaseInstanceProvider;
 
 class MULTIMC_LOGIC_EXPORT LegacyUpgradeTask : public InstanceTask
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit LegacyUpgradeTask(InstancePtr origInstance);
+    explicit LegacyUpgradeTask(InstancePtr origInstance);
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
-	void copyFinished();
-	void copyAborted();
+    //! Entry point for tasks.
+    virtual void executeTask() override;
+    void copyFinished();
+    void copyAborted();
 
 private: /* data */
-	InstancePtr m_origInstance;
-	QFuture<bool> m_copyFuture;
-	QFutureWatcher<bool> m_copyFutureWatcher;
+    InstancePtr m_origInstance;
+    QFuture<bool> m_copyFuture;
+    QFutureWatcher<bool> m_copyFutureWatcher;
 };
diff --git a/api/logic/minecraft/testdata/lib-native-arch.json b/api/logic/minecraft/testdata/lib-native-arch.json
index a73aac54..501826ae 100644
--- a/api/logic/minecraft/testdata/lib-native-arch.json
+++ b/api/logic/minecraft/testdata/lib-native-arch.json
@@ -1,46 +1,46 @@
 {
-	"downloads": {
-		"classifiers": {
-			"natives-osx": {
-				"path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar",
-				"sha1": "62503ee712766cf77f97252e5902786fd834b8c5",
-				"size": 418331,
-				"url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar"
-			},
-			"natives-windows-32": {
-				"path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar",
-				"sha1": "7c6affe439099806a4f552da14c42f9d643d8b23",
-				"size": 386792,
-				"url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"
-			},
-			"natives-windows-64": {
-				"path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar",
-				"sha1": "39d0c3d363735b4785598e0e7fbf8297c706a9f9",
-				"size": 463390,
-				"url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"
-			}
-		}
-	},
-	"extract": {
-		"exclude": [
-			"META-INF/"
-		]
-	},
-	"name": "tv.twitch:twitch-platform:5.16",
-	"natives": {
-		"linux": "natives-linux",
-		"osx": "natives-osx",
-		"windows": "natives-windows-${arch}"
-	},
-	"rules": [
-		{
-			"action": "allow"
-		},
-		{
-			"action": "disallow",
-			"os": {
-				"name": "linux"
-			}
-		}
-	]
+    "downloads": {
+        "classifiers": {
+            "natives-osx": {
+                "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar",
+                "sha1": "62503ee712766cf77f97252e5902786fd834b8c5",
+                "size": 418331,
+                "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-osx.jar"
+            },
+            "natives-windows-32": {
+                "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar",
+                "sha1": "7c6affe439099806a4f552da14c42f9d643d8b23",
+                "size": 386792,
+                "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-32.jar"
+            },
+            "natives-windows-64": {
+                "path": "tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar",
+                "sha1": "39d0c3d363735b4785598e0e7fbf8297c706a9f9",
+                "size": 463390,
+                "url": "https://libraries.minecraft.net/tv/twitch/twitch-platform/5.16/twitch-platform-5.16-natives-windows-64.jar"
+            }
+        }
+    },
+    "extract": {
+        "exclude": [
+            "META-INF/"
+        ]
+    },
+    "name": "tv.twitch:twitch-platform:5.16",
+    "natives": {
+        "linux": "natives-linux",
+        "osx": "natives-osx",
+        "windows": "natives-windows-${arch}"
+    },
+    "rules": [
+        {
+            "action": "allow"
+        },
+        {
+            "action": "disallow",
+            "os": {
+                "name": "linux"
+            }
+        }
+    ]
 }
diff --git a/api/logic/minecraft/testdata/lib-native.json b/api/logic/minecraft/testdata/lib-native.json
index 0a95b2b9..5b9f3b55 100644
--- a/api/logic/minecraft/testdata/lib-native.json
+++ b/api/logic/minecraft/testdata/lib-native.json
@@ -1,52 +1,52 @@
 {
-	"downloads": {
-		"artifact": {
-			"path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar",
-			"sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33",
-			"size": 22,
-			"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"
-		},
-		"classifiers": {
-			"natives-linux": {
-				"path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar",
-				"sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b",
-				"size": 578680,
-				"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
-			},
-			"natives-osx": {
-				"path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar",
-				"sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed",
-				"size": 426822,
-				"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
-			},
-			"natives-windows": {
-				"path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar",
-				"sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0",
-				"size": 613748,
-				"url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar"
-			}
-		}
-	},
-	"extract": {
-		"exclude": [
-			"META-INF/"
-		]
-	},
-	"name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
-	"natives": {
-		"linux": "natives-linux",
-		"osx": "natives-osx",
-		"windows": "natives-windows"
-	},
-	"rules": [
-		{
-			"action": "allow"
-		},
-		{
-			"action": "disallow",
-			"os": {
-				"name": "osx"
-			}
-		}
-	]
+    "downloads": {
+        "artifact": {
+            "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar",
+            "sha1": "b04f3ee8f5e43fa3b162981b50bb72fe1acabb33",
+            "size": 22,
+            "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209.jar"
+        },
+        "classifiers": {
+            "natives-linux": {
+                "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar",
+                "sha1": "931074f46c795d2f7b30ed6395df5715cfd7675b",
+                "size": 578680,
+                "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+            },
+            "natives-osx": {
+                "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar",
+                "sha1": "bcab850f8f487c3f4c4dbabde778bb82bd1a40ed",
+                "size": 426822,
+                "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
+            },
+            "natives-windows": {
+                "path": "org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar",
+                "sha1": "b84d5102b9dbfabfeb5e43c7e2828d98a7fc80e0",
+                "size": 613748,
+                "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl-platform/2.9.4-nightly-20150209/lwjgl-platform-2.9.4-nightly-20150209-natives-windows.jar"
+            }
+        }
+    },
+    "extract": {
+        "exclude": [
+            "META-INF/"
+        ]
+    },
+    "name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+    "natives": {
+        "linux": "natives-linux",
+        "osx": "natives-osx",
+        "windows": "natives-windows"
+    },
+    "rules": [
+        {
+            "action": "allow"
+        },
+        {
+            "action": "disallow",
+            "os": {
+                "name": "osx"
+            }
+        }
+    ]
 }
diff --git a/api/logic/minecraft/testdata/lib-simple.json b/api/logic/minecraft/testdata/lib-simple.json
index 3ef0f490..90bbff07 100644
--- a/api/logic/minecraft/testdata/lib-simple.json
+++ b/api/logic/minecraft/testdata/lib-simple.json
@@ -1,11 +1,11 @@
 {
-	"downloads": {
-		"artifact": {
-			"path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
-			"sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
-			"size": 5618,
-			"url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
-		}
-	},
-	"name": "com.paulscode:codecwav:20101023"
+    "downloads": {
+        "artifact": {
+            "path": "com/paulscode/codecwav/20101023/codecwav-20101023.jar",
+            "sha1": "12f031cfe88fef5c1dd36c563c0a3a69bd7261da",
+            "size": 5618,
+            "url": "https://libraries.minecraft.net/com/paulscode/codecwav/20101023/codecwav-20101023.jar"
+        }
+    },
+    "name": "com.paulscode:codecwav:20101023"
 }
diff --git a/api/logic/minecraft/update/AssetUpdateTask.cpp b/api/logic/minecraft/update/AssetUpdateTask.cpp
index 905c5b3d..1661822d 100644
--- a/api/logic/minecraft/update/AssetUpdateTask.cpp
+++ b/api/logic/minecraft/update/AssetUpdateTask.cpp
@@ -7,7 +7,7 @@
 
 AssetUpdateTask::AssetUpdateTask(MinecraftInstance * inst)
 {
-	m_inst = inst;
+    m_inst = inst;
 }
 
 AssetUpdateTask::~AssetUpdateTask()
@@ -16,92 +16,92 @@ AssetUpdateTask::~AssetUpdateTask()
 
 void AssetUpdateTask::executeTask()
 {
-	setStatus(tr("Updating assets index..."));
-	auto components = m_inst->getComponentList();
-	auto profile = components->getProfile();
-	auto assets = profile->getMinecraftAssets();
-	QUrl indexUrl = assets->url;
-	QString localPath = assets->id + ".json";
-	auto job = new NetJob(tr("Asset index for %1").arg(m_inst->name()));
+    setStatus(tr("Updating assets index..."));
+    auto components = m_inst->getComponentList();
+    auto profile = components->getProfile();
+    auto assets = profile->getMinecraftAssets();
+    QUrl indexUrl = assets->url;
+    QString localPath = assets->id + ".json";
+    auto job = new NetJob(tr("Asset index for %1").arg(m_inst->name()));
 
-	auto metacache = ENV.metacache();
-	auto entry = metacache->resolveEntry("asset_indexes", localPath);
-	entry->setStale(true);
-	auto hexSha1 = assets->sha1.toLatin1();
-	qDebug() << "Asset index SHA1:" << hexSha1;
-	auto dl = Net::Download::makeCached(indexUrl, entry);
-	auto rawSha1 = QByteArray::fromHex(assets->sha1.toLatin1());
-	dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
-	job->addNetAction(dl);
+    auto metacache = ENV.metacache();
+    auto entry = metacache->resolveEntry("asset_indexes", localPath);
+    entry->setStale(true);
+    auto hexSha1 = assets->sha1.toLatin1();
+    qDebug() << "Asset index SHA1:" << hexSha1;
+    auto dl = Net::Download::makeCached(indexUrl, entry);
+    auto rawSha1 = QByteArray::fromHex(assets->sha1.toLatin1());
+    dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
+    job->addNetAction(dl);
 
-	downloadJob.reset(job);
+    downloadJob.reset(job);
 
-	connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::assetIndexFinished);
-	connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed);
-	connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
+    connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::assetIndexFinished);
+    connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetIndexFailed);
+    connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
 
-	qDebug() << m_inst->name() << ": Starting asset index download";
-	downloadJob->start();
+    qDebug() << m_inst->name() << ": Starting asset index download";
+    downloadJob->start();
 }
 
 bool AssetUpdateTask::canAbort() const
 {
-	return true;
+    return true;
 }
 
 void AssetUpdateTask::assetIndexFinished()
 {
-	AssetsIndex index;
-	qDebug() << m_inst->name() << ": Finished asset index download";
+    AssetsIndex index;
+    qDebug() << m_inst->name() << ": Finished asset index download";
 
-	auto components = m_inst->getComponentList();
-	auto profile = components->getProfile();
-	auto assets = profile->getMinecraftAssets();
+    auto components = m_inst->getComponentList();
+    auto profile = components->getProfile();
+    auto assets = profile->getMinecraftAssets();
 
-	QString asset_fname = "assets/indexes/" + assets->id + ".json";
-	// FIXME: this looks like a job for a generic validator based on json schema?
-	if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, &index))
-	{
-		auto metacache = ENV.metacache();
-		auto entry = metacache->resolveEntry("asset_indexes", assets->id + ".json");
-		metacache->evictEntry(entry);
-		emitFailed(tr("Failed to read the assets index!"));
-	}
+    QString asset_fname = "assets/indexes/" + assets->id + ".json";
+    // FIXME: this looks like a job for a generic validator based on json schema?
+    if (!AssetsUtils::loadAssetsIndexJson(assets->id, asset_fname, &index))
+    {
+        auto metacache = ENV.metacache();
+        auto entry = metacache->resolveEntry("asset_indexes", assets->id + ".json");
+        metacache->evictEntry(entry);
+        emitFailed(tr("Failed to read the assets index!"));
+    }
 
-	auto job = index.getDownloadJob();
-	if(job)
-	{
-		setStatus(tr("Getting the assets files from Mojang..."));
-		downloadJob = job;
-		connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded);
-		connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed);
-		connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
-		downloadJob->start();
-		return;
-	}
-	emitSucceeded();
+    auto job = index.getDownloadJob();
+    if(job)
+    {
+        setStatus(tr("Getting the assets files from Mojang..."));
+        downloadJob = job;
+        connect(downloadJob.get(), &NetJob::succeeded, this, &AssetUpdateTask::emitSucceeded);
+        connect(downloadJob.get(), &NetJob::failed, this, &AssetUpdateTask::assetsFailed);
+        connect(downloadJob.get(), &NetJob::progress, this, &AssetUpdateTask::progress);
+        downloadJob->start();
+        return;
+    }
+    emitSucceeded();
 }
 
 void AssetUpdateTask::assetIndexFailed(QString reason)
 {
-	qDebug() << m_inst->name() << ": Failed asset index download";
-	emitFailed(tr("Failed to download the assets index:\n%1").arg(reason));
+    qDebug() << m_inst->name() << ": Failed asset index download";
+    emitFailed(tr("Failed to download the assets index:\n%1").arg(reason));
 }
 
 void AssetUpdateTask::assetsFailed(QString reason)
 {
-	emitFailed(tr("Failed to download assets:\n%1").arg(reason));
+    emitFailed(tr("Failed to download assets:\n%1").arg(reason));
 }
 
 bool AssetUpdateTask::abort()
 {
-	if(downloadJob)
-	{
-		return downloadJob->abort();
-	}
-	else
-	{
-		qWarning() << "Prematurely aborted FMLLibrariesTask";
-	}
-	return true;
+    if(downloadJob)
+    {
+        return downloadJob->abort();
+    }
+    else
+    {
+        qWarning() << "Prematurely aborted FMLLibrariesTask";
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/update/AssetUpdateTask.h b/api/logic/minecraft/update/AssetUpdateTask.h
index 870cede5..fdfa8f1c 100644
--- a/api/logic/minecraft/update/AssetUpdateTask.h
+++ b/api/logic/minecraft/update/AssetUpdateTask.h
@@ -5,24 +5,24 @@ class MinecraftInstance;
 
 class AssetUpdateTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	AssetUpdateTask(MinecraftInstance * inst);
-	virtual ~AssetUpdateTask();
+    AssetUpdateTask(MinecraftInstance * inst);
+    virtual ~AssetUpdateTask();
 
-	void executeTask() override;
+    void executeTask() override;
 
-	bool canAbort() const override;
+    bool canAbort() const override;
 
 private slots:
-	void assetIndexFinished();
-	void assetIndexFailed(QString reason);
-	void assetsFailed(QString reason);
+    void assetIndexFinished();
+    void assetIndexFailed(QString reason);
+    void assetsFailed(QString reason);
 
 public slots:
-	bool abort() override;
+    bool abort() override;
 
 private:
-	MinecraftInstance *m_inst;
-	NetJobPtr downloadJob;
+    MinecraftInstance *m_inst;
+    NetJobPtr downloadJob;
 };
diff --git a/api/logic/minecraft/update/FMLLibrariesTask.cpp b/api/logic/minecraft/update/FMLLibrariesTask.cpp
index 1bd339e4..5b4975ab 100644
--- a/api/logic/minecraft/update/FMLLibrariesTask.cpp
+++ b/api/logic/minecraft/update/FMLLibrariesTask.cpp
@@ -7,125 +7,125 @@
 
 FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance * inst)
 {
-	m_inst = inst;
+    m_inst = inst;
 }
 void FMLLibrariesTask::executeTask()
 {
-	// Get the mod list
-	MinecraftInstance *inst = (MinecraftInstance *)m_inst;
-	auto components = inst->getComponentList();
-	auto profile = components->getProfile();
+    // Get the mod list
+    MinecraftInstance *inst = (MinecraftInstance *)m_inst;
+    auto components = inst->getComponentList();
+    auto profile = components->getProfile();
 
-	if (!profile->hasTrait("legacyFML"))
-	{
-		emitSucceeded();
-		return;
-	}
+    if (!profile->hasTrait("legacyFML"))
+    {
+        emitSucceeded();
+        return;
+    }
 
-	QString version = components->getComponentVersion("net.minecraft");
-	auto &fmlLibsMapping = g_VersionFilterData.fmlLibsMapping;
-	if (!fmlLibsMapping.contains(version))
-	{
-		emitSucceeded();
-		return;
-	}
+    QString version = components->getComponentVersion("net.minecraft");
+    auto &fmlLibsMapping = g_VersionFilterData.fmlLibsMapping;
+    if (!fmlLibsMapping.contains(version))
+    {
+        emitSucceeded();
+        return;
+    }
 
-	auto &libList = fmlLibsMapping[version];
+    auto &libList = fmlLibsMapping[version];
 
-	// determine if we need some libs for FML or forge
-	setStatus(tr("Checking for FML libraries..."));
-	if(!components->getComponent("net.minecraftforge"))
-	{
-		emitSucceeded();
-		return;
-	}
+    // determine if we need some libs for FML or forge
+    setStatus(tr("Checking for FML libraries..."));
+    if(!components->getComponent("net.minecraftforge"))
+    {
+        emitSucceeded();
+        return;
+    }
 
-	// now check the lib folder inside the instance for files.
-	for (auto &lib : libList)
-	{
-		QFileInfo libInfo(FS::PathCombine(inst->libDir(), lib.filename));
-		if (libInfo.exists())
-			continue;
-		fmlLibsToProcess.append(lib);
-	}
+    // now check the lib folder inside the instance for files.
+    for (auto &lib : libList)
+    {
+        QFileInfo libInfo(FS::PathCombine(inst->libDir(), lib.filename));
+        if (libInfo.exists())
+            continue;
+        fmlLibsToProcess.append(lib);
+    }
 
-	// if everything is in place, there's nothing to do here...
-	if (fmlLibsToProcess.isEmpty())
-	{
-		emitSucceeded();
-		return;
-	}
+    // if everything is in place, there's nothing to do here...
+    if (fmlLibsToProcess.isEmpty())
+    {
+        emitSucceeded();
+        return;
+    }
 
-	// download missing libs to our place
-	setStatus(tr("Dowloading FML libraries..."));
-	auto dljob = new NetJob("FML libraries");
-	auto metacache = ENV.metacache();
-	for (auto &lib : fmlLibsToProcess)
-	{
-		auto entry = metacache->resolveEntry("fmllibs", lib.filename);
-		QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.filename
-									: URLConstants::FMLLIBS_FORGE_BASE_URL + lib.filename;
-		dljob->addNetAction(Net::Download::makeCached(QUrl(urlString), entry));
-	}
+    // download missing libs to our place
+    setStatus(tr("Dowloading FML libraries..."));
+    auto dljob = new NetJob("FML libraries");
+    auto metacache = ENV.metacache();
+    for (auto &lib : fmlLibsToProcess)
+    {
+        auto entry = metacache->resolveEntry("fmllibs", lib.filename);
+        QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.filename
+                                    : URLConstants::FMLLIBS_FORGE_BASE_URL + lib.filename;
+        dljob->addNetAction(Net::Download::makeCached(QUrl(urlString), entry));
+    }
 
-	connect(dljob, &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished);
-	connect(dljob, &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed);
-	connect(dljob, &NetJob::progress, this, &FMLLibrariesTask::progress);
-	downloadJob.reset(dljob);
-	downloadJob->start();
+    connect(dljob, &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished);
+    connect(dljob, &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed);
+    connect(dljob, &NetJob::progress, this, &FMLLibrariesTask::progress);
+    downloadJob.reset(dljob);
+    downloadJob->start();
 }
 
 bool FMLLibrariesTask::canAbort() const
 {
-	return true;
+    return true;
 }
 
 void FMLLibrariesTask::fmllibsFinished()
 {
-	downloadJob.reset();
-	if (!fmlLibsToProcess.isEmpty())
-	{
-		setStatus(tr("Copying FML libraries into the instance..."));
-		MinecraftInstance *inst = (MinecraftInstance *)m_inst;
-		auto metacache = ENV.metacache();
-		int index = 0;
-		for (auto &lib : fmlLibsToProcess)
-		{
-			progress(index, fmlLibsToProcess.size());
-			auto entry = metacache->resolveEntry("fmllibs", lib.filename);
-			auto path = FS::PathCombine(inst->libDir(), lib.filename);
-			if (!FS::ensureFilePathExists(path))
-			{
-				emitFailed(tr("Failed creating FML library folder inside the instance."));
-				return;
-			}
-			if (!QFile::copy(entry->getFullPath(), FS::PathCombine(inst->libDir(), lib.filename)))
-			{
-				emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename));
-				return;
-			}
-			index++;
-		}
-		progress(index, fmlLibsToProcess.size());
-	}
-	emitSucceeded();
+    downloadJob.reset();
+    if (!fmlLibsToProcess.isEmpty())
+    {
+        setStatus(tr("Copying FML libraries into the instance..."));
+        MinecraftInstance *inst = (MinecraftInstance *)m_inst;
+        auto metacache = ENV.metacache();
+        int index = 0;
+        for (auto &lib : fmlLibsToProcess)
+        {
+            progress(index, fmlLibsToProcess.size());
+            auto entry = metacache->resolveEntry("fmllibs", lib.filename);
+            auto path = FS::PathCombine(inst->libDir(), lib.filename);
+            if (!FS::ensureFilePathExists(path))
+            {
+                emitFailed(tr("Failed creating FML library folder inside the instance."));
+                return;
+            }
+            if (!QFile::copy(entry->getFullPath(), FS::PathCombine(inst->libDir(), lib.filename)))
+            {
+                emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename));
+                return;
+            }
+            index++;
+        }
+        progress(index, fmlLibsToProcess.size());
+    }
+    emitSucceeded();
 }
 void FMLLibrariesTask::fmllibsFailed(QString reason)
 {
-	QStringList failed = downloadJob->getFailedFiles();
-	QString failed_all = failed.join("\n");
-	emitFailed(tr("Failed to download the following files:\n%1\n\nReason:%2\nPlease try again.").arg(failed_all, reason));
+    QStringList failed = downloadJob->getFailedFiles();
+    QString failed_all = failed.join("\n");
+    emitFailed(tr("Failed to download the following files:\n%1\n\nReason:%2\nPlease try again.").arg(failed_all, reason));
 }
 
 bool FMLLibrariesTask::abort()
 {
-	if(downloadJob)
-	{
-		return downloadJob->abort();
-	}
-	else
-	{
-		qWarning() << "Prematurely aborted FMLLibrariesTask";
-	}
-	return true;
+    if(downloadJob)
+    {
+        return downloadJob->abort();
+    }
+    else
+    {
+        qWarning() << "Prematurely aborted FMLLibrariesTask";
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/update/FMLLibrariesTask.h b/api/logic/minecraft/update/FMLLibrariesTask.h
index f281890d..a1e70ed4 100644
--- a/api/logic/minecraft/update/FMLLibrariesTask.h
+++ b/api/logic/minecraft/update/FMLLibrariesTask.h
@@ -7,25 +7,25 @@ class MinecraftInstance;
 
 class FMLLibrariesTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	FMLLibrariesTask(MinecraftInstance * inst);
-	virtual ~FMLLibrariesTask() {};
+    FMLLibrariesTask(MinecraftInstance * inst);
+    virtual ~FMLLibrariesTask() {};
 
-	void executeTask() override;
+    void executeTask() override;
 
-	bool canAbort() const override;
+    bool canAbort() const override;
 
 private slots:
-	void fmllibsFinished();
-	void fmllibsFailed(QString reason);
+    void fmllibsFinished();
+    void fmllibsFailed(QString reason);
 
 public slots:
-	bool abort() override;
+    bool abort() override;
 
 private:
-	MinecraftInstance *m_inst;
-	NetJobPtr downloadJob;
-	QList<FMLlib> fmlLibsToProcess;
+    MinecraftInstance *m_inst;
+    NetJobPtr downloadJob;
+    QList<FMLlib> fmlLibsToProcess;
 };
 
diff --git a/api/logic/minecraft/update/FoldersTask.cpp b/api/logic/minecraft/update/FoldersTask.cpp
index 34e2292a..2073b14e 100644
--- a/api/logic/minecraft/update/FoldersTask.cpp
+++ b/api/logic/minecraft/update/FoldersTask.cpp
@@ -3,19 +3,19 @@
 #include <QDir>
 
 FoldersTask::FoldersTask(MinecraftInstance * inst)
-	:Task()
+    :Task()
 {
-	m_inst = inst;
+    m_inst = inst;
 }
 
 void FoldersTask::executeTask()
 {
-	// Make directories
-	QDir mcDir(m_inst->minecraftRoot());
-	if (!mcDir.exists() && !mcDir.mkpath("."))
-	{
-		emitFailed(tr("Failed to create folder for minecraft binaries."));
-		return;
-	}
-	emitSucceeded();
+    // Make directories
+    QDir mcDir(m_inst->minecraftRoot());
+    if (!mcDir.exists() && !mcDir.mkpath("."))
+    {
+        emitFailed(tr("Failed to create folder for minecraft binaries."));
+        return;
+    }
+    emitSucceeded();
 }
diff --git a/api/logic/minecraft/update/FoldersTask.h b/api/logic/minecraft/update/FoldersTask.h
index e0781ad8..f6ed5e6d 100644
--- a/api/logic/minecraft/update/FoldersTask.h
+++ b/api/logic/minecraft/update/FoldersTask.h
@@ -5,13 +5,13 @@
 class MinecraftInstance;
 class FoldersTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	FoldersTask(MinecraftInstance * inst);
-	virtual ~FoldersTask() {};
+    FoldersTask(MinecraftInstance * inst);
+    virtual ~FoldersTask() {};
 
-	void executeTask() override;
+    void executeTask() override;
 private:
-	MinecraftInstance *m_inst;
+    MinecraftInstance *m_inst;
 };
 
diff --git a/api/logic/minecraft/update/LibrariesTask.cpp b/api/logic/minecraft/update/LibrariesTask.cpp
index 0bec61c1..6dcb149c 100644
--- a/api/logic/minecraft/update/LibrariesTask.cpp
+++ b/api/logic/minecraft/update/LibrariesTask.cpp
@@ -5,86 +5,86 @@
 
 LibrariesTask::LibrariesTask(MinecraftInstance * inst)
 {
-	m_inst = inst;
+    m_inst = inst;
 }
 
 void LibrariesTask::executeTask()
 {
-	setStatus(tr("Getting the library files from Mojang..."));
-	qDebug() << m_inst->name() << ": downloading libraries";
-	MinecraftInstance *inst = (MinecraftInstance *)m_inst;
+    setStatus(tr("Getting the library files from Mojang..."));
+    qDebug() << m_inst->name() << ": downloading libraries";
+    MinecraftInstance *inst = (MinecraftInstance *)m_inst;
 
-	// Build a list of URLs that will need to be downloaded.
-	auto components = inst->getComponentList();
-	auto profile = components->getProfile();
+    // Build a list of URLs that will need to be downloaded.
+    auto components = inst->getComponentList();
+    auto profile = components->getProfile();
 
-	auto job = new NetJob(tr("Libraries for instance %1").arg(inst->name()));
-	downloadJob.reset(job);
+    auto job = new NetJob(tr("Libraries for instance %1").arg(inst->name()));
+    downloadJob.reset(job);
 
-	auto metacache = ENV.metacache();
-	QList<LibraryPtr> brokenLocalLibs;
-	QStringList failedFiles;
-	auto createJob = [&](const LibraryPtr & lib)
-	{
-		if(!lib)
-		{
-			emitFailed(tr("Null jar is specified in the metadata, aborting."));
-			return;
-		}
-		auto dls = lib->getDownloads(currentSystem, metacache.get(), failedFiles, inst->getLocalLibraryPath());
-		for(auto dl : dls)
-		{
-			downloadJob->addNetAction(dl);
-		}
-	};
-	auto createJobs = [&](const QList<LibraryPtr> & libs)
-	{
-		for (auto lib : libs)
-		{
-			createJob(lib);
-		}
-	};
-	createJobs(profile->getLibraries());
-	createJobs(profile->getNativeLibraries());
-	createJobs(profile->getJarMods());
-	createJob(profile->getMainJar());
+    auto metacache = ENV.metacache();
+    QList<LibraryPtr> brokenLocalLibs;
+    QStringList failedFiles;
+    auto createJob = [&](const LibraryPtr & lib)
+    {
+        if(!lib)
+        {
+            emitFailed(tr("Null jar is specified in the metadata, aborting."));
+            return;
+        }
+        auto dls = lib->getDownloads(currentSystem, metacache.get(), failedFiles, inst->getLocalLibraryPath());
+        for(auto dl : dls)
+        {
+            downloadJob->addNetAction(dl);
+        }
+    };
+    auto createJobs = [&](const QList<LibraryPtr> & libs)
+    {
+        for (auto lib : libs)
+        {
+            createJob(lib);
+        }
+    };
+    createJobs(profile->getLibraries());
+    createJobs(profile->getNativeLibraries());
+    createJobs(profile->getJarMods());
+    createJob(profile->getMainJar());
 
-	// FIXME: this is never filled!!!!
-	if (!brokenLocalLibs.empty())
-	{
-		downloadJob.reset();
-		QString failed_all = failedFiles.join("\n");
-		emitFailed(tr("Some libraries marked as 'local' are missing their jar "
-					"files:\n%1\n\nYou'll have to correct this problem manually. If this is "
-					"an externally tracked instance, make sure to run it at least once "
-					"outside of MultiMC.").arg(failed_all));
-		return;
-	}
-	connect(downloadJob.get(), &NetJob::succeeded, this, &LibrariesTask::emitSucceeded);
-	connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed);
-	connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress);
-	downloadJob->start();
+    // FIXME: this is never filled!!!!
+    if (!brokenLocalLibs.empty())
+    {
+        downloadJob.reset();
+        QString failed_all = failedFiles.join("\n");
+        emitFailed(tr("Some libraries marked as 'local' are missing their jar "
+                    "files:\n%1\n\nYou'll have to correct this problem manually. If this is "
+                    "an externally tracked instance, make sure to run it at least once "
+                    "outside of MultiMC.").arg(failed_all));
+        return;
+    }
+    connect(downloadJob.get(), &NetJob::succeeded, this, &LibrariesTask::emitSucceeded);
+    connect(downloadJob.get(), &NetJob::failed, this, &LibrariesTask::jarlibFailed);
+    connect(downloadJob.get(), &NetJob::progress, this, &LibrariesTask::progress);
+    downloadJob->start();
 }
 
 bool LibrariesTask::canAbort() const
 {
-	return true;
+    return true;
 }
 
 void LibrariesTask::jarlibFailed(QString reason)
 {
-	emitFailed(tr("Game update failed: it was impossible to fetch the required libraries.\nReason:\n%1").arg(reason));
+    emitFailed(tr("Game update failed: it was impossible to fetch the required libraries.\nReason:\n%1").arg(reason));
 }
 
 bool LibrariesTask::abort()
 {
-	if(downloadJob)
-	{
-		return downloadJob->abort();
-	}
-	else
-	{
-		qWarning() << "Prematurely aborted LibrariesTask";
-	}
-	return true;
+    if(downloadJob)
+    {
+        return downloadJob->abort();
+    }
+    else
+    {
+        qWarning() << "Prematurely aborted LibrariesTask";
+    }
+    return true;
 }
diff --git a/api/logic/minecraft/update/LibrariesTask.h b/api/logic/minecraft/update/LibrariesTask.h
index cb9babc3..49f76932 100644
--- a/api/logic/minecraft/update/LibrariesTask.h
+++ b/api/logic/minecraft/update/LibrariesTask.h
@@ -5,22 +5,22 @@ class MinecraftInstance;
 
 class LibrariesTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	LibrariesTask(MinecraftInstance * inst);
-	virtual ~LibrariesTask() {};
+    LibrariesTask(MinecraftInstance * inst);
+    virtual ~LibrariesTask() {};
 
-	void executeTask() override;
+    void executeTask() override;
 
-	bool canAbort() const override;
+    bool canAbort() const override;
 
 private slots:
-	void jarlibFailed(QString reason);
+    void jarlibFailed(QString reason);
 
 public slots:
-	bool abort() override;
+    bool abort() override;
 
 private:
-	MinecraftInstance *m_inst;
-	NetJobPtr downloadJob;
+    MinecraftInstance *m_inst;
+    NetJobPtr downloadJob;
 };
diff --git a/api/logic/modplatform/flame/FileResolvingTask.cpp b/api/logic/modplatform/flame/FileResolvingTask.cpp
index 5eb82458..24cafcdd 100644
--- a/api/logic/modplatform/flame/FileResolvingTask.cpp
+++ b/api/logic/modplatform/flame/FileResolvingTask.cpp
@@ -4,114 +4,114 @@
 const char * metabase = "https://cursemeta.dries007.net";
 
 Flame::FileResolvingTask::FileResolvingTask(Flame::Manifest& toProcess)
-	: m_toProcess(toProcess)
+    : m_toProcess(toProcess)
 {
 }
 
 void Flame::FileResolvingTask::executeTask()
 {
-	setStatus(tr("Resolving mod IDs..."));
-	setProgress(0, m_toProcess.files.size());
-	m_dljob.reset(new NetJob("Mod id resolver"));
-	results.resize(m_toProcess.files.size());
-	int index = 0;
-	for(auto & file: m_toProcess.files)
-	{
-		auto projectIdStr = QString::number(file.projectId);
-		auto fileIdStr = QString::number(file.fileId);
-		QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
-		auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
-		m_dljob->addNetAction(dl);
-		index ++;
-	}
-	connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
-	m_dljob->start();
+    setStatus(tr("Resolving mod IDs..."));
+    setProgress(0, m_toProcess.files.size());
+    m_dljob.reset(new NetJob("Mod id resolver"));
+    results.resize(m_toProcess.files.size());
+    int index = 0;
+    for(auto & file: m_toProcess.files)
+    {
+        auto projectIdStr = QString::number(file.projectId);
+        auto fileIdStr = QString::number(file.fileId);
+        QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
+        auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
+        m_dljob->addNetAction(dl);
+        index ++;
+    }
+    connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
+    m_dljob->start();
 }
 
 void Flame::FileResolvingTask::netJobFinished()
 {
-	bool failed = false;
-	int index = 0;
-	for(auto & bytes: results)
-	{
-		try
-		{
-			auto doc = Json::requireDocument(bytes);
-			auto obj = Json::requireObject(doc);
-			auto & out = m_toProcess.files[index];
-			// result code signifies true failure.
-			if(obj.contains("code"))
-			{
-				qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a negative result:";
-				qCritical() << bytes;
-				failed = true;
-				continue;
-			}
-			out.fileName = Json::requireString(obj, "FileNameOnDisk");
-			QString rawUrl = Json::requireString(obj, "DownloadURL");
-			out.url = QUrl(rawUrl, QUrl::TolerantMode);
-			if(!out.url.isValid())
-			{
-				throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
-			}
-			// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
-			// It is also optional
-			QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
-			if(!projObj.isEmpty())
-			{
-				QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
-				if(strType == "singlefile")
-				{
-					out.type = File::Type::SingleFile;
-				}
-				else if(strType == "ctoc")
-				{
-					out.type = File::Type::Ctoc;
-				}
-				else if(strType == "cmod2")
-				{
-					out.type = File::Type::Cmod2;
-				}
-				else if(strType == "mod")
-				{
-					out.type = File::Type::Mod;
-				}
-				else if(strType == "folder")
-				{
-					out.type = File::Type::Folder;
-				}
-				else if(strType == "modpack")
-				{
-					out.type = File::Type::Modpack;
-				}
-				else
-				{
-					qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of unknown file type:" << strType;
-					out.type = File::Type::Unknown;
-					failed = true;
-					continue;
-				}
-				out.targetFolder = Json::ensureString(projObj, "Path", "mods");
-			}
-			out.resolved = true;
-		}
-		catch (const JSONValidationError &e)
-		{
-			auto & out = m_toProcess.files[index];
-			qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
-			qCritical() << e.cause();
-			qCritical() << "JSON:";
-			qCritical() << bytes;
-			failed = true;
-		}
-		index++;
-	}
-	if(!failed)
-	{
-		emitSucceeded();
-	}
-	else
-	{
-		emitFailed(tr("Some mod ID resolving tasks failed."));
-	}
+    bool failed = false;
+    int index = 0;
+    for(auto & bytes: results)
+    {
+        try
+        {
+            auto doc = Json::requireDocument(bytes);
+            auto obj = Json::requireObject(doc);
+            auto & out = m_toProcess.files[index];
+            // result code signifies true failure.
+            if(obj.contains("code"))
+            {
+                qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a negative result:";
+                qCritical() << bytes;
+                failed = true;
+                continue;
+            }
+            out.fileName = Json::requireString(obj, "FileNameOnDisk");
+            QString rawUrl = Json::requireString(obj, "DownloadURL");
+            out.url = QUrl(rawUrl, QUrl::TolerantMode);
+            if(!out.url.isValid())
+            {
+                throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
+            }
+            // This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
+            // It is also optional
+            QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
+            if(!projObj.isEmpty())
+            {
+                QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
+                if(strType == "singlefile")
+                {
+                    out.type = File::Type::SingleFile;
+                }
+                else if(strType == "ctoc")
+                {
+                    out.type = File::Type::Ctoc;
+                }
+                else if(strType == "cmod2")
+                {
+                    out.type = File::Type::Cmod2;
+                }
+                else if(strType == "mod")
+                {
+                    out.type = File::Type::Mod;
+                }
+                else if(strType == "folder")
+                {
+                    out.type = File::Type::Folder;
+                }
+                else if(strType == "modpack")
+                {
+                    out.type = File::Type::Modpack;
+                }
+                else
+                {
+                    qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of unknown file type:" << strType;
+                    out.type = File::Type::Unknown;
+                    failed = true;
+                    continue;
+                }
+                out.targetFolder = Json::ensureString(projObj, "Path", "mods");
+            }
+            out.resolved = true;
+        }
+        catch (const JSONValidationError &e)
+        {
+            auto & out = m_toProcess.files[index];
+            qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
+            qCritical() << e.cause();
+            qCritical() << "JSON:";
+            qCritical() << bytes;
+            failed = true;
+        }
+        index++;
+    }
+    if(!failed)
+    {
+        emitSucceeded();
+    }
+    else
+    {
+        emitFailed(tr("Some mod ID resolving tasks failed."));
+    }
 }
diff --git a/api/logic/modplatform/flame/FileResolvingTask.h b/api/logic/modplatform/flame/FileResolvingTask.h
index e5ed633e..5679b907 100644
--- a/api/logic/modplatform/flame/FileResolvingTask.h
+++ b/api/logic/modplatform/flame/FileResolvingTask.h
@@ -10,25 +10,25 @@ namespace Flame
 {
 class MULTIMC_LOGIC_EXPORT FileResolvingTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit FileResolvingTask(Flame::Manifest &toProcess);
-	virtual ~FileResolvingTask() {};
+    explicit FileResolvingTask(Flame::Manifest &toProcess);
+    virtual ~FileResolvingTask() {};
 
-	const Flame::Manifest &getResults() const
-	{
-		return m_toProcess;
-	}
+    const Flame::Manifest &getResults() const
+    {
+        return m_toProcess;
+    }
 
 protected:
-	virtual void executeTask() override;
+    virtual void executeTask() override;
 
 protected slots:
-	void netJobFinished();
+    void netJobFinished();
 
 private: /* data */
-	Flame::Manifest m_toProcess;
-	QVector<QByteArray> results;
-	NetJobPtr m_dljob;
+    Flame::Manifest m_toProcess;
+    QVector<QByteArray> results;
+    NetJobPtr m_dljob;
 };
 }
diff --git a/api/logic/modplatform/flame/PackManifest.cpp b/api/logic/modplatform/flame/PackManifest.cpp
index 6a9324fe..0f57c9bc 100644
--- a/api/logic/modplatform/flame/PackManifest.cpp
+++ b/api/logic/modplatform/flame/PackManifest.cpp
@@ -3,64 +3,64 @@
 
 static void loadFileV1(Flame::File & f, QJsonObject & file)
 {
-	f.projectId = Json::requireInteger(file, "projectID");
-	f.fileId = Json::requireInteger(file, "fileID");
-	f.required = Json::ensureBoolean(file, QString("required"), true);
+    f.projectId = Json::requireInteger(file, "projectID");
+    f.fileId = Json::requireInteger(file, "fileID");
+    f.required = Json::ensureBoolean(file, QString("required"), true);
 }
 
 static void loadModloaderV1(Flame::Modloader & m, QJsonObject & modLoader)
 {
-	m.id = Json::requireString(modLoader, "id");
-	m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
+    m.id = Json::requireString(modLoader, "id");
+    m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
 }
 
 static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
 {
-	m.version = Json::requireString(minecraft, "version");
-	// extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
-	// intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
-	m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
-	auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
-	for (const auto & item : arr)
-	{
-		auto obj = Json::requireObject(item);
-		Flame::Modloader loader;
-		loadModloaderV1(loader, obj);
-		m.modLoaders.append(loader);
-	}
+    m.version = Json::requireString(minecraft, "version");
+    // extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
+    // intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
+    m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
+    auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
+    for (const auto & item : arr)
+    {
+        auto obj = Json::requireObject(item);
+        Flame::Modloader loader;
+        loadModloaderV1(loader, obj);
+        m.modLoaders.append(loader);
+    }
 }
 
 static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
 {
-	auto mc = Json::requireObject(manifest, "minecraft");
-	loadMinecraftV1(m.minecraft, mc);
-	m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
-	m.version = Json::ensureString(manifest, QString("version"), QString());
-	m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward");
-	auto arr = Json::ensureArray(manifest, "files", QJsonArray());
-	for (const auto & item : arr)
-	{
-		auto obj = Json::requireObject(item);
-		Flame::File file;
-		loadFileV1(file, obj);
-		m.files.append(file);
-	}
-	m.overrides = Json::ensureString(manifest, "overrides", "overrides");
+    auto mc = Json::requireObject(manifest, "minecraft");
+    loadMinecraftV1(m.minecraft, mc);
+    m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
+    m.version = Json::ensureString(manifest, QString("version"), QString());
+    m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward");
+    auto arr = Json::ensureArray(manifest, "files", QJsonArray());
+    for (const auto & item : arr)
+    {
+        auto obj = Json::requireObject(item);
+        Flame::File file;
+        loadFileV1(file, obj);
+        m.files.append(file);
+    }
+    m.overrides = Json::ensureString(manifest, "overrides", "overrides");
 }
 
 void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
 {
-	auto doc = Json::requireDocument(filepath);
-	auto obj = Json::requireObject(doc);
-	m.manifestType = Json::requireString(obj, "manifestType");
-	if(m.manifestType != "minecraftModpack")
-	{
-		throw JSONValidationError("Not a modpack manifest!");
-	}
-	m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
-	if(m.manifestVersion != 1)
-	{
-		throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
-	}
-	loadManifestV1(m, obj);
+    auto doc = Json::requireDocument(filepath);
+    auto obj = Json::requireObject(doc);
+    m.manifestType = Json::requireString(obj, "manifestType");
+    if(m.manifestType != "minecraftModpack")
+    {
+        throw JSONValidationError("Not a modpack manifest!");
+    }
+    m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
+    if(m.manifestVersion != 1)
+    {
+        throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
+    }
+    loadManifestV1(m, obj);
 }
diff --git a/api/logic/modplatform/flame/PackManifest.h b/api/logic/modplatform/flame/PackManifest.h
index 1a5254a8..34232eee 100644
--- a/api/logic/modplatform/flame/PackManifest.h
+++ b/api/logic/modplatform/flame/PackManifest.h
@@ -8,51 +8,51 @@ namespace Flame
 {
 struct File
 {
-	int projectId = 0;
-	int fileId = 0;
-	// NOTE: the opposite to 'optional'. This is at the time of writing unused.
-	bool required = true;
+    int projectId = 0;
+    int fileId = 0;
+    // NOTE: the opposite to 'optional'. This is at the time of writing unused.
+    bool required = true;
 
-	// our
-	bool resolved = false;
-	QString fileName;
-	QUrl url;
-	QString targetFolder = QLatin1Literal("mods");
-	enum class Type
-	{
-		Unknown,
-		Folder,
-		Ctoc,
-		SingleFile,
-		Cmod2,
-		Modpack,
-		Mod
-	} type = Type::Mod;
+    // our
+    bool resolved = false;
+    QString fileName;
+    QUrl url;
+    QString targetFolder = QLatin1Literal("mods");
+    enum class Type
+    {
+        Unknown,
+        Folder,
+        Ctoc,
+        SingleFile,
+        Cmod2,
+        Modpack,
+        Mod
+    } type = Type::Mod;
 };
 
 struct Modloader
 {
-	QString id;
-	bool primary = false;
+    QString id;
+    bool primary = false;
 };
 
 struct Minecraft
 {
-	QString version;
-	QString libraries;
-	QVector<Flame::Modloader> modLoaders;
+    QString version;
+    QString libraries;
+    QVector<Flame::Modloader> modLoaders;
 };
 
 struct Manifest
 {
-	QString manifestType;
-	int manifestVersion = 0;
-	Flame::Minecraft minecraft;
-	QString name;
-	QString version;
-	QString author;
-	QVector<Flame::File> files;
-	QString overrides;
+    QString manifestType;
+    int manifestVersion = 0;
+    Flame::Minecraft minecraft;
+    QString name;
+    QString version;
+    QString author;
+    QVector<Flame::File> files;
+    QString overrides;
 };
 
 void loadManifest(Flame::Manifest & m, const QString &filepath);
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
index 5588a7fd..67248f2c 100644
--- a/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
+++ b/api/logic/modplatform/ftb/FtbPackFetchTask.cpp
@@ -11,107 +11,107 @@ FtbPackFetchTask::~FtbPackFetchTask()
 
 void FtbPackFetchTask::fetch()
 {
-	NetJob *netJob = new NetJob("FtbModpackFetch");
+    NetJob *netJob = new NetJob("FtbModpackFetch");
 
-	QUrl publicPacksUrl = QUrl("https://ftb.cursecdn.com/FTB2/static/modpacks.xml");
-	qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
-	netJob->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData));
+    QUrl publicPacksUrl = QUrl("https://ftb.cursecdn.com/FTB2/static/modpacks.xml");
+    qDebug() << "Downloading public version info from" << publicPacksUrl.toString();
+    netJob->addNetAction(Net::Download::makeByteArray(publicPacksUrl, &publicModpacksXmlFileData));
 
-	QUrl thirdPartyUrl = QUrl("https://ftb.cursecdn.com/FTB2/static/thirdparty.xml");
-	qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
-	netJob->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData));
+    QUrl thirdPartyUrl = QUrl("https://ftb.cursecdn.com/FTB2/static/thirdparty.xml");
+    qDebug() << "Downloading thirdparty version info from" << thirdPartyUrl.toString();
+    netJob->addNetAction(Net::Download::makeByteArray(thirdPartyUrl, &thirdPartyModpacksXmlFileData));
 
-	QObject::connect(netJob, &NetJob::succeeded, this, &FtbPackFetchTask::fileDownloadFinished);
-	QObject::connect(netJob, &NetJob::failed, this, &FtbPackFetchTask::fileDownloadFailed);
+    QObject::connect(netJob, &NetJob::succeeded, this, &FtbPackFetchTask::fileDownloadFinished);
+    QObject::connect(netJob, &NetJob::failed, this, &FtbPackFetchTask::fileDownloadFailed);
 
-	jobPtr.reset(netJob);
-	netJob->start();
+    jobPtr.reset(netJob);
+    netJob->start();
 }
 
 void FtbPackFetchTask::fileDownloadFinished()
 {
-	jobPtr.reset();
+    jobPtr.reset();
 
-	QStringList failedLists;
+    QStringList failedLists;
 
-	if(!parseAndAddPacks(publicModpacksXmlFileData, FtbPackType::Public, publicPacks)) {
-		failedLists.append(tr("Public Packs"));
-	}
+    if(!parseAndAddPacks(publicModpacksXmlFileData, FtbPackType::Public, publicPacks)) {
+        failedLists.append(tr("Public Packs"));
+    }
 
-	if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, FtbPackType::ThirdParty, thirdPartyPacks)) {
-		failedLists.append(tr("Third Party Packs"));
-	}
+    if(!parseAndAddPacks(thirdPartyModpacksXmlFileData, FtbPackType::ThirdParty, thirdPartyPacks)) {
+        failedLists.append(tr("Third Party Packs"));
+    }
 
-	if(failedLists.size() > 0) {
-		emit failed(QString("Failed to download some pack lists:%1").arg(failedLists.join("\n- ")));
-	} else {
-		emit finished(publicPacks, thirdPartyPacks);
-	}
+    if(failedLists.size() > 0) {
+        emit failed(QString("Failed to download some pack lists:%1").arg(failedLists.join("\n- ")));
+    } else {
+        emit finished(publicPacks, thirdPartyPacks);
+    }
 }
 
 bool FtbPackFetchTask::parseAndAddPacks(QByteArray &data, FtbPackType packType, FtbModpackList &list)
 {
-	QDomDocument doc;
-
-	QString errorMsg = "Unknown error.";
-	int errorLine = -1;
-	int errorCol = -1;
-
-	if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)){
-		auto fullErrMsg = QString("Failed to fetch modpack data: %s %d:%d!").arg(errorMsg, errorLine, errorCol);
-		qWarning() << fullErrMsg;
-		data.clear();
-		return false;
-	}
-
-	QDomNodeList nodes = doc.elementsByTagName("modpack");
-	for(int i = 0; i < nodes.length(); i++) {
-		QDomElement element = nodes.at(i).toElement();
-
-		FtbModpack modpack;
-		modpack.name = element.attribute("name");
-		modpack.currentVersion = element.attribute("version");
-		modpack.mcVersion = element.attribute("mcVersion");
-		modpack.description = element.attribute("description");
-		modpack.mods = element.attribute("mods");
-		modpack.logo = element.attribute("logo");
-		modpack.oldVersions = element.attribute("oldVersions").split(";");
-		modpack.broken = false;
-		modpack.bugged = false;
-
-		//remove empty if the xml is bugged
-		for(QString curr : modpack.oldVersions) {
-			if(curr.isNull() || curr.isEmpty()) {
-				modpack.oldVersions.removeAll(curr);
-				modpack.bugged = true;
-				qWarning() << "Removed some empty versions from" << modpack.name;
-			}
-		}
-
-		if(modpack.oldVersions.size() < 1) {
-			if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) {
-				modpack.oldVersions.append(modpack.currentVersion);
-				qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")";
-			} else {
-				modpack.broken = true;
-				qWarning() << "Broken pack:" << modpack.name << " => No valid version!";
-			}
-		}
-
-		modpack.author = element.attribute("author");
-
-		modpack.dir = element.attribute("dir");
-		modpack.file = element.attribute("url");
-
-		modpack.type = packType;
-
-		list.append(modpack);
-	}
-
-	return true;
+    QDomDocument doc;
+
+    QString errorMsg = "Unknown error.";
+    int errorLine = -1;
+    int errorCol = -1;
+
+    if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol)){
+        auto fullErrMsg = QString("Failed to fetch modpack data: %s %d:%d!").arg(errorMsg, errorLine, errorCol);
+        qWarning() << fullErrMsg;
+        data.clear();
+        return false;
+    }
+
+    QDomNodeList nodes = doc.elementsByTagName("modpack");
+    for(int i = 0; i < nodes.length(); i++) {
+        QDomElement element = nodes.at(i).toElement();
+
+        FtbModpack modpack;
+        modpack.name = element.attribute("name");
+        modpack.currentVersion = element.attribute("version");
+        modpack.mcVersion = element.attribute("mcVersion");
+        modpack.description = element.attribute("description");
+        modpack.mods = element.attribute("mods");
+        modpack.logo = element.attribute("logo");
+        modpack.oldVersions = element.attribute("oldVersions").split(";");
+        modpack.broken = false;
+        modpack.bugged = false;
+
+        //remove empty if the xml is bugged
+        for(QString curr : modpack.oldVersions) {
+            if(curr.isNull() || curr.isEmpty()) {
+                modpack.oldVersions.removeAll(curr);
+                modpack.bugged = true;
+                qWarning() << "Removed some empty versions from" << modpack.name;
+            }
+        }
+
+        if(modpack.oldVersions.size() < 1) {
+            if(!modpack.currentVersion.isNull() && !modpack.currentVersion.isEmpty()) {
+                modpack.oldVersions.append(modpack.currentVersion);
+                qWarning() << "Added current version to oldVersions because oldVersions was empty! (" + modpack.name + ")";
+            } else {
+                modpack.broken = true;
+                qWarning() << "Broken pack:" << modpack.name << " => No valid version!";
+            }
+        }
+
+        modpack.author = element.attribute("author");
+
+        modpack.dir = element.attribute("dir");
+        modpack.file = element.attribute("url");
+
+        modpack.type = packType;
+
+        list.append(modpack);
+    }
+
+    return true;
 }
 
 void FtbPackFetchTask::fileDownloadFailed(QString reason){
-	qWarning() << "Fetching FtbPacks failed: " << reason;
-	emit failed(reason);
+    qWarning() << "Fetching FtbPacks failed: " << reason;
+    emit failed(reason);
 }
diff --git a/api/logic/modplatform/ftb/FtbPackFetchTask.h b/api/logic/modplatform/ftb/FtbPackFetchTask.h
index b5635b12..c919a6e1 100644
--- a/api/logic/modplatform/ftb/FtbPackFetchTask.h
+++ b/api/logic/modplatform/ftb/FtbPackFetchTask.h
@@ -8,30 +8,30 @@
 
 class MULTIMC_LOGIC_EXPORT FtbPackFetchTask : public QObject {
 
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	FtbPackFetchTask();
-	virtual ~FtbPackFetchTask();
+    FtbPackFetchTask();
+    virtual ~FtbPackFetchTask();
 
-	void fetch();
+    void fetch();
 
 private:
-	NetJobPtr jobPtr;
+    NetJobPtr jobPtr;
 
-	QByteArray publicModpacksXmlFileData;
-	QByteArray thirdPartyModpacksXmlFileData;
+    QByteArray publicModpacksXmlFileData;
+    QByteArray thirdPartyModpacksXmlFileData;
 
-	bool parseAndAddPacks(QByteArray &data, FtbPackType packType, FtbModpackList &list);
-	FtbModpackList publicPacks;
-	FtbModpackList thirdPartyPacks;
+    bool parseAndAddPacks(QByteArray &data, FtbPackType packType, FtbModpackList &list);
+    FtbModpackList publicPacks;
+    FtbModpackList thirdPartyPacks;
 
 protected slots:
-	void fileDownloadFinished();
-	void fileDownloadFailed(QString reason);
+    void fileDownloadFinished();
+    void fileDownloadFailed(QString reason);
 
 signals:
-	void finished(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks);
-	void failed(QString reason);
+    void finished(FtbModpackList publicPacks, FtbModpackList thirdPartyPacks);
+    void failed(QString reason);
 
 };
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
index 7815ef46..cf0abea5 100644
--- a/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
+++ b/api/logic/modplatform/ftb/FtbPackInstallTask.cpp
@@ -11,188 +11,188 @@
 
 FtbPackInstallTask::FtbPackInstallTask(FtbModpack pack, QString version)
 {
-	m_pack = pack;
-	m_version = version;
+    m_pack = pack;
+    m_version = version;
 }
 
 void FtbPackInstallTask::executeTask()
 {
-	downloadPack();
+    downloadPack();
 }
 
 void FtbPackInstallTask::downloadPack()
 {
-	setStatus(tr("Downloading zip for %1").arg(m_pack.name));
+    setStatus(tr("Downloading zip for %1").arg(m_pack.name));
 
-	auto packoffset = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file);
-	auto entry = ENV.metacache()->resolveEntry("FTBPacks", packoffset);
-	NetJob *job = new NetJob("Download FTB Pack");
+    auto packoffset = QString("%1/%2/%3").arg(m_pack.dir, m_version.replace(".", "_"), m_pack.file);
+    auto entry = ENV.metacache()->resolveEntry("FTBPacks", packoffset);
+    NetJob *job = new NetJob("Download FTB Pack");
 
-	entry->setStale(true);
-	QString url = QString("http://ftb.cursecdn.com/FTB2/modpacks/%1").arg(packoffset);
-	job->addNetAction(Net::Download::makeCached(url, entry));
-	archivePath = entry->getFullPath();
+    entry->setStale(true);
+    QString url = QString("http://ftb.cursecdn.com/FTB2/modpacks/%1").arg(packoffset);
+    job->addNetAction(Net::Download::makeCached(url, entry));
+    archivePath = entry->getFullPath();
 
-	netJobContainer.reset(job);
-	connect(job, &NetJob::succeeded, this, &FtbPackInstallTask::onDownloadSucceeded);
-	connect(job, &NetJob::failed, this, &FtbPackInstallTask::onDownloadFailed);
-	connect(job, &NetJob::progress, this, &FtbPackInstallTask::onDownloadProgress);
-	job->start();
+    netJobContainer.reset(job);
+    connect(job, &NetJob::succeeded, this, &FtbPackInstallTask::onDownloadSucceeded);
+    connect(job, &NetJob::failed, this, &FtbPackInstallTask::onDownloadFailed);
+    connect(job, &NetJob::progress, this, &FtbPackInstallTask::onDownloadProgress);
+    job->start();
 
-	progress(1, 4);
+    progress(1, 4);
 }
 
 void FtbPackInstallTask::onDownloadSucceeded()
 {
-	abortable = false;
-	unzip();
+    abortable = false;
+    unzip();
 }
 
 void FtbPackInstallTask::onDownloadFailed(QString reason)
 {
-	emitFailed(reason);
+    emitFailed(reason);
 }
 
 void FtbPackInstallTask::onDownloadProgress(qint64 current, qint64 total)
 {
-	abortable = true;
-	progress(current, total * 4);
-	setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10));
+    abortable = true;
+    progress(current, total * 4);
+    setStatus(tr("Downloading zip for %1 (%2%)").arg(m_pack.name).arg(current / 10));
 }
 
 void FtbPackInstallTask::unzip()
 {
-	progress(2, 4);
-	setStatus(tr("Extracting modpack"));
-	QDir extractDir(m_stagingPath);
-
-	m_packZip.reset(new QuaZip(archivePath));
-	if(!m_packZip->open(QuaZip::mdUnzip))
-	{
-		emitFailed(tr("Failed to open modpack file %1!").arg(archivePath));
-		return;
-	}
-
-	m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip");
-	connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &FtbPackInstallTask::onUnzipFinished);
-	connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &FtbPackInstallTask::onUnzipCanceled);
-	m_extractFutureWatcher.setFuture(m_extractFuture);
+    progress(2, 4);
+    setStatus(tr("Extracting modpack"));
+    QDir extractDir(m_stagingPath);
+
+    m_packZip.reset(new QuaZip(archivePath));
+    if(!m_packZip->open(QuaZip::mdUnzip))
+    {
+        emitFailed(tr("Failed to open modpack file %1!").arg(archivePath));
+        return;
+    }
+
+    m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip");
+    connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &FtbPackInstallTask::onUnzipFinished);
+    connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &FtbPackInstallTask::onUnzipCanceled);
+    m_extractFutureWatcher.setFuture(m_extractFuture);
 }
 
 void FtbPackInstallTask::onUnzipFinished()
 {
-	install();
+    install();
 }
 
 void FtbPackInstallTask::onUnzipCanceled()
 {
-	emitAborted();
+    emitAborted();
 }
 
 void FtbPackInstallTask::install()
 {
-	progress(3, 4);
-	setStatus(tr("Installing modpack"));
-	QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
-	if(unzipMcDir.exists())
-	{
-		//ok, found minecraft dir, move contents to instance dir
-		if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"))
-		{
-			emitFailed(tr("Failed to move unzipped minecraft!"));
-			return;
-		}
-	}
-
-	QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
-	auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
-	instanceSettings->registerSetting("InstanceType", "Legacy");
-	instanceSettings->set("InstanceType", "OneSix");
-
-	MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
-	auto components = instance.getComponentList();
-	components->buildingFromScratch();
-	components->setComponentVersion("net.minecraft", m_pack.mcVersion, true);
-
-	bool fallback = true;
-
-	//handle different versions
-	QFile packJson(m_stagingPath + "/.minecraft/pack.json");
-	QDir jarmodDir = QDir(m_stagingPath + "/unzip/instMods");
-	if(packJson.exists())
-	{
-		packJson.open(QIODevice::ReadOnly | QIODevice::Text);
-		QJsonDocument doc = QJsonDocument::fromJson(packJson.readAll());
-		packJson.close();
-
-		//we only care about the libs
-		QJsonArray libs = doc.object().value("libraries").toArray();
-
-		foreach (const QJsonValue &value, libs)
-		{
-			QString nameValue = value.toObject().value("name").toString();
-			if(!nameValue.startsWith("net.minecraftforge"))
-			{
-				continue;
-			}
-
-			GradleSpecifier forgeVersion(nameValue);
-
-			components->setComponentVersion("net.minecraftforge", forgeVersion.version().replace(m_pack.mcVersion, "").replace("-", ""));
-			packJson.remove();
-			fallback = false;
-			break;
-		}
-
-	}
-
-	if(jarmodDir.exists())
-	{
-		qDebug() << "Found jarmods, installing...";
-
-		QStringList jarmods;
-		for (auto info: jarmodDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
-		{
-			qDebug() << "Jarmod:" << info.fileName();
-			jarmods.push_back(info.absoluteFilePath());
-		}
-
-		components->installJarMods(jarmods);
-		fallback = false;
-	}
-
-	//just nuke unzip directory, it s not needed anymore
-	FS::deletePath(m_stagingPath + "/unzip");
-
-	if(fallback)
-	{
-		//TODO: Some fallback mechanism... or just keep failing!
-		emitFailed(tr("No installation method found!"));
-		return;
-	}
-
-	components->saveNow();
-
-	progress(4, 4);
-
-	instance.init();
-	instance.setName(m_instName);
-	if(m_instIcon == "default")
-	{
-		m_instIcon = "ftb_logo";
-	}
-	instance.setIconKey(m_instIcon);
-	instance.setGroupInitial(m_instGroup);
-	instanceSettings->resumeSave();
-
-	emitSucceeded();
+    progress(3, 4);
+    setStatus(tr("Installing modpack"));
+    QDir unzipMcDir(m_stagingPath + "/unzip/minecraft");
+    if(unzipMcDir.exists())
+    {
+        //ok, found minecraft dir, move contents to instance dir
+        if(!QDir().rename(m_stagingPath + "/unzip/minecraft", m_stagingPath + "/.minecraft"))
+        {
+            emitFailed(tr("Failed to move unzipped minecraft!"));
+            return;
+        }
+    }
+
+    QString instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
+    auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
+    instanceSettings->registerSetting("InstanceType", "Legacy");
+    instanceSettings->set("InstanceType", "OneSix");
+
+    MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
+    auto components = instance.getComponentList();
+    components->buildingFromScratch();
+    components->setComponentVersion("net.minecraft", m_pack.mcVersion, true);
+
+    bool fallback = true;
+
+    //handle different versions
+    QFile packJson(m_stagingPath + "/.minecraft/pack.json");
+    QDir jarmodDir = QDir(m_stagingPath + "/unzip/instMods");
+    if(packJson.exists())
+    {
+        packJson.open(QIODevice::ReadOnly | QIODevice::Text);
+        QJsonDocument doc = QJsonDocument::fromJson(packJson.readAll());
+        packJson.close();
+
+        //we only care about the libs
+        QJsonArray libs = doc.object().value("libraries").toArray();
+
+        foreach (const QJsonValue &value, libs)
+        {
+            QString nameValue = value.toObject().value("name").toString();
+            if(!nameValue.startsWith("net.minecraftforge"))
+            {
+                continue;
+            }
+
+            GradleSpecifier forgeVersion(nameValue);
+
+            components->setComponentVersion("net.minecraftforge", forgeVersion.version().replace(m_pack.mcVersion, "").replace("-", ""));
+            packJson.remove();
+            fallback = false;
+            break;
+        }
+
+    }
+
+    if(jarmodDir.exists())
+    {
+        qDebug() << "Found jarmods, installing...";
+
+        QStringList jarmods;
+        for (auto info: jarmodDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files))
+        {
+            qDebug() << "Jarmod:" << info.fileName();
+            jarmods.push_back(info.absoluteFilePath());
+        }
+
+        components->installJarMods(jarmods);
+        fallback = false;
+    }
+
+    //just nuke unzip directory, it s not needed anymore
+    FS::deletePath(m_stagingPath + "/unzip");
+
+    if(fallback)
+    {
+        //TODO: Some fallback mechanism... or just keep failing!
+        emitFailed(tr("No installation method found!"));
+        return;
+    }
+
+    components->saveNow();
+
+    progress(4, 4);
+
+    instance.init();
+    instance.setName(m_instName);
+    if(m_instIcon == "default")
+    {
+        m_instIcon = "ftb_logo";
+    }
+    instance.setIconKey(m_instIcon);
+    instance.setGroupInitial(m_instGroup);
+    instanceSettings->resumeSave();
+
+    emitSucceeded();
 }
 
 bool FtbPackInstallTask::abort()
 {
-	if(abortable)
-	{
-		return netJobContainer->abort();
-	}
-	return false;
+    if(abortable)
+    {
+        return netJobContainer->abort();
+    }
+    return false;
 }
diff --git a/api/logic/modplatform/ftb/FtbPackInstallTask.h b/api/logic/modplatform/ftb/FtbPackInstallTask.h
index 0bfba3d6..8705ef89 100644
--- a/api/logic/modplatform/ftb/FtbPackInstallTask.h
+++ b/api/logic/modplatform/ftb/FtbPackInstallTask.h
@@ -11,39 +11,39 @@
 
 class MULTIMC_LOGIC_EXPORT FtbPackInstallTask : public InstanceTask {
 
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	explicit FtbPackInstallTask(FtbModpack pack, QString version);
-	virtual ~FtbPackInstallTask(){}
+    explicit FtbPackInstallTask(FtbModpack pack, QString version);
+    virtual ~FtbPackInstallTask(){}
 
-	bool abort() override;
+    bool abort() override;
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
+    //! Entry point for tasks.
+    virtual void executeTask() override;
 
 private:
-	void downloadPack();
-	void unzip();
-	void install();
+    void downloadPack();
+    void unzip();
+    void install();
 
 private slots:
-	void onDownloadSucceeded();
-	void onDownloadFailed(QString reason);
-	void onDownloadProgress(qint64 current, qint64 total);
+    void onDownloadSucceeded();
+    void onDownloadFailed(QString reason);
+    void onDownloadProgress(qint64 current, qint64 total);
 
-	void onUnzipFinished();
-	void onUnzipCanceled();
+    void onUnzipFinished();
+    void onUnzipCanceled();
 
 private: /* data */
-	bool abortable = false;
-	std::unique_ptr<QuaZip> m_packZip;
-	QFuture<QStringList> m_extractFuture;
-	QFutureWatcher<QStringList> m_extractFutureWatcher;
-	NetJobPtr netJobContainer;
-	QString archivePath;
-
-	FtbModpack m_pack;
-	QString m_version;
+    bool abortable = false;
+    std::unique_ptr<QuaZip> m_packZip;
+    QFuture<QStringList> m_extractFuture;
+    QFutureWatcher<QStringList> m_extractFutureWatcher;
+    NetJobPtr netJobContainer;
+    QString archivePath;
+
+    FtbModpack m_pack;
+    QString m_version;
 };
diff --git a/api/logic/modplatform/ftb/PackHelpers.h b/api/logic/modplatform/ftb/PackHelpers.h
index 39b65927..0b36f10b 100644
--- a/api/logic/modplatform/ftb/PackHelpers.h
+++ b/api/logic/modplatform/ftb/PackHelpers.h
@@ -7,29 +7,29 @@
 
 //Header for structs etc...
 enum FtbPackType {
-	Public,
-	ThirdParty,
-	Private
+    Public,
+    ThirdParty,
+    Private
 };
 
 struct FtbModpack {
-	QString name;
-	QString description;
-	QString author;
-	QStringList oldVersions;
-	QString currentVersion;
-	QString mcVersion;
-	QString mods;
-	QString logo;
-
-	//Technical data
-	QString dir;
-	QString file; //<- Url in the xml, but doesn't make much sense
-
-	bool bugged = false;
-	bool broken = false;
-
-	FtbPackType type;
+    QString name;
+    QString description;
+    QString author;
+    QStringList oldVersions;
+    QString currentVersion;
+    QString mcVersion;
+    QString mods;
+    QString logo;
+
+    //Technical data
+    QString dir;
+    QString file; //<- Url in the xml, but doesn't make much sense
+
+    bool bugged = false;
+    bool broken = false;
+
+    FtbPackType type;
 };
 
 //We need it for the proxy model
diff --git a/api/logic/net/ByteArraySink.h b/api/logic/net/ByteArraySink.h
index 03b77fcc..20e6764c 100644
--- a/api/logic/net/ByteArraySink.h
+++ b/api/logic/net/ByteArraySink.h
@@ -9,54 +9,54 @@ namespace Net {
 class ByteArraySink : public Sink
 {
 public:
-	ByteArraySink(QByteArray *output)
-		:m_output(output)
-	{
-		// nil
-	};
+    ByteArraySink(QByteArray *output)
+        :m_output(output)
+    {
+        // nil
+    };
 
-	virtual ~ByteArraySink()
-	{
-		// nil
-	}
+    virtual ~ByteArraySink()
+    {
+        // nil
+    }
 
 public:
-	JobStatus init(QNetworkRequest & request) override
-	{
-		m_output->clear();
-		if(initAllValidators(request))
-			return Job_InProgress;
-		return Job_Failed;
-	};
-
-	JobStatus write(QByteArray & data) override
-	{
-		m_output->append(data);
-		if(writeAllValidators(data))
-			return Job_InProgress;
-		return Job_Failed;
-	}
-
-	JobStatus abort() override
-	{
-		m_output->clear();
-		failAllValidators();
-		return Job_Failed;
-	}
-
-	JobStatus finalize(QNetworkReply &reply) override
-	{
-		if(finalizeAllValidators(reply))
-			return Job_Finished;
-		return Job_Failed;
-	}
-
-	bool hasLocalData() override
-	{
-		return false;
-	}
+    JobStatus init(QNetworkRequest & request) override
+    {
+        m_output->clear();
+        if(initAllValidators(request))
+            return Job_InProgress;
+        return Job_Failed;
+    };
+
+    JobStatus write(QByteArray & data) override
+    {
+        m_output->append(data);
+        if(writeAllValidators(data))
+            return Job_InProgress;
+        return Job_Failed;
+    }
+
+    JobStatus abort() override
+    {
+        m_output->clear();
+        failAllValidators();
+        return Job_Failed;
+    }
+
+    JobStatus finalize(QNetworkReply &reply) override
+    {
+        if(finalizeAllValidators(reply))
+            return Job_Finished;
+        return Job_Failed;
+    }
+
+    bool hasLocalData() override
+    {
+        return false;
+    }
 
 private:
-	QByteArray * m_output;
+    QByteArray * m_output;
 };
 }
diff --git a/api/logic/net/ChecksumValidator.h b/api/logic/net/ChecksumValidator.h
index 187e4b30..0d6b19c2 100644
--- a/api/logic/net/ChecksumValidator.h
+++ b/api/logic/net/ChecksumValidator.h
@@ -9,47 +9,47 @@ namespace Net {
 class ChecksumValidator: public Validator
 {
 public: /* con/des */
-	ChecksumValidator(QCryptographicHash::Algorithm algorithm, QByteArray expected = QByteArray())
-		:m_checksum(algorithm), m_expected(expected)
-	{
-	};
-	virtual ~ChecksumValidator() {};
+    ChecksumValidator(QCryptographicHash::Algorithm algorithm, QByteArray expected = QByteArray())
+        :m_checksum(algorithm), m_expected(expected)
+    {
+    };
+    virtual ~ChecksumValidator() {};
 
 public: /* methods */
-	bool init(QNetworkRequest &) override
-	{
-		m_checksum.reset();
-		return true;
-	}
-	bool write(QByteArray & data) override
-	{
-		m_checksum.addData(data);
-		return true;
-	}
-	bool abort() override
-	{
-		return true;
-	}
-	bool validate(QNetworkReply &) override
-	{
-		if(m_expected.size() && m_expected != hash())
-		{
-			qWarning() << "Checksum mismatch, download is bad.";
-			return false;
-		}
-		return true;
-	}
-	QByteArray hash()
-	{
-		return m_checksum.result();
-	}
-	void setExpected(QByteArray expected)
-	{
-		m_expected = expected;
-	}
+    bool init(QNetworkRequest &) override
+    {
+        m_checksum.reset();
+        return true;
+    }
+    bool write(QByteArray & data) override
+    {
+        m_checksum.addData(data);
+        return true;
+    }
+    bool abort() override
+    {
+        return true;
+    }
+    bool validate(QNetworkReply &) override
+    {
+        if(m_expected.size() && m_expected != hash())
+        {
+            qWarning() << "Checksum mismatch, download is bad.";
+            return false;
+        }
+        return true;
+    }
+    QByteArray hash()
+    {
+        return m_checksum.result();
+    }
+    void setExpected(QByteArray expected)
+    {
+        m_expected = expected;
+    }
 
 private: /* data */
-	QCryptographicHash m_checksum;
-	QByteArray m_expected;
+    QCryptographicHash m_checksum;
+    QByteArray m_expected;
 };
 }
\ No newline at end of file
diff --git a/api/logic/net/Download.cpp b/api/logic/net/Download.cpp
index 631d3076..fc634e3d 100644
--- a/api/logic/net/Download.cpp
+++ b/api/logic/net/Download.cpp
@@ -28,271 +28,271 @@ namespace Net {
 
 Download::Download():NetAction()
 {
-	m_status = Job_NotStarted;
+    m_status = Job_NotStarted;
 }
 
 Download::Ptr Download::makeCached(QUrl url, MetaEntryPtr entry, Options options)
 {
-	Download * dl = new Download();
-	dl->m_url = url;
-	dl->m_options = options;
-	auto md5Node = new ChecksumValidator(QCryptographicHash::Md5);
-	auto cachedNode = new MetaCacheSink(entry, md5Node);
-	dl->m_sink.reset(cachedNode);
-	dl->m_target_path = entry->getFullPath();
-	return std::shared_ptr<Download>(dl);
+    Download * dl = new Download();
+    dl->m_url = url;
+    dl->m_options = options;
+    auto md5Node = new ChecksumValidator(QCryptographicHash::Md5);
+    auto cachedNode = new MetaCacheSink(entry, md5Node);
+    dl->m_sink.reset(cachedNode);
+    dl->m_target_path = entry->getFullPath();
+    return std::shared_ptr<Download>(dl);
 }
 
 Download::Ptr Download::makeByteArray(QUrl url, QByteArray *output, Options options)
 {
-	Download * dl = new Download();
-	dl->m_url = url;
-	dl->m_options = options;
-	dl->m_sink.reset(new ByteArraySink(output));
-	return std::shared_ptr<Download>(dl);
+    Download * dl = new Download();
+    dl->m_url = url;
+    dl->m_options = options;
+    dl->m_sink.reset(new ByteArraySink(output));
+    return std::shared_ptr<Download>(dl);
 }
 
 Download::Ptr Download::makeFile(QUrl url, QString path, Options options)
 {
-	Download * dl = new Download();
-	dl->m_url = url;
-	dl->m_options = options;
-	dl->m_sink.reset(new FileSink(path));
-	return std::shared_ptr<Download>(dl);
+    Download * dl = new Download();
+    dl->m_url = url;
+    dl->m_options = options;
+    dl->m_sink.reset(new FileSink(path));
+    return std::shared_ptr<Download>(dl);
 }
 
 void Download::addValidator(Validator * v)
 {
-	m_sink->addValidator(v);
+    m_sink->addValidator(v);
 }
 
 void Download::start()
 {
-	if(m_status == Job_Aborted)
-	{
-		qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
-		emit aborted(m_index_within_job);
-		return;
-	}
-	QNetworkRequest request(m_url);
-	m_status = m_sink->init(request);
-	switch(m_status)
-	{
-		case Job_Finished:
-			emit succeeded(m_index_within_job);
-			qDebug() << "Download cache hit " << m_url.toString();
-			return;
-		case Job_InProgress:
-			qDebug() << "Downloading " << m_url.toString();
-			break;
-		case Job_Failed_Proceed: // this is meaningless in this context. We do need a sink.
-		case Job_NotStarted:
-		case Job_Failed:
-			emit failed(m_index_within_job);
-			return;
-		case Job_Aborted:
-			return;
-	}
+    if(m_status == Job_Aborted)
+    {
+        qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
+        emit aborted(m_index_within_job);
+        return;
+    }
+    QNetworkRequest request(m_url);
+    m_status = m_sink->init(request);
+    switch(m_status)
+    {
+        case Job_Finished:
+            emit succeeded(m_index_within_job);
+            qDebug() << "Download cache hit " << m_url.toString();
+            return;
+        case Job_InProgress:
+            qDebug() << "Downloading " << m_url.toString();
+            break;
+        case Job_Failed_Proceed: // this is meaningless in this context. We do need a sink.
+        case Job_NotStarted:
+        case Job_Failed:
+            emit failed(m_index_within_job);
+            return;
+        case Job_Aborted:
+            return;
+    }
 
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0");
+    request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0");
 
-	QNetworkReply *rep =  ENV.qnam().get(request);
+    QNetworkReply *rep =  ENV.qnam().get(request);
 
-	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, &QNetworkReply::sslErrors, this, &Download::sslErrors);
-	connect(rep, &QNetworkReply::readyRead, this, &Download::downloadReadyRead);
+    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, &QNetworkReply::sslErrors, this, &Download::sslErrors);
+    connect(rep, &QNetworkReply::readyRead, this, &Download::downloadReadyRead);
 }
 
 void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	m_total_progress = bytesTotal;
-	m_progress = bytesReceived;
-	emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
+    m_total_progress = bytesTotal;
+    m_progress = bytesReceived;
+    emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
 }
 
 void Download::downloadError(QNetworkReply::NetworkError error)
 {
-	if(error == QNetworkReply::OperationCanceledError)
-	{
-		qCritical() << "Aborted " << m_url.toString();
-		m_status = Job_Aborted;
-	}
-	else
-	{
-		if(m_options & Option::AcceptLocalFiles)
-		{
-			if(m_sink->hasLocalData())
-			{
-				m_status = Job_Failed_Proceed;
-				return;
-			}
-		}
-		// error happened during download.
-		qCritical() << "Failed " << m_url.toString() << " with reason " << error;
-		m_status = Job_Failed;
-	}
+    if(error == QNetworkReply::OperationCanceledError)
+    {
+        qCritical() << "Aborted " << m_url.toString();
+        m_status = Job_Aborted;
+    }
+    else
+    {
+        if(m_options & Option::AcceptLocalFiles)
+        {
+            if(m_sink->hasLocalData())
+            {
+                m_status = Job_Failed_Proceed;
+                return;
+            }
+        }
+        // error happened during download.
+        qCritical() << "Failed " << m_url.toString() << " with reason " << error;
+        m_status = Job_Failed;
+    }
 }
 
 void Download::sslErrors(const QList<QSslError> & errors)
 {
-	int i = 1;
-	for (auto error : errors)
-	{
-		qCritical() << "Download" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString();
-		auto cert = error.certificate();
-		qCritical() << "Certificate in question:\n" << cert.toText();
-		i++;
-	}
+    int i = 1;
+    for (auto error : errors)
+    {
+        qCritical() << "Download" << m_url.toString() << "SSL Error #" << i << " : " << error.errorString();
+        auto cert = error.certificate();
+        qCritical() << "Certificate in question:\n" << cert.toText();
+        i++;
+    }
 }
 
 bool Download::handleRedirect()
 {
-	QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl();
-	if(!redirect.isValid())
-	{
-		if(!m_reply->hasRawHeader("Location"))
-		{
-			// no redirect -> it's fine to continue
-			return false;
-		}
-		// there is a Location header, but it's not correct. we need to apply some workarounds...
-		QByteArray redirectBA = m_reply->rawHeader("Location");
-		if(redirectBA.size() == 0)
-		{
-			// empty, yet present redirect header? WTF?
-			return false;
-		}
-		QString redirectStr = QString::fromUtf8(redirectBA);
+    QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl();
+    if(!redirect.isValid())
+    {
+        if(!m_reply->hasRawHeader("Location"))
+        {
+            // no redirect -> it's fine to continue
+            return false;
+        }
+        // there is a Location header, but it's not correct. we need to apply some workarounds...
+        QByteArray redirectBA = m_reply->rawHeader("Location");
+        if(redirectBA.size() == 0)
+        {
+            // empty, yet present redirect header? WTF?
+            return false;
+        }
+        QString redirectStr = QString::fromUtf8(redirectBA);
 
-		/*
-		 * IF the URL begins with //, we need to insert the URL scheme.
-		 * See: https://bugreports.qt-project.org/browse/QTBUG-41061
-		 */
-		if(redirectStr.startsWith("//"))
-		{
-			redirectStr = m_reply->url().scheme() + ":" + redirectStr;
-		}
+        /*
+         * IF the URL begins with //, we need to insert the URL scheme.
+         * See: https://bugreports.qt-project.org/browse/QTBUG-41061
+         */
+        if(redirectStr.startsWith("//"))
+        {
+            redirectStr = m_reply->url().scheme() + ":" + redirectStr;
+        }
 
-		/*
-		 * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues.
-		 * FIXME: report Qt bug for this
-		 */
-		redirect = QUrl(redirectStr, QUrl::TolerantMode);
-		if(!redirect.isValid())
-		{
-			qWarning() << "Failed to parse redirect URL:" << redirectStr;
-			downloadError(QNetworkReply::ProtocolFailure);
-			return false;
-		}
-		qDebug() << "Fixed location header:" << redirect;
-	}
-	else
-	{
-		qDebug() << "Location header:" << redirect;
-	}
+        /*
+         * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues.
+         * FIXME: report Qt bug for this
+         */
+        redirect = QUrl(redirectStr, QUrl::TolerantMode);
+        if(!redirect.isValid())
+        {
+            qWarning() << "Failed to parse redirect URL:" << redirectStr;
+            downloadError(QNetworkReply::ProtocolFailure);
+            return false;
+        }
+        qDebug() << "Fixed location header:" << redirect;
+    }
+    else
+    {
+        qDebug() << "Location header:" << redirect;
+    }
 
-	m_url = QUrl(redirect.toString());
-	qDebug() << "Following redirect to " << m_url.toString();
-	start();
-	return true;
+    m_url = QUrl(redirect.toString());
+    qDebug() << "Following redirect to " << m_url.toString();
+    start();
+    return true;
 }
 
 
 void Download::downloadFinished()
 {
-	// handle HTTP redirection first
-	if(handleRedirect())
-	{
-		qDebug() << "Download redirected:" << m_url.toString();
-		return;
-	}
+    // handle HTTP redirection first
+    if(handleRedirect())
+    {
+        qDebug() << "Download redirected:" << m_url.toString();
+        return;
+    }
 
-	// if the download failed before this point ...
-	if (m_status == Job_Failed_Proceed)
-	{
-		qDebug() << "Download failed but we are allowed to proceed:" << m_url.toString();
-		m_sink->abort();
-		m_reply.reset();
-		emit succeeded(m_index_within_job);
-		return;
-	}
-	else if (m_status == Job_Failed)
-	{
-		qDebug() << "Download failed in previous step:" << m_url.toString();
-		m_sink->abort();
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		return;
-	}
-	else if(m_status == Job_Aborted)
-	{
-		qDebug() << "Download aborted in previous step:" << m_url.toString();
-		m_sink->abort();
-		m_reply.reset();
-		emit aborted(m_index_within_job);
-		return;
-	}
+    // if the download failed before this point ...
+    if (m_status == Job_Failed_Proceed)
+    {
+        qDebug() << "Download failed but we are allowed to proceed:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit succeeded(m_index_within_job);
+        return;
+    }
+    else if (m_status == Job_Failed)
+    {
+        qDebug() << "Download failed in previous step:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        return;
+    }
+    else if(m_status == Job_Aborted)
+    {
+        qDebug() << "Download aborted in previous step:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit aborted(m_index_within_job);
+        return;
+    }
 
-	// make sure we got all the remaining data, if any
-	auto data = m_reply->readAll();
-	if(data.size())
-	{
-		qDebug() << "Writing extra" << data.size() << "bytes to" << m_target_path;
-		m_status = m_sink->write(data);
-	}
+    // make sure we got all the remaining data, if any
+    auto data = m_reply->readAll();
+    if(data.size())
+    {
+        qDebug() << "Writing extra" << data.size() << "bytes to" << m_target_path;
+        m_status = m_sink->write(data);
+    }
 
-	// otherwise, finalize the whole graph
-	m_status = m_sink->finalize(*m_reply.get());
-	if (m_status != Job_Finished)
-	{
-		qDebug() << "Download failed to finalize:" << m_url.toString();
-		m_sink->abort();
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		return;
-	}
-	m_reply.reset();
-	qDebug() << "Download succeeded:" << m_url.toString();
-	emit succeeded(m_index_within_job);
+    // otherwise, finalize the whole graph
+    m_status = m_sink->finalize(*m_reply.get());
+    if (m_status != Job_Finished)
+    {
+        qDebug() << "Download failed to finalize:" << m_url.toString();
+        m_sink->abort();
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        return;
+    }
+    m_reply.reset();
+    qDebug() << "Download succeeded:" << m_url.toString();
+    emit succeeded(m_index_within_job);
 }
 
 void Download::downloadReadyRead()
 {
-	if(m_status == Job_InProgress)
-	{
-		auto data = m_reply->readAll();
-		m_status = m_sink->write(data);
-		if(m_status == Job_Failed)
-		{
-			qCritical() << "Failed to process response chunk for " << m_target_path;
-		}
-		// qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes";
-	}
-	else
-	{
-		qCritical() << "Cannot write to " << m_target_path << ", illegal status" << m_status;
-	}
+    if(m_status == Job_InProgress)
+    {
+        auto data = m_reply->readAll();
+        m_status = m_sink->write(data);
+        if(m_status == Job_Failed)
+        {
+            qCritical() << "Failed to process response chunk for " << m_target_path;
+        }
+        // qDebug() << "Download" << m_url.toString() << "gained" << data.size() << "bytes";
+    }
+    else
+    {
+        qCritical() << "Cannot write to " << m_target_path << ", illegal status" << m_status;
+    }
 }
 
 }
 
 bool Net::Download::abort()
 {
-	if(m_reply)
-	{
-		m_reply->abort();
-	}
-	else
-	{
-		m_status = Job_Aborted;
-	}
-	return true;
+    if(m_reply)
+    {
+        m_reply->abort();
+    }
+    else
+    {
+        m_status = Job_Aborted;
+    }
+    return true;
 }
 
 bool Net::Download::canAbort()
 {
-	return true;
+    return true;
 }
diff --git a/api/logic/net/Download.h b/api/logic/net/Download.h
index 00bf108c..9d9d7743 100644
--- a/api/logic/net/Download.h
+++ b/api/logic/net/Download.h
@@ -24,52 +24,52 @@
 namespace Net {
 class MULTIMC_LOGIC_EXPORT Download : public NetAction
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public: /* types */
-	typedef std::shared_ptr<class Download> Ptr;
-	enum class Option
-	{
-		NoOptions = 0,
-		AcceptLocalFiles = 1
-	};
-	Q_DECLARE_FLAGS(Options, Option)
+    typedef std::shared_ptr<class Download> Ptr;
+    enum class Option
+    {
+        NoOptions = 0,
+        AcceptLocalFiles = 1
+    };
+    Q_DECLARE_FLAGS(Options, Option)
 
 protected: /* con/des */
-	explicit Download();
+    explicit Download();
 public:
-	virtual ~Download(){};
-	static Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions);
-	static Download::Ptr makeByteArray(QUrl url, QByteArray *output, Options options = Option::NoOptions);
-	static Download::Ptr makeFile(QUrl url, QString path, Options options = Option::NoOptions);
+    virtual ~Download(){};
+    static Download::Ptr makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions);
+    static Download::Ptr makeByteArray(QUrl url, QByteArray *output, Options options = Option::NoOptions);
+    static Download::Ptr makeFile(QUrl url, QString path, Options options = Option::NoOptions);
 
 public: /* methods */
-	QString getTargetFilepath()
-	{
-		return m_target_path;
-	}
-	void addValidator(Validator * v);
-	bool abort() override;
-	bool canAbort() override;
+    QString getTargetFilepath()
+    {
+        return m_target_path;
+    }
+    void addValidator(Validator * v);
+    bool abort() override;
+    bool canAbort() override;
 
 private: /* methods */
-	bool handleRedirect();
+    bool handleRedirect();
 
 protected slots:
-	void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
-	void downloadError(QNetworkReply::NetworkError error) override;
+    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
+    void downloadError(QNetworkReply::NetworkError error) override;
     void sslErrors(const QList<QSslError> & errors);
-	void downloadFinished() override;
-	void downloadReadyRead() override;
+    void downloadFinished() override;
+    void downloadReadyRead() override;
 
 public slots:
-	void start() override;
+    void start() override;
 
 private: /* data */
-	// FIXME: remove this, it has no business being here.
-	QString m_target_path;
-	std::unique_ptr<Sink> m_sink;
-	Options m_options;
+    // FIXME: remove this, it has no business being here.
+    QString m_target_path;
+    std::unique_ptr<Sink> m_sink;
+    Options m_options;
 };
 }
 
diff --git a/api/logic/net/FileSink.cpp b/api/logic/net/FileSink.cpp
index e3ff0498..8b3e917d 100644
--- a/api/logic/net/FileSink.cpp
+++ b/api/logic/net/FileSink.cpp
@@ -7,109 +7,109 @@
 namespace Net {
 
 FileSink::FileSink(QString filename)
-	:m_filename(filename)
+    :m_filename(filename)
 {
-	// nil
+    // nil
 }
 
 FileSink::~FileSink()
 {
-	// nil
+    // nil
 }
 
 JobStatus FileSink::init(QNetworkRequest& request)
 {
-	auto result = initCache(request);
-	if(result != Job_InProgress)
-	{
-		return result;
-	}
-	// create a new save file and open it for writing
-	if (!FS::ensureFilePathExists(m_filename))
-	{
-		qCritical() << "Could not create folder for " + m_filename;
-		return Job_Failed;
-	}
-	wroteAnyData = false;
-	m_output_file.reset(new QSaveFile(m_filename));
-	if (!m_output_file->open(QIODevice::WriteOnly))
-	{
-		qCritical() << "Could not open " + m_filename + " for writing";
-		return Job_Failed;
-	}
+    auto result = initCache(request);
+    if(result != Job_InProgress)
+    {
+        return result;
+    }
+    // create a new save file and open it for writing
+    if (!FS::ensureFilePathExists(m_filename))
+    {
+        qCritical() << "Could not create folder for " + m_filename;
+        return Job_Failed;
+    }
+    wroteAnyData = false;
+    m_output_file.reset(new QSaveFile(m_filename));
+    if (!m_output_file->open(QIODevice::WriteOnly))
+    {
+        qCritical() << "Could not open " + m_filename + " for writing";
+        return Job_Failed;
+    }
 
-	if(initAllValidators(request))
-		return Job_InProgress;
-	return Job_Failed;
+    if(initAllValidators(request))
+        return Job_InProgress;
+    return Job_Failed;
 }
 
 JobStatus FileSink::initCache(QNetworkRequest &)
 {
-	return Job_InProgress;
+    return Job_InProgress;
 }
 
 JobStatus FileSink::write(QByteArray& data)
 {
-	if (!writeAllValidators(data) || m_output_file->write(data) != data.size())
-	{
-		qCritical() << "Failed writing into " + m_filename;
-		m_output_file->cancelWriting();
-		m_output_file.reset();
-		wroteAnyData = false;
-		return Job_Failed;
-	}
-	wroteAnyData = true;
-	return Job_InProgress;
+    if (!writeAllValidators(data) || m_output_file->write(data) != data.size())
+    {
+        qCritical() << "Failed writing into " + m_filename;
+        m_output_file->cancelWriting();
+        m_output_file.reset();
+        wroteAnyData = false;
+        return Job_Failed;
+    }
+    wroteAnyData = true;
+    return Job_InProgress;
 }
 
 JobStatus FileSink::abort()
 {
-	m_output_file->cancelWriting();
-	failAllValidators();
-	return Job_Failed;
+    m_output_file->cancelWriting();
+    failAllValidators();
+    return Job_Failed;
 }
 
 JobStatus FileSink::finalize(QNetworkReply& reply)
 {
-	bool gotFile = false;
-	QVariant statusCodeV = reply.attribute(QNetworkRequest::HttpStatusCodeAttribute);
-	bool validStatus = false;
-	int statusCode = statusCodeV.toInt(&validStatus);
-	if(validStatus)
-	{
-		// this leaves out 304 Not Modified
-		gotFile = statusCode == 200 || statusCode == 203;
-	}
-	// if we wrote any data to the save file, we try to commit the data to the real file.
-	// if it actually got a proper file, we write it even if it was empty
-	if (gotFile || wroteAnyData)
-	{
-		// ask validators for data consistency
-		// we only do this for actual downloads, not 'your data is still the same' cache hits
-		if(!finalizeAllValidators(reply))
-			return Job_Failed;
-		// nothing went wrong...
-		if (!m_output_file->commit())
-		{
-			qCritical() << "Failed to commit changes to " << m_filename;
-			m_output_file->cancelWriting();
-			return Job_Failed;
-		}
-	}
-	// then get rid of the save file
-	m_output_file.reset();
+    bool gotFile = false;
+    QVariant statusCodeV = reply.attribute(QNetworkRequest::HttpStatusCodeAttribute);
+    bool validStatus = false;
+    int statusCode = statusCodeV.toInt(&validStatus);
+    if(validStatus)
+    {
+        // this leaves out 304 Not Modified
+        gotFile = statusCode == 200 || statusCode == 203;
+    }
+    // if we wrote any data to the save file, we try to commit the data to the real file.
+    // if it actually got a proper file, we write it even if it was empty
+    if (gotFile || wroteAnyData)
+    {
+        // ask validators for data consistency
+        // we only do this for actual downloads, not 'your data is still the same' cache hits
+        if(!finalizeAllValidators(reply))
+            return Job_Failed;
+        // nothing went wrong...
+        if (!m_output_file->commit())
+        {
+            qCritical() << "Failed to commit changes to " << m_filename;
+            m_output_file->cancelWriting();
+            return Job_Failed;
+        }
+    }
+    // then get rid of the save file
+    m_output_file.reset();
 
-	return finalizeCache(reply);
+    return finalizeCache(reply);
 }
 
 JobStatus FileSink::finalizeCache(QNetworkReply &)
 {
-	return Job_Finished;
+    return Job_Finished;
 }
 
 bool FileSink::hasLocalData()
 {
-	QFileInfo info(m_filename);
-	return info.exists() && info.size() != 0;
+    QFileInfo info(m_filename);
+    return info.exists() && info.size() != 0;
 }
 }
diff --git a/api/logic/net/FileSink.h b/api/logic/net/FileSink.h
index 035d5bfd..875fe511 100644
--- a/api/logic/net/FileSink.h
+++ b/api/logic/net/FileSink.h
@@ -6,23 +6,23 @@ namespace Net {
 class FileSink : public Sink
 {
 public: /* con/des */
-	FileSink(QString filename);
-	virtual ~FileSink();
+    FileSink(QString filename);
+    virtual ~FileSink();
 
 public: /* methods */
-	JobStatus init(QNetworkRequest & request) override;
-	JobStatus write(QByteArray & data) override;
-	JobStatus abort() override;
-	JobStatus finalize(QNetworkReply & reply) override;
-	bool hasLocalData() override;
+    JobStatus init(QNetworkRequest & request) override;
+    JobStatus write(QByteArray & data) override;
+    JobStatus abort() override;
+    JobStatus finalize(QNetworkReply & reply) override;
+    bool hasLocalData() override;
 
 protected: /* methods */
-	virtual JobStatus initCache(QNetworkRequest &);
-	virtual JobStatus finalizeCache(QNetworkReply &reply);
+    virtual JobStatus initCache(QNetworkRequest &);
+    virtual JobStatus finalizeCache(QNetworkReply &reply);
 
 protected: /* data */
-	QString m_filename;
-	bool wroteAnyData = false;
-	std::unique_ptr<QSaveFile> m_output_file;
+    QString m_filename;
+    bool wroteAnyData = false;
+    std::unique_ptr<QSaveFile> m_output_file;
 };
 }
diff --git a/api/logic/net/HttpMetaCache.cpp b/api/logic/net/HttpMetaCache.cpp
index 95906d2c..66325f71 100644
--- a/api/logic/net/HttpMetaCache.cpp
+++ b/api/logic/net/HttpMetaCache.cpp
@@ -30,244 +30,244 @@
 
 QString MetaEntry::getFullPath()
 {
-	// FIXME: make local?
-	return FS::PathCombine(basePath, relativePath);
+    // FIXME: make local?
+    return FS::PathCombine(basePath, relativePath);
 }
 
 HttpMetaCache::HttpMetaCache(QString path) : QObject()
 {
-	m_index_file = path;
-	saveBatchingTimer.setSingleShot(true);
-	saveBatchingTimer.setTimerType(Qt::VeryCoarseTimer);
-	connect(&saveBatchingTimer, SIGNAL(timeout()), SLOT(SaveNow()));
+    m_index_file = path;
+    saveBatchingTimer.setSingleShot(true);
+    saveBatchingTimer.setTimerType(Qt::VeryCoarseTimer);
+    connect(&saveBatchingTimer, SIGNAL(timeout()), SLOT(SaveNow()));
 }
 
 HttpMetaCache::~HttpMetaCache()
 {
-	saveBatchingTimer.stop();
-	SaveNow();
+    saveBatchingTimer.stop();
+    SaveNow();
 }
 
 MetaEntryPtr HttpMetaCache::getEntry(QString base, QString resource_path)
 {
-	// no base. no base path. can't store
-	if (!m_entries.contains(base))
-	{
-		// TODO: log problem
-		return MetaEntryPtr();
-	}
-	EntryMap &map = m_entries[base];
-	if (map.entry_list.contains(resource_path))
-	{
-		return map.entry_list[resource_path];
-	}
-	return MetaEntryPtr();
+    // no base. no base path. can't store
+    if (!m_entries.contains(base))
+    {
+        // TODO: log problem
+        return MetaEntryPtr();
+    }
+    EntryMap &map = m_entries[base];
+    if (map.entry_list.contains(resource_path))
+    {
+        return map.entry_list[resource_path];
+    }
+    return MetaEntryPtr();
 }
 
 MetaEntryPtr HttpMetaCache::resolveEntry(QString base, QString resource_path, QString expected_etag)
 {
-	auto entry = getEntry(base, resource_path);
-	// it's not present? generate a default stale entry
-	if (!entry)
-	{
-		return staleEntry(base, resource_path);
-	}
+    auto entry = getEntry(base, resource_path);
+    // it's not present? generate a default stale entry
+    if (!entry)
+    {
+        return staleEntry(base, resource_path);
+    }
 
-	auto &selected_base = m_entries[base];
-	QString real_path = FS::PathCombine(selected_base.base_path, resource_path);
-	QFileInfo finfo(real_path);
+    auto &selected_base = m_entries[base];
+    QString real_path = FS::PathCombine(selected_base.base_path, resource_path);
+    QFileInfo finfo(real_path);
 
-	// is the file really there? if not -> stale
-	if (!finfo.isFile() || !finfo.isReadable())
-	{
-		// if the file doesn't exist, we disown the entry
-		selected_base.entry_list.remove(resource_path);
-		return staleEntry(base, resource_path);
-	}
+    // is the file really there? if not -> stale
+    if (!finfo.isFile() || !finfo.isReadable())
+    {
+        // if the file doesn't exist, we disown the entry
+        selected_base.entry_list.remove(resource_path);
+        return staleEntry(base, resource_path);
+    }
 
-	if (!expected_etag.isEmpty() && expected_etag != entry->etag)
-	{
-		// if the etag doesn't match expected, we disown the entry
-		selected_base.entry_list.remove(resource_path);
-		return staleEntry(base, resource_path);
-	}
+    if (!expected_etag.isEmpty() && expected_etag != entry->etag)
+    {
+        // if the etag doesn't match expected, we disown the entry
+        selected_base.entry_list.remove(resource_path);
+        return staleEntry(base, resource_path);
+    }
 
-	// if the file changed, check md5sum
-	qint64 file_last_changed = finfo.lastModified().toUTC().toMSecsSinceEpoch();
-	if (file_last_changed != entry->local_changed_timestamp)
-	{
-		QFile input(real_path);
-		input.open(QIODevice::ReadOnly);
-		QString md5sum = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Md5)
-							 .toHex()
-							 .constData();
-		if (entry->md5sum != md5sum)
-		{
-			selected_base.entry_list.remove(resource_path);
-			return staleEntry(base, resource_path);
-		}
-		// md5sums matched... keep entry and save the new state to file
-		entry->local_changed_timestamp = file_last_changed;
-		SaveEventually();
-	}
+    // if the file changed, check md5sum
+    qint64 file_last_changed = finfo.lastModified().toUTC().toMSecsSinceEpoch();
+    if (file_last_changed != entry->local_changed_timestamp)
+    {
+        QFile input(real_path);
+        input.open(QIODevice::ReadOnly);
+        QString md5sum = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Md5)
+                             .toHex()
+                             .constData();
+        if (entry->md5sum != md5sum)
+        {
+            selected_base.entry_list.remove(resource_path);
+            return staleEntry(base, resource_path);
+        }
+        // md5sums matched... keep entry and save the new state to file
+        entry->local_changed_timestamp = file_last_changed;
+        SaveEventually();
+    }
 
-	// entry passed all the checks we cared about.
-	entry->basePath = getBasePath(base);
-	return entry;
+    // entry passed all the checks we cared about.
+    entry->basePath = getBasePath(base);
+    return entry;
 }
 
 bool HttpMetaCache::updateEntry(MetaEntryPtr stale_entry)
 {
-	if (!m_entries.contains(stale_entry->baseId))
-	{
-		qCritical() << "Cannot add entry with unknown base: "
-					 << stale_entry->baseId.toLocal8Bit();
-		return false;
-	}
-	if (stale_entry->stale)
-	{
-		qCritical() << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit();
-		return false;
-	}
-	m_entries[stale_entry->baseId].entry_list[stale_entry->relativePath] = stale_entry;
-	SaveEventually();
-	return true;
+    if (!m_entries.contains(stale_entry->baseId))
+    {
+        qCritical() << "Cannot add entry with unknown base: "
+                     << stale_entry->baseId.toLocal8Bit();
+        return false;
+    }
+    if (stale_entry->stale)
+    {
+        qCritical() << "Cannot add stale entry: " << stale_entry->getFullPath().toLocal8Bit();
+        return false;
+    }
+    m_entries[stale_entry->baseId].entry_list[stale_entry->relativePath] = stale_entry;
+    SaveEventually();
+    return true;
 }
 
 bool HttpMetaCache::evictEntry(MetaEntryPtr entry)
 {
-	if(entry)
-	{
-		entry->stale = true;
-		SaveEventually();
-		return true;
-	}
-	return false;
+    if(entry)
+    {
+        entry->stale = true;
+        SaveEventually();
+        return true;
+    }
+    return false;
 }
 
 MetaEntryPtr HttpMetaCache::staleEntry(QString base, QString resource_path)
 {
-	auto foo = new MetaEntry();
-	foo->baseId = base;
-	foo->basePath = getBasePath(base);
-	foo->relativePath = resource_path;
-	foo->stale = true;
-	return MetaEntryPtr(foo);
+    auto foo = new MetaEntry();
+    foo->baseId = base;
+    foo->basePath = getBasePath(base);
+    foo->relativePath = resource_path;
+    foo->stale = true;
+    return MetaEntryPtr(foo);
 }
 
 void HttpMetaCache::addBase(QString base, QString base_root)
 {
-	// TODO: report error
-	if (m_entries.contains(base))
-		return;
-	// TODO: check if the base path is valid
-	EntryMap foo;
-	foo.base_path = base_root;
-	m_entries[base] = foo;
+    // TODO: report error
+    if (m_entries.contains(base))
+        return;
+    // TODO: check if the base path is valid
+    EntryMap foo;
+    foo.base_path = base_root;
+    m_entries[base] = foo;
 }
 
 QString HttpMetaCache::getBasePath(QString base)
 {
-	if (m_entries.contains(base))
-	{
-		return m_entries[base].base_path;
-	}
-	return QString();
+    if (m_entries.contains(base))
+    {
+        return m_entries[base].base_path;
+    }
+    return QString();
 }
 
 void HttpMetaCache::Load()
 {
-	if(m_index_file.isNull())
-		return;
+    if(m_index_file.isNull())
+        return;
 
-	QFile index(m_index_file);
-	if (!index.open(QIODevice::ReadOnly))
-		return;
+    QFile index(m_index_file);
+    if (!index.open(QIODevice::ReadOnly))
+        return;
 
-	QJsonDocument json = QJsonDocument::fromJson(index.readAll());
-	if (!json.isObject())
-		return;
-	auto root = json.object();
-	// check file version first
-	auto version_val = root.value("version");
-	if (!version_val.isString())
-		return;
-	if (version_val.toString() != "1")
-		return;
+    QJsonDocument json = QJsonDocument::fromJson(index.readAll());
+    if (!json.isObject())
+        return;
+    auto root = json.object();
+    // check file version first
+    auto version_val = root.value("version");
+    if (!version_val.isString())
+        return;
+    if (version_val.toString() != "1")
+        return;
 
-	// read the entry array
-	auto entries_val = root.value("entries");
-	if (!entries_val.isArray())
-		return;
-	QJsonArray array = entries_val.toArray();
-	for (auto element : array)
-	{
-		if (!element.isObject())
-			return;
-		auto element_obj = element.toObject();
-		QString base = element_obj.value("base").toString();
-		if (!m_entries.contains(base))
-			continue;
-		auto &entrymap = m_entries[base];
-		auto foo = new MetaEntry();
-		foo->baseId = base;
-		QString path = foo->relativePath = element_obj.value("path").toString();
-		foo->md5sum = element_obj.value("md5sum").toString();
-		foo->etag = element_obj.value("etag").toString();
-		foo->local_changed_timestamp = element_obj.value("last_changed_timestamp").toDouble();
-		foo->remote_changed_timestamp =
-			element_obj.value("remote_changed_timestamp").toString();
-		// presumed innocent until closer examination
-		foo->stale = false;
-		entrymap.entry_list[path] = MetaEntryPtr(foo);
-	}
+    // read the entry array
+    auto entries_val = root.value("entries");
+    if (!entries_val.isArray())
+        return;
+    QJsonArray array = entries_val.toArray();
+    for (auto element : array)
+    {
+        if (!element.isObject())
+            return;
+        auto element_obj = element.toObject();
+        QString base = element_obj.value("base").toString();
+        if (!m_entries.contains(base))
+            continue;
+        auto &entrymap = m_entries[base];
+        auto foo = new MetaEntry();
+        foo->baseId = base;
+        QString path = foo->relativePath = element_obj.value("path").toString();
+        foo->md5sum = element_obj.value("md5sum").toString();
+        foo->etag = element_obj.value("etag").toString();
+        foo->local_changed_timestamp = element_obj.value("last_changed_timestamp").toDouble();
+        foo->remote_changed_timestamp =
+            element_obj.value("remote_changed_timestamp").toString();
+        // presumed innocent until closer examination
+        foo->stale = false;
+        entrymap.entry_list[path] = MetaEntryPtr(foo);
+    }
 }
 
 void HttpMetaCache::SaveEventually()
 {
-	// reset the save timer
-	saveBatchingTimer.stop();
-	saveBatchingTimer.start(30000);
+    // reset the save timer
+    saveBatchingTimer.stop();
+    saveBatchingTimer.start(30000);
 }
 
 void HttpMetaCache::SaveNow()
 {
-	if(m_index_file.isNull())
-		return;
-	QJsonObject toplevel;
-	toplevel.insert("version", QJsonValue(QString("1")));
-	QJsonArray entriesArr;
-	for (auto group : m_entries)
-	{
-		for (auto entry : group.entry_list)
-		{
-			// do not save stale entries. they are dead.
-			if(entry->stale)
-			{
-				continue;
-			}
-			QJsonObject entryObj;
-			entryObj.insert("base", QJsonValue(entry->baseId));
-			entryObj.insert("path", QJsonValue(entry->relativePath));
-			entryObj.insert("md5sum", QJsonValue(entry->md5sum));
-			entryObj.insert("etag", QJsonValue(entry->etag));
-			entryObj.insert("last_changed_timestamp",
-							QJsonValue(double(entry->local_changed_timestamp)));
-			if (!entry->remote_changed_timestamp.isEmpty())
-				entryObj.insert("remote_changed_timestamp",
-								QJsonValue(entry->remote_changed_timestamp));
-			entriesArr.append(entryObj);
-		}
-	}
-	toplevel.insert("entries", entriesArr);
+    if(m_index_file.isNull())
+        return;
+    QJsonObject toplevel;
+    toplevel.insert("version", QJsonValue(QString("1")));
+    QJsonArray entriesArr;
+    for (auto group : m_entries)
+    {
+        for (auto entry : group.entry_list)
+        {
+            // do not save stale entries. they are dead.
+            if(entry->stale)
+            {
+                continue;
+            }
+            QJsonObject entryObj;
+            entryObj.insert("base", QJsonValue(entry->baseId));
+            entryObj.insert("path", QJsonValue(entry->relativePath));
+            entryObj.insert("md5sum", QJsonValue(entry->md5sum));
+            entryObj.insert("etag", QJsonValue(entry->etag));
+            entryObj.insert("last_changed_timestamp",
+                            QJsonValue(double(entry->local_changed_timestamp)));
+            if (!entry->remote_changed_timestamp.isEmpty())
+                entryObj.insert("remote_changed_timestamp",
+                                QJsonValue(entry->remote_changed_timestamp));
+            entriesArr.append(entryObj);
+        }
+    }
+    toplevel.insert("entries", entriesArr);
 
-	QJsonDocument doc(toplevel);
-	try
-	{
-		FS::write(m_index_file, doc.toJson());
-	}
-	catch (const Exception &e)
-	{
-		qWarning() << e.what();
-	}
+    QJsonDocument doc(toplevel);
+    try
+    {
+        FS::write(m_index_file, doc.toJson());
+    }
+    catch (const Exception &e)
+    {
+        qWarning() << e.what();
+    }
 }
diff --git a/api/logic/net/HttpMetaCache.h b/api/logic/net/HttpMetaCache.h
index 7ee5f735..6e240723 100644
--- a/api/logic/net/HttpMetaCache.h
+++ b/api/logic/net/HttpMetaCache.h
@@ -27,99 +27,99 @@ class MULTIMC_LOGIC_EXPORT MetaEntry
 {
 friend class HttpMetaCache;
 protected:
-	MetaEntry() {}
+    MetaEntry() {}
 public:
-	bool isStale()
-	{
-		return stale;
-	}
-	void setStale(bool stale)
-	{
-		this->stale = stale;
-	}
-	QString getFullPath();
-	QString getRemoteChangedTimestamp()
-	{
-		return remote_changed_timestamp;
-	}
-	void setRemoteChangedTimestamp(QString remote_changed_timestamp)
-	{
-		this->remote_changed_timestamp = remote_changed_timestamp;
-	}
-	void setLocalChangedTimestamp(qint64 timestamp)
-	{
-		local_changed_timestamp = timestamp;
-	}
-	QString getETag()
-	{
-		return etag;
-	}
-	void setETag(QString etag)
-	{
-		this->etag = etag;
-	}
-	QString getMD5Sum()
-	{
-		return md5sum;
-	}
-	void setMD5Sum(QString md5sum)
-	{
-		this->md5sum = md5sum;
-	}
+    bool isStale()
+    {
+        return stale;
+    }
+    void setStale(bool stale)
+    {
+        this->stale = stale;
+    }
+    QString getFullPath();
+    QString getRemoteChangedTimestamp()
+    {
+        return remote_changed_timestamp;
+    }
+    void setRemoteChangedTimestamp(QString remote_changed_timestamp)
+    {
+        this->remote_changed_timestamp = remote_changed_timestamp;
+    }
+    void setLocalChangedTimestamp(qint64 timestamp)
+    {
+        local_changed_timestamp = timestamp;
+    }
+    QString getETag()
+    {
+        return etag;
+    }
+    void setETag(QString etag)
+    {
+        this->etag = etag;
+    }
+    QString getMD5Sum()
+    {
+        return md5sum;
+    }
+    void setMD5Sum(QString md5sum)
+    {
+        this->md5sum = md5sum;
+    }
 protected:
-	QString baseId;
-	QString basePath;
-	QString relativePath;
-	QString md5sum;
-	QString etag;
-	qint64 local_changed_timestamp = 0;
-	QString remote_changed_timestamp; // QString for now, RFC 2822 encoded time
-	bool stale = true;
+    QString baseId;
+    QString basePath;
+    QString relativePath;
+    QString md5sum;
+    QString etag;
+    qint64 local_changed_timestamp = 0;
+    QString remote_changed_timestamp; // QString for now, RFC 2822 encoded time
+    bool stale = true;
 };
 
 typedef std::shared_ptr<MetaEntry> MetaEntryPtr;
 
 class MULTIMC_LOGIC_EXPORT HttpMetaCache : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	// supply path to the cache index file
-	HttpMetaCache(QString path = QString());
-	~HttpMetaCache();
+    // supply path to the cache index file
+    HttpMetaCache(QString path = QString());
+    ~HttpMetaCache();
 
-	// get the entry solely from the cache
-	// you probably don't want this, unless you have some specific caching needs.
-	MetaEntryPtr getEntry(QString base, QString resource_path);
+    // get the entry solely from the cache
+    // you probably don't want this, unless you have some specific caching needs.
+    MetaEntryPtr getEntry(QString base, QString resource_path);
 
-	// get the entry from cache and verify that it isn't stale (within reason)
-	MetaEntryPtr resolveEntry(QString base, QString resource_path,
-							  QString expected_etag = QString());
+    // get the entry from cache and verify that it isn't stale (within reason)
+    MetaEntryPtr resolveEntry(QString base, QString resource_path,
+                              QString expected_etag = QString());
 
-	// add a previously resolved stale entry
-	bool updateEntry(MetaEntryPtr stale_entry);
+    // add a previously resolved stale entry
+    bool updateEntry(MetaEntryPtr stale_entry);
 
-	// evict selected entry from cache
-	bool evictEntry(MetaEntryPtr entry);
+    // evict selected entry from cache
+    bool evictEntry(MetaEntryPtr entry);
 
-	void addBase(QString base, QString base_root);
+    void addBase(QString base, QString base_root);
 
-	// (re)start a timer that calls SaveNow later.
-	void SaveEventually();
-	void Load();
-	QString getBasePath(QString base);
+    // (re)start a timer that calls SaveNow later.
+    void SaveEventually();
+    void Load();
+    QString getBasePath(QString base);
 public
 slots:
-	void SaveNow();
+    void SaveNow();
 
 private:
-	// create a new stale entry, given the parameters
-	MetaEntryPtr staleEntry(QString base, QString resource_path);
-	struct EntryMap
-	{
-		QString base_path;
-		QMap<QString, MetaEntryPtr> entry_list;
-	};
-	QMap<QString, EntryMap> m_entries;
-	QString m_index_file;
-	QTimer saveBatchingTimer;
+    // create a new stale entry, given the parameters
+    MetaEntryPtr staleEntry(QString base, QString resource_path);
+    struct EntryMap
+    {
+        QString base_path;
+        QMap<QString, MetaEntryPtr> entry_list;
+    };
+    QMap<QString, EntryMap> m_entries;
+    QString m_index_file;
+    QTimer saveBatchingTimer;
 };
diff --git a/api/logic/net/MetaCacheSink.cpp b/api/logic/net/MetaCacheSink.cpp
index b4b337d6..d7f18533 100644
--- a/api/logic/net/MetaCacheSink.cpp
+++ b/api/logic/net/MetaCacheSink.cpp
@@ -7,59 +7,59 @@
 namespace Net {
 
 MetaCacheSink::MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum)
-	:Net::FileSink(entry->getFullPath()), m_entry(entry), m_md5Node(md5sum)
+    :Net::FileSink(entry->getFullPath()), m_entry(entry), m_md5Node(md5sum)
 {
-	addValidator(md5sum);
+    addValidator(md5sum);
 }
 
 MetaCacheSink::~MetaCacheSink()
 {
-	// nil
+    // nil
 }
 
 JobStatus MetaCacheSink::initCache(QNetworkRequest& request)
 {
-	if (!m_entry->isStale())
-	{
-		return Job_Finished;
-	}
-	// check if file exists, if it does, use its information for the request
-	QFile current(m_filename);
-	if(current.exists() && current.size() != 0)
-	{
-		if (m_entry->getRemoteChangedTimestamp().size())
-		{
-			request.setRawHeader(QString("If-Modified-Since").toLatin1(), m_entry->getRemoteChangedTimestamp().toLatin1());
-		}
-		if (m_entry->getETag().size())
-		{
-			request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
-		}
-	}
-	return Job_InProgress;
+    if (!m_entry->isStale())
+    {
+        return Job_Finished;
+    }
+    // check if file exists, if it does, use its information for the request
+    QFile current(m_filename);
+    if(current.exists() && current.size() != 0)
+    {
+        if (m_entry->getRemoteChangedTimestamp().size())
+        {
+            request.setRawHeader(QString("If-Modified-Since").toLatin1(), m_entry->getRemoteChangedTimestamp().toLatin1());
+        }
+        if (m_entry->getETag().size())
+        {
+            request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
+        }
+    }
+    return Job_InProgress;
 }
 
 JobStatus MetaCacheSink::finalizeCache(QNetworkReply & reply)
 {
-	QFileInfo output_file_info(m_filename);
-	if(wroteAnyData)
-	{
-		m_entry->setMD5Sum(m_md5Node->hash().toHex().constData());
-	}
-	m_entry->setETag(reply.rawHeader("ETag").constData());
-	if (reply.hasRawHeader("Last-Modified"))
-	{
-		m_entry->setRemoteChangedTimestamp(reply.rawHeader("Last-Modified").constData());
-	}
-	m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
-	m_entry->setStale(false);
-	ENV.metacache()->updateEntry(m_entry);
-	return Job_Finished;
+    QFileInfo output_file_info(m_filename);
+    if(wroteAnyData)
+    {
+        m_entry->setMD5Sum(m_md5Node->hash().toHex().constData());
+    }
+    m_entry->setETag(reply.rawHeader("ETag").constData());
+    if (reply.hasRawHeader("Last-Modified"))
+    {
+        m_entry->setRemoteChangedTimestamp(reply.rawHeader("Last-Modified").constData());
+    }
+    m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
+    m_entry->setStale(false);
+    ENV.metacache()->updateEntry(m_entry);
+    return Job_Finished;
 }
 
 bool MetaCacheSink::hasLocalData()
 {
-	QFileInfo info(m_filename);
-	return info.exists() && info.size() != 0;
+    QFileInfo info(m_filename);
+    return info.exists() && info.size() != 0;
 }
 }
diff --git a/api/logic/net/MetaCacheSink.h b/api/logic/net/MetaCacheSink.h
index 0f3bbdf6..edcf7ad1 100644
--- a/api/logic/net/MetaCacheSink.h
+++ b/api/logic/net/MetaCacheSink.h
@@ -7,16 +7,16 @@ namespace Net {
 class MetaCacheSink : public FileSink
 {
 public: /* con/des */
-	MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum);
-	virtual ~MetaCacheSink();
-	bool hasLocalData() override;
+    MetaCacheSink(MetaEntryPtr entry, ChecksumValidator * md5sum);
+    virtual ~MetaCacheSink();
+    bool hasLocalData() override;
 
 protected: /* methods */
-	JobStatus initCache(QNetworkRequest & request) override;
-	JobStatus finalizeCache(QNetworkReply & reply) override;
+    JobStatus initCache(QNetworkRequest & request) override;
+    JobStatus finalizeCache(QNetworkReply & reply) override;
 
 private: /* data */
-	MetaEntryPtr m_entry;
-	ChecksumValidator * m_md5Node;
+    MetaEntryPtr m_entry;
+    ChecksumValidator * m_md5Node;
 };
 }
diff --git a/api/logic/net/Mode.h b/api/logic/net/Mode.h
index 62e26d92..9a95f5ad 100644
--- a/api/logic/net/Mode.h
+++ b/api/logic/net/Mode.h
@@ -4,7 +4,7 @@ namespace Net
 {
 enum class Mode
 {
-	Offline,
-	Online
+    Offline,
+    Online
 };
 }
diff --git a/api/logic/net/NetAction.h b/api/logic/net/NetAction.h
index 08e40a29..e1d2881e 100644
--- a/api/logic/net/NetAction.h
+++ b/api/logic/net/NetAction.h
@@ -25,91 +25,91 @@
 
 enum JobStatus
 {
-	Job_NotStarted,
-	Job_InProgress,
-	Job_Finished,
-	Job_Failed,
-	Job_Aborted,
-	/*
-	 * FIXME: @NUKE this confuses the task failing with us having a fallback in the form of local data. Clear up the confusion.
-	 * Same could be true for aborted task - the presence of pre-existing result is a separate concern
-	 */
-	Job_Failed_Proceed
+    Job_NotStarted,
+    Job_InProgress,
+    Job_Finished,
+    Job_Failed,
+    Job_Aborted,
+    /*
+     * FIXME: @NUKE this confuses the task failing with us having a fallback in the form of local data. Clear up the confusion.
+     * Same could be true for aborted task - the presence of pre-existing result is a separate concern
+     */
+    Job_Failed_Proceed
 };
 
 typedef std::shared_ptr<class NetAction> NetActionPtr;
 class MULTIMC_LOGIC_EXPORT NetAction : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 protected:
-	explicit NetAction() : QObject(0) {};
+    explicit NetAction() : QObject(0) {};
 
 public:
-	virtual ~NetAction() {};
-
-	bool isRunning() const
-	{
-		return m_status == Job_InProgress;
-	}
-	bool isFinished() const
-	{
-		return m_status >= Job_Finished;
-	}
-	bool wasSuccessful() const
-	{
-		return m_status == Job_Finished || m_status == Job_Failed_Proceed;
-	}
-
-	qint64 totalProgress() const
-	{
-		return m_total_progress;
-	}
-	qint64 currentProgress() const
-	{
-		return m_progress;
-	}
-	virtual bool abort()
-	{
-		return false;
-	}
-	virtual bool canAbort()
-	{
-		return false;
-	}
-	QUrl url()
-	{
-		return m_url;
-	}
+    virtual ~NetAction() {};
+
+    bool isRunning() const
+    {
+        return m_status == Job_InProgress;
+    }
+    bool isFinished() const
+    {
+        return m_status >= Job_Finished;
+    }
+    bool wasSuccessful() const
+    {
+        return m_status == Job_Finished || m_status == Job_Failed_Proceed;
+    }
+
+    qint64 totalProgress() const
+    {
+        return m_total_progress;
+    }
+    qint64 currentProgress() const
+    {
+        return m_progress;
+    }
+    virtual bool abort()
+    {
+        return false;
+    }
+    virtual bool canAbort()
+    {
+        return false;
+    }
+    QUrl url()
+    {
+        return m_url;
+    }
 
 signals:
-	void started(int index);
-	void netActionProgress(int index, qint64 current, qint64 total);
-	void succeeded(int index);
-	void failed(int index);
-	void aborted(int index);
+    void started(int index);
+    void netActionProgress(int index, qint64 current, qint64 total);
+    void succeeded(int index);
+    void failed(int index);
+    void aborted(int index);
 
 protected slots:
-	virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0;
-	virtual void downloadError(QNetworkReply::NetworkError error) = 0;
-	virtual void downloadFinished() = 0;
-	virtual void downloadReadyRead() = 0;
+    virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) = 0;
+    virtual void downloadError(QNetworkReply::NetworkError error) = 0;
+    virtual void downloadFinished() = 0;
+    virtual void downloadReadyRead() = 0;
 
 public slots:
-	virtual void start() = 0;
+    virtual void start() = 0;
 
 public:
-	/// index within the parent job, FIXME: nuke
-	int m_index_within_job = 0;
+    /// index within the parent job, FIXME: nuke
+    int m_index_within_job = 0;
 
-	/// the network reply
-	unique_qobject_ptr<QNetworkReply> m_reply;
+    /// the network reply
+    unique_qobject_ptr<QNetworkReply> m_reply;
 
-	/// source URL
-	QUrl m_url;
+    /// source URL
+    QUrl m_url;
 
-	qint64 m_progress = 0;
-	qint64 m_total_progress = 1;
+    qint64 m_progress = 0;
+    qint64 m_total_progress = 1;
 
 protected:
-	JobStatus m_status = Job_NotStarted;
+    JobStatus m_status = Job_NotStarted;
 };
diff --git a/api/logic/net/NetJob.cpp b/api/logic/net/NetJob.cpp
index 1ff8e28f..19ef742e 100644
--- a/api/logic/net/NetJob.cpp
+++ b/api/logic/net/NetJob.cpp
@@ -20,197 +20,197 @@
 
 void NetJob::partSucceeded(int index)
 {
-	// do progress. all slots are 1 in size at least
-	auto &slot = parts_progress[index];
-	partProgress(index, slot.total_progress, slot.total_progress);
-
-	m_doing.remove(index);
-	m_done.insert(index);
-	downloads[index].get()->disconnect(this);
-	startMoreParts();
+    // do progress. all slots are 1 in size at least
+    auto &slot = parts_progress[index];
+    partProgress(index, slot.total_progress, slot.total_progress);
+
+    m_doing.remove(index);
+    m_done.insert(index);
+    downloads[index].get()->disconnect(this);
+    startMoreParts();
 }
 
 void NetJob::partFailed(int index)
 {
-	m_doing.remove(index);
-	auto &slot = parts_progress[index];
-	if (slot.failures == 3)
-	{
-		m_failed.insert(index);
-	}
-	else
-	{
-		slot.failures++;
-		m_todo.enqueue(index);
-	}
-	downloads[index].get()->disconnect(this);
-	startMoreParts();
+    m_doing.remove(index);
+    auto &slot = parts_progress[index];
+    if (slot.failures == 3)
+    {
+        m_failed.insert(index);
+    }
+    else
+    {
+        slot.failures++;
+        m_todo.enqueue(index);
+    }
+    downloads[index].get()->disconnect(this);
+    startMoreParts();
 }
 
 void NetJob::partAborted(int index)
 {
-	m_aborted = true;
-	m_doing.remove(index);
-	m_failed.insert(index);
-	downloads[index].get()->disconnect(this);
-	startMoreParts();
+    m_aborted = true;
+    m_doing.remove(index);
+    m_failed.insert(index);
+    downloads[index].get()->disconnect(this);
+    startMoreParts();
 }
 
 void NetJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal)
 {
-	auto &slot = parts_progress[index];
-	slot.current_progress = bytesReceived;
-	slot.total_progress = bytesTotal;
-
-	int done = m_done.size();
-	int doing = m_doing.size();
-	int all = parts_progress.size();
-
-	qint64 bytesAll = 0;
-	qint64 bytesTotalAll = 0;
-	for(auto & partIdx: m_doing)
-	{
-		auto part = parts_progress[partIdx];
-		// do not count parts with unknown/nonsensical total size
-		if(part.total_progress <= 0)
-		{
-			continue;
-		}
-		bytesAll += part.current_progress;
-		bytesTotalAll += part.total_progress;
-	}
-
-	qint64 inprogress = (bytesTotalAll == 0) ? 0 : (bytesAll * 1000) / bytesTotalAll;
-	auto current = done * 1000 + doing * inprogress;
-	auto current_total = all * 1000;
-	// HACK: make sure it never jumps backwards.
-	// FAIL: This breaks if the size is not known (or is it something else?) and jumps to 1000, so if it is 1000 reset it to inprogress
-	if(m_current_progress == 1000) {
-		m_current_progress = inprogress;
-	}
-	if(m_current_progress > current)
-	{
-		current = m_current_progress;
-	}
-	m_current_progress = current;
-	setProgress(current, current_total);
+    auto &slot = parts_progress[index];
+    slot.current_progress = bytesReceived;
+    slot.total_progress = bytesTotal;
+
+    int done = m_done.size();
+    int doing = m_doing.size();
+    int all = parts_progress.size();
+
+    qint64 bytesAll = 0;
+    qint64 bytesTotalAll = 0;
+    for(auto & partIdx: m_doing)
+    {
+        auto part = parts_progress[partIdx];
+        // do not count parts with unknown/nonsensical total size
+        if(part.total_progress <= 0)
+        {
+            continue;
+        }
+        bytesAll += part.current_progress;
+        bytesTotalAll += part.total_progress;
+    }
+
+    qint64 inprogress = (bytesTotalAll == 0) ? 0 : (bytesAll * 1000) / bytesTotalAll;
+    auto current = done * 1000 + doing * inprogress;
+    auto current_total = all * 1000;
+    // HACK: make sure it never jumps backwards.
+    // FAIL: This breaks if the size is not known (or is it something else?) and jumps to 1000, so if it is 1000 reset it to inprogress
+    if(m_current_progress == 1000) {
+        m_current_progress = inprogress;
+    }
+    if(m_current_progress > current)
+    {
+        current = m_current_progress;
+    }
+    m_current_progress = current;
+    setProgress(current, current_total);
 }
 
 void NetJob::executeTask()
 {
-	// hack that delays early failures so they can be caught easier
-	QMetaObject::invokeMethod(this, "startMoreParts", Qt::QueuedConnection);
+    // hack that delays early failures so they can be caught easier
+    QMetaObject::invokeMethod(this, "startMoreParts", Qt::QueuedConnection);
 }
 
 void NetJob::startMoreParts()
 {
-	if(!isRunning())
-	{
-		// this actually makes sense. You can put running downloads into a NetJob and then not start it until much later.
-		return;
-	}
-	// OK. We are actively processing tasks, proceed.
-	// Check for final conditions if there's nothing in the queue.
-	if(!m_todo.size())
-	{
-		if(!m_doing.size())
-		{
-			if(!m_failed.size())
-			{
-				emitSucceeded();
-			}
-			else if(m_aborted)
-			{
-				emitAborted();
-			}
-			else
-			{
-				emitFailed(tr("Job '%1' failed to process:\n%2").arg(objectName()).arg(getFailedFiles().join("\n")));
-			}
-		}
-		return;
-	}
-	// There's work to do, try to start more parts.
-	while (m_doing.size() < 6)
-	{
-		if(!m_todo.size())
-			return;
-		int doThis = m_todo.dequeue();
-		m_doing.insert(doThis);
-		auto part = downloads[doThis];
-		// connect signals :D
-		connect(part.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
-		connect(part.get(), SIGNAL(failed(int)), SLOT(partFailed(int)));
-		connect(part.get(), SIGNAL(aborted(int)), SLOT(partAborted(int)));
-		connect(part.get(), SIGNAL(netActionProgress(int, qint64, qint64)),
-				SLOT(partProgress(int, qint64, qint64)));
-		part->start();
-	}
+    if(!isRunning())
+    {
+        // this actually makes sense. You can put running downloads into a NetJob and then not start it until much later.
+        return;
+    }
+    // OK. We are actively processing tasks, proceed.
+    // Check for final conditions if there's nothing in the queue.
+    if(!m_todo.size())
+    {
+        if(!m_doing.size())
+        {
+            if(!m_failed.size())
+            {
+                emitSucceeded();
+            }
+            else if(m_aborted)
+            {
+                emitAborted();
+            }
+            else
+            {
+                emitFailed(tr("Job '%1' failed to process:\n%2").arg(objectName()).arg(getFailedFiles().join("\n")));
+            }
+        }
+        return;
+    }
+    // There's work to do, try to start more parts.
+    while (m_doing.size() < 6)
+    {
+        if(!m_todo.size())
+            return;
+        int doThis = m_todo.dequeue();
+        m_doing.insert(doThis);
+        auto part = downloads[doThis];
+        // connect signals :D
+        connect(part.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
+        connect(part.get(), SIGNAL(failed(int)), SLOT(partFailed(int)));
+        connect(part.get(), SIGNAL(aborted(int)), SLOT(partAborted(int)));
+        connect(part.get(), SIGNAL(netActionProgress(int, qint64, qint64)),
+                SLOT(partProgress(int, qint64, qint64)));
+        part->start();
+    }
 }
 
 
 QStringList NetJob::getFailedFiles()
 {
-	QStringList failed;
-	for (auto index: m_failed)
-	{
-		failed.push_back(downloads[index]->url().toString());
-	}
-	failed.sort();
-	return failed;
+    QStringList failed;
+    for (auto index: m_failed)
+    {
+        failed.push_back(downloads[index]->url().toString());
+    }
+    failed.sort();
+    return failed;
 }
 
 bool NetJob::canAbort() const
 {
-	bool canFullyAbort = true;
-	// can abort the waiting?
-	for(auto index: m_todo)
-	{
-		auto part = downloads[index];
-		canFullyAbort &= part->canAbort();
-	}
-	// can abort the active?
-	for(auto index: m_doing)
-	{
-		auto part = downloads[index];
-		canFullyAbort &= part->canAbort();
-	}
-	return canFullyAbort;
+    bool canFullyAbort = true;
+    // can abort the waiting?
+    for(auto index: m_todo)
+    {
+        auto part = downloads[index];
+        canFullyAbort &= part->canAbort();
+    }
+    // can abort the active?
+    for(auto index: m_doing)
+    {
+        auto part = downloads[index];
+        canFullyAbort &= part->canAbort();
+    }
+    return canFullyAbort;
 }
 
 bool NetJob::abort()
 {
-	bool fullyAborted = true;
-	// fail all waiting
-	m_failed.unite(m_todo.toSet());
-	m_todo.clear();
-	// abort active
-	auto toKill = m_doing.toList();
-	for(auto index: toKill)
-	{
-		auto part = downloads[index];
-		fullyAborted &= part->abort();
-	}
-	return fullyAborted;
+    bool fullyAborted = true;
+    // fail all waiting
+    m_failed.unite(m_todo.toSet());
+    m_todo.clear();
+    // abort active
+    auto toKill = m_doing.toList();
+    for(auto index: toKill)
+    {
+        auto part = downloads[index];
+        fullyAborted &= part->abort();
+    }
+    return fullyAborted;
 }
 
 bool NetJob::addNetAction(NetActionPtr action)
 {
-	action->m_index_within_job = downloads.size();
-	downloads.append(action);
-	part_info pi;
-	parts_progress.append(pi);
-	partProgress(parts_progress.count() - 1, action->currentProgress(), action->totalProgress());
-
-	if(action->isRunning())
-	{
-		connect(action.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
-		connect(action.get(), SIGNAL(failed(int)), SLOT(partFailed(int)));
-		connect(action.get(), SIGNAL(netActionProgress(int, qint64, qint64)), SLOT(partProgress(int, qint64, qint64)));
-	}
-	else
-	{
-		m_todo.append(parts_progress.size() - 1);
-	}
-	return true;
+    action->m_index_within_job = downloads.size();
+    downloads.append(action);
+    part_info pi;
+    parts_progress.append(pi);
+    partProgress(parts_progress.count() - 1, action->currentProgress(), action->totalProgress());
+
+    if(action->isRunning())
+    {
+        connect(action.get(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
+        connect(action.get(), SIGNAL(failed(int)), SLOT(partFailed(int)));
+        connect(action.get(), SIGNAL(netActionProgress(int, qint64, qint64)), SLOT(partProgress(int, qint64, qint64)));
+    }
+    else
+    {
+        m_todo.append(parts_progress.size() - 1);
+    }
+    return true;
 }
diff --git a/api/logic/net/NetJob.h b/api/logic/net/NetJob.h
index be58c61a..3051b943 100644
--- a/api/logic/net/NetJob.h
+++ b/api/logic/net/NetJob.h
@@ -28,64 +28,64 @@ typedef shared_qobject_ptr<NetJob> NetJobPtr;
 
 class MULTIMC_LOGIC_EXPORT NetJob : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit NetJob(QString job_name) : Task()
-	{
-		setObjectName(job_name);
-	}
-	virtual ~NetJob() {}
+    explicit NetJob(QString job_name) : Task()
+    {
+        setObjectName(job_name);
+    }
+    virtual ~NetJob() {}
 
-	bool addNetAction(NetActionPtr action);
+    bool addNetAction(NetActionPtr action);
 
-	NetActionPtr operator[](int index)
-	{
-		return downloads[index];
-	}
-	const NetActionPtr at(const int index)
-	{
-		return downloads.at(index);
-	}
-	NetActionPtr first()
-	{
-		if (downloads.size())
-			return downloads[0];
-		return NetActionPtr();
-	}
-	int size() const
-	{
-		return downloads.size();
-	}
-	QStringList getFailedFiles();
+    NetActionPtr operator[](int index)
+    {
+        return downloads[index];
+    }
+    const NetActionPtr at(const int index)
+    {
+        return downloads.at(index);
+    }
+    NetActionPtr first()
+    {
+        if (downloads.size())
+            return downloads[0];
+        return NetActionPtr();
+    }
+    int size() const
+    {
+        return downloads.size();
+    }
+    QStringList getFailedFiles();
 
-	bool canAbort() const override;
+    bool canAbort() const override;
 
 private slots:
-	void startMoreParts();
+    void startMoreParts();
 
 public slots:
-	virtual void executeTask() override;
-	virtual bool abort() override;
+    virtual void executeTask() override;
+    virtual bool abort() override;
 
 private slots:
-	void partProgress(int index, qint64 bytesReceived, qint64 bytesTotal);
-	void partSucceeded(int index);
-	void partFailed(int index);
-	void partAborted(int index);
+    void partProgress(int index, qint64 bytesReceived, qint64 bytesTotal);
+    void partSucceeded(int index);
+    void partFailed(int index);
+    void partAborted(int index);
 
 private:
-	struct part_info
-	{
-		qint64 current_progress = 0;
-		qint64 total_progress = 1;
-		int failures = 0;
-	};
-	QList<NetActionPtr> downloads;
-	QList<part_info> parts_progress;
-	QQueue<int> m_todo;
-	QSet<int> m_doing;
-	QSet<int> m_done;
-	QSet<int> m_failed;
-	qint64 m_current_progress = 0;
-	bool m_aborted = false;
+    struct part_info
+    {
+        qint64 current_progress = 0;
+        qint64 total_progress = 1;
+        int failures = 0;
+    };
+    QList<NetActionPtr> downloads;
+    QList<part_info> parts_progress;
+    QQueue<int> m_todo;
+    QSet<int> m_doing;
+    QSet<int> m_done;
+    QSet<int> m_failed;
+    qint64 m_current_progress = 0;
+    bool m_aborted = false;
 };
diff --git a/api/logic/net/PasteUpload.cpp b/api/logic/net/PasteUpload.cpp
index d1ddf39d..3526e207 100644
--- a/api/logic/net/PasteUpload.cpp
+++ b/api/logic/net/PasteUpload.cpp
@@ -8,18 +8,18 @@
 
 PasteUpload::PasteUpload(QWidget *window, QString text, QString key) : m_window(window)
 {
-	m_key = key;
-	QByteArray temp;
-	QJsonObject topLevelObj;
-	QJsonObject sectionObject;
-	sectionObject.insert("contents", text);
-	QJsonArray sectionArray;
-	sectionArray.append(sectionObject);
-	topLevelObj.insert("description", "MultiMC Log Upload");
-	topLevelObj.insert("sections", sectionArray);
-	QJsonDocument docOut;
-	docOut.setObject(topLevelObj);
-	m_jsonContent = docOut.toJson();
+    m_key = key;
+    QByteArray temp;
+    QJsonObject topLevelObj;
+    QJsonObject sectionObject;
+    sectionObject.insert("contents", text);
+    QJsonArray sectionArray;
+    sectionArray.append(sectionObject);
+    topLevelObj.insert("description", "MultiMC Log Upload");
+    topLevelObj.insert("sections", sectionArray);
+    QJsonDocument docOut;
+    docOut.setObject(topLevelObj);
+    m_jsonContent = docOut.toJson();
 }
 
 PasteUpload::~PasteUpload()
@@ -28,76 +28,76 @@ PasteUpload::~PasteUpload()
 
 bool PasteUpload::validateText()
 {
-	return m_jsonContent.size() <= maxSize();
+    return m_jsonContent.size() <= maxSize();
 }
 
 void PasteUpload::executeTask()
 {
-	QNetworkRequest request(QUrl("https://api.paste.ee/v1/pastes"));
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+    QNetworkRequest request(QUrl("https://api.paste.ee/v1/pastes"));
+    request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
 
-	request.setRawHeader("Content-Type", "application/json");
-	request.setRawHeader("Content-Length", QByteArray::number(m_jsonContent.size()));
-	request.setRawHeader("X-Auth-Token", m_key.toStdString().c_str());
+    request.setRawHeader("Content-Type", "application/json");
+    request.setRawHeader("Content-Length", QByteArray::number(m_jsonContent.size()));
+    request.setRawHeader("X-Auth-Token", m_key.toStdString().c_str());
 
-	QNetworkReply *rep = ENV.qnam().post(request, m_jsonContent);
+    QNetworkReply *rep = ENV.qnam().post(request, m_jsonContent);
 
-	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(finished()), this, SLOT(downloadFinished()));
+    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(finished()), this, SLOT(downloadFinished()));
 }
 
 void PasteUpload::downloadError(QNetworkReply::NetworkError error)
 {
-	// error happened during download.
-	qCritical() << "Network error: " << error;
-	emitFailed(m_reply->errorString());
+    // error happened during download.
+    qCritical() << "Network error: " << error;
+    emitFailed(m_reply->errorString());
 }
 
 void PasteUpload::downloadFinished()
 {
-	QByteArray data = m_reply->readAll();
-	// if the download succeeded
-	if (m_reply->error() == QNetworkReply::NetworkError::NoError)
-	{
-		m_reply.reset();
-		QJsonParseError jsonError;
-		QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
-		if (jsonError.error != QJsonParseError::NoError)
-		{
-			emitFailed(jsonError.errorString());
-			return;
-		}
-		if (!parseResult(doc))
-		{
-			emitFailed(tr("paste.ee returned an error. Please consult the logs for more information"));
-			return;
-		}
-	}
-	// else the download failed
-	else
-	{
-		emitFailed(QString("Network error: %1").arg(m_reply->errorString()));
-		m_reply.reset();
-		return;
-	}
-	emitSucceeded();
+    QByteArray data = m_reply->readAll();
+    // if the download succeeded
+    if (m_reply->error() == QNetworkReply::NetworkError::NoError)
+    {
+        m_reply.reset();
+        QJsonParseError jsonError;
+        QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
+        if (jsonError.error != QJsonParseError::NoError)
+        {
+            emitFailed(jsonError.errorString());
+            return;
+        }
+        if (!parseResult(doc))
+        {
+            emitFailed(tr("paste.ee returned an error. Please consult the logs for more information"));
+            return;
+        }
+    }
+    // else the download failed
+    else
+    {
+        emitFailed(QString("Network error: %1").arg(m_reply->errorString()));
+        m_reply.reset();
+        return;
+    }
+    emitSucceeded();
 }
 
 bool PasteUpload::parseResult(QJsonDocument doc)
 {
-	auto object = doc.object();
-	auto status = object.value("success").toBool();
-	if (!status)
-	{
-		qCritical() << "paste.ee reported error:" << QString(object.value("error").toString());
-		return false;
-	}
-	m_pasteLink = object.value("link").toString();
-	m_pasteID = object.value("id").toString();
-	qDebug() << m_pasteLink;
-	return true;
+    auto object = doc.object();
+    auto status = object.value("success").toBool();
+    if (!status)
+    {
+        qCritical() << "paste.ee reported error:" << QString(object.value("error").toString());
+        return false;
+    }
+    m_pasteLink = object.value("link").toString();
+    m_pasteID = object.value("id").toString();
+    qDebug() << m_pasteLink;
+    return true;
 }
 
diff --git a/api/logic/net/PasteUpload.h b/api/logic/net/PasteUpload.h
index 24f5b0eb..11e05c2e 100644
--- a/api/logic/net/PasteUpload.h
+++ b/api/logic/net/PasteUpload.h
@@ -8,42 +8,42 @@
 
 class MULTIMC_LOGIC_EXPORT PasteUpload : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	PasteUpload(QWidget *window, QString text, QString key = "public");
-	virtual ~PasteUpload();
+    PasteUpload(QWidget *window, QString text, QString key = "public");
+    virtual ~PasteUpload();
 
-	QString pasteLink()
-	{
-		return m_pasteLink;
-	}
-	QString pasteID()
-	{
-		return m_pasteID;
-	}
-	int maxSize()
-	{
-		// 2MB for paste.ee - public
-		if(m_key == "public")
-			return 1024*1024*2;
-		// 12MB for paste.ee - with actual key
-		return 1024*1024*12;
-	}
-	bool validateText();
+    QString pasteLink()
+    {
+        return m_pasteLink;
+    }
+    QString pasteID()
+    {
+        return m_pasteID;
+    }
+    int maxSize()
+    {
+        // 2MB for paste.ee - public
+        if(m_key == "public")
+            return 1024*1024*2;
+        // 12MB for paste.ee - with actual key
+        return 1024*1024*12;
+    }
+    bool validateText();
 protected:
-	virtual void executeTask();
+    virtual void executeTask();
 
 private:
-	bool parseResult(QJsonDocument doc);
-	QString m_error;
-	QWidget *m_window;
-	QString m_pasteID;
-	QString m_pasteLink;
-	QString m_key;
-	QByteArray m_jsonContent;
-	std::shared_ptr<QNetworkReply> m_reply;
+    bool parseResult(QJsonDocument doc);
+    QString m_error;
+    QWidget *m_window;
+    QString m_pasteID;
+    QString m_pasteLink;
+    QString m_key;
+    QByteArray m_jsonContent;
+    std::shared_ptr<QNetworkReply> m_reply;
 public
 slots:
-	void downloadError(QNetworkReply::NetworkError);
-	void downloadFinished();
+    void downloadError(QNetworkReply::NetworkError);
+    void downloadFinished();
 };
diff --git a/api/logic/net/Sink.h b/api/logic/net/Sink.h
index de9b1722..d526895c 100644
--- a/api/logic/net/Sink.h
+++ b/api/logic/net/Sink.h
@@ -9,63 +9,63 @@ namespace Net {
 class MULTIMC_LOGIC_EXPORT Sink
 {
 public: /* con/des */
-	Sink() {};
-	virtual ~Sink() {};
+    Sink() {};
+    virtual ~Sink() {};
 
 public: /* methods */
-	virtual JobStatus init(QNetworkRequest & request) = 0;
-	virtual JobStatus write(QByteArray & data) = 0;
-	virtual JobStatus abort() = 0;
-	virtual JobStatus finalize(QNetworkReply & reply) = 0;
-	virtual bool hasLocalData() = 0;
+    virtual JobStatus init(QNetworkRequest & request) = 0;
+    virtual JobStatus write(QByteArray & data) = 0;
+    virtual JobStatus abort() = 0;
+    virtual JobStatus finalize(QNetworkReply & reply) = 0;
+    virtual bool hasLocalData() = 0;
 
-	void addValidator(Validator * validator)
-	{
-		if(validator)
-		{
-			validators.push_back(std::shared_ptr<Validator>(validator));
-		}
-	}
+    void addValidator(Validator * validator)
+    {
+        if(validator)
+        {
+            validators.push_back(std::shared_ptr<Validator>(validator));
+        }
+    }
 
 protected: /* methods */
-	bool finalizeAllValidators(QNetworkReply & reply)
-	{
-		for(auto & validator: validators)
-		{
-			if(!validator->validate(reply))
-				return false;
-		}
-		return true;
-	}
-	bool failAllValidators()
-	{
-		bool success = true;
-		for(auto & validator: validators)
-		{
-			success &= validator->abort();
-		}
-		return success;
-	}
-	bool initAllValidators(QNetworkRequest & request)
-	{
-		for(auto & validator: validators)
-		{
-			if(!validator->init(request))
-				return false;
-		}
-		return true;
-	}
-	bool writeAllValidators(QByteArray & data)
-	{
-		for(auto & validator: validators)
-		{
-			if(!validator->write(data))
-				return false;
-		}
-		return true;
-	}
+    bool finalizeAllValidators(QNetworkReply & reply)
+    {
+        for(auto & validator: validators)
+        {
+            if(!validator->validate(reply))
+                return false;
+        }
+        return true;
+    }
+    bool failAllValidators()
+    {
+        bool success = true;
+        for(auto & validator: validators)
+        {
+            success &= validator->abort();
+        }
+        return success;
+    }
+    bool initAllValidators(QNetworkRequest & request)
+    {
+        for(auto & validator: validators)
+        {
+            if(!validator->init(request))
+                return false;
+        }
+        return true;
+    }
+    bool writeAllValidators(QByteArray & data)
+    {
+        for(auto & validator: validators)
+        {
+            if(!validator->write(data))
+                return false;
+        }
+        return true;
+    }
 
 protected: /* data */
-	std::vector<std::shared_ptr<Validator>> validators;
+    std::vector<std::shared_ptr<Validator>> validators;
 };
 }
diff --git a/api/logic/net/URLConstants.cpp b/api/logic/net/URLConstants.cpp
index bd476b2c..5d848d80 100644
--- a/api/logic/net/URLConstants.cpp
+++ b/api/logic/net/URLConstants.cpp
@@ -4,12 +4,12 @@ namespace URLConstants {
 
 QString getLegacyJarUrl(QString version)
 {
-	return "http://" + AWS_DOWNLOAD_VERSIONS + getJarPath(version);
+    return "http://" + AWS_DOWNLOAD_VERSIONS + getJarPath(version);
 }
 
 QString getJarPath(QString version)
 {
-	return version + "/" + version + ".jar";
+    return version + "/" + version + ".jar";
 }
 
 
diff --git a/api/logic/net/Validator.h b/api/logic/net/Validator.h
index a390ab28..955412ce 100644
--- a/api/logic/net/Validator.h
+++ b/api/logic/net/Validator.h
@@ -8,13 +8,13 @@ namespace Net {
 class MULTIMC_LOGIC_EXPORT Validator
 {
 public: /* con/des */
-	Validator() {};
-	virtual ~Validator() {};
+    Validator() {};
+    virtual ~Validator() {};
 
 public: /* methods */
-	virtual bool init(QNetworkRequest & request) = 0;
-	virtual bool write(QByteArray & data) = 0;
-	virtual bool abort() = 0;
-	virtual bool validate(QNetworkReply & reply) = 0;
+    virtual bool init(QNetworkRequest & request) = 0;
+    virtual bool write(QByteArray & data) = 0;
+    virtual bool abort() = 0;
+    virtual bool validate(QNetworkReply & reply) = 0;
 };
 }
\ No newline at end of file
diff --git a/api/logic/news/NewsChecker.cpp b/api/logic/news/NewsChecker.cpp
index 0ee3f9da..1f5058ef 100644
--- a/api/logic/news/NewsChecker.cpp
+++ b/api/logic/news/NewsChecker.cpp
@@ -22,110 +22,110 @@
 
 NewsChecker::NewsChecker(const QString& feedUrl)
 {
-	m_feedUrl = feedUrl;
+    m_feedUrl = feedUrl;
 }
 
 void NewsChecker::reloadNews()
 {
-	// Start a netjob to download the RSS feed and call rssDownloadFinished() when it's done.
-	if (isLoadingNews())
-	{
-		qDebug() << "Ignored request to reload news. Currently reloading already.";
-		return;
-	}
-
-	qDebug() << "Reloading news.";
-
-	NetJob* job = new NetJob("News RSS Feed");
-	job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData));
-	QObject::connect(job, &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
-	QObject::connect(job, &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
-	m_newsNetJob.reset(job);
-	job->start();
+    // Start a netjob to download the RSS feed and call rssDownloadFinished() when it's done.
+    if (isLoadingNews())
+    {
+        qDebug() << "Ignored request to reload news. Currently reloading already.";
+        return;
+    }
+
+    qDebug() << "Reloading news.";
+
+    NetJob* job = new NetJob("News RSS Feed");
+    job->addNetAction(Net::Download::makeByteArray(m_feedUrl, &newsData));
+    QObject::connect(job, &NetJob::succeeded, this, &NewsChecker::rssDownloadFinished);
+    QObject::connect(job, &NetJob::failed, this, &NewsChecker::rssDownloadFailed);
+    m_newsNetJob.reset(job);
+    job->start();
 }
 
 void NewsChecker::rssDownloadFinished()
 {
-	// Parse the XML file and process the RSS feed entries.
-	qDebug() << "Finished loading RSS feed.";
-
-	m_newsNetJob.reset();
-	QDomDocument doc;
-	{
-		// Stuff to store error info in.
-		QString errorMsg = "Unknown error.";
-		int errorLine = -1;
-		int errorCol = -1;
-
-		// 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);
-			fail(fullErrorMsg);
-			newsData.clear();
-			return;
-		}
-		newsData.clear();
-	}
-
-	// If the parsing succeeded, read it.
-	QDomNodeList items = doc.elementsByTagName("item");
-	m_newsEntries.clear();
-	for (int i = 0; i < items.length(); i++)
-	{
-		QDomElement element = items.at(i).toElement();
-		NewsEntryPtr entry;
-		entry.reset(new NewsEntry());
-		QString errorMsg = "An unknown error occurred.";
-		if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg))
-		{
-			qDebug() << "Loaded news entry" << entry->title;
-			m_newsEntries.append(entry);
-		}
-		else
-		{
-			qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
-		}
-	}
-
-	succeed();
+    // Parse the XML file and process the RSS feed entries.
+    qDebug() << "Finished loading RSS feed.";
+
+    m_newsNetJob.reset();
+    QDomDocument doc;
+    {
+        // Stuff to store error info in.
+        QString errorMsg = "Unknown error.";
+        int errorLine = -1;
+        int errorCol = -1;
+
+        // 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);
+            fail(fullErrorMsg);
+            newsData.clear();
+            return;
+        }
+        newsData.clear();
+    }
+
+    // If the parsing succeeded, read it.
+    QDomNodeList items = doc.elementsByTagName("item");
+    m_newsEntries.clear();
+    for (int i = 0; i < items.length(); i++)
+    {
+        QDomElement element = items.at(i).toElement();
+        NewsEntryPtr entry;
+        entry.reset(new NewsEntry());
+        QString errorMsg = "An unknown error occurred.";
+        if (NewsEntry::fromXmlElement(element, entry.get(), &errorMsg))
+        {
+            qDebug() << "Loaded news entry" << entry->title;
+            m_newsEntries.append(entry);
+        }
+        else
+        {
+            qWarning() << "Failed to load news entry at index" << i << ":" << errorMsg;
+        }
+    }
+
+    succeed();
 }
 
 void NewsChecker::rssDownloadFailed(QString reason)
 {
-	// Set an error message and fail.
-	fail(tr("Failed to load news RSS feed:\n%1").arg(reason));
+    // Set an error message and fail.
+    fail(tr("Failed to load news RSS feed:\n%1").arg(reason));
 }
 
 
 QList<NewsEntryPtr> NewsChecker::getNewsEntries() const
 {
-	return m_newsEntries;
+    return m_newsEntries;
 }
 
 bool NewsChecker::isLoadingNews() const
 {
-	return m_newsNetJob.get() != nullptr;
+    return m_newsNetJob.get() != nullptr;
 }
 
 QString NewsChecker::getLastLoadErrorMsg() const
 {
-	return m_lastLoadError;
+    return m_lastLoadError;
 }
 
 void NewsChecker::succeed()
 {
-	m_lastLoadError = "";
-	qDebug() << "News loading succeeded.";
-	m_newsNetJob.reset();
-	emit newsLoaded();
+    m_lastLoadError = "";
+    qDebug() << "News loading succeeded.";
+    m_newsNetJob.reset();
+    emit newsLoaded();
 }
 
 void NewsChecker::fail(const QString& errorMsg)
 {
-	m_lastLoadError = errorMsg;
-	qDebug() << "Failed to load news:" << errorMsg;
-	m_newsNetJob.reset();
-	emit newsLoadingFailed(errorMsg);
+    m_lastLoadError = errorMsg;
+    qDebug() << "Failed to load news:" << errorMsg;
+    m_newsNetJob.reset();
+    emit newsLoadingFailed(errorMsg);
 }
 
diff --git a/api/logic/news/NewsChecker.h b/api/logic/news/NewsChecker.h
index 44f2534a..7af5bd5d 100644
--- a/api/logic/news/NewsChecker.h
+++ b/api/logic/news/NewsChecker.h
@@ -27,79 +27,79 @@
 
 class MULTIMC_LOGIC_EXPORT NewsChecker : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	/*!
-	 * Constructs a news reader to read from the given RSS feed URL.
-	 */
-	NewsChecker(const QString& feedUrl);
-
-	/*!
-	 * Returns the error message for the last time the news was loaded.
-	 * Empty string if the last load was successful.
-	 */
-	QString getLastLoadErrorMsg() const;
-
-	/*!
-	 * Returns true if the news has been loaded successfully.
-	 */
-	bool isNewsLoaded() const;
-
-	//! True if the news is currently loading. If true, reloadNews() will do nothing.
-	bool isLoadingNews() const;
-
-	/*!
-	 * Returns a list of news entries.
-	 */
-	QList<NewsEntryPtr> getNewsEntries() const;
-
-	/*!
-	 * Reloads the news from the website's RSS feed.
-	 * If the news is already loading, this does nothing.
-	 */
-	void Q_SLOT reloadNews();
+    /*!
+     * Constructs a news reader to read from the given RSS feed URL.
+     */
+    NewsChecker(const QString& feedUrl);
+
+    /*!
+     * Returns the error message for the last time the news was loaded.
+     * Empty string if the last load was successful.
+     */
+    QString getLastLoadErrorMsg() const;
+
+    /*!
+     * Returns true if the news has been loaded successfully.
+     */
+    bool isNewsLoaded() const;
+
+    //! True if the news is currently loading. If true, reloadNews() will do nothing.
+    bool isLoadingNews() const;
+
+    /*!
+     * Returns a list of news entries.
+     */
+    QList<NewsEntryPtr> getNewsEntries() const;
+
+    /*!
+     * Reloads the news from the website's RSS feed.
+     * If the news is already loading, this does nothing.
+     */
+    void Q_SLOT reloadNews();
 
 signals:
-	/*!
-	 * Signal fired after the news has finished loading.
-	 */
-	void newsLoaded();
+    /*!
+     * Signal fired after the news has finished loading.
+     */
+    void newsLoaded();
 
-	/*!
-	 * Signal fired after the news fails to load.
-	 */
-	void newsLoadingFailed(QString errorMsg);
+    /*!
+     * Signal fired after the news fails to load.
+     */
+    void newsLoadingFailed(QString errorMsg);
 
 protected slots:
-	void rssDownloadFinished();
-	void rssDownloadFailed(QString reason);
+    void rssDownloadFinished();
+    void rssDownloadFailed(QString reason);
 
 protected: /* data */
-	//! The URL for the RSS feed to fetch.
-	QString m_feedUrl;
+    //! The URL for the RSS feed to fetch.
+    QString m_feedUrl;
 
-	//! List of news entries.
-	QList<NewsEntryPtr> m_newsEntries;
+    //! List of news entries.
+    QList<NewsEntryPtr> m_newsEntries;
 
-	//! The network job to use to load the news.
-	NetJobPtr m_newsNetJob;
+    //! The network job to use to load the news.
+    NetJobPtr m_newsNetJob;
 
-	//! True if news has been loaded.
-	bool m_loadedNews;
+    //! True if news has been loaded.
+    bool m_loadedNews;
 
-	QByteArray newsData;
+    QByteArray newsData;
 
-	/*!
-	 * Gets the error message that was given last time the news was loaded.
-	 * If the last news load succeeded, this will be an empty string.
-	 */
-	QString m_lastLoadError;
+    /*!
+     * Gets the error message that was given last time the news was loaded.
+     * If the last news load succeeded, this will be an empty string.
+     */
+    QString m_lastLoadError;
 
 protected slots:
-	/// Emits newsLoaded() and sets m_lastLoadError to empty string.
-	void succeed();
+    /// Emits newsLoaded() and sets m_lastLoadError to empty string.
+    void succeed();
 
-	/// Emits newsLoadingFailed() and sets m_lastLoadError to the given message.
-	void fail(const QString& errorMsg);
+    /// Emits newsLoadingFailed() and sets m_lastLoadError to the given message.
+    void fail(const QString& errorMsg);
 };
 
diff --git a/api/logic/news/NewsEntry.cpp b/api/logic/news/NewsEntry.cpp
index 4377f766..82d654be 100644
--- a/api/logic/news/NewsEntry.cpp
+++ b/api/logic/news/NewsEntry.cpp
@@ -19,23 +19,23 @@
 #include <QVariant>
 
 NewsEntry::NewsEntry(QObject* parent) :
-	QObject(parent)
+    QObject(parent)
 {
-	this->title = tr("Untitled");
-	this->content = tr("No content.");
-	this->link = "";
-	this->author = tr("Unknown Author");
-	this->pubDate = QDateTime::currentDateTime();
+    this->title = tr("Untitled");
+    this->content = tr("No content.");
+    this->link = "";
+    this->author = tr("Unknown Author");
+    this->pubDate = QDateTime::currentDateTime();
 }
 
 NewsEntry::NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent) :
-	QObject(parent)
+    QObject(parent)
 {
-	this->title = title;
-	this->content = content;
-	this->link = link;
-	this->author = author;
-	this->pubDate = pubDate;
+    this->title = title;
+    this->content = content;
+    this->link = link;
+    this->author = author;
+    this->pubDate = pubDate;
 }
 
 /*!
@@ -43,35 +43,35 @@ NewsEntry::NewsEntry(const QString& title, const QString& content, const QString
  */
 inline QString childValue(const QDomElement& element, const QString& childName, QString defaultVal="")
 {
-	QDomNodeList nodes = element.elementsByTagName(childName);
-	if (nodes.count() > 0)
-	{
-		QDomElement element = nodes.at(0).toElement();
-		return element.text();
-	}
-	else
-	{
-		return defaultVal;
-	}
+    QDomNodeList nodes = element.elementsByTagName(childName);
+    if (nodes.count() > 0)
+    {
+        QDomElement element = nodes.at(0).toElement();
+        return element.text();
+    }
+    else
+    {
+        return defaultVal;
+    }
 }
 
 bool NewsEntry::fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg)
 {
-	QString title = childValue(element, "title", tr("Untitled"));
-	QString content = childValue(element, "description", tr("No content."));
-	QString link = childValue(element, "link");
-	QString author = childValue(element, "dc:creator", tr("Unknown Author"));
-	QString pubDateStr = childValue(element, "pubDate");
+    QString title = childValue(element, "title", tr("Untitled"));
+    QString content = childValue(element, "description", tr("No content."));
+    QString link = childValue(element, "link");
+    QString author = childValue(element, "dc:creator", tr("Unknown Author"));
+    QString pubDateStr = childValue(element, "pubDate");
 
-	// FIXME: For now, we're just ignoring timezones. We assume that all time zones in the RSS feed are the same.
-	QString dateFormat("ddd, dd MMM yyyy hh:mm:ss");
-	QDateTime pubDate = QDateTime::fromString(pubDateStr, dateFormat);
+    // FIXME: For now, we're just ignoring timezones. We assume that all time zones in the RSS feed are the same.
+    QString dateFormat("ddd, dd MMM yyyy hh:mm:ss");
+    QDateTime pubDate = QDateTime::fromString(pubDateStr, dateFormat);
 
-	entry->title = title;
-	entry->content = content;
-	entry->link = link;
-	entry->author = author;
-	entry->pubDate = pubDate;
-	return true;
+    entry->title = title;
+    entry->content = content;
+    entry->link = link;
+    entry->author = author;
+    entry->pubDate = pubDate;
+    return true;
 }
 
diff --git a/api/logic/news/NewsEntry.h b/api/logic/news/NewsEntry.h
index 16a17f9c..832766fb 100644
--- a/api/logic/news/NewsEntry.h
+++ b/api/logic/news/NewsEntry.h
@@ -24,41 +24,41 @@
 
 class NewsEntry : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	/*!
-	 * Constructs an empty news entry.
-	 */
-	explicit NewsEntry(QObject* parent=0);
+    /*!
+     * Constructs an empty news entry.
+     */
+    explicit NewsEntry(QObject* parent=0);
 
-	/*!
-	 * Constructs a new news entry.
-	 * Note that content may contain HTML.
-	 */
-	NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent=0);
+    /*!
+     * Constructs a new news entry.
+     * Note that content may contain HTML.
+     */
+    NewsEntry(const QString& title, const QString& content, const QString& link, const QString& author, const QDateTime& pubDate, QObject* parent=0);
 
-	/*!
-	 * Attempts to load information from the given XML element into the given news entry pointer.
-	 * If this fails, the function will return false and store an error message in the errorMsg pointer.
-	 */
-	static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg=0);
+    /*!
+     * Attempts to load information from the given XML element into the given news entry pointer.
+     * If this fails, the function will return false and store an error message in the errorMsg pointer.
+     */
+    static bool fromXmlElement(const QDomElement& element, NewsEntry* entry, QString* errorMsg=0);
 
 
-	//! The post title.
-	QString title;
+    //! The post title.
+    QString title;
 
-	//! The post's content. May contain HTML.
-	QString content;
+    //! The post's content. May contain HTML.
+    QString content;
 
-	//! URL to the post.
-	QString link;
+    //! URL to the post.
+    QString link;
 
-	//! The post's author.
-	QString author;
-	
-	//! The date and time that this post was published.
-	QDateTime pubDate;
+    //! The post's author.
+    QString author;
+    
+    //! The date and time that this post was published.
+    QDateTime pubDate;
 };
 
 typedef std::shared_ptr<NewsEntry> NewsEntryPtr;
diff --git a/api/logic/notifications/NotificationChecker.cpp b/api/logic/notifications/NotificationChecker.cpp
index 6d006c31..8209c28b 100644
--- a/api/logic/notifications/NotificationChecker.cpp
+++ b/api/logic/notifications/NotificationChecker.cpp
@@ -10,120 +10,120 @@
 
 
 NotificationChecker::NotificationChecker(QObject *parent)
-	: QObject(parent)
+    : QObject(parent)
 {
 }
 
 void NotificationChecker::setNotificationsUrl(const QUrl &notificationsUrl)
 {
-	m_notificationsUrl = notificationsUrl;
+    m_notificationsUrl = notificationsUrl;
 }
 
 void NotificationChecker::setApplicationChannel(QString channel)
 {
-	m_appVersionChannel = channel;
+    m_appVersionChannel = channel;
 }
 
 void NotificationChecker::setApplicationFullVersion(QString version)
 {
-	m_appFullVersion = version;
+    m_appFullVersion = version;
 }
 
 void NotificationChecker::setApplicationPlatform(QString platform)
 {
-	m_appPlatform = platform;
+    m_appPlatform = platform;
 }
 
 QList<NotificationChecker::NotificationEntry> NotificationChecker::notificationEntries() const
 {
-	return m_entries;
+    return m_entries;
 }
 
 void NotificationChecker::checkForNotifications()
 {
-	if (!m_notificationsUrl.isValid())
-	{
-		qCritical() << "Failed to check for notifications. No notifications URL set."
-					 << "If you'd like to use MultiMC's notification system, please pass the "
-						"URL to CMake at compile time.";
-		return;
-	}
-	if (m_checkJob)
-	{
-		return;
-	}
-	m_checkJob.reset(new NetJob("Checking for notifications"));
-	auto entry = ENV.metacache()->resolveEntry("root", "notifications.json");
-	entry->setStale(true);
-	m_checkJob->addNetAction(m_download = Net::Download::makeCached(m_notificationsUrl, entry));
-	connect(m_download.get(), &Net::Download::succeeded, this, &NotificationChecker::downloadSucceeded);
-	m_checkJob->start();
+    if (!m_notificationsUrl.isValid())
+    {
+        qCritical() << "Failed to check for notifications. No notifications URL set."
+                     << "If you'd like to use MultiMC's notification system, please pass the "
+                        "URL to CMake at compile time.";
+        return;
+    }
+    if (m_checkJob)
+    {
+        return;
+    }
+    m_checkJob.reset(new NetJob("Checking for notifications"));
+    auto entry = ENV.metacache()->resolveEntry("root", "notifications.json");
+    entry->setStale(true);
+    m_checkJob->addNetAction(m_download = Net::Download::makeCached(m_notificationsUrl, entry));
+    connect(m_download.get(), &Net::Download::succeeded, this, &NotificationChecker::downloadSucceeded);
+    m_checkJob->start();
 }
 
 void NotificationChecker::downloadSucceeded(int)
 {
-	m_entries.clear();
-
-	QFile file(m_download->getTargetFilepath());
-	if (file.open(QFile::ReadOnly))
-	{
-		QJsonArray root = QJsonDocument::fromJson(file.readAll()).array();
-		for (auto it = root.begin(); it != root.end(); ++it)
-		{
-			QJsonObject obj = (*it).toObject();
-			NotificationEntry entry;
-			entry.id = obj.value("id").toDouble();
-			entry.message = obj.value("message").toString();
-			entry.channel = obj.value("channel").toString();
-			entry.platform = obj.value("platform").toString();
-			entry.from = obj.value("from").toString();
-			entry.to = obj.value("to").toString();
-			const QString type = obj.value("type").toString("critical");
-			if (type == "critical")
-			{
-				entry.type = NotificationEntry::Critical;
-			}
-			else if (type == "warning")
-			{
-				entry.type = NotificationEntry::Warning;
-			}
-			else if (type == "information")
-			{
-				entry.type = NotificationEntry::Information;
-			}
-			if(entryApplies(entry))
-				m_entries.append(entry);
-		}
-	}
-
-	m_checkJob.reset();
-
-	emit notificationCheckFinished();
+    m_entries.clear();
+
+    QFile file(m_download->getTargetFilepath());
+    if (file.open(QFile::ReadOnly))
+    {
+        QJsonArray root = QJsonDocument::fromJson(file.readAll()).array();
+        for (auto it = root.begin(); it != root.end(); ++it)
+        {
+            QJsonObject obj = (*it).toObject();
+            NotificationEntry entry;
+            entry.id = obj.value("id").toDouble();
+            entry.message = obj.value("message").toString();
+            entry.channel = obj.value("channel").toString();
+            entry.platform = obj.value("platform").toString();
+            entry.from = obj.value("from").toString();
+            entry.to = obj.value("to").toString();
+            const QString type = obj.value("type").toString("critical");
+            if (type == "critical")
+            {
+                entry.type = NotificationEntry::Critical;
+            }
+            else if (type == "warning")
+            {
+                entry.type = NotificationEntry::Warning;
+            }
+            else if (type == "information")
+            {
+                entry.type = NotificationEntry::Information;
+            }
+            if(entryApplies(entry))
+                m_entries.append(entry);
+        }
+    }
+
+    m_checkJob.reset();
+
+    emit notificationCheckFinished();
 }
 
 bool versionLessThan(const QString &v1, const QString &v2)
 {
-	QStringList l1 = v1.split('.');
-	QStringList l2 = v2.split('.');
-	while (!l1.isEmpty() && !l2.isEmpty())
-	{
-		int one = l1.isEmpty() ? 0 : l1.takeFirst().toInt();
-		int two = l2.isEmpty() ? 0 : l2.takeFirst().toInt();
-		if (one != two)
-		{
-			return one < two;
-		}
-	}
-	return false;
+    QStringList l1 = v1.split('.');
+    QStringList l2 = v2.split('.');
+    while (!l1.isEmpty() && !l2.isEmpty())
+    {
+        int one = l1.isEmpty() ? 0 : l1.takeFirst().toInt();
+        int two = l2.isEmpty() ? 0 : l2.takeFirst().toInt();
+        if (one != two)
+        {
+            return one < two;
+        }
+    }
+    return false;
 }
 
 bool NotificationChecker::entryApplies(const NotificationChecker::NotificationEntry& entry) const
 {
-	bool channelApplies = entry.channel.isEmpty() || entry.channel == m_appVersionChannel;
-	bool platformApplies = entry.platform.isEmpty() || entry.platform == m_appPlatform;
-	bool fromApplies =
-		entry.from.isEmpty() || entry.from == m_appFullVersion || !versionLessThan(m_appFullVersion, entry.from);
-	bool toApplies =
-		entry.to.isEmpty() || entry.to == m_appFullVersion || !versionLessThan(entry.to, m_appFullVersion);
-	return channelApplies && platformApplies && fromApplies && toApplies;
+    bool channelApplies = entry.channel.isEmpty() || entry.channel == m_appVersionChannel;
+    bool platformApplies = entry.platform.isEmpty() || entry.platform == m_appPlatform;
+    bool fromApplies =
+        entry.from.isEmpty() || entry.from == m_appFullVersion || !versionLessThan(m_appFullVersion, entry.from);
+    bool toApplies =
+        entry.to.isEmpty() || entry.to == m_appFullVersion || !versionLessThan(entry.to, m_appFullVersion);
+    return channelApplies && platformApplies && fromApplies && toApplies;
 }
diff --git a/api/logic/notifications/NotificationChecker.h b/api/logic/notifications/NotificationChecker.h
index c8e831d5..4b1b893d 100644
--- a/api/logic/notifications/NotificationChecker.h
+++ b/api/logic/notifications/NotificationChecker.h
@@ -9,55 +9,55 @@
 
 class MULTIMC_LOGIC_EXPORT NotificationChecker : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	explicit NotificationChecker(QObject *parent = 0);
-
-	void setNotificationsUrl(const QUrl &notificationsUrl);
-	void setApplicationPlatform(QString platform);
-	void setApplicationChannel(QString channel);
-	void setApplicationFullVersion(QString version);
-
-	struct NotificationEntry
-	{
-		int id;
-		QString message;
-		enum
-		{
-			Critical,
-			Warning,
-			Information
-		} type;
-		QString channel;
-		QString platform;
-		QString from;
-		QString to;
-	};
-
-	QList<NotificationEntry> notificationEntries() const;
+    explicit NotificationChecker(QObject *parent = 0);
+
+    void setNotificationsUrl(const QUrl &notificationsUrl);
+    void setApplicationPlatform(QString platform);
+    void setApplicationChannel(QString channel);
+    void setApplicationFullVersion(QString version);
+
+    struct NotificationEntry
+    {
+        int id;
+        QString message;
+        enum
+        {
+            Critical,
+            Warning,
+            Information
+        } type;
+        QString channel;
+        QString platform;
+        QString from;
+        QString to;
+    };
+
+    QList<NotificationEntry> notificationEntries() const;
 
 public
 slots:
-	void checkForNotifications();
+    void checkForNotifications();
 
 private
 slots:
-	void downloadSucceeded(int);
+    void downloadSucceeded(int);
 
 signals:
-	void notificationCheckFinished();
+    void notificationCheckFinished();
 
 private:
-	bool entryApplies(const NotificationEntry &entry) const;
+    bool entryApplies(const NotificationEntry &entry) const;
 
 private:
-	QList<NotificationEntry> m_entries;
-	QUrl m_notificationsUrl;
-	NetJobPtr m_checkJob;
-	Net::Download::Ptr m_download;
-
-	QString m_appVersionChannel;
-	QString m_appPlatform;
-	QString m_appFullVersion;
+    QList<NotificationEntry> m_entries;
+    QUrl m_notificationsUrl;
+    NetJobPtr m_checkJob;
+    Net::Download::Ptr m_download;
+
+    QString m_appVersionChannel;
+    QString m_appPlatform;
+    QString m_appFullVersion;
 };
diff --git a/api/logic/pathmatcher/FSTreeMatcher.h b/api/logic/pathmatcher/FSTreeMatcher.h
index a5bed57c..361924af 100644
--- a/api/logic/pathmatcher/FSTreeMatcher.h
+++ b/api/logic/pathmatcher/FSTreeMatcher.h
@@ -7,15 +7,15 @@
 class FSTreeMatcher : public IPathMatcher
 {
 public:
-	virtual ~FSTreeMatcher() {};
-	FSTreeMatcher(SeparatorPrefixTree<'/'> & tree) : m_fsTree(tree)
-	{
-	}
+    virtual ~FSTreeMatcher() {};
+    FSTreeMatcher(SeparatorPrefixTree<'/'> & tree) : m_fsTree(tree)
+    {
+    }
 
-	virtual bool matches(const QString &string) const override
-	{
-		return m_fsTree.covers(string);
-	}
+    virtual bool matches(const QString &string) const override
+    {
+        return m_fsTree.covers(string);
+    }
 
-	SeparatorPrefixTree<'/'> & m_fsTree;
+    SeparatorPrefixTree<'/'> & m_fsTree;
 };
diff --git a/api/logic/pathmatcher/IPathMatcher.h b/api/logic/pathmatcher/IPathMatcher.h
index 1d410947..b60621c9 100644
--- a/api/logic/pathmatcher/IPathMatcher.h
+++ b/api/logic/pathmatcher/IPathMatcher.h
@@ -4,9 +4,9 @@
 class IPathMatcher
 {
 public:
-	typedef std::shared_ptr<IPathMatcher> Ptr;
+    typedef std::shared_ptr<IPathMatcher> Ptr;
 
 public:
-	virtual ~IPathMatcher(){};
-	virtual bool matches(const QString &string) const = 0;
+    virtual ~IPathMatcher(){};
+    virtual bool matches(const QString &string) const = 0;
 };
diff --git a/api/logic/pathmatcher/MultiMatcher.h b/api/logic/pathmatcher/MultiMatcher.h
index 91f70aa4..8bc1b6ee 100644
--- a/api/logic/pathmatcher/MultiMatcher.h
+++ b/api/logic/pathmatcher/MultiMatcher.h
@@ -5,27 +5,27 @@
 class MultiMatcher : public IPathMatcher
 {
 public:
-	virtual ~MultiMatcher() {};
-	MultiMatcher()
-	{
-	}
-	MultiMatcher &add(Ptr add)
-	{
-		m_matchers.append(add);
-		return *this;
-	}
+    virtual ~MultiMatcher() {};
+    MultiMatcher()
+    {
+    }
+    MultiMatcher &add(Ptr add)
+    {
+        m_matchers.append(add);
+        return *this;
+    }
 
-	virtual bool matches(const QString &string) const override
-	{
-		for(auto iter: m_matchers)
-		{
-			if(iter->matches(string))
-			{
-				return true;
-			}
-		}
-		return false;
-	}
+    virtual bool matches(const QString &string) const override
+    {
+        for(auto iter: m_matchers)
+        {
+            if(iter->matches(string))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
 
-	QList<Ptr> m_matchers;
+    QList<Ptr> m_matchers;
 };
diff --git a/api/logic/pathmatcher/RegexpMatcher.h b/api/logic/pathmatcher/RegexpMatcher.h
index da552123..825d488c 100644
--- a/api/logic/pathmatcher/RegexpMatcher.h
+++ b/api/logic/pathmatcher/RegexpMatcher.h
@@ -4,39 +4,39 @@
 class RegexpMatcher : public IPathMatcher
 {
 public:
-	virtual ~RegexpMatcher() {};
-	RegexpMatcher(const QString &regexp)
-	{
-		m_regexp.setPattern(regexp);
-		m_onlyFilenamePart = !regexp.contains('/');
-	}
+    virtual ~RegexpMatcher() {};
+    RegexpMatcher(const QString &regexp)
+    {
+        m_regexp.setPattern(regexp);
+        m_onlyFilenamePart = !regexp.contains('/');
+    }
 
-	RegexpMatcher &caseSensitive(bool cs = true)
-	{
-		if(cs)
-		{
-			m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
-		}
-		else
-		{
-			m_regexp.setPatternOptions(QRegularExpression::NoPatternOption);
-		}
-		return *this;
-	}
+    RegexpMatcher &caseSensitive(bool cs = true)
+    {
+        if(cs)
+        {
+            m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+        }
+        else
+        {
+            m_regexp.setPatternOptions(QRegularExpression::NoPatternOption);
+        }
+        return *this;
+    }
 
-	virtual bool matches(const QString &string) const override
-	{
-		if(m_onlyFilenamePart)
-		{
-			auto slash = string.lastIndexOf('/');
-			if(slash != -1)
-			{
-				auto part = string.mid(slash + 1);
-				return m_regexp.match(part).hasMatch();
-			}
-		}
-		return m_regexp.match(string).hasMatch();
-	}
-	QRegularExpression m_regexp;
-	bool m_onlyFilenamePart = false;
+    virtual bool matches(const QString &string) const override
+    {
+        if(m_onlyFilenamePart)
+        {
+            auto slash = string.lastIndexOf('/');
+            if(slash != -1)
+            {
+                auto part = string.mid(slash + 1);
+                return m_regexp.match(part).hasMatch();
+            }
+        }
+        return m_regexp.match(string).hasMatch();
+    }
+    QRegularExpression m_regexp;
+    bool m_onlyFilenamePart = false;
 };
diff --git a/api/logic/screenshots/ImgurAlbumCreation.cpp b/api/logic/screenshots/ImgurAlbumCreation.cpp
index 3724e3df..3d32f597 100644
--- a/api/logic/screenshots/ImgurAlbumCreation.cpp
+++ b/api/logic/screenshots/ImgurAlbumCreation.cpp
@@ -12,77 +12,77 @@
 
 ImgurAlbumCreation::ImgurAlbumCreation(QList<ScreenshotPtr> screenshots) : NetAction(), m_screenshots(screenshots)
 {
-	m_url = URLConstants::IMGUR_BASE_URL + "album.json";
-	m_status = Job_NotStarted;
+    m_url = URLConstants::IMGUR_BASE_URL + "album.json";
+    m_status = Job_NotStarted;
 }
 
 void ImgurAlbumCreation::start()
 {
-	m_status = Job_InProgress;
-	QNetworkRequest request(m_url);
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
-	request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
-	request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
-	request.setRawHeader("Accept", "application/json");
+    m_status = Job_InProgress;
+    QNetworkRequest request(m_url);
+    request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
+    request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
+    request.setRawHeader("Accept", "application/json");
 
-	QStringList hashes;
-	for (auto shot : m_screenshots)
-	{
-		hashes.append(shot->m_imgurDeleteHash);
-	}
+    QStringList hashes;
+    for (auto shot : m_screenshots)
+    {
+        hashes.append(shot->m_imgurDeleteHash);
+    }
 
-	const QByteArray data = "deletehashes=" + hashes.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden";
+    const QByteArray data = "deletehashes=" + hashes.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden";
 
-	QNetworkReply *rep = ENV.qnam().post(request, data);
+    QNetworkReply *rep = ENV.qnam().post(request, data);
 
-	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)));
+    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)));
 }
 void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error)
 {
-	qDebug() << m_reply->errorString();
-	m_status = Job_Failed;
+    qDebug() << m_reply->errorString();
+    m_status = Job_Failed;
 }
 void ImgurAlbumCreation::downloadFinished()
 {
-	if (m_status != Job_Failed)
-	{
-		QByteArray data = m_reply->readAll();
-		m_reply.reset();
-		QJsonParseError jsonError;
-		QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
-		if (jsonError.error != QJsonParseError::NoError)
-		{
-			qDebug() << jsonError.errorString();
-			emit failed(m_index_within_job);
-			return;
-		}
-		auto object = doc.object();
-		if (!object.value("success").toBool())
-		{
-			qDebug() << doc.toJson();
-			emit failed(m_index_within_job);
-			return;
-		}
-		m_deleteHash = object.value("data").toObject().value("deletehash").toString();
-		m_id = object.value("data").toObject().value("id").toString();
-		m_status = Job_Finished;
-		emit succeeded(m_index_within_job);
-		return;
-	}
-	else
-	{
-		qDebug() << m_reply->readAll();
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		return;
-	}
+    if (m_status != Job_Failed)
+    {
+        QByteArray data = m_reply->readAll();
+        m_reply.reset();
+        QJsonParseError jsonError;
+        QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
+        if (jsonError.error != QJsonParseError::NoError)
+        {
+            qDebug() << jsonError.errorString();
+            emit failed(m_index_within_job);
+            return;
+        }
+        auto object = doc.object();
+        if (!object.value("success").toBool())
+        {
+            qDebug() << doc.toJson();
+            emit failed(m_index_within_job);
+            return;
+        }
+        m_deleteHash = object.value("data").toObject().value("deletehash").toString();
+        m_id = object.value("data").toObject().value("id").toString();
+        m_status = Job_Finished;
+        emit succeeded(m_index_within_job);
+        return;
+    }
+    else
+    {
+        qDebug() << m_reply->readAll();
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        return;
+    }
 }
 void ImgurAlbumCreation::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	m_total_progress = bytesTotal;
-	m_progress = bytesReceived;
-	emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
+    m_total_progress = bytesTotal;
+    m_progress = bytesReceived;
+    emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
 }
diff --git a/api/logic/screenshots/ImgurAlbumCreation.h b/api/logic/screenshots/ImgurAlbumCreation.h
index 469174e4..55478021 100644
--- a/api/logic/screenshots/ImgurAlbumCreation.h
+++ b/api/logic/screenshots/ImgurAlbumCreation.h
@@ -8,37 +8,37 @@ typedef std::shared_ptr<class ImgurAlbumCreation> ImgurAlbumCreationPtr;
 class MULTIMC_LOGIC_EXPORT ImgurAlbumCreation : public NetAction
 {
 public:
-	explicit ImgurAlbumCreation(QList<ScreenshotPtr> screenshots);
-	static ImgurAlbumCreationPtr make(QList<ScreenshotPtr> screenshots)
-	{
-		return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots));
-	}
+    explicit ImgurAlbumCreation(QList<ScreenshotPtr> screenshots);
+    static ImgurAlbumCreationPtr make(QList<ScreenshotPtr> screenshots)
+    {
+        return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots));
+    }
 
-	QString deleteHash() const
-	{
-		return m_deleteHash;
-	}
-	QString id() const
-	{
-		return m_id;
-	}
+    QString deleteHash() const
+    {
+        return m_deleteHash;
+    }
+    QString id() const
+    {
+        return m_id;
+    }
 
 protected
 slots:
-	virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
-	virtual void downloadError(QNetworkReply::NetworkError error);
-	virtual void downloadFinished();
-	virtual void downloadReadyRead()
-	{
-	}
+    virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+    virtual void downloadError(QNetworkReply::NetworkError error);
+    virtual void downloadFinished();
+    virtual void downloadReadyRead()
+    {
+    }
 
 public
 slots:
-	virtual void start();
+    virtual void start();
 
 private:
-	QList<ScreenshotPtr> m_screenshots;
+    QList<ScreenshotPtr> m_screenshots;
 
-	QString m_deleteHash;
-	QString m_id;
+    QString m_deleteHash;
+    QString m_id;
 };
diff --git a/api/logic/screenshots/ImgurUpload.cpp b/api/logic/screenshots/ImgurUpload.cpp
index 659879f6..74165869 100644
--- a/api/logic/screenshots/ImgurUpload.cpp
+++ b/api/logic/screenshots/ImgurUpload.cpp
@@ -14,101 +14,101 @@
 
 ImgurUpload::ImgurUpload(ScreenshotPtr shot) : NetAction(), m_shot(shot)
 {
-	m_url = URLConstants::IMGUR_BASE_URL + "upload.json";
-	m_status = Job_NotStarted;
+    m_url = URLConstants::IMGUR_BASE_URL + "upload.json";
+    m_status = Job_NotStarted;
 }
 
 void ImgurUpload::start()
 {
-	finished = false;
-	m_status = Job_InProgress;
-	QNetworkRequest request(m_url);
-	request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
-	request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
-	request.setRawHeader("Accept", "application/json");
+    finished = false;
+    m_status = Job_InProgress;
+    QNetworkRequest request(m_url);
+    request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
+    request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3");
+    request.setRawHeader("Accept", "application/json");
 
-	QFile f(m_shot->m_file.absoluteFilePath());
-	if (!f.open(QFile::ReadOnly))
-	{
-		emit failed(m_index_within_job);
-		return;
-	}
+    QFile f(m_shot->m_file.absoluteFilePath());
+    if (!f.open(QFile::ReadOnly))
+    {
+        emit failed(m_index_within_job);
+        return;
+    }
 
-	QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
-	QHttpPart filePart;
-	filePart.setBody(f.readAll().toBase64());
-	filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
-	filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"image\"");
-	multipart->append(filePart);
-	QHttpPart typePart;
-	typePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"type\"");
-	typePart.setBody("base64");
-	multipart->append(typePart);
-	QHttpPart namePart;
-	namePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"name\"");
-	namePart.setBody(m_shot->m_file.baseName().toUtf8());
-	multipart->append(namePart);
+    QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
+    QHttpPart filePart;
+    filePart.setBody(f.readAll().toBase64());
+    filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
+    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"image\"");
+    multipart->append(filePart);
+    QHttpPart typePart;
+    typePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"type\"");
+    typePart.setBody("base64");
+    multipart->append(typePart);
+    QHttpPart namePart;
+    namePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"name\"");
+    namePart.setBody(m_shot->m_file.baseName().toUtf8());
+    multipart->append(namePart);
 
-	QNetworkReply *rep = ENV.qnam().post(request, multipart);
+    QNetworkReply *rep = ENV.qnam().post(request, multipart);
 
-	m_reply.reset(rep);
-	connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress);
-	connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished);
-	connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
-			SLOT(downloadError(QNetworkReply::NetworkError)));
+    m_reply.reset(rep);
+    connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress);
+    connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished);
+    connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+            SLOT(downloadError(QNetworkReply::NetworkError)));
 }
 void ImgurUpload::downloadError(QNetworkReply::NetworkError error)
 {
-	qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll();
-	if(finished)
-	{
-		qCritical() << "Double finished ImgurUpload!";
-		return;
-	}
-	m_status = Job_Failed;
-	finished = true;
-	m_reply.reset();
-	emit failed(m_index_within_job);
+    qCritical() << "ImgurUpload failed with error" << m_reply->errorString() << "Server reply:\n" << m_reply->readAll();
+    if(finished)
+    {
+        qCritical() << "Double finished ImgurUpload!";
+        return;
+    }
+    m_status = Job_Failed;
+    finished = true;
+    m_reply.reset();
+    emit failed(m_index_within_job);
 }
 void ImgurUpload::downloadFinished()
 {
-	if(finished)
-	{
-		qCritical() << "Double finished ImgurUpload!";
-		return;
-	}
-	QByteArray data = m_reply->readAll();
-	m_reply.reset();
-	QJsonParseError jsonError;
-	QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
-	if (jsonError.error != QJsonParseError::NoError)
-	{
-		qDebug() << "imgur server did not reply with JSON" << jsonError.errorString();
-		finished = true;
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		return;
-	}
-	auto object = doc.object();
-	if (!object.value("success").toBool())
-	{
-		qDebug() << "Screenshot upload not successful:" << doc.toJson();
-		finished = true;
-		m_reply.reset();
-		emit failed(m_index_within_job);
-		return;
-	}
-	m_shot->m_imgurId = object.value("data").toObject().value("id").toString();
-	m_shot->m_url = object.value("data").toObject().value("link").toString();
-	m_shot->m_imgurDeleteHash = object.value("data").toObject().value("deletehash").toString();
-	m_status = Job_Finished;
-	finished = true;
-	emit succeeded(m_index_within_job);
-	return;
+    if(finished)
+    {
+        qCritical() << "Double finished ImgurUpload!";
+        return;
+    }
+    QByteArray data = m_reply->readAll();
+    m_reply.reset();
+    QJsonParseError jsonError;
+    QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
+    if (jsonError.error != QJsonParseError::NoError)
+    {
+        qDebug() << "imgur server did not reply with JSON" << jsonError.errorString();
+        finished = true;
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        return;
+    }
+    auto object = doc.object();
+    if (!object.value("success").toBool())
+    {
+        qDebug() << "Screenshot upload not successful:" << doc.toJson();
+        finished = true;
+        m_reply.reset();
+        emit failed(m_index_within_job);
+        return;
+    }
+    m_shot->m_imgurId = object.value("data").toObject().value("id").toString();
+    m_shot->m_url = object.value("data").toObject().value("link").toString();
+    m_shot->m_imgurDeleteHash = object.value("data").toObject().value("deletehash").toString();
+    m_status = Job_Finished;
+    finished = true;
+    emit succeeded(m_index_within_job);
+    return;
 }
 void ImgurUpload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
-	m_total_progress = bytesTotal;
-	m_progress = bytesReceived;
-	emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
+    m_total_progress = bytesTotal;
+    m_progress = bytesReceived;
+    emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
 }
diff --git a/api/logic/screenshots/ImgurUpload.h b/api/logic/screenshots/ImgurUpload.h
index 0a766b8f..d79807f2 100644
--- a/api/logic/screenshots/ImgurUpload.h
+++ b/api/logic/screenshots/ImgurUpload.h
@@ -8,26 +8,26 @@ typedef std::shared_ptr<class ImgurUpload> ImgurUploadPtr;
 class MULTIMC_LOGIC_EXPORT ImgurUpload : public NetAction
 {
 public:
-	explicit ImgurUpload(ScreenshotPtr shot);
-	static ImgurUploadPtr make(ScreenshotPtr shot)
-	{
-		return ImgurUploadPtr(new ImgurUpload(shot));
-	}
+    explicit ImgurUpload(ScreenshotPtr shot);
+    static ImgurUploadPtr make(ScreenshotPtr shot)
+    {
+        return ImgurUploadPtr(new ImgurUpload(shot));
+    }
 
 protected
 slots:
-	virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
-	virtual void downloadError(QNetworkReply::NetworkError error);
-	virtual void downloadFinished();
-	virtual void downloadReadyRead()
-	{
-	}
+    virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+    virtual void downloadError(QNetworkReply::NetworkError error);
+    virtual void downloadFinished();
+    virtual void downloadReadyRead()
+    {
+    }
 
 public
 slots:
-	virtual void start();
+    virtual void start();
 
 private:
-	ScreenshotPtr m_shot;
-	bool finished = true;
+    ScreenshotPtr m_shot;
+    bool finished = true;
 };
diff --git a/api/logic/screenshots/Screenshot.h b/api/logic/screenshots/Screenshot.h
index 2c70ecf5..9db3a8a1 100644
--- a/api/logic/screenshots/Screenshot.h
+++ b/api/logic/screenshots/Screenshot.h
@@ -7,14 +7,14 @@
 
 struct ScreenShot
 {
-	ScreenShot(QFileInfo file)
-	{
-		m_file = file;
-	}
-	QFileInfo m_file;
-	QString m_url;
-	QString m_imgurId;
-	QString m_imgurDeleteHash;
+    ScreenShot(QFileInfo file)
+    {
+        m_file = file;
+    }
+    QFileInfo m_file;
+    QString m_url;
+    QString m_imgurId;
+    QString m_imgurDeleteHash;
 };
 
 typedef std::shared_ptr<ScreenShot> ScreenshotPtr;
diff --git a/api/logic/settings/INIFile.cpp b/api/logic/settings/INIFile.cpp
index 67c6cf29..5431443e 100644
--- a/api/logic/settings/INIFile.cpp
+++ b/api/logic/settings/INIFile.cpp
@@ -28,124 +28,124 @@ INIFile::INIFile()
 
 QString INIFile::unescape(QString orig)
 {
-	QString out;
-	QChar prev = 0;
-	for(auto c: orig)
-	{
-		if(prev == '\\')
-		{
-			if(c == 'n')
-				out += '\n';
-			else if (c == 't')
-				out += '\t';
-			else
-				out += c;
-			prev = 0;
-		}
-		else
-		{
-			if(c == '\\')
-			{
-				prev = c;
-				continue;
-			}
-			out += c;
-			prev = 0;
-		}
-	}
-	return out;
+    QString out;
+    QChar prev = 0;
+    for(auto c: orig)
+    {
+        if(prev == '\\')
+        {
+            if(c == 'n')
+                out += '\n';
+            else if (c == 't')
+                out += '\t';
+            else
+                out += c;
+            prev = 0;
+        }
+        else
+        {
+            if(c == '\\')
+            {
+                prev = c;
+                continue;
+            }
+            out += c;
+            prev = 0;
+        }
+    }
+    return out;
 }
 
 QString INIFile::escape(QString orig)
 {
-	QString out;
-	for(auto c: orig)
-	{
-		if(c == '\n')
-			out += "\\n";
-		else if (c == '\t')
-			out += "\\t";
-		else if(c == '\\')
-			out += "\\\\";
-		else
-			out += c;
-	}
-	return out;
+    QString out;
+    for(auto c: orig)
+    {
+        if(c == '\n')
+            out += "\\n";
+        else if (c == '\t')
+            out += "\\t";
+        else if(c == '\\')
+            out += "\\\\";
+        else
+            out += c;
+    }
+    return out;
 }
 
 bool INIFile::saveFile(QString fileName)
 {
-	QByteArray outArray;
-	for (Iterator iter = begin(); iter != end(); iter++)
-	{
-		QString value = iter.value().toString();
-		value = escape(value);
-		outArray.append(iter.key().toUtf8());
-		outArray.append('=');
-		outArray.append(value.toUtf8());
-		outArray.append('\n');
-	}
-
-	try
-	{
-		FS::write(fileName, outArray);
-	}
-	catch (const Exception &e)
-	{
-		qCritical() << e.what();
-		return false;
-	}
-
-	return true;
+    QByteArray outArray;
+    for (Iterator iter = begin(); iter != end(); iter++)
+    {
+        QString value = iter.value().toString();
+        value = escape(value);
+        outArray.append(iter.key().toUtf8());
+        outArray.append('=');
+        outArray.append(value.toUtf8());
+        outArray.append('\n');
+    }
+
+    try
+    {
+        FS::write(fileName, outArray);
+    }
+    catch (const Exception &e)
+    {
+        qCritical() << e.what();
+        return false;
+    }
+
+    return true;
 }
 
 
 bool INIFile::loadFile(QString fileName)
 {
-	QFile file(fileName);
-	if (!file.open(QIODevice::ReadOnly))
-		return false;
-	bool success = loadFile(file.readAll());
-	file.close();
-	return success;
+    QFile file(fileName);
+    if (!file.open(QIODevice::ReadOnly))
+        return false;
+    bool success = loadFile(file.readAll());
+    file.close();
+    return success;
 }
 
 bool INIFile::loadFile(QByteArray file)
 {
-	QTextStream in(file);
-	in.setCodec("UTF-8");
+    QTextStream in(file);
+    in.setCodec("UTF-8");
 
-	QStringList lines = in.readAll().split('\n');
-	for (int i = 0; i < lines.count(); i++)
-	{
-		QString &lineRaw = lines[i];
-		// Ignore comments.
-		QString line = lineRaw.left(lineRaw.indexOf('#')).trimmed();
+    QStringList lines = in.readAll().split('\n');
+    for (int i = 0; i < lines.count(); i++)
+    {
+        QString &lineRaw = lines[i];
+        // Ignore comments.
+        QString line = lineRaw.left(lineRaw.indexOf('#')).trimmed();
 
-		int eqPos = line.indexOf('=');
-		if (eqPos == -1)
-			continue;
-		QString key = line.left(eqPos).trimmed();
-		QString valueStr = line.right(line.length() - eqPos - 1).trimmed();
+        int eqPos = line.indexOf('=');
+        if (eqPos == -1)
+            continue;
+        QString key = line.left(eqPos).trimmed();
+        QString valueStr = line.right(line.length() - eqPos - 1).trimmed();
 
-		valueStr = unescape(valueStr);
+        valueStr = unescape(valueStr);
 
-		QVariant value(valueStr);
-		this->operator[](key) = value;
-	}
+        QVariant value(valueStr);
+        this->operator[](key) = value;
+    }
 
-	return true;
+    return true;
 }
 
 QVariant INIFile::get(QString key, QVariant def) const
 {
-	if (!this->contains(key))
-		return def;
-	else
-		return this->operator[](key);
+    if (!this->contains(key))
+        return def;
+    else
+        return this->operator[](key);
 }
 
 void INIFile::set(QString key, QVariant val)
 {
-	this->operator[](key) = val;
+    this->operator[](key) = val;
 }
diff --git a/api/logic/settings/INIFile.h b/api/logic/settings/INIFile.h
index f0c63d3c..bdf7fd9a 100644
--- a/api/logic/settings/INIFile.h
+++ b/api/logic/settings/INIFile.h
@@ -25,14 +25,14 @@
 class MULTIMC_LOGIC_EXPORT INIFile : public QMap<QString, QVariant>
 {
 public:
-	explicit INIFile();
+    explicit INIFile();
 
-	bool loadFile(QByteArray file);
-	bool loadFile(QString fileName);
-	bool saveFile(QString fileName);
+    bool loadFile(QByteArray file);
+    bool loadFile(QString fileName);
+    bool saveFile(QString fileName);
 
-	QVariant get(QString key, QVariant def) const;
-	void set(QString key, QVariant val);
-	static QString unescape(QString orig);
-	static QString escape(QString orig);
+    QVariant get(QString key, QVariant def) const;
+    void set(QString key, QVariant val);
+    static QString unescape(QString orig);
+    static QString escape(QString orig);
 };
diff --git a/api/logic/settings/INIFile_test.cpp b/api/logic/settings/INIFile_test.cpp
index b3ae7375..45f70973 100644
--- a/api/logic/settings/INIFile_test.cpp
+++ b/api/logic/settings/INIFile_test.cpp
@@ -5,56 +5,56 @@
 
 class IniFileTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void initTestCase()
-	{
-
-	}
-	void cleanupTestCase()
-	{
-
-	}
-
-	void test_Escape_data()
-	{
-		QTest::addColumn<QString>("through");
-
-		QTest::newRow("unix path") << "/abc/def/ghi/jkl";
-		QTest::newRow("windows path") << "C:\\Program files\\terrible\\name\\of something\\";
-		QTest::newRow("Plain text") << "Lorem ipsum dolor sit amet.";
-		QTest::newRow("Escape sequences") << "Lorem\n\t\n\\n\\tAAZ\nipsum dolor\n\nsit amet.";
-		QTest::newRow("Escape sequences 2") << "\"\n\n\"";
-	}
-	void test_Escape()
-	{
-		QFETCH(QString, through);
-
-		QString there = INIFile::escape(through);
-		QString back = INIFile::unescape(there);
-
-		QCOMPARE(back, through);
-	}
-
-	void test_SaveLoad()
-	{
-		QString a = "a";
-		QString b = "a\nb\t\n\\\\\\C:\\Program files\\terrible\\name\\of something\\";
-		QString filename = "test_SaveLoad.ini";
-
-		// save
-		INIFile f;
-		f.set("a", a);
-		f.set("b", b);
-		f.saveFile(filename);
-
-		// load
-		INIFile f2;
-		f2.loadFile(filename);
-		QCOMPARE(a, f2.get("a","NOT SET").toString());
-		QCOMPARE(b, f2.get("b","NOT SET").toString());
-	}
+    void initTestCase()
+    {
+
+    }
+    void cleanupTestCase()
+    {
+
+    }
+
+    void test_Escape_data()
+    {
+        QTest::addColumn<QString>("through");
+
+        QTest::newRow("unix path") << "/abc/def/ghi/jkl";
+        QTest::newRow("windows path") << "C:\\Program files\\terrible\\name\\of something\\";
+        QTest::newRow("Plain text") << "Lorem ipsum dolor sit amet.";
+        QTest::newRow("Escape sequences") << "Lorem\n\t\n\\n\\tAAZ\nipsum dolor\n\nsit amet.";
+        QTest::newRow("Escape sequences 2") << "\"\n\n\"";
+    }
+    void test_Escape()
+    {
+        QFETCH(QString, through);
+
+        QString there = INIFile::escape(through);
+        QString back = INIFile::unescape(there);
+
+        QCOMPARE(back, through);
+    }
+
+    void test_SaveLoad()
+    {
+        QString a = "a";
+        QString b = "a\nb\t\n\\\\\\C:\\Program files\\terrible\\name\\of something\\";
+        QString filename = "test_SaveLoad.ini";
+
+        // save
+        INIFile f;
+        f.set("a", a);
+        f.set("b", b);
+        f.saveFile(filename);
+
+        // load
+        INIFile f2;
+        f2.loadFile(filename);
+        QCOMPARE(a, f2.get("a","NOT SET").toString());
+        QCOMPARE(b, f2.get("b","NOT SET").toString());
+    }
 };
 
 QTEST_GUILESS_MAIN(IniFileTest)
diff --git a/api/logic/settings/INISettingsObject.cpp b/api/logic/settings/INISettingsObject.cpp
index ff2cee31..43791c24 100644
--- a/api/logic/settings/INISettingsObject.cpp
+++ b/api/logic/settings/INISettingsObject.cpp
@@ -17,91 +17,91 @@
 #include "Setting.h"
 
 INISettingsObject::INISettingsObject(const QString &path, QObject *parent)
-	: SettingsObject(parent)
+    : SettingsObject(parent)
 {
-	m_filePath = path;
-	m_ini.loadFile(path);
+    m_filePath = path;
+    m_ini.loadFile(path);
 }
 
 void INISettingsObject::setFilePath(const QString &filePath)
 {
-	m_filePath = filePath;
+    m_filePath = filePath;
 }
 
 bool INISettingsObject::reload()
 {
-	return m_ini.loadFile(m_filePath) && SettingsObject::reload();
+    return m_ini.loadFile(m_filePath) && SettingsObject::reload();
 }
 
 void INISettingsObject::suspendSave()
 {
-	m_suspendSave = true;
+    m_suspendSave = true;
 }
 
 void INISettingsObject::resumeSave()
 {
-	m_suspendSave = false;
-	if(m_doSave)
-	{
-		m_ini.saveFile(m_filePath);
-	}
+    m_suspendSave = false;
+    if(m_doSave)
+    {
+        m_ini.saveFile(m_filePath);
+    }
 }
 
 void INISettingsObject::changeSetting(const Setting &setting, QVariant value)
 {
-	if (contains(setting.id()))
-	{
-		// valid value -> set the main config, remove all the sysnonyms
-		if (value.isValid())
-		{
-			auto list = setting.configKeys();
-			m_ini.set(list.takeFirst(), value);
-			for(auto iter: list)
-				m_ini.remove(iter);
-		}
-		// invalid -> remove all (just like resetSetting)
-		else
-		{
-			for(auto iter: setting.configKeys())
-				m_ini.remove(iter);
-		}
-		doSave();
-	}
+    if (contains(setting.id()))
+    {
+        // valid value -> set the main config, remove all the sysnonyms
+        if (value.isValid())
+        {
+            auto list = setting.configKeys();
+            m_ini.set(list.takeFirst(), value);
+            for(auto iter: list)
+                m_ini.remove(iter);
+        }
+        // invalid -> remove all (just like resetSetting)
+        else
+        {
+            for(auto iter: setting.configKeys())
+                m_ini.remove(iter);
+        }
+        doSave();
+    }
 }
 
 void INISettingsObject::doSave()
 {
-	if(m_suspendSave)
-	{
-		m_doSave = true;
-	}
-	else
-	{
-		m_ini.saveFile(m_filePath);
-	}
+    if(m_suspendSave)
+    {
+        m_doSave = true;
+    }
+    else
+    {
+        m_ini.saveFile(m_filePath);
+    }
 }
 
 void INISettingsObject::resetSetting(const Setting &setting)
 {
-	// if we have the setting, remove all the synonyms. ALL OF THEM
-	if (contains(setting.id()))
-	{
-		for(auto iter: setting.configKeys())
-			m_ini.remove(iter);
-		doSave();
-	}
+    // if we have the setting, remove all the synonyms. ALL OF THEM
+    if (contains(setting.id()))
+    {
+        for(auto iter: setting.configKeys())
+            m_ini.remove(iter);
+        doSave();
+    }
 }
 
 QVariant INISettingsObject::retrieveValue(const Setting &setting)
 {
-	// if we have the setting, return value of the first matching synonym
-	if (contains(setting.id()))
-	{
-		for(auto iter: setting.configKeys())
-		{
-			if(m_ini.contains(iter))
-				return m_ini[iter];
-		}
-	}
-	return QVariant();
+    // if we have the setting, return value of the first matching synonym
+    if (contains(setting.id()))
+    {
+        for(auto iter: setting.configKeys())
+        {
+            if(m_ini.contains(iter))
+                return m_ini[iter];
+        }
+    }
+    return QVariant();
 }
diff --git a/api/logic/settings/INISettingsObject.h b/api/logic/settings/INISettingsObject.h
index 111215e6..3fc09593 100644
--- a/api/logic/settings/INISettingsObject.h
+++ b/api/logic/settings/INISettingsObject.h
@@ -28,39 +28,39 @@
  */
 class MULTIMC_LOGIC_EXPORT INISettingsObject : public SettingsObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit INISettingsObject(const QString &path, QObject *parent = 0);
+    explicit INISettingsObject(const QString &path, QObject *parent = 0);
 
-	/*!
-	 * \brief Gets the path to the INI file.
-	 * \return The path to the INI file.
-	 */
-	virtual QString filePath() const
-	{
-		return m_filePath;
-	}
+    /*!
+     * \brief Gets the path to the INI file.
+     * \return The path to the INI file.
+     */
+    virtual QString filePath() const
+    {
+        return m_filePath;
+    }
 
-	/*!
-	 * \brief Sets the path to the INI file and reloads it.
-	 * \param filePath The INI file's new path.
-	 */
-	virtual void setFilePath(const QString &filePath);
+    /*!
+     * \brief Sets the path to the INI file and reloads it.
+     * \param filePath The INI file's new path.
+     */
+    virtual void setFilePath(const QString &filePath);
 
-	bool reload() override;
+    bool reload() override;
 
-	void suspendSave() override;
-	void resumeSave() override;
+    void suspendSave() override;
+    void resumeSave() override;
 
 protected slots:
-	virtual void changeSetting(const Setting &setting, QVariant value) override;
-	virtual void resetSetting(const Setting &setting) override;
+    virtual void changeSetting(const Setting &setting, QVariant value) override;
+    virtual void resetSetting(const Setting &setting) override;
 
 protected:
-	virtual QVariant retrieveValue(const Setting &setting) override;
-	void doSave();
+    virtual QVariant retrieveValue(const Setting &setting) override;
+    void doSave();
 
 protected:
-	INIFile m_ini;
-	QString m_filePath;
+    INIFile m_ini;
+    QString m_filePath;
 };
diff --git a/api/logic/settings/OverrideSetting.cpp b/api/logic/settings/OverrideSetting.cpp
index a3d48e03..e0e407bd 100644
--- a/api/logic/settings/OverrideSetting.cpp
+++ b/api/logic/settings/OverrideSetting.cpp
@@ -16,39 +16,39 @@
 #include "OverrideSetting.h"
 
 OverrideSetting::OverrideSetting(std::shared_ptr<Setting> other, std::shared_ptr<Setting> gate)
-	: Setting(other->configKeys(), QVariant())
+    : Setting(other->configKeys(), QVariant())
 {
-	Q_ASSERT(other);
-	Q_ASSERT(gate);
-	m_other = other;
-	m_gate = gate;
+    Q_ASSERT(other);
+    Q_ASSERT(gate);
+    m_other = other;
+    m_gate = gate;
 }
 
 bool OverrideSetting::isOverriding() const
 {
-	return m_gate->get().toBool();
+    return m_gate->get().toBool();
 }
 
 QVariant OverrideSetting::defValue() const
 {
-	return m_other->get();
+    return m_other->get();
 }
 
 QVariant OverrideSetting::get() const
 {
-	if(isOverriding())
-	{
-		return Setting::get();
-	}
-	return m_other->get();
+    if(isOverriding())
+    {
+        return Setting::get();
+    }
+    return m_other->get();
 }
 
 void OverrideSetting::reset()
 {
-	Setting::reset();
+    Setting::reset();
 }
 
 void OverrideSetting::set(QVariant value)
 {
-	Setting::set(value);
+    Setting::set(value);
 }
diff --git a/api/logic/settings/OverrideSetting.h b/api/logic/settings/OverrideSetting.h
index f2cbc5dc..db28e2fc 100644
--- a/api/logic/settings/OverrideSetting.h
+++ b/api/logic/settings/OverrideSetting.h
@@ -28,19 +28,19 @@
  */
 class OverrideSetting : public Setting
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit OverrideSetting(std::shared_ptr<Setting> overriden, std::shared_ptr<Setting> gate);
+    explicit OverrideSetting(std::shared_ptr<Setting> overriden, std::shared_ptr<Setting> gate);
 
-	virtual QVariant defValue() const;
-	virtual QVariant get() const;
-	virtual void set (QVariant value);
-	virtual void reset();
+    virtual QVariant defValue() const;
+    virtual QVariant get() const;
+    virtual void set (QVariant value);
+    virtual void reset();
 
 private:
-	bool isOverriding() const;
+    bool isOverriding() const;
 
 protected:
-	std::shared_ptr<Setting> m_other;
-	std::shared_ptr<Setting> m_gate;
+    std::shared_ptr<Setting> m_other;
+    std::shared_ptr<Setting> m_gate;
 };
diff --git a/api/logic/settings/PassthroughSetting.cpp b/api/logic/settings/PassthroughSetting.cpp
index 5da5d11c..58522385 100644
--- a/api/logic/settings/PassthroughSetting.cpp
+++ b/api/logic/settings/PassthroughSetting.cpp
@@ -16,54 +16,54 @@
 #include "PassthroughSetting.h"
 
 PassthroughSetting::PassthroughSetting(std::shared_ptr<Setting> other, std::shared_ptr<Setting> gate)
-	: Setting(other->configKeys(), QVariant())
+    : Setting(other->configKeys(), QVariant())
 {
-	Q_ASSERT(other);
-	m_other = other;
-	m_gate = gate;
+    Q_ASSERT(other);
+    m_other = other;
+    m_gate = gate;
 }
 
 bool PassthroughSetting::isOverriding() const
 {
-	if(!m_gate)
-	{
-		return false;
-	}
-	return m_gate->get().toBool();
+    if(!m_gate)
+    {
+        return false;
+    }
+    return m_gate->get().toBool();
 }
 
 QVariant PassthroughSetting::defValue() const
 {
-	if(isOverriding())
-	{
-		return m_other->get();
-	}
-	return m_other->defValue();
+    if(isOverriding())
+    {
+        return m_other->get();
+    }
+    return m_other->defValue();
 }
 
 QVariant PassthroughSetting::get() const
 {
-	if(isOverriding())
-	{
-		return Setting::get();
-	}
-	return m_other->get();
+    if(isOverriding())
+    {
+        return Setting::get();
+    }
+    return m_other->get();
 }
 
 void PassthroughSetting::reset()
 {
-	if(isOverriding())
-	{
-		Setting::reset();
-	}
-	m_other->reset();
+    if(isOverriding())
+    {
+        Setting::reset();
+    }
+    m_other->reset();
 }
 
 void PassthroughSetting::set(QVariant value)
 {
-	if(isOverriding())
-	{
-		Setting::set(value);
-	}
-	m_other->set(value);
+    if(isOverriding())
+    {
+        Setting::set(value);
+    }
+    m_other->set(value);
 }
diff --git a/api/logic/settings/PassthroughSetting.h b/api/logic/settings/PassthroughSetting.h
index ee844da4..7999be97 100644
--- a/api/logic/settings/PassthroughSetting.h
+++ b/api/logic/settings/PassthroughSetting.h
@@ -27,19 +27,19 @@
  */
 class PassthroughSetting : public Setting
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit PassthroughSetting(std::shared_ptr<Setting> overriden, std::shared_ptr<Setting> gate);
+    explicit PassthroughSetting(std::shared_ptr<Setting> overriden, std::shared_ptr<Setting> gate);
 
-	virtual QVariant defValue() const;
-	virtual QVariant get() const;
-	virtual void set (QVariant value);
-	virtual void reset();
+    virtual QVariant defValue() const;
+    virtual QVariant get() const;
+    virtual void set (QVariant value);
+    virtual void reset();
 
 private:
-	bool isOverriding() const;
+    bool isOverriding() const;
 
 protected:
-	std::shared_ptr<Setting> m_other;
-	std::shared_ptr<Setting> m_gate;
+    std::shared_ptr<Setting> m_other;
+    std::shared_ptr<Setting> m_gate;
 };
diff --git a/api/logic/settings/Setting.cpp b/api/logic/settings/Setting.cpp
index fa0041e0..8bb42f5e 100644
--- a/api/logic/settings/Setting.cpp
+++ b/api/logic/settings/Setting.cpp
@@ -17,37 +17,37 @@
 #include "settings/SettingsObject.h"
 
 Setting::Setting(QStringList synonyms, QVariant defVal)
-	: QObject(), m_synonyms(synonyms), m_defVal(defVal)
+    : QObject(), m_synonyms(synonyms), m_defVal(defVal)
 {
 }
 
 QVariant Setting::get() const
 {
-	SettingsObject *sbase = m_storage;
-	if (!sbase)
-	{
-		return defValue();
-	}
-	else
-	{
-		QVariant test = sbase->retrieveValue(*this);
-		if (!test.isValid())
-			return defValue();
-		return test;
-	}
+    SettingsObject *sbase = m_storage;
+    if (!sbase)
+    {
+        return defValue();
+    }
+    else
+    {
+        QVariant test = sbase->retrieveValue(*this);
+        if (!test.isValid())
+            return defValue();
+        return test;
+    }
 }
 
 QVariant Setting::defValue() const
 {
-	return m_defVal;
+    return m_defVal;
 }
 
 void Setting::set(QVariant value)
 {
-	emit SettingChanged(*this, value);
+    emit SettingChanged(*this, value);
 }
 
 void Setting::reset()
 {
-	emit settingReset(*this);
+    emit settingReset(*this);
 }
diff --git a/api/logic/settings/Setting.h b/api/logic/settings/Setting.h
index 3edea7be..0e9224c5 100644
--- a/api/logic/settings/Setting.h
+++ b/api/logic/settings/Setting.h
@@ -29,91 +29,91 @@ class SettingsObject;
  */
 class MULTIMC_LOGIC_EXPORT Setting : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	/**
-	 * Construct a Setting
-	 *
-	 * Synonyms are all the possible names used in the settings object, in order of preference.
-	 * First synonym is the ID, which identifies the setting in MultiMC.
-	 *
-	 * defVal is the default value that will be returned when the settings object
-	 * doesn't have any value for this setting.
-	 */
-	explicit Setting(QStringList synonyms, QVariant defVal = QVariant());
+    /**
+     * Construct a Setting
+     *
+     * Synonyms are all the possible names used in the settings object, in order of preference.
+     * First synonym is the ID, which identifies the setting in MultiMC.
+     *
+     * defVal is the default value that will be returned when the settings object
+     * doesn't have any value for this setting.
+     */
+    explicit Setting(QStringList synonyms, QVariant defVal = QVariant());
 
-	/*!
-	 * \brief Gets this setting's ID.
-	 * This is used to refer to the setting within the application.
-	 * \warning Changing the ID while the setting is registered with a SettingsObject results in
-	 * undefined behavior.
-	 * \return The ID of the setting.
-	 */
-	virtual QString id() const
-	{
-		return m_synonyms.first();
-	}
+    /*!
+     * \brief Gets this setting's ID.
+     * This is used to refer to the setting within the application.
+     * \warning Changing the ID while the setting is registered with a SettingsObject results in
+     * undefined behavior.
+     * \return The ID of the setting.
+     */
+    virtual QString id() const
+    {
+        return m_synonyms.first();
+    }
 
-	/*!
-	 * \brief Gets this setting's config file key.
-	 * This is used to store the setting's value in the config file. It is usually
-	 * the same as the setting's ID, but it can be different.
-	 * \return The setting's config file key.
-	 */
-	virtual QStringList configKeys() const
-	{
-		return m_synonyms;
-	}
+    /*!
+     * \brief Gets this setting's config file key.
+     * This is used to store the setting's value in the config file. It is usually
+     * the same as the setting's ID, but it can be different.
+     * \return The setting's config file key.
+     */
+    virtual QStringList configKeys() const
+    {
+        return m_synonyms;
+    }
 
-	/*!
-	 * \brief Gets this setting's value as a QVariant.
-	 * This is done by calling the SettingsObject's retrieveValue() function.
-	 * If this Setting doesn't have a SettingsObject, this returns an invalid QVariant.
-	 * \return QVariant containing this setting's value.
-	 * \sa value()
-	 */
-	virtual QVariant get() const;
+    /*!
+     * \brief Gets this setting's value as a QVariant.
+     * This is done by calling the SettingsObject's retrieveValue() function.
+     * If this Setting doesn't have a SettingsObject, this returns an invalid QVariant.
+     * \return QVariant containing this setting's value.
+     * \sa value()
+     */
+    virtual QVariant get() const;
 
-	/*!
-	 * \brief Gets this setting's default value.
-	 * \return The default value of this setting.
-	 */
-	virtual QVariant defValue() const;
+    /*!
+     * \brief Gets this setting's default value.
+     * \return The default value of this setting.
+     */
+    virtual QVariant defValue() const;
 
 signals:
-	/*!
-	 * \brief Signal emitted when this Setting object's value changes.
-	 * \param setting A reference to the Setting that changed.
-	 * \param value This Setting object's new value.
-	 */
-	void SettingChanged(const Setting &setting, QVariant value);
+    /*!
+     * \brief Signal emitted when this Setting object's value changes.
+     * \param setting A reference to the Setting that changed.
+     * \param value This Setting object's new value.
+     */
+    void SettingChanged(const Setting &setting, QVariant value);
 
-	/*!
-	 * \brief Signal emitted when this Setting object's value resets to default.
-	 * \param setting A reference to the Setting that changed.
-	 */
-	void settingReset(const Setting &setting);
+    /*!
+     * \brief Signal emitted when this Setting object's value resets to default.
+     * \param setting A reference to the Setting that changed.
+     */
+    void settingReset(const Setting &setting);
 
 public
 slots:
-	/*!
-	 * \brief Changes the setting's value.
-	 * This is done by emitting the SettingChanged() signal which will then be
-	 * handled by the SettingsObject object and cause the setting to change.
-	 * \param value The new value.
-	 */
-	virtual void set(QVariant value);
+    /*!
+     * \brief Changes the setting's value.
+     * This is done by emitting the SettingChanged() signal which will then be
+     * handled by the SettingsObject object and cause the setting to change.
+     * \param value The new value.
+     */
+    virtual void set(QVariant value);
 
-	/*!
-	 * \brief Reset the setting to default
-	 * This is done by emitting the settingReset() signal which will then be
-	 * handled by the SettingsObject object and cause the setting to change.
-	 */
-	virtual void reset();
+    /*!
+     * \brief Reset the setting to default
+     * This is done by emitting the settingReset() signal which will then be
+     * handled by the SettingsObject object and cause the setting to change.
+     */
+    virtual void reset();
 
 protected:
-	friend class SettingsObject;
-	SettingsObject * m_storage;
-	QStringList m_synonyms;
-	QVariant m_defVal;
+    friend class SettingsObject;
+    SettingsObject * m_storage;
+    QStringList m_synonyms;
+    QVariant m_defVal;
 };
diff --git a/api/logic/settings/SettingsObject.cpp b/api/logic/settings/SettingsObject.cpp
index 87a8c2a8..d1851415 100644
--- a/api/logic/settings/SettingsObject.cpp
+++ b/api/logic/settings/SettingsObject.cpp
@@ -27,116 +27,116 @@ SettingsObject::SettingsObject(QObject *parent) : QObject(parent)
 
 SettingsObject::~SettingsObject()
 {
-	m_settings.clear();
+    m_settings.clear();
 }
 
 std::shared_ptr<Setting> SettingsObject::registerOverride(std::shared_ptr<Setting> original,
-														  std::shared_ptr<Setting> gate)
+                                                          std::shared_ptr<Setting> gate)
 {
-	if (contains(original->id()))
-	{
-		qCritical() << QString("Failed to register setting %1. ID already exists.")
-				   .arg(original->id());
-		return nullptr; // Fail
-	}
-	auto override = std::make_shared<OverrideSetting>(original, gate);
-	override->m_storage = this;
-	connectSignals(*override);
-	m_settings.insert(override->id(), override);
-	return override;
+    if (contains(original->id()))
+    {
+        qCritical() << QString("Failed to register setting %1. ID already exists.")
+                   .arg(original->id());
+        return nullptr; // Fail
+    }
+    auto override = std::make_shared<OverrideSetting>(original, gate);
+    override->m_storage = this;
+    connectSignals(*override);
+    m_settings.insert(override->id(), override);
+    return override;
 }
 
 std::shared_ptr<Setting> SettingsObject::registerPassthrough(std::shared_ptr<Setting> original,
-															 std::shared_ptr<Setting> gate)
+                                                             std::shared_ptr<Setting> gate)
 {
-	if (contains(original->id()))
-	{
-		qCritical() << QString("Failed to register setting %1. ID already exists.")
-				   .arg(original->id());
-		return nullptr; // Fail
-	}
-	auto passthrough = std::make_shared<PassthroughSetting>(original, gate);
-	passthrough->m_storage = this;
-	connectSignals(*passthrough);
-	m_settings.insert(passthrough->id(), passthrough);
-	return passthrough;
+    if (contains(original->id()))
+    {
+        qCritical() << QString("Failed to register setting %1. ID already exists.")
+                   .arg(original->id());
+        return nullptr; // Fail
+    }
+    auto passthrough = std::make_shared<PassthroughSetting>(original, gate);
+    passthrough->m_storage = this;
+    connectSignals(*passthrough);
+    m_settings.insert(passthrough->id(), passthrough);
+    return passthrough;
 }
 
 std::shared_ptr<Setting> SettingsObject::registerSetting(QStringList synonyms, QVariant defVal)
 {
-	if (synonyms.empty())
-		return nullptr;
-	if (contains(synonyms.first()))
-	{
-		qCritical() << QString("Failed to register setting %1. ID already exists.")
-				   .arg(synonyms.first());
-		return nullptr; // Fail
-	}
-	auto setting = std::make_shared<Setting>(synonyms, defVal);
-	setting->m_storage = this;
-	connectSignals(*setting);
-	m_settings.insert(setting->id(), setting);
-	return setting;
+    if (synonyms.empty())
+        return nullptr;
+    if (contains(synonyms.first()))
+    {
+        qCritical() << QString("Failed to register setting %1. ID already exists.")
+                   .arg(synonyms.first());
+        return nullptr; // Fail
+    }
+    auto setting = std::make_shared<Setting>(synonyms, defVal);
+    setting->m_storage = this;
+    connectSignals(*setting);
+    m_settings.insert(setting->id(), setting);
+    return setting;
 }
 
 std::shared_ptr<Setting> SettingsObject::getSetting(const QString &id) const
 {
-	// Make sure there is a setting with the given ID.
-	if (!m_settings.contains(id))
-		return NULL;
+    // Make sure there is a setting with the given ID.
+    if (!m_settings.contains(id))
+        return NULL;
 
-	return m_settings[id];
+    return m_settings[id];
 }
 
 QVariant SettingsObject::get(const QString &id) const
 {
-	auto setting = getSetting(id);
-	return (setting ? setting->get() : QVariant());
+    auto setting = getSetting(id);
+    return (setting ? setting->get() : QVariant());
 }
 
 bool SettingsObject::set(const QString &id, QVariant value)
 {
-	auto setting = getSetting(id);
-	if (!setting)
-	{
-		qCritical() << QString("Error changing setting %1. Setting doesn't exist.").arg(id);
-		return false;
-	}
-	else
-	{
-		setting->set(value);
-		return true;
-	}
+    auto setting = getSetting(id);
+    if (!setting)
+    {
+        qCritical() << QString("Error changing setting %1. Setting doesn't exist.").arg(id);
+        return false;
+    }
+    else
+    {
+        setting->set(value);
+        return true;
+    }
 }
 
 void SettingsObject::reset(const QString &id) const
 {
-	auto setting = getSetting(id);
-	if (setting)
-		setting->reset();
+    auto setting = getSetting(id);
+    if (setting)
+        setting->reset();
 }
 
 bool SettingsObject::contains(const QString &id)
 {
-	return m_settings.contains(id);
+    return m_settings.contains(id);
 }
 
 bool SettingsObject::reload()
 {
-	for (auto setting : m_settings.values())
-	{
-		setting->set(setting->get());
-	}
-	return true;
+    for (auto setting : m_settings.values())
+    {
+        setting->set(setting->get());
+    }
+    return true;
 }
 
 void SettingsObject::connectSignals(const Setting &setting)
 {
-	connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)),
-			SLOT(changeSetting(const Setting &, QVariant)));
-	connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)),
-			SIGNAL(SettingChanged(const Setting &, QVariant)));
+    connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)),
+            SLOT(changeSetting(const Setting &, QVariant)));
+    connect(&setting, SIGNAL(SettingChanged(const Setting &, QVariant)),
+            SIGNAL(SettingChanged(const Setting &, QVariant)));
 
-	connect(&setting, SIGNAL(settingReset(Setting)), SLOT(resetSetting(const Setting &)));
-	connect(&setting, SIGNAL(settingReset(Setting)), SIGNAL(settingReset(const Setting &)));
+    connect(&setting, SIGNAL(settingReset(Setting)), SLOT(resetSetting(const Setting &)));
+    connect(&setting, SIGNAL(settingReset(Setting)), SIGNAL(settingReset(const Setting &)));
 }
diff --git a/api/logic/settings/SettingsObject.h b/api/logic/settings/SettingsObject.h
index 8582d8ad..10a34f81 100644
--- a/api/logic/settings/SettingsObject.h
+++ b/api/logic/settings/SettingsObject.h
@@ -42,173 +42,173 @@ typedef std::shared_ptr<SettingsObject> SettingsObjectPtr;
  */
 class MULTIMC_LOGIC_EXPORT SettingsObject : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	class Lock
-	{
-	public:
-		Lock(SettingsObjectPtr locked)
-			:m_locked(locked)
-		{
-			m_locked->suspendSave();
-		}
-		~Lock()
-		{
-			m_locked->resumeSave();
-		}
-	private:
-		SettingsObjectPtr m_locked;
-	};
+    class Lock
+    {
+    public:
+        Lock(SettingsObjectPtr locked)
+            :m_locked(locked)
+        {
+            m_locked->suspendSave();
+        }
+        ~Lock()
+        {
+            m_locked->resumeSave();
+        }
+    private:
+        SettingsObjectPtr m_locked;
+    };
 public:
-	explicit SettingsObject(QObject *parent = 0);
-	virtual ~SettingsObject();
-	/*!
-	 * Registers an override setting for the given original setting in this settings object
-	 * gate decides if the passthrough (true) or the original (false) is used for value
-	 *
-	 * This will fail if there is already a setting with the same ID as
-	 * the one that is being registered.
-	 * \return A valid Setting shared pointer if successful.
-	 */
-	std::shared_ptr<Setting> registerOverride(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate);
-
-	/*!
-	 * Registers a passthorugh setting for the given original setting in this settings object
-	 * gate decides if the passthrough (true) or the original (false) is used for value
-	 *
-	 * This will fail if there is already a setting with the same ID as
-	 * the one that is being registered.
-	 * \return A valid Setting shared pointer if successful.
-	 */
-	std::shared_ptr<Setting> registerPassthrough(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate);
-
-	/*!
-	 * Registers the given setting with this SettingsObject and connects the necessary  signals.
-	 *
-	 * This will fail if there is already a setting with the same ID as
-	 * the one that is being registered.
-	 * \return A valid Setting shared pointer if successful.
-	 */
-	std::shared_ptr<Setting> registerSetting(QStringList synonyms,
-											 QVariant defVal = QVariant());
-
-	/*!
-	 * Registers the given setting with this SettingsObject and connects the necessary signals.
-	 *
-	 * This will fail if there is already a setting with the same ID as
-	 * the one that is being registered.
-	 * \return A valid Setting shared pointer if successful.
-	 */
-	std::shared_ptr<Setting> registerSetting(QString id, QVariant defVal = QVariant())
-	{
-		return registerSetting(QStringList(id), defVal);
-	}
-
-	/*!
-	 * \brief Gets the setting with the given ID.
-	 * \param id The ID of the setting to get.
-	 * \return A pointer to the setting with the given ID.
-	 * Returns null if there is no setting with the given ID.
-	 * \sa operator []()
-	 */
-	std::shared_ptr<Setting> getSetting(const QString &id) const;
-
-	/*!
-	 * \brief Gets the value of the setting with the given ID.
-	 * \param id The ID of the setting to get.
-	 * \return The setting's value as a QVariant.
-	 * If no setting with the given ID exists, returns an invalid QVariant.
-	 */
-	QVariant get(const QString &id) const;
-
-	/*!
-	 * \brief Sets the value of the setting with the given ID.
-	 * If no setting with the given ID exists, returns false
-	 * \param id The ID of the setting to change.
-	 * \param value The new value of the setting.
-	 * \return True if successful, false if it failed.
-	 */
-	bool set(const QString &id, QVariant value);
-
-	/*!
-	 * \brief Reverts the setting with the given ID to default.
-	 * \param id The ID of the setting to reset.
-	 */
-	void reset(const QString &id) const;
-
-	/*!
-	 * \brief Checks if this SettingsObject contains a setting with the given ID.
-	 * \param id The ID to check for.
-	 * \return True if the SettingsObject has a setting with the given ID.
-	 */
-	bool contains(const QString &id);
-
-	/*!
-	 * \brief Reloads the settings and emit signals for changed settings
-	 * \return True if reloading was successful
-	 */
-	virtual bool reload();
-
-	virtual void suspendSave() = 0;
-	virtual void resumeSave() = 0;
+    explicit SettingsObject(QObject *parent = 0);
+    virtual ~SettingsObject();
+    /*!
+     * Registers an override setting for the given original setting in this settings object
+     * gate decides if the passthrough (true) or the original (false) is used for value
+     *
+     * This will fail if there is already a setting with the same ID as
+     * the one that is being registered.
+     * \return A valid Setting shared pointer if successful.
+     */
+    std::shared_ptr<Setting> registerOverride(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate);
+
+    /*!
+     * Registers a passthorugh setting for the given original setting in this settings object
+     * gate decides if the passthrough (true) or the original (false) is used for value
+     *
+     * This will fail if there is already a setting with the same ID as
+     * the one that is being registered.
+     * \return A valid Setting shared pointer if successful.
+     */
+    std::shared_ptr<Setting> registerPassthrough(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate);
+
+    /*!
+     * Registers the given setting with this SettingsObject and connects the necessary  signals.
+     *
+     * This will fail if there is already a setting with the same ID as
+     * the one that is being registered.
+     * \return A valid Setting shared pointer if successful.
+     */
+    std::shared_ptr<Setting> registerSetting(QStringList synonyms,
+                                             QVariant defVal = QVariant());
+
+    /*!
+     * Registers the given setting with this SettingsObject and connects the necessary signals.
+     *
+     * This will fail if there is already a setting with the same ID as
+     * the one that is being registered.
+     * \return A valid Setting shared pointer if successful.
+     */
+    std::shared_ptr<Setting> registerSetting(QString id, QVariant defVal = QVariant())
+    {
+        return registerSetting(QStringList(id), defVal);
+    }
+
+    /*!
+     * \brief Gets the setting with the given ID.
+     * \param id The ID of the setting to get.
+     * \return A pointer to the setting with the given ID.
+     * Returns null if there is no setting with the given ID.
+     * \sa operator []()
+     */
+    std::shared_ptr<Setting> getSetting(const QString &id) const;
+
+    /*!
+     * \brief Gets the value of the setting with the given ID.
+     * \param id The ID of the setting to get.
+     * \return The setting's value as a QVariant.
+     * If no setting with the given ID exists, returns an invalid QVariant.
+     */
+    QVariant get(const QString &id) const;
+
+    /*!
+     * \brief Sets the value of the setting with the given ID.
+     * If no setting with the given ID exists, returns false
+     * \param id The ID of the setting to change.
+     * \param value The new value of the setting.
+     * \return True if successful, false if it failed.
+     */
+    bool set(const QString &id, QVariant value);
+
+    /*!
+     * \brief Reverts the setting with the given ID to default.
+     * \param id The ID of the setting to reset.
+     */
+    void reset(const QString &id) const;
+
+    /*!
+     * \brief Checks if this SettingsObject contains a setting with the given ID.
+     * \param id The ID to check for.
+     * \return True if the SettingsObject has a setting with the given ID.
+     */
+    bool contains(const QString &id);
+
+    /*!
+     * \brief Reloads the settings and emit signals for changed settings
+     * \return True if reloading was successful
+     */
+    virtual bool reload();
+
+    virtual void suspendSave() = 0;
+    virtual void resumeSave() = 0;
 signals:
-	/*!
-	 * \brief Signal emitted when one of this SettingsObject object's settings changes.
-	 * This is usually just connected directly to each Setting object's
-	 * SettingChanged() signals.
-	 * \param setting A reference to the Setting object that changed.
-	 * \param value The Setting object's new value.
-	 */
-	void SettingChanged(const Setting &setting, QVariant value);
-
-	/*!
-	 * \brief Signal emitted when one of this SettingsObject object's settings resets.
-	 * This is usually just connected directly to each Setting object's
-	 * settingReset() signals.
-	 * \param setting A reference to the Setting object that changed.
-	 */
-	void settingReset(const Setting &setting);
+    /*!
+     * \brief Signal emitted when one of this SettingsObject object's settings changes.
+     * This is usually just connected directly to each Setting object's
+     * SettingChanged() signals.
+     * \param setting A reference to the Setting object that changed.
+     * \param value The Setting object's new value.
+     */
+    void SettingChanged(const Setting &setting, QVariant value);
+
+    /*!
+     * \brief Signal emitted when one of this SettingsObject object's settings resets.
+     * This is usually just connected directly to each Setting object's
+     * settingReset() signals.
+     * \param setting A reference to the Setting object that changed.
+     */
+    void settingReset(const Setting &setting);
 
 protected
 slots:
-	/*!
-	 * \brief Changes a setting.
-	 * This slot is usually connected to each Setting object's
-	 * SettingChanged() signal. The signal is emitted, causing this slot
-	 * to update the setting's value in the config file.
-	 * \param setting A reference to the Setting object that changed.
-	 * \param value The setting's new value.
-	 */
-	virtual void changeSetting(const Setting &setting, QVariant value) = 0;
-
-	/*!
-	 * \brief Resets a setting.
-	 * This slot is usually connected to each Setting object's
-	 * settingReset() signal. The signal is emitted, causing this slot
-	 * to update the setting's value in the config file.
-	 * \param setting A reference to the Setting object that changed.
-	 */
-	virtual void resetSetting(const Setting &setting) = 0;
+    /*!
+     * \brief Changes a setting.
+     * This slot is usually connected to each Setting object's
+     * SettingChanged() signal. The signal is emitted, causing this slot
+     * to update the setting's value in the config file.
+     * \param setting A reference to the Setting object that changed.
+     * \param value The setting's new value.
+     */
+    virtual void changeSetting(const Setting &setting, QVariant value) = 0;
+
+    /*!
+     * \brief Resets a setting.
+     * This slot is usually connected to each Setting object's
+     * settingReset() signal. The signal is emitted, causing this slot
+     * to update the setting's value in the config file.
+     * \param setting A reference to the Setting object that changed.
+     */
+    virtual void resetSetting(const Setting &setting) = 0;
 
 protected:
-	/*!
-	 * \brief Connects the necessary signals to the given Setting.
-	 * \param setting The setting to connect.
-	 */
-	void connectSignals(const Setting &setting);
+    /*!
+     * \brief Connects the necessary signals to the given Setting.
+     * \param setting The setting to connect.
+     */
+    void connectSignals(const Setting &setting);
 
-	/*!
-	 * \brief Function used by Setting objects to get their values from the SettingsObject.
-	 * \param setting The
-	 * \return
-	 */
-	virtual QVariant retrieveValue(const Setting &setting) = 0;
+    /*!
+     * \brief Function used by Setting objects to get their values from the SettingsObject.
+     * \param setting The
+     * \return
+     */
+    virtual QVariant retrieveValue(const Setting &setting) = 0;
 
-	friend class Setting;
+    friend class Setting;
 
 private:
-	QMap<QString, std::shared_ptr<Setting>> m_settings;
+    QMap<QString, std::shared_ptr<Setting>> m_settings;
 protected:
-	bool m_suspendSave = false;
-	bool m_doSave = false;
+    bool m_suspendSave = false;
+    bool m_doSave = false;
 };
diff --git a/api/logic/status/StatusChecker.cpp b/api/logic/status/StatusChecker.cpp
index bff9fda9..ffadcc74 100644
--- a/api/logic/status/StatusChecker.cpp
+++ b/api/logic/status/StatusChecker.cpp
@@ -28,121 +28,121 @@ StatusChecker::StatusChecker()
 
 void StatusChecker::timerEvent(QTimerEvent *e)
 {
-	QObject::timerEvent(e);
-	reloadStatus();
+    QObject::timerEvent(e);
+    reloadStatus();
 }
 
 void StatusChecker::reloadStatus()
 {
-	if (isLoadingStatus())
-	{
-		// qDebug() << "Ignored request to reload status. Currently reloading already.";
-		return;
-	}
-
-	// qDebug() << "Reloading status.";
-
-	NetJob* job = new NetJob("Status JSON");
-	job->addNetAction(Net::Download::makeByteArray(URLConstants::MOJANG_STATUS_URL, &dataSink));
-	QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished);
-	QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed);
-	m_statusNetJob.reset(job);
-	emit statusLoading(true);
-	job->start();
+    if (isLoadingStatus())
+    {
+        // qDebug() << "Ignored request to reload status. Currently reloading already.";
+        return;
+    }
+
+    // qDebug() << "Reloading status.";
+
+    NetJob* job = new NetJob("Status JSON");
+    job->addNetAction(Net::Download::makeByteArray(URLConstants::MOJANG_STATUS_URL, &dataSink));
+    QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished);
+    QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed);
+    m_statusNetJob.reset(job);
+    emit statusLoading(true);
+    job->start();
 }
 
 void StatusChecker::statusDownloadFinished()
 {
-	qDebug() << "Finished loading status JSON.";
-	m_statusEntries.clear();
-	m_statusNetJob.reset();
-
-	QJsonParseError jsonError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(dataSink, &jsonError);
-
-	if (jsonError.error != QJsonParseError::NoError)
-	{
-		fail("Error parsing status JSON:" + jsonError.errorString());
-		return;
-	}
-
-	if (!jsonDoc.isArray())
-	{
-		fail("Error parsing status JSON: JSON root is not an array");
-		return;
-	}
-
-	QJsonArray root = jsonDoc.array();
-
-	for(auto status = root.begin(); status != root.end(); ++status)
-	{
-		QVariantMap map = (*status).toObject().toVariantMap();
-
-		for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
-		{
-			QString key = iter.key();
-			QVariant value = iter.value();
-
-			if(value.type() == QVariant::Type::String)
-			{
-				m_statusEntries.insert(key, value.toString());
-				//qDebug() << "Status JSON object: " << key << m_statusEntries[key];
-			}
-			else
-			{
-				fail("Malformed status JSON: expected status type to be a string.");
-				return;
-			}
-		}
-	}
-
-	succeed();
+    qDebug() << "Finished loading status JSON.";
+    m_statusEntries.clear();
+    m_statusNetJob.reset();
+
+    QJsonParseError jsonError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(dataSink, &jsonError);
+
+    if (jsonError.error != QJsonParseError::NoError)
+    {
+        fail("Error parsing status JSON:" + jsonError.errorString());
+        return;
+    }
+
+    if (!jsonDoc.isArray())
+    {
+        fail("Error parsing status JSON: JSON root is not an array");
+        return;
+    }
+
+    QJsonArray root = jsonDoc.array();
+
+    for(auto status = root.begin(); status != root.end(); ++status)
+    {
+        QVariantMap map = (*status).toObject().toVariantMap();
+
+        for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
+        {
+            QString key = iter.key();
+            QVariant value = iter.value();
+
+            if(value.type() == QVariant::Type::String)
+            {
+                m_statusEntries.insert(key, value.toString());
+                //qDebug() << "Status JSON object: " << key << m_statusEntries[key];
+            }
+            else
+            {
+                fail("Malformed status JSON: expected status type to be a string.");
+                return;
+            }
+        }
+    }
+
+    succeed();
 }
 
 void StatusChecker::statusDownloadFailed(QString reason)
 {
-	fail(tr("Failed to load status JSON:\n%1").arg(reason));
+    fail(tr("Failed to load status JSON:\n%1").arg(reason));
 }
 
 
 QMap<QString, QString> StatusChecker::getStatusEntries() const
 {
-	return m_statusEntries;
+    return m_statusEntries;
 }
 
 bool StatusChecker::isLoadingStatus() const
 {
-	return m_statusNetJob.get() != nullptr;
+    return m_statusNetJob.get() != nullptr;
 }
 
 QString StatusChecker::getLastLoadErrorMsg() const
 {
-	return m_lastLoadError;
+    return m_lastLoadError;
 }
 
 void StatusChecker::succeed()
 {
-	if(m_prevEntries != m_statusEntries)
-	{
-		emit statusChanged(m_statusEntries);
-		m_prevEntries = m_statusEntries;
-	}
-	m_lastLoadError = "";
-	qDebug() << "Status loading succeeded.";
-	m_statusNetJob.reset();
-	emit statusLoading(false);
+    if(m_prevEntries != m_statusEntries)
+    {
+        emit statusChanged(m_statusEntries);
+        m_prevEntries = m_statusEntries;
+    }
+    m_lastLoadError = "";
+    qDebug() << "Status loading succeeded.";
+    m_statusNetJob.reset();
+    emit statusLoading(false);
 }
 
 void StatusChecker::fail(const QString& errorMsg)
 {
-	if(m_prevEntries != m_statusEntries)
-	{
-		emit statusChanged(m_statusEntries);
-		m_prevEntries = m_statusEntries;
-	}
-	m_lastLoadError = errorMsg;
-	qDebug() << "Failed to load status:" << errorMsg;
-	m_statusNetJob.reset();
-	emit statusLoading(false);
+    if(m_prevEntries != m_statusEntries)
+    {
+        emit statusChanged(m_statusEntries);
+        m_prevEntries = m_statusEntries;
+    }
+    m_lastLoadError = errorMsg;
+    qDebug() << "Failed to load status:" << errorMsg;
+    m_statusNetJob.reset();
+    emit statusLoading(false);
 }
 
diff --git a/api/logic/status/StatusChecker.h b/api/logic/status/StatusChecker.h
index f19aba9a..51a86910 100644
--- a/api/logic/status/StatusChecker.h
+++ b/api/logic/status/StatusChecker.h
@@ -25,36 +25,36 @@
 
 class MULTIMC_LOGIC_EXPORT StatusChecker : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public: /* con/des */
-	StatusChecker();
+    StatusChecker();
 
 public: /* methods */
-	QString getLastLoadErrorMsg() const;
-	bool isLoadingStatus() const;
-	QMap<QString, QString> getStatusEntries() const;
+    QString getLastLoadErrorMsg() const;
+    bool isLoadingStatus() const;
+    QMap<QString, QString> getStatusEntries() const;
 
 signals:
-	void statusLoading(bool loading);
-	void statusChanged(QMap<QString, QString> newStatus);
+    void statusLoading(bool loading);
+    void statusChanged(QMap<QString, QString> newStatus);
 
 public slots:
-	void reloadStatus();
+    void reloadStatus();
 
 protected: /* methods */
-	virtual void timerEvent(QTimerEvent *);
+    virtual void timerEvent(QTimerEvent *);
 
 protected slots:
-	void statusDownloadFinished();
-	void statusDownloadFailed(QString reason);
-	void succeed();
-	void fail(const QString& errorMsg);
+    void statusDownloadFinished();
+    void statusDownloadFailed(QString reason);
+    void succeed();
+    void fail(const QString& errorMsg);
 
 protected: /* data */
-	QMap<QString, QString> m_prevEntries;
-	QMap<QString, QString> m_statusEntries;
-	NetJobPtr m_statusNetJob;
-	QString m_lastLoadError;
-	QByteArray dataSink;
+    QMap<QString, QString> m_prevEntries;
+    QMap<QString, QString> m_statusEntries;
+    NetJobPtr m_statusNetJob;
+    QString m_lastLoadError;
+    QByteArray dataSink;
 };
 
diff --git a/api/logic/tasks/SequentialTask.cpp b/api/logic/tasks/SequentialTask.cpp
index ac0e7820..d0777132 100644
--- a/api/logic/tasks/SequentialTask.cpp
+++ b/api/logic/tasks/SequentialTask.cpp
@@ -6,50 +6,50 @@ SequentialTask::SequentialTask(QObject *parent) : Task(parent), m_currentIndex(-
 
 void SequentialTask::addTask(std::shared_ptr<Task> task)
 {
-	m_queue.append(task);
+    m_queue.append(task);
 }
 
 void SequentialTask::executeTask()
 {
-	m_currentIndex = -1;
-	startNext();
+    m_currentIndex = -1;
+    startNext();
 }
 
 void SequentialTask::startNext()
 {
-	if (m_currentIndex != -1)
-	{
-		std::shared_ptr<Task> previous = m_queue[m_currentIndex];
-		disconnect(previous.get(), 0, this, 0);
-	}
-	m_currentIndex++;
-	if (m_queue.isEmpty() || m_currentIndex >= m_queue.size())
-	{
-		emitSucceeded();
-		return;
-	}
-	std::shared_ptr<Task> next = m_queue[m_currentIndex];
-	connect(next.get(), SIGNAL(failed(QString)), this, SLOT(subTaskFailed(QString)));
-	connect(next.get(), SIGNAL(status(QString)), this, SLOT(subTaskStatus(QString)));
-	connect(next.get(), SIGNAL(progress(qint64, qint64)), this, SLOT(subTaskProgress(qint64, qint64)));
-	connect(next.get(), SIGNAL(succeeded()), this, SLOT(startNext()));
-	next->start();
+    if (m_currentIndex != -1)
+    {
+        std::shared_ptr<Task> previous = m_queue[m_currentIndex];
+        disconnect(previous.get(), 0, this, 0);
+    }
+    m_currentIndex++;
+    if (m_queue.isEmpty() || m_currentIndex >= m_queue.size())
+    {
+        emitSucceeded();
+        return;
+    }
+    std::shared_ptr<Task> next = m_queue[m_currentIndex];
+    connect(next.get(), SIGNAL(failed(QString)), this, SLOT(subTaskFailed(QString)));
+    connect(next.get(), SIGNAL(status(QString)), this, SLOT(subTaskStatus(QString)));
+    connect(next.get(), SIGNAL(progress(qint64, qint64)), this, SLOT(subTaskProgress(qint64, qint64)));
+    connect(next.get(), SIGNAL(succeeded()), this, SLOT(startNext()));
+    next->start();
 }
 
 void SequentialTask::subTaskFailed(const QString &msg)
 {
-	emitFailed(msg);
+    emitFailed(msg);
 }
 void SequentialTask::subTaskStatus(const QString &msg)
 {
-	setStatus(msg);
+    setStatus(msg);
 }
 void SequentialTask::subTaskProgress(qint64 current, qint64 total)
 {
-	if(total == 0)
-	{
-		setProgress(0, 100);
-		return;
-	}
-	setProgress(current, total);
+    if(total == 0)
+    {
+        setProgress(0, 100);
+        return;
+    }
+    setProgress(current, total);
 }
diff --git a/api/logic/tasks/SequentialTask.h b/api/logic/tasks/SequentialTask.h
index a2f3580f..2ca77c00 100644
--- a/api/logic/tasks/SequentialTask.h
+++ b/api/logic/tasks/SequentialTask.h
@@ -9,24 +9,24 @@
 
 class MULTIMC_LOGIC_EXPORT SequentialTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit SequentialTask(QObject *parent = 0);
-	virtual ~SequentialTask() {};
+    explicit SequentialTask(QObject *parent = 0);
+    virtual ~SequentialTask() {};
 
-	void addTask(std::shared_ptr<Task> task);
+    void addTask(std::shared_ptr<Task> task);
 
 protected:
-	void executeTask();
+    void executeTask();
 
 private
 slots:
-	void startNext();
-	void subTaskFailed(const QString &msg);
-	void subTaskStatus(const QString &msg);
-	void subTaskProgress(qint64 current, qint64 total);
+    void startNext();
+    void subTaskFailed(const QString &msg);
+    void subTaskStatus(const QString &msg);
+    void subTaskProgress(qint64 current, qint64 total);
 
 private:
-	QQueue<std::shared_ptr<Task> > m_queue;
-	int m_currentIndex;
+    QQueue<std::shared_ptr<Task> > m_queue;
+    int m_currentIndex;
 };
diff --git a/api/logic/tasks/Task.cpp b/api/logic/tasks/Task.cpp
index 2523aeb2..f7f2d491 100644
--- a/api/logic/tasks/Task.cpp
+++ b/api/logic/tasks/Task.cpp
@@ -23,124 +23,124 @@ Task::Task(QObject *parent) : QObject(parent)
 
 void Task::setStatus(const QString &new_status)
 {
-	if(m_status != new_status)
-	{
-		m_status = new_status;
-		emit status(m_status);
-	}
+    if(m_status != new_status)
+    {
+        m_status = new_status;
+        emit status(m_status);
+    }
 }
 
 void Task::setProgress(qint64 current, qint64 total)
 {
-	m_progress = current;
-	m_progressTotal = total;
-	emit progress(m_progress, m_progressTotal);
+    m_progress = current;
+    m_progressTotal = total;
+    emit progress(m_progress, m_progressTotal);
 }
 
 void Task::start()
 {
-	m_running = true;
-	emit started();
-	qDebug() << "Task" << describe() << "started";
-	executeTask();
+    m_running = true;
+    emit started();
+    qDebug() << "Task" << describe() << "started";
+    executeTask();
 }
 
 void Task::emitFailed(QString reason)
 {
-	// Don't fail twice.
-	if (!m_running)
-	{
-		qCritical() << "Task" << describe() << "failed while not running!!!!: " << reason;
-		return;
-	}
-	m_running = false;
-	m_finished = true;
-	m_succeeded = false;
-	m_failReason = reason;
-	qCritical() << "Task" << describe() << "failed: " << reason;
-	emit failed(reason);
-	emit finished();
+    // Don't fail twice.
+    if (!m_running)
+    {
+        qCritical() << "Task" << describe() << "failed while not running!!!!: " << reason;
+        return;
+    }
+    m_running = false;
+    m_finished = true;
+    m_succeeded = false;
+    m_failReason = reason;
+    qCritical() << "Task" << describe() << "failed: " << reason;
+    emit failed(reason);
+    emit finished();
 }
 
 void Task::emitAborted()
 {
-	// Don't abort twice.
-	if (!m_running)
-	{
-		qCritical() << "Task" << describe() << "aborted while not running!!!!";
-		return;
-	}
-	m_running = false;
-	m_finished = true;
-	m_succeeded = false;
-	m_failReason = "Aborted.";
-	qDebug() << "Task" << describe() << "aborted.";
-	emit failed(m_failReason);
-	emit finished();
+    // Don't abort twice.
+    if (!m_running)
+    {
+        qCritical() << "Task" << describe() << "aborted while not running!!!!";
+        return;
+    }
+    m_running = false;
+    m_finished = true;
+    m_succeeded = false;
+    m_failReason = "Aborted.";
+    qDebug() << "Task" << describe() << "aborted.";
+    emit failed(m_failReason);
+    emit finished();
 }
 
 void Task::emitSucceeded()
 {
-	// Don't succeed twice.
-	if (!m_running)
-	{
-		qCritical() << "Task" << describe() << "succeeded while not running!!!!";
-		return;
-	}
-	m_running = false;
-	m_finished = true;
-	m_succeeded = true;
-	qDebug() << "Task" << describe() << "succeeded";
-	emit succeeded();
-	emit finished();
+    // Don't succeed twice.
+    if (!m_running)
+    {
+        qCritical() << "Task" << describe() << "succeeded while not running!!!!";
+        return;
+    }
+    m_running = false;
+    m_finished = true;
+    m_succeeded = true;
+    qDebug() << "Task" << describe() << "succeeded";
+    emit succeeded();
+    emit finished();
 }
 
 QString Task::describe()
 {
-	QString outStr;
-	QTextStream out(&outStr);
-	out << metaObject()->className() << QChar('(');
-	auto name = objectName();
-	if(name.isEmpty())
-	{
-		out << QString("0x%1").arg((quintptr)this, 0, 16);
-	}
-	else
-	{
-		out << name;
-	}
-	out << QChar(')');
-	out.flush();
-	return outStr;
+    QString outStr;
+    QTextStream out(&outStr);
+    out << metaObject()->className() << QChar('(');
+    auto name = objectName();
+    if(name.isEmpty())
+    {
+        out << QString("0x%1").arg((quintptr)this, 0, 16);
+    }
+    else
+    {
+        out << name;
+    }
+    out << QChar(')');
+    out.flush();
+    return outStr;
 }
 
 bool Task::isRunning() const
 {
-	return m_running;
+    return m_running;
 }
 
 bool Task::isFinished() const
 {
-	return m_finished;
+    return m_finished;
 }
 
 bool Task::wasSuccessful() const
 {
-	return m_succeeded;
+    return m_succeeded;
 }
 
 QString Task::failReason() const
 {
-	return m_failReason;
+    return m_failReason;
 }
 
 void Task::logWarning(const QString& line)
 {
-	qWarning() << line;
-	m_Warnings.append(line);
+    qWarning() << line;
+    m_Warnings.append(line);
 }
 
 QStringList Task::warnings() const
 {
-	return m_Warnings;
+    return m_Warnings;
 }
diff --git a/api/logic/tasks/Task.h b/api/logic/tasks/Task.h
index 643f8510..58dbc4ca 100644
--- a/api/logic/tasks/Task.h
+++ b/api/logic/tasks/Task.h
@@ -23,78 +23,78 @@
 
 class MULTIMC_LOGIC_EXPORT Task : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit Task(QObject *parent = 0);
-	virtual ~Task() {};
+    explicit Task(QObject *parent = 0);
+    virtual ~Task() {};
 
-	bool isRunning() const;
-	bool isFinished() const;
-	bool wasSuccessful() const;
+    bool isRunning() const;
+    bool isFinished() const;
+    bool wasSuccessful() const;
 
-	/*!
-	 * Returns the string that was passed to emitFailed as the error message when the task failed.
-	 * If the task hasn't failed, returns an empty string.
-	 */
-	QString failReason() const;
+    /*!
+     * Returns the string that was passed to emitFailed as the error message when the task failed.
+     * If the task hasn't failed, returns an empty string.
+     */
+    QString failReason() const;
 
-	virtual QStringList warnings() const;
+    virtual QStringList warnings() const;
 
-	virtual bool canAbort() const { return false; }
+    virtual bool canAbort() const { return false; }
 
-	QString getStatus()
-	{
-		return m_status;
-	}
+    QString getStatus()
+    {
+        return m_status;
+    }
 
-	qint64 getProgress()
-	{
-		return m_progress;
-	}
+    qint64 getProgress()
+    {
+        return m_progress;
+    }
 
-	qint64 getTotalProgress()
-	{
-		return m_progressTotal;
-	}
+    qint64 getTotalProgress()
+    {
+        return m_progressTotal;
+    }
 
 protected:
-	void logWarning(const QString & line);
+    void logWarning(const QString & line);
 
 private:
-	QString describe();
+    QString describe();
 
 signals:
-	void started();
-	void progress(qint64 current, qint64 total);
-	void finished();
-	void succeeded();
-	void failed(QString reason);
-	void status(QString status);
+    void started();
+    void progress(qint64 current, qint64 total);
+    void finished();
+    void succeeded();
+    void failed(QString reason);
+    void status(QString status);
 
 public slots:
-	virtual void start();
-	virtual bool abort() { return false; };
+    virtual void start();
+    virtual bool abort() { return false; };
 
 protected:
-	virtual void executeTask() = 0;
+    virtual void executeTask() = 0;
 
 protected slots:
-	virtual void emitSucceeded();
-	virtual void emitAborted();
-	virtual void emitFailed(QString reason);
+    virtual void emitSucceeded();
+    virtual void emitAborted();
+    virtual void emitFailed(QString reason);
 
 public slots:
-	void setStatus(const QString &status);
-	void setProgress(qint64 current, qint64 total);
+    void setStatus(const QString &status);
+    void setProgress(qint64 current, qint64 total);
 
 private:
-	bool m_running = false;
-	bool m_finished = false;
-	bool m_succeeded = false;
-	QStringList m_Warnings;
-	QString m_failReason = "";
-	QString m_status;
-	int m_progress = 0;
-	int m_progressTotal = 100;
+    bool m_running = false;
+    bool m_finished = false;
+    bool m_succeeded = false;
+    QStringList m_Warnings;
+    QString m_failReason = "";
+    QString m_status;
+    int m_progress = 0;
+    int m_progressTotal = 100;
 };
 
diff --git a/api/logic/tools/BaseExternalTool.cpp b/api/logic/tools/BaseExternalTool.cpp
index 2b97c3c9..38d81788 100644
--- a/api/logic/tools/BaseExternalTool.cpp
+++ b/api/logic/tools/BaseExternalTool.cpp
@@ -10,7 +10,7 @@
 #include "BaseInstance.h"
 
 BaseExternalTool::BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent)
-	: QObject(parent), m_instance(instance), globalSettings(settings)
+    : QObject(parent), m_instance(instance), globalSettings(settings)
 {
 }
 
@@ -19,14 +19,14 @@ BaseExternalTool::~BaseExternalTool()
 }
 
 BaseDetachedTool::BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent)
-	: BaseExternalTool(settings, instance, parent)
+    : BaseExternalTool(settings, instance, parent)
 {
 
 }
 
 void BaseDetachedTool::run()
 {
-	runImpl();
+    runImpl();
 }
 
 
@@ -35,7 +35,7 @@ BaseExternalToolFactory::~BaseExternalToolFactory()
 }
 
 BaseDetachedTool *BaseDetachedToolFactory::createDetachedTool(InstancePtr instance,
-															  QObject *parent)
+                                                              QObject *parent)
 {
-	return qobject_cast<BaseDetachedTool *>(createTool(instance, parent));
+    return qobject_cast<BaseDetachedTool *>(createTool(instance, parent));
 }
diff --git a/api/logic/tools/BaseExternalTool.h b/api/logic/tools/BaseExternalTool.h
index fe1b5dc6..b393b9ef 100644
--- a/api/logic/tools/BaseExternalTool.h
+++ b/api/logic/tools/BaseExternalTool.h
@@ -11,50 +11,50 @@ class QProcess;
 
 class MULTIMC_LOGIC_EXPORT BaseExternalTool : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
-	virtual ~BaseExternalTool();
+    explicit BaseExternalTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
+    virtual ~BaseExternalTool();
 
 protected:
-	InstancePtr m_instance;
-	SettingsObjectPtr globalSettings;
+    InstancePtr m_instance;
+    SettingsObjectPtr globalSettings;
 };
 
 class MULTIMC_LOGIC_EXPORT BaseDetachedTool : public BaseExternalTool
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
+    explicit BaseDetachedTool(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
 
 public
 slots:
-	void run();
+    void run();
 
 protected:
-	virtual void runImpl() = 0;
+    virtual void runImpl() = 0;
 };
 
 class MULTIMC_LOGIC_EXPORT BaseExternalToolFactory
 {
 public:
-	virtual ~BaseExternalToolFactory();
+    virtual ~BaseExternalToolFactory();
 
-	virtual QString name() const = 0;
+    virtual QString name() const = 0;
 
-	virtual void registerSettings(SettingsObjectPtr settings) = 0;
+    virtual void registerSettings(SettingsObjectPtr settings) = 0;
 
-	virtual BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) = 0;
+    virtual BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) = 0;
 
-	virtual bool check(QString *error) = 0;
-	virtual bool check(const QString &path, QString *error) = 0;
+    virtual bool check(QString *error) = 0;
+    virtual bool check(const QString &path, QString *error) = 0;
 
 protected:
-	SettingsObjectPtr globalSettings;
+    SettingsObjectPtr globalSettings;
 };
 
 class MULTIMC_LOGIC_EXPORT BaseDetachedToolFactory : public BaseExternalToolFactory
 {
 public:
-	virtual BaseDetachedTool *createDetachedTool(InstancePtr instance, QObject *parent = 0);
+    virtual BaseDetachedTool *createDetachedTool(InstancePtr instance, QObject *parent = 0);
 };
diff --git a/api/logic/tools/BaseProfiler.cpp b/api/logic/tools/BaseProfiler.cpp
index 5ff0fa44..c7d83549 100644
--- a/api/logic/tools/BaseProfiler.cpp
+++ b/api/logic/tools/BaseProfiler.cpp
@@ -3,33 +3,33 @@
 #include <QProcess>
 
 BaseProfiler::BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent)
-	: BaseExternalTool(settings, instance, parent)
+    : BaseExternalTool(settings, instance, parent)
 {
 }
 
 void BaseProfiler::beginProfiling(std::shared_ptr<LaunchTask> process)
 {
-	beginProfilingImpl(process);
+    beginProfilingImpl(process);
 }
 
 void BaseProfiler::abortProfiling()
 {
-	abortProfilingImpl();
+    abortProfilingImpl();
 }
 
 void BaseProfiler::abortProfilingImpl()
 {
-	if (!m_profilerProcess)
-	{
-		return;
-	}
-	m_profilerProcess->terminate();
-	m_profilerProcess->deleteLater();
-	m_profilerProcess = 0;
-	emit abortLaunch(tr("Profiler aborted"));
+    if (!m_profilerProcess)
+    {
+        return;
+    }
+    m_profilerProcess->terminate();
+    m_profilerProcess->deleteLater();
+    m_profilerProcess = 0;
+    emit abortLaunch(tr("Profiler aborted"));
 }
 
 BaseProfiler *BaseProfilerFactory::createProfiler(InstancePtr instance, QObject *parent)
 {
-	return qobject_cast<BaseProfiler *>(createTool(instance, parent));
+    return qobject_cast<BaseProfiler *>(createTool(instance, parent));
 }
diff --git a/api/logic/tools/BaseProfiler.h b/api/logic/tools/BaseProfiler.h
index 3340b7e4..f3e1ce3d 100644
--- a/api/logic/tools/BaseProfiler.h
+++ b/api/logic/tools/BaseProfiler.h
@@ -11,28 +11,28 @@ class QProcess;
 
 class MULTIMC_LOGIC_EXPORT BaseProfiler : public BaseExternalTool
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
+    explicit BaseProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
 
 public
 slots:
-	void beginProfiling(std::shared_ptr<LaunchTask> process);
-	void abortProfiling();
+    void beginProfiling(std::shared_ptr<LaunchTask> process);
+    void abortProfiling();
 
 protected:
-	QProcess *m_profilerProcess;
+    QProcess *m_profilerProcess;
 
-	virtual void beginProfilingImpl(std::shared_ptr<LaunchTask> process) = 0;
-	virtual void abortProfilingImpl();
+    virtual void beginProfilingImpl(std::shared_ptr<LaunchTask> process) = 0;
+    virtual void abortProfilingImpl();
 
 signals:
-	void readyToLaunch(const QString &message);
-	void abortLaunch(const QString &message);
+    void readyToLaunch(const QString &message);
+    void abortLaunch(const QString &message);
 };
 
 class MULTIMC_LOGIC_EXPORT BaseProfilerFactory : public BaseExternalToolFactory
 {
 public:
-	virtual BaseProfiler *createProfiler(InstancePtr instance, QObject *parent = 0);
+    virtual BaseProfiler *createProfiler(InstancePtr instance, QObject *parent = 0);
 };
diff --git a/api/logic/tools/JProfiler.cpp b/api/logic/tools/JProfiler.cpp
index a0e3c895..b50322fe 100644
--- a/api/logic/tools/JProfiler.cpp
+++ b/api/logic/tools/JProfiler.cpp
@@ -8,109 +8,109 @@
 
 class JProfiler : public BaseProfiler
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	JProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
+    JProfiler(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
 
 private slots:
-	void profilerStarted();
-	void profilerFinished(int exit, QProcess::ExitStatus status);
+    void profilerStarted();
+    void profilerFinished(int exit, QProcess::ExitStatus status);
 
 protected:
-	void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
+    void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
 
 private:
-	int listeningPort = 0;
+    int listeningPort = 0;
 };
 
 JProfiler::JProfiler(SettingsObjectPtr settings, InstancePtr instance,
-					 QObject *parent)
-	: BaseProfiler(settings, instance, parent)
+                     QObject *parent)
+    : BaseProfiler(settings, instance, parent)
 {
 }
 
 void JProfiler::profilerStarted()
 {
-	emit readyToLaunch(tr("Listening on port: %1").arg(listeningPort));
+    emit readyToLaunch(tr("Listening on port: %1").arg(listeningPort));
 }
 
 void JProfiler::profilerFinished(int exit, QProcess::ExitStatus status)
 {
-	if (status == QProcess::CrashExit)
-	{
-		emit abortLaunch(tr("Profiler aborted"));
-	}
-	if (m_profilerProcess)
-	{
-		m_profilerProcess->deleteLater();
-		m_profilerProcess = 0;
-	}
+    if (status == QProcess::CrashExit)
+    {
+        emit abortLaunch(tr("Profiler aborted"));
+    }
+    if (m_profilerProcess)
+    {
+        m_profilerProcess->deleteLater();
+        m_profilerProcess = 0;
+    }
 }
 
 void JProfiler::beginProfilingImpl(std::shared_ptr<LaunchTask> process)
 {
-	listeningPort = globalSettings->get("JProfilerPort").toInt();
-	QProcess *profiler = new QProcess(this);
-	QStringList profilerArgs =
-	{
-		"-d", QString::number(process->pid()),
-		"--gui",
-		"-p", QString::number(listeningPort)
-	};
-	auto basePath = globalSettings->get("JProfilerPath").toString();
+    listeningPort = globalSettings->get("JProfilerPort").toInt();
+    QProcess *profiler = new QProcess(this);
+    QStringList profilerArgs =
+    {
+        "-d", QString::number(process->pid()),
+        "--gui",
+        "-p", QString::number(listeningPort)
+    };
+    auto basePath = globalSettings->get("JProfilerPath").toString();
 
 #ifdef Q_OS_WIN
-	QString profilerProgram = QDir(basePath).absoluteFilePath("bin/jpenable.exe");
+    QString profilerProgram = QDir(basePath).absoluteFilePath("bin/jpenable.exe");
 #else
-	QString profilerProgram = QDir(basePath).absoluteFilePath("bin/jpenable");
+    QString profilerProgram = QDir(basePath).absoluteFilePath("bin/jpenable");
 #endif
 
-	profiler->setArguments(profilerArgs);
-	profiler->setProgram(profilerProgram);
+    profiler->setArguments(profilerArgs);
+    profiler->setProgram(profilerProgram);
 
-	connect(profiler, SIGNAL(started()), SLOT(profilerStarted()));
-	connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus)));
+    connect(profiler, SIGNAL(started()), SLOT(profilerStarted()));
+    connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus)));
 
-	m_profilerProcess = profiler;
-	profiler->start();
+    m_profilerProcess = profiler;
+    profiler->start();
 }
 
 void JProfilerFactory::registerSettings(SettingsObjectPtr settings)
 {
-	settings->registerSetting("JProfilerPath");
-	settings->registerSetting("JProfilerPort", 42042);
-	globalSettings = settings;
+    settings->registerSetting("JProfilerPath");
+    settings->registerSetting("JProfilerPort", 42042);
+    globalSettings = settings;
 }
 
 BaseExternalTool *JProfilerFactory::createTool(InstancePtr instance, QObject *parent)
 {
-	return new JProfiler(globalSettings, instance, parent);
+    return new JProfiler(globalSettings, instance, parent);
 }
 
 bool JProfilerFactory::check(QString *error)
 {
-	return check(globalSettings->get("JProfilerPath").toString(), error);
+    return check(globalSettings->get("JProfilerPath").toString(), error);
 }
 
 bool JProfilerFactory::check(const QString &path, QString *error)
 {
-	if (path.isEmpty())
-	{
-		*error = QObject::tr("Empty path");
-		return false;
-	}
-	QDir dir(path);
-	if (!dir.exists())
-	{
-		*error = QObject::tr("Path does not exist");
-		return false;
-	}
-	if (!dir.exists("bin") || !(dir.exists("bin/jprofiler") || dir.exists("bin/jprofiler.exe")) || !dir.exists("bin/agent.jar"))
-	{
-		*error = QObject::tr("Invalid JProfiler install");
-		return false;
-	}
-	return true;
+    if (path.isEmpty())
+    {
+        *error = QObject::tr("Empty path");
+        return false;
+    }
+    QDir dir(path);
+    if (!dir.exists())
+    {
+        *error = QObject::tr("Path does not exist");
+        return false;
+    }
+    if (!dir.exists("bin") || !(dir.exists("bin/jprofiler") || dir.exists("bin/jprofiler.exe")) || !dir.exists("bin/agent.jar"))
+    {
+        *error = QObject::tr("Invalid JProfiler install");
+        return false;
+    }
+    return true;
 }
 
 #include "JProfiler.moc"
diff --git a/api/logic/tools/JProfiler.h b/api/logic/tools/JProfiler.h
index d658d6c2..f211ddbf 100644
--- a/api/logic/tools/JProfiler.h
+++ b/api/logic/tools/JProfiler.h
@@ -7,9 +7,9 @@
 class MULTIMC_LOGIC_EXPORT JProfilerFactory : public BaseProfilerFactory
 {
 public:
-	QString name() const override { return "JProfiler"; }
-	void registerSettings(SettingsObjectPtr settings) override;
-	BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override;
-	bool check(QString *error) override;
-	bool check(const QString &path, QString *error) override;
+    QString name() const override { return "JProfiler"; }
+    void registerSettings(SettingsObjectPtr settings) override;
+    BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override;
+    bool check(QString *error) override;
+    bool check(const QString &path, QString *error) override;
 };
diff --git a/api/logic/tools/JVisualVM.cpp b/api/logic/tools/JVisualVM.cpp
index 8fdb594f..10886857 100644
--- a/api/logic/tools/JVisualVM.cpp
+++ b/api/logic/tools/JVisualVM.cpp
@@ -9,96 +9,96 @@
 
 class JVisualVM : public BaseProfiler
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
+    JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject *parent = 0);
 
 private slots:
-	void profilerStarted();
-	void profilerFinished(int exit, QProcess::ExitStatus status);
+    void profilerStarted();
+    void profilerFinished(int exit, QProcess::ExitStatus status);
 
 protected:
-	void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
+    void beginProfilingImpl(std::shared_ptr<LaunchTask> process);
 };
 
 
 JVisualVM::JVisualVM(SettingsObjectPtr settings, InstancePtr instance, QObject *parent)
-	: BaseProfiler(settings, instance, parent)
+    : BaseProfiler(settings, instance, parent)
 {
 }
 
 void JVisualVM::profilerStarted()
 {
-	emit readyToLaunch(tr("JVisualVM started"));
+    emit readyToLaunch(tr("JVisualVM started"));
 }
 
 void JVisualVM::profilerFinished(int exit, QProcess::ExitStatus status)
 {
-	if (status == QProcess::CrashExit)
-	{
-		emit abortLaunch(tr("Profiler aborted"));
-	}
-	if (m_profilerProcess)
-	{
-		m_profilerProcess->deleteLater();
-		m_profilerProcess = 0;
-	}
+    if (status == QProcess::CrashExit)
+    {
+        emit abortLaunch(tr("Profiler aborted"));
+    }
+    if (m_profilerProcess)
+    {
+        m_profilerProcess->deleteLater();
+        m_profilerProcess = 0;
+    }
 }
 
 void JVisualVM::beginProfilingImpl(std::shared_ptr<LaunchTask> process)
 {
-	QProcess *profiler = new QProcess(this);
-	QStringList profilerArgs =
-	{
-		"--openpid", QString::number(process->pid())
-	};
-	auto programPath = globalSettings->get("JVisualVMPath").toString();
+    QProcess *profiler = new QProcess(this);
+    QStringList profilerArgs =
+    {
+        "--openpid", QString::number(process->pid())
+    };
+    auto programPath = globalSettings->get("JVisualVMPath").toString();
 
-	profiler->setArguments(profilerArgs);
-	profiler->setProgram(programPath);
+    profiler->setArguments(profilerArgs);
+    profiler->setProgram(programPath);
 
-	connect(profiler, SIGNAL(started()), SLOT(profilerStarted()));
-	connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus)));
+    connect(profiler, SIGNAL(started()), SLOT(profilerStarted()));
+    connect(profiler, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(profilerFinished(int,QProcess::ExitStatus)));
 
-	profiler->start();
-	m_profilerProcess = profiler;
+    profiler->start();
+    m_profilerProcess = profiler;
 }
 
 void JVisualVMFactory::registerSettings(SettingsObjectPtr settings)
 {
-	QString defaultValue = QStandardPaths::findExecutable("jvisualvm");
-	if (defaultValue.isNull())
-	{
-		defaultValue = QStandardPaths::findExecutable("visualvm");
-	}
-	settings->registerSetting("JVisualVMPath", defaultValue);
-	globalSettings = settings;
+    QString defaultValue = QStandardPaths::findExecutable("jvisualvm");
+    if (defaultValue.isNull())
+    {
+        defaultValue = QStandardPaths::findExecutable("visualvm");
+    }
+    settings->registerSetting("JVisualVMPath", defaultValue);
+    globalSettings = settings;
 }
 
 BaseExternalTool *JVisualVMFactory::createTool(InstancePtr instance, QObject *parent)
 {
-	return new JVisualVM(globalSettings, instance, parent);
+    return new JVisualVM(globalSettings, instance, parent);
 }
 
 bool JVisualVMFactory::check(QString *error)
 {
-	return check(globalSettings->get("JVisualVMPath").toString(), error);
+    return check(globalSettings->get("JVisualVMPath").toString(), error);
 }
 
 bool JVisualVMFactory::check(const QString &path, QString *error)
 {
-	if (path.isEmpty())
-	{
-		*error = QObject::tr("Empty path");
-		return false;
-	}
-	QFileInfo finfo(path);
-	if (!finfo.isExecutable() || !finfo.fileName().contains("visualvm"))
-	{
-		*error = QObject::tr("Invalid path to JVisualVM");
-		return false;
-	}
-	return true;
+    if (path.isEmpty())
+    {
+        *error = QObject::tr("Empty path");
+        return false;
+    }
+    QFileInfo finfo(path);
+    if (!finfo.isExecutable() || !finfo.fileName().contains("visualvm"))
+    {
+        *error = QObject::tr("Invalid path to JVisualVM");
+        return false;
+    }
+    return true;
 }
 
 #include "JVisualVM.moc"
diff --git a/api/logic/tools/JVisualVM.h b/api/logic/tools/JVisualVM.h
index 0674da13..91d48d94 100644
--- a/api/logic/tools/JVisualVM.h
+++ b/api/logic/tools/JVisualVM.h
@@ -7,9 +7,9 @@
 class MULTIMC_LOGIC_EXPORT JVisualVMFactory : public BaseProfilerFactory
 {
 public:
-	QString name() const override { return "JVisualVM"; }
-	void registerSettings(SettingsObjectPtr settings) override;
-	BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override;
-	bool check(QString *error) override;
-	bool check(const QString &path, QString *error) override;
+    QString name() const override { return "JVisualVM"; }
+    void registerSettings(SettingsObjectPtr settings) override;
+    BaseExternalTool *createTool(InstancePtr instance, QObject *parent = 0) override;
+    bool check(QString *error) override;
+    bool check(const QString &path, QString *error) override;
 };
diff --git a/api/logic/tools/MCEditTool.cpp b/api/logic/tools/MCEditTool.cpp
index 74715d3f..880327c7 100644
--- a/api/logic/tools/MCEditTool.cpp
+++ b/api/logic/tools/MCEditTool.cpp
@@ -10,68 +10,68 @@
 
 MCEditTool::MCEditTool(SettingsObjectPtr settings)
 {
-	settings->registerSetting("MCEditPath");
-	m_settings = settings;
+    settings->registerSetting("MCEditPath");
+    m_settings = settings;
 }
 
 void MCEditTool::setPath(QString& path)
 {
-	m_settings->set("MCEditPath", path);
+    m_settings->set("MCEditPath", path);
 }
 
 QString MCEditTool::path() const
 {
-	return m_settings->get("MCEditPath").toString();
+    return m_settings->get("MCEditPath").toString();
 }
 
 bool MCEditTool::check(const QString& toolPath, QString& error)
 {
-	if (toolPath.isEmpty())
-	{
-		error = QObject::tr("Path is empty");
-		return false;
-	}
-	const QDir dir(toolPath);
-	if (!dir.exists())
-	{
-		error = QObject::tr("Path does not exist");
-		return false;
-	}
-	if (!dir.exists("mcedit.sh") && !dir.exists("mcedit.py") && !dir.exists("mcedit.exe") && !dir.exists("Contents") && !dir.exists("mcedit2.exe"))
-	{
-		error = QObject::tr("Path does not seem to be a MCEdit path");
-		return false;
-	}
-	return true;
+    if (toolPath.isEmpty())
+    {
+        error = QObject::tr("Path is empty");
+        return false;
+    }
+    const QDir dir(toolPath);
+    if (!dir.exists())
+    {
+        error = QObject::tr("Path does not exist");
+        return false;
+    }
+    if (!dir.exists("mcedit.sh") && !dir.exists("mcedit.py") && !dir.exists("mcedit.exe") && !dir.exists("Contents") && !dir.exists("mcedit2.exe"))
+    {
+        error = QObject::tr("Path does not seem to be a MCEdit path");
+        return false;
+    }
+    return true;
 }
 
 QString MCEditTool::getProgramPath()
 {
 #ifdef Q_OS_OSX
-	return path();
+    return path();
 #else
-	const QString mceditPath = path();
-	QDir mceditDir(mceditPath);
+    const QString mceditPath = path();
+    QDir mceditDir(mceditPath);
 #ifdef Q_OS_LINUX
-	if (mceditDir.exists("mcedit.sh"))
-	{
-		return mceditDir.absoluteFilePath("mcedit.sh");
-	}
-	else if (mceditDir.exists("mcedit.py"))
-	{
-		return mceditDir.absoluteFilePath("mcedit.py");
-	}
-	return QString();
+    if (mceditDir.exists("mcedit.sh"))
+    {
+        return mceditDir.absoluteFilePath("mcedit.sh");
+    }
+    else if (mceditDir.exists("mcedit.py"))
+    {
+        return mceditDir.absoluteFilePath("mcedit.py");
+    }
+    return QString();
 #elif defined(Q_OS_WIN32)
-	if (mceditDir.exists("mcedit.exe"))
-	{
-		return mceditDir.absoluteFilePath("mcedit.exe");
-	}
-	else if (mceditDir.exists("mcedit2.exe"))
-	{
-		return mceditDir.absoluteFilePath("mcedit2.exe");
-	}
-	return QString();
+    if (mceditDir.exists("mcedit.exe"))
+    {
+        return mceditDir.absoluteFilePath("mcedit.exe");
+    }
+    else if (mceditDir.exists("mcedit2.exe"))
+    {
+        return mceditDir.absoluteFilePath("mcedit2.exe");
+    }
+    return QString();
 #endif
 #endif
 }
diff --git a/api/logic/tools/MCEditTool.h b/api/logic/tools/MCEditTool.h
index 51feb1fe..1465494e 100644
--- a/api/logic/tools/MCEditTool.h
+++ b/api/logic/tools/MCEditTool.h
@@ -7,11 +7,11 @@
 class MULTIMC_LOGIC_EXPORT MCEditTool
 {
 public:
-	MCEditTool(SettingsObjectPtr settings);
-	void setPath(QString & path);
-	QString path() const;
-	bool check(const QString &toolPath, QString &error);
-	QString getProgramPath();
+    MCEditTool(SettingsObjectPtr settings);
+    void setPath(QString & path);
+    QString path() const;
+    bool check(const QString &toolPath, QString &error);
+    QString getProgramPath();
 private:
-	SettingsObjectPtr m_settings;
+    SettingsObjectPtr m_settings;
 };
diff --git a/api/logic/translations/TranslationsModel.cpp b/api/logic/translations/TranslationsModel.cpp
index 18625ee5..185cc8c4 100644
--- a/api/logic/translations/TranslationsModel.cpp
+++ b/api/logic/translations/TranslationsModel.cpp
@@ -15,33 +15,33 @@ const static QLatin1Literal defaultLangCode("en");
 
 struct Language
 {
-	QString key;
-	QLocale locale;
-	bool updated;
+    QString key;
+    QLocale locale;
+    bool updated;
 };
 
 struct TranslationsModel::Private
 {
-	QDir m_dir;
-
-	// initial state is just english
-	QVector<Language> m_languages = {{defaultLangCode, QLocale(defaultLangCode), false}};
-	QString m_selectedLanguage = defaultLangCode;
-	std::unique_ptr<QTranslator> m_qt_translator;
-	std::unique_ptr<QTranslator> m_app_translator;
-
-	std::shared_ptr<Net::Download> m_index_task;
-	QString m_downloadingTranslation;
-	NetJobPtr m_dl_job;
-	NetJobPtr m_index_job;
-	QString m_nextDownload;
+    QDir m_dir;
+
+    // initial state is just english
+    QVector<Language> m_languages = {{defaultLangCode, QLocale(defaultLangCode), false}};
+    QString m_selectedLanguage = defaultLangCode;
+    std::unique_ptr<QTranslator> m_qt_translator;
+    std::unique_ptr<QTranslator> m_app_translator;
+
+    std::shared_ptr<Net::Download> m_index_task;
+    QString m_downloadingTranslation;
+    NetJobPtr m_dl_job;
+    NetJobPtr m_index_job;
+    QString m_nextDownload;
 };
 
 TranslationsModel::TranslationsModel(QString path, QObject* parent): QAbstractListModel(parent)
 {
-	d.reset(new Private);
-	d->m_dir.setPath(path);
-	loadLocalIndex();
+    d.reset(new Private);
+    d->m_dir.setPath(path);
+    loadLocalIndex();
 }
 
 TranslationsModel::~TranslationsModel()
@@ -50,270 +50,270 @@ TranslationsModel::~TranslationsModel()
 
 QVariant TranslationsModel::data(const QModelIndex& index, int role) const
 {
-	if (!index.isValid())
-		return QVariant();
-
-	int row = index.row();
-
-	if (row < 0 || row >= d->m_languages.size())
-		return QVariant();
-
-	switch (role)
-	{
-	case Qt::DisplayRole:
-		return d->m_languages[row].locale.nativeLanguageName();
-	case Qt::UserRole:
-		return d->m_languages[row].key;
-	default:
-		return QVariant();
-	}
+    if (!index.isValid())
+        return QVariant();
+
+    int row = index.row();
+
+    if (row < 0 || row >= d->m_languages.size())
+        return QVariant();
+
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        return d->m_languages[row].locale.nativeLanguageName();
+    case Qt::UserRole:
+        return d->m_languages[row].key;
+    default:
+        return QVariant();
+    }
 }
 
 int TranslationsModel::rowCount(const QModelIndex& parent) const
 {
-	return d->m_languages.size();
+    return d->m_languages.size();
 }
 
 Language * TranslationsModel::findLanguage(const QString& key)
 {
-	auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language & lang)
-	{
-		return lang.key == key;
-	});
-	if(found == d->m_languages.end())
-	{
-		return nullptr;
-	}
-	else
-	{
-		return found;
-	}
+    auto found = std::find_if(d->m_languages.begin(), d->m_languages.end(), [&](Language & lang)
+    {
+        return lang.key == key;
+    });
+    if(found == d->m_languages.end())
+    {
+        return nullptr;
+    }
+    else
+    {
+        return found;
+    }
 }
 
 bool TranslationsModel::selectLanguage(QString key)
 {
-	QString &langCode = key;
-	auto langPtr = findLanguage(key);
-	if(!langPtr)
-	{
-		qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode;
-		langCode = defaultLangCode;
-	}
-	else
-	{
-		langCode = langPtr->key;
-	}
-
-	// uninstall existing translators if there are any
-	if (d->m_app_translator)
-	{
-		QCoreApplication::removeTranslator(d->m_app_translator.get());
-		d->m_app_translator.reset();
-	}
-	if (d->m_qt_translator)
-	{
-		QCoreApplication::removeTranslator(d->m_qt_translator.get());
-		d->m_qt_translator.reset();
-	}
-
-	/*
-	 * FIXME: potential source of crashes:
-	 * In a multithreaded application, the default locale should be set at application startup, before any non-GUI threads are created.
-	 * This function is not reentrant.
-	 */
-	QLocale locale(langCode);
-	QLocale::setDefault(locale);
-
-	// if it's the default UI language, finish
-	if(langCode == defaultLangCode)
-	{
-		d->m_selectedLanguage = langCode;
-		return true;
-	}
-
-	// otherwise install new translations
-	bool successful = false;
-	// FIXME: this is likely never present. FIX IT.
-	d->m_qt_translator.reset(new QTranslator());
-	if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
-	{
-		qDebug() << "Loading Qt Language File for" << langCode.toLocal8Bit().constData() << "...";
-		if (!QCoreApplication::installTranslator(d->m_qt_translator.get()))
-		{
-			qCritical() << "Loading Qt Language File failed.";
-			d->m_qt_translator.reset();
-		}
-		else
-		{
-			successful = true;
-		}
-	}
-	else
-	{
-		d->m_qt_translator.reset();
-	}
-
-	d->m_app_translator.reset(new QTranslator());
-	if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path()))
-	{
-		qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "...";
-		if (!QCoreApplication::installTranslator(d->m_app_translator.get()))
-		{
-			qCritical() << "Loading Application Language File failed.";
-			d->m_app_translator.reset();
-		}
-		else
-		{
-			successful = true;
-		}
-	}
-	else
-	{
-		d->m_app_translator.reset();
-	}
-	d->m_selectedLanguage = langCode;
-	return successful;
+    QString &langCode = key;
+    auto langPtr = findLanguage(key);
+    if(!langPtr)
+    {
+        qWarning() << "Selected invalid language" << key << ", defaulting to" << defaultLangCode;
+        langCode = defaultLangCode;
+    }
+    else
+    {
+        langCode = langPtr->key;
+    }
+
+    // uninstall existing translators if there are any
+    if (d->m_app_translator)
+    {
+        QCoreApplication::removeTranslator(d->m_app_translator.get());
+        d->m_app_translator.reset();
+    }
+    if (d->m_qt_translator)
+    {
+        QCoreApplication::removeTranslator(d->m_qt_translator.get());
+        d->m_qt_translator.reset();
+    }
+
+    /*
+     * FIXME: potential source of crashes:
+     * In a multithreaded application, the default locale should be set at application startup, before any non-GUI threads are created.
+     * This function is not reentrant.
+     */
+    QLocale locale(langCode);
+    QLocale::setDefault(locale);
+
+    // if it's the default UI language, finish
+    if(langCode == defaultLangCode)
+    {
+        d->m_selectedLanguage = langCode;
+        return true;
+    }
+
+    // otherwise install new translations
+    bool successful = false;
+    // FIXME: this is likely never present. FIX IT.
+    d->m_qt_translator.reset(new QTranslator());
+    if (d->m_qt_translator->load("qt_" + langCode, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+    {
+        qDebug() << "Loading Qt Language File for" << langCode.toLocal8Bit().constData() << "...";
+        if (!QCoreApplication::installTranslator(d->m_qt_translator.get()))
+        {
+            qCritical() << "Loading Qt Language File failed.";
+            d->m_qt_translator.reset();
+        }
+        else
+        {
+            successful = true;
+        }
+    }
+    else
+    {
+        d->m_qt_translator.reset();
+    }
+
+    d->m_app_translator.reset(new QTranslator());
+    if (d->m_app_translator->load("mmc_" + langCode, d->m_dir.path()))
+    {
+        qDebug() << "Loading Application Language File for" << langCode.toLocal8Bit().constData() << "...";
+        if (!QCoreApplication::installTranslator(d->m_app_translator.get()))
+        {
+            qCritical() << "Loading Application Language File failed.";
+            d->m_app_translator.reset();
+        }
+        else
+        {
+            successful = true;
+        }
+    }
+    else
+    {
+        d->m_app_translator.reset();
+    }
+    d->m_selectedLanguage = langCode;
+    return successful;
 }
 
 QModelIndex TranslationsModel::selectedIndex()
 {
-	auto found = findLanguage(d->m_selectedLanguage);
-	if(found)
-	{
-		// QVector iterator freely converts to pointer to contained type
-		return index(found - d->m_languages.begin(), 0, QModelIndex());
-	}
-	return QModelIndex();
+    auto found = findLanguage(d->m_selectedLanguage);
+    if(found)
+    {
+        // QVector iterator freely converts to pointer to contained type
+        return index(found - d->m_languages.begin(), 0, QModelIndex());
+    }
+    return QModelIndex();
 }
 
 QString TranslationsModel::selectedLanguage()
 {
-	return d->m_selectedLanguage;
+    return d->m_selectedLanguage;
 }
 
 void TranslationsModel::downloadIndex()
 {
-	if(d->m_index_job || d->m_dl_job)
-	{
-		return;
-	}
-	qDebug() << "Downloading Translations Index...";
-	d->m_index_job.reset(new NetJob("Translations Index"));
-	MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "index");
-	d->m_index_task = Net::Download::makeCached(QUrl("http://files.multimc.org/translations/index"), entry);
-	d->m_index_job->addNetAction(d->m_index_task);
-	connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed);
-	connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexRecieved);
-	d->m_index_job->start();
+    if(d->m_index_job || d->m_dl_job)
+    {
+        return;
+    }
+    qDebug() << "Downloading Translations Index...";
+    d->m_index_job.reset(new NetJob("Translations Index"));
+    MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "index");
+    d->m_index_task = Net::Download::makeCached(QUrl("http://files.multimc.org/translations/index"), entry);
+    d->m_index_job->addNetAction(d->m_index_task);
+    connect(d->m_index_job.get(), &NetJob::failed, this, &TranslationsModel::indexFailed);
+    connect(d->m_index_job.get(), &NetJob::succeeded, this, &TranslationsModel::indexRecieved);
+    d->m_index_job->start();
 }
 
 void TranslationsModel::indexRecieved()
 {
-	qDebug() << "Got translations index!";
-	d->m_index_job.reset();
-	loadLocalIndex();
-	if(d->m_selectedLanguage != defaultLangCode)
-	{
-		downloadTranslation(d->m_selectedLanguage);
-	}
+    qDebug() << "Got translations index!";
+    d->m_index_job.reset();
+    loadLocalIndex();
+    if(d->m_selectedLanguage != defaultLangCode)
+    {
+        downloadTranslation(d->m_selectedLanguage);
+    }
 }
 
 void TranslationsModel::loadLocalIndex()
 {
-	QByteArray data;
-	try
-	{
-		data = FS::read(d->m_dir.absoluteFilePath("index"));
-	}
-	catch (const Exception &e)
-	{
-		qCritical() << "Translations Download Failed: index file not readable";
-		return;
-	}
-	QVector<Language> languages;
-	QList<QByteArray> lines = data.split('\n');
-	// add the default english.
-	languages.append({defaultLangCode, QLocale(defaultLangCode), true});
-	for (const auto line : lines)
-	{
-		if(!line.isEmpty())
-		{
-			auto str = QString::fromLatin1(line);
-			str.remove(".qm");
-			languages.append({str, QLocale(str), false});
-		}
-	}
-	beginResetModel();
-	d->m_languages.swap(languages);
-	endResetModel();
+    QByteArray data;
+    try
+    {
+        data = FS::read(d->m_dir.absoluteFilePath("index"));
+    }
+    catch (const Exception &e)
+    {
+        qCritical() << "Translations Download Failed: index file not readable";
+        return;
+    }
+    QVector<Language> languages;
+    QList<QByteArray> lines = data.split('\n');
+    // add the default english.
+    languages.append({defaultLangCode, QLocale(defaultLangCode), true});
+    for (const auto line : lines)
+    {
+        if(!line.isEmpty())
+        {
+            auto str = QString::fromLatin1(line);
+            str.remove(".qm");
+            languages.append({str, QLocale(str), false});
+        }
+    }
+    beginResetModel();
+    d->m_languages.swap(languages);
+    endResetModel();
 }
 
 void TranslationsModel::updateLanguage(QString key)
 {
-	if(key == defaultLangCode)
-	{
-		qWarning() << "Cannot update builtin language" << key;
-		return;
-	}
-	auto found = findLanguage(key);
-	if(!found)
-	{
-		qWarning() << "Cannot update invalid language" << key;
-		return;
-	}
-	if(!found->updated)
-	{
-		downloadTranslation(key);
-	}
+    if(key == defaultLangCode)
+    {
+        qWarning() << "Cannot update builtin language" << key;
+        return;
+    }
+    auto found = findLanguage(key);
+    if(!found)
+    {
+        qWarning() << "Cannot update invalid language" << key;
+        return;
+    }
+    if(!found->updated)
+    {
+        downloadTranslation(key);
+    }
 }
 
 void TranslationsModel::downloadTranslation(QString key)
 {
-	if(d->m_dl_job)
-	{
-		d->m_nextDownload = key;
-		return;
-	}
-	d->m_downloadingTranslation = key;
-	MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "mmc_" + key + ".qm");
-	entry->setStale(true);
-	d->m_dl_job.reset(new NetJob("Translation for " + key));
-	d->m_dl_job->addNetAction(Net::Download::makeCached(QUrl(URLConstants::TRANSLATIONS_BASE_URL + key + ".qm"), entry));
-	connect(d->m_dl_job.get(), &NetJob::succeeded, this, &TranslationsModel::dlGood);
-	connect(d->m_dl_job.get(), &NetJob::failed, this, &TranslationsModel::dlFailed);
-	d->m_dl_job->start();
+    if(d->m_dl_job)
+    {
+        d->m_nextDownload = key;
+        return;
+    }
+    d->m_downloadingTranslation = key;
+    MetaEntryPtr entry = ENV.metacache()->resolveEntry("translations", "mmc_" + key + ".qm");
+    entry->setStale(true);
+    d->m_dl_job.reset(new NetJob("Translation for " + key));
+    d->m_dl_job->addNetAction(Net::Download::makeCached(QUrl(URLConstants::TRANSLATIONS_BASE_URL + key + ".qm"), entry));
+    connect(d->m_dl_job.get(), &NetJob::succeeded, this, &TranslationsModel::dlGood);
+    connect(d->m_dl_job.get(), &NetJob::failed, this, &TranslationsModel::dlFailed);
+    d->m_dl_job->start();
 }
 
 void TranslationsModel::downloadNext()
 {
-	if(!d->m_nextDownload.isEmpty())
-	{
-		downloadTranslation(d->m_nextDownload);
-		d->m_nextDownload.clear();
-	}
+    if(!d->m_nextDownload.isEmpty())
+    {
+        downloadTranslation(d->m_nextDownload);
+        d->m_nextDownload.clear();
+    }
 }
 
 void TranslationsModel::dlFailed(QString reason)
 {
-	qCritical() << "Translations Download Failed:" << reason;
-	d->m_dl_job.reset();
-	downloadNext();
+    qCritical() << "Translations Download Failed:" << reason;
+    d->m_dl_job.reset();
+    downloadNext();
 }
 
 void TranslationsModel::dlGood()
 {
-	qDebug() << "Got translation:" << d->m_downloadingTranslation;
-
-	if(d->m_downloadingTranslation == d->m_selectedLanguage)
-	{
-		selectLanguage(d->m_selectedLanguage);
-	}
-	d->m_dl_job.reset();
-	downloadNext();
+    qDebug() << "Got translation:" << d->m_downloadingTranslation;
+
+    if(d->m_downloadingTranslation == d->m_selectedLanguage)
+    {
+        selectLanguage(d->m_selectedLanguage);
+    }
+    d->m_dl_job.reset();
+    downloadNext();
 }
 
 void TranslationsModel::indexFailed(QString reason)
 {
-	qCritical() << "Translations Index Download Failed:" << reason;
-	d->m_index_job.reset();
+    qCritical() << "Translations Index Download Failed:" << reason;
+    d->m_index_job.reset();
 }
diff --git a/api/logic/translations/TranslationsModel.h b/api/logic/translations/TranslationsModel.h
index bd481134..8a9298d4 100644
--- a/api/logic/translations/TranslationsModel.h
+++ b/api/logic/translations/TranslationsModel.h
@@ -23,39 +23,39 @@ struct Language;
 
 class MULTIMC_LOGIC_EXPORT TranslationsModel : public QAbstractListModel
 {
-	Q_OBJECT
+    Q_OBJECT
 public:
-	explicit TranslationsModel(QString path, QObject *parent = 0);
-	virtual ~TranslationsModel();
+    explicit TranslationsModel(QString path, QObject *parent = 0);
+    virtual ~TranslationsModel();
 
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
 
-	bool selectLanguage(QString key);
-	void updateLanguage(QString key);
-	QModelIndex selectedIndex();
-	QString selectedLanguage();
+    bool selectLanguage(QString key);
+    void updateLanguage(QString key);
+    QModelIndex selectedIndex();
+    QString selectedLanguage();
 
-	void downloadIndex();
+    void downloadIndex();
 
 private:
-	Language *findLanguage(const QString & key);
-	void loadLocalIndex();
-	void downloadTranslation(QString key);
-	void downloadNext();
+    Language *findLanguage(const QString & key);
+    void loadLocalIndex();
+    void downloadTranslation(QString key);
+    void downloadNext();
 
-	// hide copy constructor
-	TranslationsModel(const TranslationsModel &) = delete;
-	// hide assign op
-	TranslationsModel &operator=(const TranslationsModel &) = delete;
+    // hide copy constructor
+    TranslationsModel(const TranslationsModel &) = delete;
+    // hide assign op
+    TranslationsModel &operator=(const TranslationsModel &) = delete;
 
 private slots:
-	void indexRecieved();
-	void indexFailed(QString reason);
-	void dlFailed(QString reason);
-	void dlGood();
+    void indexRecieved();
+    void indexFailed(QString reason);
+    void dlFailed(QString reason);
+    void dlGood();
 
 private: /* data */
-	struct Private;
-	std::unique_ptr<Private> d;
+    struct Private;
+    std::unique_ptr<Private> d;
 };
diff --git a/api/logic/updater/DownloadTask.cpp b/api/logic/updater/DownloadTask.cpp
index e0adf593..cb92018d 100644
--- a/api/logic/updater/DownloadTask.cpp
+++ b/api/logic/updater/DownloadTask.cpp
@@ -27,140 +27,140 @@ namespace GoUpdate
 {
 
 DownloadTask::DownloadTask(Status status, QString target, QObject *parent)
-	: Task(parent), m_updateFilesDir(target)
+    : Task(parent), m_updateFilesDir(target)
 {
-	m_status = status;
+    m_status = status;
 
-	m_updateFilesDir.setAutoRemove(false);
+    m_updateFilesDir.setAutoRemove(false);
 }
 
 void DownloadTask::executeTask()
 {
-	loadVersionInfo();
+    loadVersionInfo();
 }
 
 void DownloadTask::loadVersionInfo()
 {
-	setStatus(tr("Loading version information..."));
+    setStatus(tr("Loading version information..."));
 
-	NetJob *netJob = new NetJob("Version Info");
+    NetJob *netJob = new NetJob("Version Info");
 
-	// Find the index URL.
-	QUrl newIndexUrl = QUrl(m_status.newRepoUrl).resolved(QString::number(m_status.newVersionId) + ".json");
-	qDebug() << m_status.newRepoUrl << " turns into " << newIndexUrl;
+    // Find the index URL.
+    QUrl newIndexUrl = QUrl(m_status.newRepoUrl).resolved(QString::number(m_status.newVersionId) + ".json");
+    qDebug() << m_status.newRepoUrl << " turns into " << newIndexUrl;
 
-	netJob->addNetAction(m_newVersionFileListDownload = Net::Download::makeByteArray(newIndexUrl, &newVersionFileListData));
+    netJob->addNetAction(m_newVersionFileListDownload = Net::Download::makeByteArray(newIndexUrl, &newVersionFileListData));
 
-	// If we have a current version URL, get that one too.
-	if (!m_status.currentRepoUrl.isEmpty())
-	{
-		QUrl cIndexUrl = QUrl(m_status.currentRepoUrl).resolved(QString::number(m_status.currentVersionId) + ".json");
-		netJob->addNetAction(m_currentVersionFileListDownload = Net::Download::makeByteArray(cIndexUrl, &currentVersionFileListData));
-		qDebug() << m_status.currentRepoUrl << " turns into " << cIndexUrl;
-	}
+    // If we have a current version URL, get that one too.
+    if (!m_status.currentRepoUrl.isEmpty())
+    {
+        QUrl cIndexUrl = QUrl(m_status.currentRepoUrl).resolved(QString::number(m_status.currentVersionId) + ".json");
+        netJob->addNetAction(m_currentVersionFileListDownload = Net::Download::makeByteArray(cIndexUrl, &currentVersionFileListData));
+        qDebug() << m_status.currentRepoUrl << " turns into " << cIndexUrl;
+    }
 
-	// connect signals and start the job
-	connect(netJob, &NetJob::succeeded, this, &DownloadTask::processDownloadedVersionInfo);
-	connect(netJob, &NetJob::failed, this, &DownloadTask::vinfoDownloadFailed);
-	m_vinfoNetJob.reset(netJob);
-	netJob->start();
+    // connect signals and start the job
+    connect(netJob, &NetJob::succeeded, this, &DownloadTask::processDownloadedVersionInfo);
+    connect(netJob, &NetJob::failed, this, &DownloadTask::vinfoDownloadFailed);
+    m_vinfoNetJob.reset(netJob);
+    netJob->start();
 }
 
 void DownloadTask::vinfoDownloadFailed()
 {
-	// Something failed. We really need the second download (current version info), so parse
-	// downloads anyways as long as the first one succeeded.
-	if (m_newVersionFileListDownload->wasSuccessful())
-	{
-		processDownloadedVersionInfo();
-		return;
-	}
-
-	// TODO: Give a more detailed error message.
-	qCritical() << "Failed to download version info files.";
-	emitFailed(tr("Failed to download version info files."));
+    // Something failed. We really need the second download (current version info), so parse
+    // downloads anyways as long as the first one succeeded.
+    if (m_newVersionFileListDownload->wasSuccessful())
+    {
+        processDownloadedVersionInfo();
+        return;
+    }
+
+    // TODO: Give a more detailed error message.
+    qCritical() << "Failed to download version info files.";
+    emitFailed(tr("Failed to download version info files."));
 }
 
 void DownloadTask::processDownloadedVersionInfo()
 {
-	VersionFileList m_currentVersionFileList;
-	VersionFileList m_newVersionFileList;
-
-	setStatus(tr("Reading file list for new version..."));
-	qDebug() << "Reading file list for new version...";
-	QString error;
-	if (!parseVersionInfo(newVersionFileListData, m_newVersionFileList, error))
-	{
-		qCritical() << error;
-		emitFailed(error);
-		return;
-	}
-
-	// if we have the current version info, use it.
-	if (m_currentVersionFileListDownload && m_currentVersionFileListDownload->wasSuccessful())
-	{
-		setStatus(tr("Reading file list for current version..."));
-		qDebug() << "Reading file list for current version...";
-		// if this fails, it's not a complete loss.
-		QString error;
-		if(!parseVersionInfo( currentVersionFileListData, m_currentVersionFileList, error))
-		{
-			qDebug() << error << "This is not a fatal error.";
-		}
-	}
-
-	// We don't need this any more.
-	m_currentVersionFileListDownload.reset();
-	m_newVersionFileListDownload.reset();
-	m_vinfoNetJob.reset();
-
-	setStatus(tr("Processing file lists - figuring out how to install the update..."));
-
-	// make a new netjob for the actual update files
-	NetJobPtr netJob (new NetJob("Update Files"));
-
-	// fill netJob and operationList
-	if (!processFileLists(m_currentVersionFileList, m_newVersionFileList, m_status.rootPath, m_updateFilesDir.path(), netJob, m_operations))
-	{
-		emitFailed(tr("Failed to process update lists..."));
-		return;
-	}
-
-	// Now start the download.
-	QObject::connect(netJob.get(), &NetJob::succeeded, this, &DownloadTask::fileDownloadFinished);
-	QObject::connect(netJob.get(), &NetJob::progress, this, &DownloadTask::fileDownloadProgressChanged);
-	QObject::connect(netJob.get(), &NetJob::failed, this, &DownloadTask::fileDownloadFailed);
-
-	setStatus(tr("Downloading %1 update files.").arg(QString::number(netJob->size())));
-	qDebug() << "Begin downloading update files to" << m_updateFilesDir.path();
-	m_filesNetJob = netJob;
-	m_filesNetJob->start();
+    VersionFileList m_currentVersionFileList;
+    VersionFileList m_newVersionFileList;
+
+    setStatus(tr("Reading file list for new version..."));
+    qDebug() << "Reading file list for new version...";
+    QString error;
+    if (!parseVersionInfo(newVersionFileListData, m_newVersionFileList, error))
+    {
+        qCritical() << error;
+        emitFailed(error);
+        return;
+    }
+
+    // if we have the current version info, use it.
+    if (m_currentVersionFileListDownload && m_currentVersionFileListDownload->wasSuccessful())
+    {
+        setStatus(tr("Reading file list for current version..."));
+        qDebug() << "Reading file list for current version...";
+        // if this fails, it's not a complete loss.
+        QString error;
+        if(!parseVersionInfo( currentVersionFileListData, m_currentVersionFileList, error))
+        {
+            qDebug() << error << "This is not a fatal error.";
+        }
+    }
+
+    // We don't need this any more.
+    m_currentVersionFileListDownload.reset();
+    m_newVersionFileListDownload.reset();
+    m_vinfoNetJob.reset();
+
+    setStatus(tr("Processing file lists - figuring out how to install the update..."));
+
+    // make a new netjob for the actual update files
+    NetJobPtr netJob (new NetJob("Update Files"));
+
+    // fill netJob and operationList
+    if (!processFileLists(m_currentVersionFileList, m_newVersionFileList, m_status.rootPath, m_updateFilesDir.path(), netJob, m_operations))
+    {
+        emitFailed(tr("Failed to process update lists..."));
+        return;
+    }
+
+    // Now start the download.
+    QObject::connect(netJob.get(), &NetJob::succeeded, this, &DownloadTask::fileDownloadFinished);
+    QObject::connect(netJob.get(), &NetJob::progress, this, &DownloadTask::fileDownloadProgressChanged);
+    QObject::connect(netJob.get(), &NetJob::failed, this, &DownloadTask::fileDownloadFailed);
+
+    setStatus(tr("Downloading %1 update files.").arg(QString::number(netJob->size())));
+    qDebug() << "Begin downloading update files to" << m_updateFilesDir.path();
+    m_filesNetJob = netJob;
+    m_filesNetJob->start();
 }
 
 void DownloadTask::fileDownloadFinished()
 {
-	emitSucceeded();
+    emitSucceeded();
 }
 
 void DownloadTask::fileDownloadFailed(QString reason)
 {
-	qCritical() << "Failed to download update files:" << reason;
-	emitFailed(tr("Failed to download update files: %1").arg(reason));
+    qCritical() << "Failed to download update files:" << reason;
+    emitFailed(tr("Failed to download update files: %1").arg(reason));
 }
 
 void DownloadTask::fileDownloadProgressChanged(qint64 current, qint64 total)
 {
-	setProgress(current, total);
+    setProgress(current, total);
 }
 
 QString DownloadTask::updateFilesDir()
 {
-	return m_updateFilesDir.path();
+    return m_updateFilesDir.path();
 }
 
 OperationList DownloadTask::operations()
 {
-	return m_operations;
+    return m_operations;
 }
 
 }
\ No newline at end of file
diff --git a/api/logic/updater/DownloadTask.h b/api/logic/updater/DownloadTask.h
index 8330d3e8..30b4b9ec 100644
--- a/api/logic/updater/DownloadTask.h
+++ b/api/logic/updater/DownloadTask.h
@@ -29,70 +29,70 @@ namespace GoUpdate
  */
 class MULTIMC_LOGIC_EXPORT DownloadTask : public Task
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	/**
-	 * Create a download task
-	 *
-	 * target is a template - XXXXXX at the end will be replaced with a random generated string, ensuring uniqueness
-	 */
-	explicit DownloadTask(Status status, QString target, QObject* parent = 0);
-	virtual ~DownloadTask() {};
+    /**
+     * Create a download task
+     *
+     * target is a template - XXXXXX at the end will be replaced with a random generated string, ensuring uniqueness
+     */
+    explicit DownloadTask(Status status, QString target, QObject* parent = 0);
+    virtual ~DownloadTask() {};
 
-	/// Get the directory that will contain the update files.
-	QString updateFilesDir();
+    /// Get the directory that will contain the update files.
+    QString updateFilesDir();
 
-	/// Get the list of operations that should be done
-	OperationList operations();
+    /// Get the list of operations that should be done
+    OperationList operations();
 
-	/// set updater download behavior
-	void setUseLocalUpdater(bool useLocal);
+    /// set updater download behavior
+    void setUseLocalUpdater(bool useLocal);
 
 protected:
-	//! Entry point for tasks.
-	virtual void executeTask() override;
-
-	/*!
-	 * Downloads the version info files from the repository.
-	 * The files for both the current build, and the build that we're updating to need to be downloaded.
-	 * If the current version's info file can't be found, MultiMC will not delete files that
-	 * were removed between versions. It will still replace files that have changed, however.
-	 * Note that although the repository URL for the current version is not given to the update task,
-	 * the task will attempt to look it up in the UpdateChecker's channel list.
-	 * If an error occurs here, the function will call emitFailed and return false.
-	 */
-	void loadVersionInfo();
-
-	NetJobPtr m_vinfoNetJob;
-	QByteArray currentVersionFileListData;
-	QByteArray newVersionFileListData;
-	Net::Download::Ptr m_currentVersionFileListDownload;
-	Net::Download::Ptr m_newVersionFileListDownload;
-
-	NetJobPtr m_filesNetJob;
-
-	Status m_status;
-
-	OperationList m_operations;
-
-	/*!
-	 * Temporary directory to store update files in.
-	 * This will be set to not auto delete. Task will fail if this fails to be created.
-	 */
-	QTemporaryDir m_updateFilesDir;
+    //! Entry point for tasks.
+    virtual void executeTask() override;
+
+    /*!
+     * Downloads the version info files from the repository.
+     * The files for both the current build, and the build that we're updating to need to be downloaded.
+     * If the current version's info file can't be found, MultiMC will not delete files that
+     * were removed between versions. It will still replace files that have changed, however.
+     * Note that although the repository URL for the current version is not given to the update task,
+     * the task will attempt to look it up in the UpdateChecker's channel list.
+     * If an error occurs here, the function will call emitFailed and return false.
+     */
+    void loadVersionInfo();
+
+    NetJobPtr m_vinfoNetJob;
+    QByteArray currentVersionFileListData;
+    QByteArray newVersionFileListData;
+    Net::Download::Ptr m_currentVersionFileListDownload;
+    Net::Download::Ptr m_newVersionFileListDownload;
+
+    NetJobPtr m_filesNetJob;
+
+    Status m_status;
+
+    OperationList m_operations;
+
+    /*!
+     * Temporary directory to store update files in.
+     * This will be set to not auto delete. Task will fail if this fails to be created.
+     */
+    QTemporaryDir m_updateFilesDir;
 
 protected slots:
-	/*!
-	 * This function is called when version information is finished downloading
-	 * and at least the new file list download succeeded
-	 */
-	void processDownloadedVersionInfo();
-	void vinfoDownloadFailed();
-
-	void fileDownloadFinished();
-	void fileDownloadFailed(QString reason);
-	void fileDownloadProgressChanged(qint64 current, qint64 total);
+    /*!
+     * This function is called when version information is finished downloading
+     * and at least the new file list download succeeded
+     */
+    void processDownloadedVersionInfo();
+    void vinfoDownloadFailed();
+
+    void fileDownloadFinished();
+    void fileDownloadFailed(QString reason);
+    void fileDownloadProgressChanged(qint64 current, qint64 total);
 };
 
 }
\ No newline at end of file
diff --git a/api/logic/updater/DownloadTask_test.cpp b/api/logic/updater/DownloadTask_test.cpp
index e75c3ffa..531b2527 100644
--- a/api/logic/updater/DownloadTask_test.cpp
+++ b/api/logic/updater/DownloadTask_test.cpp
@@ -12,11 +12,11 @@ using namespace GoUpdate;
 
 FileSourceList encodeBaseFile(const char *suffix)
 {
-	auto base = QDir::currentPath();
-	QUrl localFile = QUrl::fromLocalFile(base + suffix);
-	QString localUrlString = localFile.toString(QUrl::FullyEncoded);
-	auto item = FileSource("http", localUrlString);
-	return FileSourceList({item});
+    auto base = QDir::currentPath();
+    QUrl localFile = QUrl::fromLocalFile(base + suffix);
+    QString localUrlString = localFile.toString(QUrl::FullyEncoded);
+    auto item = FileSource("http", localUrlString);
+    return FileSourceList({item});
 }
 
 Q_DECLARE_METATYPE(VersionFileList)
@@ -24,191 +24,191 @@ Q_DECLARE_METATYPE(Operation)
 
 QDebug operator<<(QDebug dbg, const FileSource &f)
 {
-	dbg.nospace() << "FileSource(type=" << f.type << " url=" << f.url
-				  << " comp=" << f.compressionType << ")";
-	return dbg.maybeSpace();
+    dbg.nospace() << "FileSource(type=" << f.type << " url=" << f.url
+                  << " comp=" << f.compressionType << ")";
+    return dbg.maybeSpace();
 }
 
 QDebug operator<<(QDebug dbg, const VersionFileEntry &v)
 {
-	dbg.nospace() << "VersionFileEntry(path=" << v.path << " mode=" << v.mode
-				  << " md5=" << v.md5 << " sources=" << v.sources << ")";
-	return dbg.maybeSpace();
+    dbg.nospace() << "VersionFileEntry(path=" << v.path << " mode=" << v.mode
+                  << " md5=" << v.md5 << " sources=" << v.sources << ")";
+    return dbg.maybeSpace();
 }
 
 QDebug operator<<(QDebug dbg, const Operation::Type &t)
 {
-	switch (t)
-	{
-	case Operation::OP_REPLACE:
-		dbg << "OP_COPY";
-		break;
-	case Operation::OP_DELETE:
-		dbg << "OP_DELETE";
-		break;
-	}
-	return dbg.maybeSpace();
+    switch (t)
+    {
+    case Operation::OP_REPLACE:
+        dbg << "OP_COPY";
+        break;
+    case Operation::OP_DELETE:
+        dbg << "OP_DELETE";
+        break;
+    }
+    return dbg.maybeSpace();
 }
 
 QDebug operator<<(QDebug dbg, const Operation &u)
 {
-	dbg.nospace() << "Operation(type=" << u.type << " file=" << u.source
-				  << " dest=" << u.destination << " mode=" << u.destinationMode << ")";
-	return dbg.maybeSpace();
+    dbg.nospace() << "Operation(type=" << u.type << " file=" << u.source
+                  << " dest=" << u.destination << " mode=" << u.destinationMode << ")";
+    return dbg.maybeSpace();
 }
 
 class DownloadTaskTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void initTestCase()
-	{
-	}
-	void cleanupTestCase()
-	{
-	}
-
-	void test_parseVersionInfo_data()
-	{
-		QTest::addColumn<QByteArray>("data");
-		QTest::addColumn<VersionFileList>("list");
-		QTest::addColumn<QString>("error");
-		QTest::addColumn<bool>("ret");
-
-		QTest::newRow("one")
-			<< MULTIMC_GET_TEST_FILE("data/1.json")
-			<< (VersionFileList()
-				<< VersionFileEntry{"fileOne",
-														493,
-														encodeBaseFile("/data/fileOneA"),
-														"9eb84090956c484e32cb6c08455a667b"}
-				<< VersionFileEntry{"fileTwo",
-														644,
-														encodeBaseFile("/data/fileTwo"),
-														"38f94f54fa3eb72b0ea836538c10b043"}
-				<< VersionFileEntry{"fileThree",
-														750,
-														encodeBaseFile("/data/fileThree"),
-														"f12df554b21e320be6471d7154130e70"})
-			<< QString() << true;
-		QTest::newRow("two")
-			<< MULTIMC_GET_TEST_FILE("data/2.json")
-			<< (VersionFileList()
-				<< VersionFileEntry{"fileOne",
-														493,
-														encodeBaseFile("/data/fileOneB"),
-														"42915a71277c9016668cce7b82c6b577"}
-				<< VersionFileEntry{"fileTwo",
-														644,
-														encodeBaseFile("/data/fileTwo"),
-														"38f94f54fa3eb72b0ea836538c10b043"})
-			<< QString() << true;
-	}
-	void test_parseVersionInfo()
-	{
-		QFETCH(QByteArray, data);
-		QFETCH(VersionFileList, list);
-		QFETCH(QString, error);
-		QFETCH(bool, ret);
-
-		VersionFileList outList;
-		QString outError;
-		bool outRet = parseVersionInfo(data, outList, outError);
-		QCOMPARE(outRet, ret);
-		QCOMPARE(outList, list);
-		QCOMPARE(outError, error);
-	}
-
-	void test_processFileLists_data()
-	{
-		QTest::addColumn<QString>("tempFolder");
-		QTest::addColumn<VersionFileList>("currentVersion");
-		QTest::addColumn<VersionFileList>("newVersion");
-		QTest::addColumn<OperationList>("expectedOperations");
-
-		QTemporaryDir tempFolderObj;
-		QString tempFolder = tempFolderObj.path();
-		// update fileOne, keep fileTwo, remove fileThree
-		QTest::newRow("test 1")
-			<< tempFolder << (VersionFileList()
-							  << VersionFileEntry{
-									 "data/fileOne", 493,
-									 FileSourceList()
-										 << FileSource(
-												"http", "http://host/path/fileOne-1"),
-									 "9eb84090956c484e32cb6c08455a667b"}
-							  << VersionFileEntry{
-									 "data/fileTwo", 644,
-									 FileSourceList()
-										 << FileSource(
-												"http", "http://host/path/fileTwo-1"),
-									 "38f94f54fa3eb72b0ea836538c10b043"}
-							  << VersionFileEntry{
-									 "data/fileThree", 420,
-									 FileSourceList()
-										 << FileSource(
-												"http", "http://host/path/fileThree-1"),
-									 "f12df554b21e320be6471d7154130e70"})
-			<< (VersionFileList()
-				<< VersionFileEntry{
-					   "data/fileOne", 493,
-					   FileSourceList()
-						   << FileSource("http",
-															 "http://host/path/fileOne-2"),
-					   "42915a71277c9016668cce7b82c6b577"}
-				<< VersionFileEntry{
-					   "data/fileTwo", 644,
-					   FileSourceList()
-						   << FileSource("http",
-															 "http://host/path/fileTwo-2"),
-					   "38f94f54fa3eb72b0ea836538c10b043"})
-			<< (OperationList()
-				<< Operation::DeleteOp("data/fileThree")
-				<< Operation::CopyOp(
-					   FS::PathCombine(tempFolder,
-								   QString("data/fileOne").replace("/", "_")),
-					   "data/fileOne", 493));
-	}
-	void test_processFileLists()
-	{
-		QFETCH(QString, tempFolder);
-		QFETCH(VersionFileList, currentVersion);
-		QFETCH(VersionFileList, newVersion);
-		QFETCH(OperationList, expectedOperations);
-
-		OperationList operations;
-
-		processFileLists(currentVersion, newVersion, QDir::currentPath(), tempFolder, new NetJob("Dummy"), operations);
-		qDebug() << (operations == expectedOperations);
-		qDebug() << operations;
-		qDebug() << expectedOperations;
-		QCOMPARE(operations, expectedOperations);
-	}
-
-	void test_OSXPathFixup()
-	{
-		QString path, pathOrig;
-		bool result;
-		// Proper OSX path
-		pathOrig = path = "MultiMC.app/Foo/Bar/Baz";
-		qDebug() << "Proper OSX path: " << path;
-		result = fixPathForOSX(path);
-		QCOMPARE(path, QString("Foo/Bar/Baz"));
-		QCOMPARE(result, true);
-
-		// Bad OSX path
-		pathOrig = path = "translations/klingon.lol";
-		qDebug() << "Bad OSX path: " << path;
-		result = fixPathForOSX(path);
-		QCOMPARE(path, pathOrig);
-		QCOMPARE(result, false);
-	}
+    void initTestCase()
+    {
+    }
+    void cleanupTestCase()
+    {
+    }
+
+    void test_parseVersionInfo_data()
+    {
+        QTest::addColumn<QByteArray>("data");
+        QTest::addColumn<VersionFileList>("list");
+        QTest::addColumn<QString>("error");
+        QTest::addColumn<bool>("ret");
+
+        QTest::newRow("one")
+            << MULTIMC_GET_TEST_FILE("data/1.json")
+            << (VersionFileList()
+                << VersionFileEntry{"fileOne",
+                                                        493,
+                                                        encodeBaseFile("/data/fileOneA"),
+                                                        "9eb84090956c484e32cb6c08455a667b"}
+                << VersionFileEntry{"fileTwo",
+                                                        644,
+                                                        encodeBaseFile("/data/fileTwo"),
+                                                        "38f94f54fa3eb72b0ea836538c10b043"}
+                << VersionFileEntry{"fileThree",
+                                                        750,
+                                                        encodeBaseFile("/data/fileThree"),
+                                                        "f12df554b21e320be6471d7154130e70"})
+            << QString() << true;
+        QTest::newRow("two")
+            << MULTIMC_GET_TEST_FILE("data/2.json")
+            << (VersionFileList()
+                << VersionFileEntry{"fileOne",
+                                                        493,
+                                                        encodeBaseFile("/data/fileOneB"),
+                                                        "42915a71277c9016668cce7b82c6b577"}
+                << VersionFileEntry{"fileTwo",
+                                                        644,
+                                                        encodeBaseFile("/data/fileTwo"),
+                                                        "38f94f54fa3eb72b0ea836538c10b043"})
+            << QString() << true;
+    }
+    void test_parseVersionInfo()
+    {
+        QFETCH(QByteArray, data);
+        QFETCH(VersionFileList, list);
+        QFETCH(QString, error);
+        QFETCH(bool, ret);
+
+        VersionFileList outList;
+        QString outError;
+        bool outRet = parseVersionInfo(data, outList, outError);
+        QCOMPARE(outRet, ret);
+        QCOMPARE(outList, list);
+        QCOMPARE(outError, error);
+    }
+
+    void test_processFileLists_data()
+    {
+        QTest::addColumn<QString>("tempFolder");
+        QTest::addColumn<VersionFileList>("currentVersion");
+        QTest::addColumn<VersionFileList>("newVersion");
+        QTest::addColumn<OperationList>("expectedOperations");
+
+        QTemporaryDir tempFolderObj;
+        QString tempFolder = tempFolderObj.path();
+        // update fileOne, keep fileTwo, remove fileThree
+        QTest::newRow("test 1")
+            << tempFolder << (VersionFileList()
+                              << VersionFileEntry{
+                                     "data/fileOne", 493,
+                                     FileSourceList()
+                                         << FileSource(
+                                                "http", "http://host/path/fileOne-1"),
+                                     "9eb84090956c484e32cb6c08455a667b"}
+                              << VersionFileEntry{
+                                     "data/fileTwo", 644,
+                                     FileSourceList()
+                                         << FileSource(
+                                                "http", "http://host/path/fileTwo-1"),
+                                     "38f94f54fa3eb72b0ea836538c10b043"}
+                              << VersionFileEntry{
+                                     "data/fileThree", 420,
+                                     FileSourceList()
+                                         << FileSource(
+                                                "http", "http://host/path/fileThree-1"),
+                                     "f12df554b21e320be6471d7154130e70"})
+            << (VersionFileList()
+                << VersionFileEntry{
+                       "data/fileOne", 493,
+                       FileSourceList()
+                           << FileSource("http",
+                                                             "http://host/path/fileOne-2"),
+                       "42915a71277c9016668cce7b82c6b577"}
+                << VersionFileEntry{
+                       "data/fileTwo", 644,
+                       FileSourceList()
+                           << FileSource("http",
+                                                             "http://host/path/fileTwo-2"),
+                       "38f94f54fa3eb72b0ea836538c10b043"})
+            << (OperationList()
+                << Operation::DeleteOp("data/fileThree")
+                << Operation::CopyOp(
+                       FS::PathCombine(tempFolder,
+                                   QString("data/fileOne").replace("/", "_")),
+                       "data/fileOne", 493));
+    }
+    void test_processFileLists()
+    {
+        QFETCH(QString, tempFolder);
+        QFETCH(VersionFileList, currentVersion);
+        QFETCH(VersionFileList, newVersion);
+        QFETCH(OperationList, expectedOperations);
+
+        OperationList operations;
+
+        processFileLists(currentVersion, newVersion, QDir::currentPath(), tempFolder, new NetJob("Dummy"), operations);
+        qDebug() << (operations == expectedOperations);
+        qDebug() << operations;
+        qDebug() << expectedOperations;
+        QCOMPARE(operations, expectedOperations);
+    }
+
+    void test_OSXPathFixup()
+    {
+        QString path, pathOrig;
+        bool result;
+        // Proper OSX path
+        pathOrig = path = "MultiMC.app/Foo/Bar/Baz";
+        qDebug() << "Proper OSX path: " << path;
+        result = fixPathForOSX(path);
+        QCOMPARE(path, QString("Foo/Bar/Baz"));
+        QCOMPARE(result, true);
+
+        // Bad OSX path
+        pathOrig = path = "translations/klingon.lol";
+        qDebug() << "Bad OSX path: " << path;
+        result = fixPathForOSX(path);
+        QCOMPARE(path, pathOrig);
+        QCOMPARE(result, false);
+    }
 };
 
 extern "C"
 {
-	QTEST_GUILESS_MAIN(DownloadTaskTest)
+    QTEST_GUILESS_MAIN(DownloadTaskTest)
 }
 
 #include "DownloadTask_test.moc"
diff --git a/api/logic/updater/GoUpdate.cpp b/api/logic/updater/GoUpdate.cpp
index 716048a0..ef040db6 100644
--- a/api/logic/updater/GoUpdate.cpp
+++ b/api/logic/updater/GoUpdate.cpp
@@ -12,208 +12,208 @@ namespace GoUpdate
 
 bool parseVersionInfo(const QByteArray &data, VersionFileList &list, QString &error)
 {
-	QJsonParseError jsonError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
-	if (jsonError.error != QJsonParseError::NoError)
-	{
-		error = QString("Failed to parse version info JSON: %1 at %2")
-					.arg(jsonError.errorString())
-					.arg(jsonError.offset);
-		qCritical() << error;
-		return false;
-	}
-
-	QJsonObject json = jsonDoc.object();
-
-	qDebug() << data;
-	qDebug() << "Loading version info from JSON.";
-	QJsonArray filesArray = json.value("Files").toArray();
-	for (QJsonValue fileValue : filesArray)
-	{
-		QJsonObject fileObj = fileValue.toObject();
-
-		QString file_path = fileObj.value("Path").toString();
+    QJsonParseError jsonError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
+    if (jsonError.error != QJsonParseError::NoError)
+    {
+        error = QString("Failed to parse version info JSON: %1 at %2")
+                    .arg(jsonError.errorString())
+                    .arg(jsonError.offset);
+        qCritical() << error;
+        return false;
+    }
+
+    QJsonObject json = jsonDoc.object();
+
+    qDebug() << data;
+    qDebug() << "Loading version info from JSON.";
+    QJsonArray filesArray = json.value("Files").toArray();
+    for (QJsonValue fileValue : filesArray)
+    {
+        QJsonObject fileObj = fileValue.toObject();
+
+        QString file_path = fileObj.value("Path").toString();
 #ifdef Q_OS_MAC
-		// On OSX, the paths for the updater need to be fixed.
-		// basically, anything that isn't in the .app folder is ignored.
-		// everything else is changed so the code that processes the files actually finds
-		// them and puts the replacements in the right spots.
-		fixPathForOSX(file_path);
+        // On OSX, the paths for the updater need to be fixed.
+        // basically, anything that isn't in the .app folder is ignored.
+        // everything else is changed so the code that processes the files actually finds
+        // them and puts the replacements in the right spots.
+        fixPathForOSX(file_path);
 #endif
-		VersionFileEntry file{file_path,		fileObj.value("Perms").toVariant().toInt(),
-							  FileSourceList(), fileObj.value("MD5").toString(), };
-		qDebug() << "File" << file.path << "with perms" << file.mode;
-
-		QJsonArray sourceArray = fileObj.value("Sources").toArray();
-		for (QJsonValue val : sourceArray)
-		{
-			QJsonObject sourceObj = val.toObject();
-
-			QString type = sourceObj.value("SourceType").toString();
-			if (type == "http")
-			{
-				file.sources.append(FileSource("http", sourceObj.value("Url").toString()));
-			}
-			else
-			{
-				qWarning() << "Unknown source type" << type << "ignored.";
-			}
-		}
-
-		qDebug() << "Loaded info for" << file.path;
-
-		list.append(file);
-	}
-
-	return true;
+        VersionFileEntry file{file_path,        fileObj.value("Perms").toVariant().toInt(),
+                              FileSourceList(), fileObj.value("MD5").toString(), };
+        qDebug() << "File" << file.path << "with perms" << file.mode;
+
+        QJsonArray sourceArray = fileObj.value("Sources").toArray();
+        for (QJsonValue val : sourceArray)
+        {
+            QJsonObject sourceObj = val.toObject();
+
+            QString type = sourceObj.value("SourceType").toString();
+            if (type == "http")
+            {
+                file.sources.append(FileSource("http", sourceObj.value("Url").toString()));
+            }
+            else
+            {
+                qWarning() << "Unknown source type" << type << "ignored.";
+            }
+        }
+
+        qDebug() << "Loaded info for" << file.path;
+
+        list.append(file);
+    }
+
+    return true;
 }
 
 bool processFileLists
 (
-	const VersionFileList &currentVersion,
-	const VersionFileList &newVersion,
-	const QString &rootPath,
-	const QString &tempPath,
-	NetJobPtr job,
-	OperationList &ops
+    const VersionFileList &currentVersion,
+    const VersionFileList &newVersion,
+    const QString &rootPath,
+    const QString &tempPath,
+    NetJobPtr job,
+    OperationList &ops
 )
 {
-	// First, if we've loaded the current version's file list, we need to iterate through it and
-	// delete anything in the current one version's list that isn't in the new version's list.
-	for (VersionFileEntry entry : currentVersion)
-	{
-		QFileInfo toDelete(FS::PathCombine(rootPath, entry.path));
-		if (!toDelete.exists())
-		{
-			qCritical() << "Expected file " << toDelete.absoluteFilePath()
-						 << " doesn't exist!";
-		}
-		bool keep = false;
-
-		//
-		for (VersionFileEntry newEntry : newVersion)
-		{
-			if (newEntry.path == entry.path)
-			{
-				qDebug() << "Not deleting" << entry.path
-							 << "because it is still present in the new version.";
-				keep = true;
-				break;
-			}
-		}
-
-		// If the loop reaches the end and we didn't find a match, delete the file.
-		if (!keep)
-		{
-			if (toDelete.exists())
-				ops.append(Operation::DeleteOp(entry.path));
-		}
-	}
-
-	// Next, check each file in MultiMC's folder and see if we need to update them.
-	for (VersionFileEntry entry : newVersion)
-	{
-		// TODO: Let's not MD5sum a ton of files on the GUI thread. We should probably find a
-		// way to do this in the background.
-		QString fileMD5;
-		QString realEntryPath = FS::PathCombine(rootPath, entry.path);
-		QFile entryFile(realEntryPath);
-		QFileInfo entryInfo(realEntryPath);
-
-		bool needs_upgrade = false;
-		if (!entryFile.exists())
-		{
-			needs_upgrade = true;
-		}
-		else
-		{
-			bool pass = true;
-			if (!entryInfo.isReadable())
-			{
-				qCritical() << "File " << realEntryPath << " is not readable.";
-				pass = false;
-			}
-			if (!entryInfo.isWritable())
-			{
-				qCritical() << "File " << realEntryPath << " is not writable.";
-				pass = false;
-			}
-			if (!entryFile.open(QFile::ReadOnly))
-			{
-				qCritical() << "File " << realEntryPath << " cannot be opened for reading.";
-				pass = false;
-			}
-			if (!pass)
-			{
-				ops.clear();
-				return false;
-			}
-		}
-
-		if(!needs_upgrade)
-		{
-			QCryptographicHash hash(QCryptographicHash::Md5);
-			auto foo = entryFile.readAll();
-
-			hash.addData(foo);
-			fileMD5 = hash.result().toHex();
-			if ((fileMD5 != entry.md5))
-			{
-				qDebug() << "MD5Sum does not match!";
-				qDebug() << "Expected:'" << entry.md5 << "'";
-				qDebug() << "Got:     '" << fileMD5 << "'";
-				needs_upgrade = true;
-			}
-		}
-
-		// skip file. it doesn't need an upgrade.
-		if (!needs_upgrade)
-		{
-			qDebug() << "File" << realEntryPath << " does not need updating.";
-			continue;
-		}
-
-		// yep. this file actually needs an upgrade. PROCEED.
-		qDebug() << "Found file" << realEntryPath << " that needs updating.";
-
-		// Go through the sources list and find one to use.
-		// TODO: Make a NetAction that takes a source list and tries each of them until one
-		// works. For now, we'll just use the first http one.
-		for (FileSource source : entry.sources)
-		{
-			if (source.type != "http")
-				continue;
-
-			qDebug() << "Will download" << entry.path << "from" << source.url;
-
-			// Download it to updatedir/<filepath>-<md5> where filepath is the file's
-			// path with slashes replaced by underscores.
-			QString dlPath = FS::PathCombine(tempPath, QString(entry.path).replace("/", "_"));
-
-			// We need to download the file to the updatefiles folder and add a task
-			// to copy it to its install path.
-			auto download = Net::Download::makeFile(source.url, dlPath);
-			auto rawMd5 = QByteArray::fromHex(entry.md5.toLatin1());
-			download->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5));
-			job->addNetAction(download);
-			ops.append(Operation::CopyOp(dlPath, entry.path, entry.mode));
-		}
-	}
-	return true;
+    // First, if we've loaded the current version's file list, we need to iterate through it and
+    // delete anything in the current one version's list that isn't in the new version's list.
+    for (VersionFileEntry entry : currentVersion)
+    {
+        QFileInfo toDelete(FS::PathCombine(rootPath, entry.path));
+        if (!toDelete.exists())
+        {
+            qCritical() << "Expected file " << toDelete.absoluteFilePath()
+                         << " doesn't exist!";
+        }
+        bool keep = false;
+
+        //
+        for (VersionFileEntry newEntry : newVersion)
+        {
+            if (newEntry.path == entry.path)
+            {
+                qDebug() << "Not deleting" << entry.path
+                             << "because it is still present in the new version.";
+                keep = true;
+                break;
+            }
+        }
+
+        // If the loop reaches the end and we didn't find a match, delete the file.
+        if (!keep)
+        {
+            if (toDelete.exists())
+                ops.append(Operation::DeleteOp(entry.path));
+        }
+    }
+
+    // Next, check each file in MultiMC's folder and see if we need to update them.
+    for (VersionFileEntry entry : newVersion)
+    {
+        // TODO: Let's not MD5sum a ton of files on the GUI thread. We should probably find a
+        // way to do this in the background.
+        QString fileMD5;
+        QString realEntryPath = FS::PathCombine(rootPath, entry.path);
+        QFile entryFile(realEntryPath);
+        QFileInfo entryInfo(realEntryPath);
+
+        bool needs_upgrade = false;
+        if (!entryFile.exists())
+        {
+            needs_upgrade = true;
+        }
+        else
+        {
+            bool pass = true;
+            if (!entryInfo.isReadable())
+            {
+                qCritical() << "File " << realEntryPath << " is not readable.";
+                pass = false;
+            }
+            if (!entryInfo.isWritable())
+            {
+                qCritical() << "File " << realEntryPath << " is not writable.";
+                pass = false;
+            }
+            if (!entryFile.open(QFile::ReadOnly))
+            {
+                qCritical() << "File " << realEntryPath << " cannot be opened for reading.";
+                pass = false;
+            }
+            if (!pass)
+            {
+                ops.clear();
+                return false;
+            }
+        }
+
+        if(!needs_upgrade)
+        {
+            QCryptographicHash hash(QCryptographicHash::Md5);
+            auto foo = entryFile.readAll();
+
+            hash.addData(foo);
+            fileMD5 = hash.result().toHex();
+            if ((fileMD5 != entry.md5))
+            {
+                qDebug() << "MD5Sum does not match!";
+                qDebug() << "Expected:'" << entry.md5 << "'";
+                qDebug() << "Got:     '" << fileMD5 << "'";
+                needs_upgrade = true;
+            }
+        }
+
+        // skip file. it doesn't need an upgrade.
+        if (!needs_upgrade)
+        {
+            qDebug() << "File" << realEntryPath << " does not need updating.";
+            continue;
+        }
+
+        // yep. this file actually needs an upgrade. PROCEED.
+        qDebug() << "Found file" << realEntryPath << " that needs updating.";
+
+        // Go through the sources list and find one to use.
+        // TODO: Make a NetAction that takes a source list and tries each of them until one
+        // works. For now, we'll just use the first http one.
+        for (FileSource source : entry.sources)
+        {
+            if (source.type != "http")
+                continue;
+
+            qDebug() << "Will download" << entry.path << "from" << source.url;
+
+            // Download it to updatedir/<filepath>-<md5> where filepath is the file's
+            // path with slashes replaced by underscores.
+            QString dlPath = FS::PathCombine(tempPath, QString(entry.path).replace("/", "_"));
+
+            // We need to download the file to the updatefiles folder and add a task
+            // to copy it to its install path.
+            auto download = Net::Download::makeFile(source.url, dlPath);
+            auto rawMd5 = QByteArray::fromHex(entry.md5.toLatin1());
+            download->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5));
+            job->addNetAction(download);
+            ops.append(Operation::CopyOp(dlPath, entry.path, entry.mode));
+        }
+    }
+    return true;
 }
 
 bool fixPathForOSX(QString &path)
 {
-	if (path.startsWith("MultiMC.app/"))
-	{
-		// remove the prefix and add a new, more appropriate one.
-		path.remove(0, 12);
-		return true;
-	}
-	else
-	{
-		qCritical() << "Update path not within .app: " << path;
-		return false;
-	}
+    if (path.startsWith("MultiMC.app/"))
+    {
+        // remove the prefix and add a new, more appropriate one.
+        path.remove(0, 12);
+        return true;
+    }
+    else
+    {
+        qCritical() << "Update path not within .app: " << path;
+        return false;
+    }
 }
 }
\ No newline at end of file
diff --git a/api/logic/updater/GoUpdate.h b/api/logic/updater/GoUpdate.h
index 0e183b9f..54559a3c 100644
--- a/api/logic/updater/GoUpdate.h
+++ b/api/logic/updater/GoUpdate.h
@@ -12,16 +12,16 @@ namespace GoUpdate
  */
 struct MULTIMC_LOGIC_EXPORT Status
 {
-	bool updateAvailable = false;
+    bool updateAvailable = false;
 
-	int newVersionId = -1;
-	QString newRepoUrl;
+    int newVersionId = -1;
+    QString newRepoUrl;
 
-	int currentVersionId = -1;
-	QString currentRepoUrl;
+    int currentVersionId = -1;
+    QString currentRepoUrl;
 
-	// path to the root of the application
-	QString rootPath;
+    // path to the root of the application
+    QString rootPath;
 };
 
 /**
@@ -29,21 +29,21 @@ struct MULTIMC_LOGIC_EXPORT Status
  */
 struct MULTIMC_LOGIC_EXPORT FileSource
 {
-	FileSource(QString type, QString url, QString compression="")
-	{
-		this->type = type;
-		this->url = url;
-		this->compressionType = compression;
-	}
-
-	bool operator==(const FileSource &f2) const
-	{
-		return type == f2.type && url == f2.url && compressionType == f2.compressionType;
-	}
-
-	QString type;
-	QString url;
-	QString compressionType;
+    FileSource(QString type, QString url, QString compression="")
+    {
+        this->type = type;
+        this->url = url;
+        this->compressionType = compression;
+    }
+
+    bool operator==(const FileSource &f2) const
+    {
+        return type == f2.type && url == f2.url && compressionType == f2.compressionType;
+    }
+
+    QString type;
+    QString url;
+    QString compressionType;
 };
 typedef QList<FileSource> FileSourceList;
 
@@ -52,14 +52,14 @@ typedef QList<FileSource> FileSourceList;
  */
 struct MULTIMC_LOGIC_EXPORT VersionFileEntry
 {
-	QString path;
-	int mode;
-	FileSourceList sources;
-	QString md5;
-	bool operator==(const VersionFileEntry &v2) const
-	{
-		return path == v2.path && mode == v2.mode && sources == v2.sources && md5 == v2.md5;
-	}
+    QString path;
+    int mode;
+    FileSourceList sources;
+    QString md5;
+    bool operator==(const VersionFileEntry &v2) const
+    {
+        return path == v2.path && mode == v2.mode && sources == v2.sources && md5 == v2.md5;
+    }
 };
 typedef QList<VersionFileEntry> VersionFileList;
 
@@ -68,39 +68,39 @@ typedef QList<VersionFileEntry> VersionFileList;
  */
 struct MULTIMC_LOGIC_EXPORT Operation
 {
-	static Operation CopyOp(QString from, QString to, int fmode=0644)
-	{
-		return Operation{OP_REPLACE, from, to, fmode};
-	}
-	static Operation DeleteOp(QString file)
-	{
-		return Operation{OP_DELETE, QString(), file, 0644};
-	}
-
-	// FIXME: for some types, some of the other fields are irrelevant!
-	bool operator==(const Operation &u2) const
-	{
-		return type == u2.type &&
-			source == u2.source &&
-			destination == u2.destination &&
-			destinationMode == u2.destinationMode;
-	}
-
-	//! Specifies the type of operation that this is.
-	enum Type
-	{
-		OP_REPLACE,
-		OP_DELETE,
-	} type;
-
-	//! The source file, if any
-	QString source;
-
-	//! The destination file.
-	QString destination;
-
-	//! The mode to change the destination file to.
-	int destinationMode;
+    static Operation CopyOp(QString from, QString to, int fmode=0644)
+    {
+        return Operation{OP_REPLACE, from, to, fmode};
+    }
+    static Operation DeleteOp(QString file)
+    {
+        return Operation{OP_DELETE, QString(), file, 0644};
+    }
+
+    // FIXME: for some types, some of the other fields are irrelevant!
+    bool operator==(const Operation &u2) const
+    {
+        return type == u2.type &&
+            source == u2.source &&
+            destination == u2.destination &&
+            destinationMode == u2.destinationMode;
+    }
+
+    //! Specifies the type of operation that this is.
+    enum Type
+    {
+        OP_REPLACE,
+        OP_DELETE,
+    } type;
+
+    //! The source file, if any
+    QString source;
+
+    //! The destination file.
+    QString destination;
+
+    //! The mode to change the destination file to.
+    int destinationMode;
 };
 typedef QList<Operation> OperationList;
 
@@ -115,12 +115,12 @@ bool MULTIMC_LOGIC_EXPORT parseVersionInfo(const QByteArray &data, VersionFileLi
  */
 bool MULTIMC_LOGIC_EXPORT processFileLists
 (
-	const VersionFileList &currentVersion,
-	const VersionFileList &newVersion,
-	const QString &rootPath,
-	const QString &tempPath,
-	NetJobPtr job,
-	OperationList &ops
+    const VersionFileList &currentVersion,
+    const VersionFileList &newVersion,
+    const QString &rootPath,
+    const QString &tempPath,
+    NetJobPtr job,
+    OperationList &ops
 );
 
 /*!
diff --git a/api/logic/updater/UpdateChecker.cpp b/api/logic/updater/UpdateChecker.cpp
index d8be2c1a..9e610d52 100644
--- a/api/logic/updater/UpdateChecker.cpp
+++ b/api/logic/updater/UpdateChecker.cpp
@@ -25,236 +25,236 @@
 
 UpdateChecker::UpdateChecker(QString channelListUrl, QString currentChannel, int currentBuild)
 {
-	m_channelListUrl = channelListUrl;
-	m_currentChannel = currentChannel;
-	m_currentBuild = currentBuild;
+    m_channelListUrl = channelListUrl;
+    m_currentChannel = currentChannel;
+    m_currentBuild = currentBuild;
 }
 
 QList<UpdateChecker::ChannelListEntry> UpdateChecker::getChannelList() const
 {
-	return m_channels;
+    return m_channels;
 }
 
 bool UpdateChecker::hasChannels() const
 {
-	return !m_channels.isEmpty();
+    return !m_channels.isEmpty();
 }
 
 void UpdateChecker::checkForUpdate(QString updateChannel, bool notifyNoUpdate)
 {
-	qDebug() << "Checking for updates.";
-
-	// If the channel list hasn't loaded yet, load it and defer checking for updates until
-	// later.
-	if (!m_chanListLoaded)
-	{
-		qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring "
-						"update check.";
-		m_checkUpdateWaiting = true;
-		m_deferredUpdateChannel = updateChannel;
-		updateChanList(notifyNoUpdate);
-		return;
-	}
-
-	if (m_updateChecking)
-	{
-		qDebug() << "Ignoring update check request. Already checking for updates.";
-		return;
-	}
-
-	m_updateChecking = true;
-
-	// Find the desired channel within the channel list and get its repo URL. If if cannot be
-	// found, error.
-	m_newRepoUrl = "";
-	for (ChannelListEntry entry : m_channels)
-	{
-		if (entry.id == updateChannel)
-			m_newRepoUrl = entry.url;
-		if (entry.id == m_currentChannel)
-			m_currentRepoUrl = entry.url;
-	}
-
-	qDebug() << "m_repoUrl = " << m_newRepoUrl;
-
-	// If we didn't find our channel, error.
-	if (m_newRepoUrl.isEmpty())
-	{
-		qCritical() << "m_repoUrl is empty!";
-		emit updateCheckFailed();
-		return;
-	}
-
-	QUrl indexUrl = QUrl(m_newRepoUrl).resolved(QUrl("index.json"));
-
-	auto job = new NetJob("GoUpdate Repository Index");
-	job->addNetAction(Net::Download::makeByteArray(indexUrl, &indexData));
-	connect(job, &NetJob::succeeded, [this, notifyNoUpdate](){ updateCheckFinished(notifyNoUpdate); });
-	connect(job, &NetJob::failed, this, &UpdateChecker::updateCheckFailed);
-	indexJob.reset(job);
-	job->start();
+    qDebug() << "Checking for updates.";
+
+    // If the channel list hasn't loaded yet, load it and defer checking for updates until
+    // later.
+    if (!m_chanListLoaded)
+    {
+        qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring "
+                        "update check.";
+        m_checkUpdateWaiting = true;
+        m_deferredUpdateChannel = updateChannel;
+        updateChanList(notifyNoUpdate);
+        return;
+    }
+
+    if (m_updateChecking)
+    {
+        qDebug() << "Ignoring update check request. Already checking for updates.";
+        return;
+    }
+
+    m_updateChecking = true;
+
+    // Find the desired channel within the channel list and get its repo URL. If if cannot be
+    // found, error.
+    m_newRepoUrl = "";
+    for (ChannelListEntry entry : m_channels)
+    {
+        if (entry.id == updateChannel)
+            m_newRepoUrl = entry.url;
+        if (entry.id == m_currentChannel)
+            m_currentRepoUrl = entry.url;
+    }
+
+    qDebug() << "m_repoUrl = " << m_newRepoUrl;
+
+    // If we didn't find our channel, error.
+    if (m_newRepoUrl.isEmpty())
+    {
+        qCritical() << "m_repoUrl is empty!";
+        emit updateCheckFailed();
+        return;
+    }
+
+    QUrl indexUrl = QUrl(m_newRepoUrl).resolved(QUrl("index.json"));
+
+    auto job = new NetJob("GoUpdate Repository Index");
+    job->addNetAction(Net::Download::makeByteArray(indexUrl, &indexData));
+    connect(job, &NetJob::succeeded, [this, notifyNoUpdate](){ updateCheckFinished(notifyNoUpdate); });
+    connect(job, &NetJob::failed, this, &UpdateChecker::updateCheckFailed);
+    indexJob.reset(job);
+    job->start();
 }
 
 void UpdateChecker::updateCheckFinished(bool notifyNoUpdate)
 {
-	qDebug() << "Finished downloading repo index. Checking for new versions.";
-
-	QJsonParseError jsonError;
-	indexJob.reset();
-
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(indexData, &jsonError);
-	indexData.clear();
-	if (jsonError.error != QJsonParseError::NoError || !jsonDoc.isObject())
-	{
-		qCritical() << "Failed to parse GoUpdate repository index. JSON error"
-					 << jsonError.errorString() << "at offset" << jsonError.offset;
-		m_updateChecking = false;
-		return;
-	}
-
-	QJsonObject object = jsonDoc.object();
-
-	bool success = false;
-	int apiVersion = object.value("ApiVersion").toVariant().toInt(&success);
-	if (apiVersion != API_VERSION || !success)
-	{
-		qCritical() << "Failed to check for updates. API version mismatch. We're using"
-					 << API_VERSION << "server has" << apiVersion;
-		m_updateChecking = false;
-		return;
-	}
-
-	qDebug() << "Processing repository version list.";
-	QJsonObject newestVersion;
-	QJsonArray versions = object.value("Versions").toArray();
-	for (QJsonValue versionVal : versions)
-	{
-		QJsonObject version = versionVal.toObject();
-		if (newestVersion.value("Id").toVariant().toInt() <
-			version.value("Id").toVariant().toInt())
-		{
-			newestVersion = version;
-		}
-	}
-
-	// We've got the version with the greatest ID number. Now compare it to our current build
-	// number and update if they're different.
-	int newBuildNumber = newestVersion.value("Id").toVariant().toInt();
-	if (newBuildNumber != m_currentBuild)
-	{
-		qDebug() << "Found newer version with ID" << newBuildNumber;
-		// Update!
-		GoUpdate::Status updateStatus;
-		updateStatus.updateAvailable = true;
-		updateStatus.currentVersionId = m_currentBuild;
-		updateStatus.currentRepoUrl = m_currentRepoUrl;
-		updateStatus.newVersionId = newBuildNumber;
-		updateStatus.newRepoUrl = m_newRepoUrl;
-		emit updateAvailable(updateStatus);
-	}
-	else if (notifyNoUpdate)
-	{
-		emit noUpdateFound();
-	}
-	m_updateChecking = false;
+    qDebug() << "Finished downloading repo index. Checking for new versions.";
+
+    QJsonParseError jsonError;
+    indexJob.reset();
+
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(indexData, &jsonError);
+    indexData.clear();
+    if (jsonError.error != QJsonParseError::NoError || !jsonDoc.isObject())
+    {
+        qCritical() << "Failed to parse GoUpdate repository index. JSON error"
+                     << jsonError.errorString() << "at offset" << jsonError.offset;
+        m_updateChecking = false;
+        return;
+    }
+
+    QJsonObject object = jsonDoc.object();
+
+    bool success = false;
+    int apiVersion = object.value("ApiVersion").toVariant().toInt(&success);
+    if (apiVersion != API_VERSION || !success)
+    {
+        qCritical() << "Failed to check for updates. API version mismatch. We're using"
+                     << API_VERSION << "server has" << apiVersion;
+        m_updateChecking = false;
+        return;
+    }
+
+    qDebug() << "Processing repository version list.";
+    QJsonObject newestVersion;
+    QJsonArray versions = object.value("Versions").toArray();
+    for (QJsonValue versionVal : versions)
+    {
+        QJsonObject version = versionVal.toObject();
+        if (newestVersion.value("Id").toVariant().toInt() <
+            version.value("Id").toVariant().toInt())
+        {
+            newestVersion = version;
+        }
+    }
+
+    // We've got the version with the greatest ID number. Now compare it to our current build
+    // number and update if they're different.
+    int newBuildNumber = newestVersion.value("Id").toVariant().toInt();
+    if (newBuildNumber != m_currentBuild)
+    {
+        qDebug() << "Found newer version with ID" << newBuildNumber;
+        // Update!
+        GoUpdate::Status updateStatus;
+        updateStatus.updateAvailable = true;
+        updateStatus.currentVersionId = m_currentBuild;
+        updateStatus.currentRepoUrl = m_currentRepoUrl;
+        updateStatus.newVersionId = newBuildNumber;
+        updateStatus.newRepoUrl = m_newRepoUrl;
+        emit updateAvailable(updateStatus);
+    }
+    else if (notifyNoUpdate)
+    {
+        emit noUpdateFound();
+    }
+    m_updateChecking = false;
 }
 
 void UpdateChecker::updateCheckFailed()
 {
-	qCritical() << "Update check failed for reasons unknown.";
+    qCritical() << "Update check failed for reasons unknown.";
 }
 
 void UpdateChecker::updateChanList(bool notifyNoUpdate)
 {
-	qDebug() << "Loading the channel list.";
-
-	if (m_chanListLoading)
-	{
-		qDebug() << "Ignoring channel list update request. Already grabbing channel list.";
-		return;
-	}
-
-	if (m_channelListUrl.isEmpty())
-	{
-		qCritical() << "Failed to update channel list. No channel list URL set."
-					<< "If you'd like to use MultiMC's update system, please pass the channel "
-						"list URL to CMake at compile time.";
-		return;
-	}
-
-	m_chanListLoading = true;
-	NetJob *job = new NetJob("Update System Channel List");
-	job->addNetAction(Net::Download::makeByteArray(QUrl(m_channelListUrl), &chanlistData));
-	connect(job, &NetJob::succeeded, [this, notifyNoUpdate]() { chanListDownloadFinished(notifyNoUpdate); });
-	QObject::connect(job, &NetJob::failed, this, &UpdateChecker::chanListDownloadFailed);
-	chanListJob.reset(job);
-	job->start();
+    qDebug() << "Loading the channel list.";
+
+    if (m_chanListLoading)
+    {
+        qDebug() << "Ignoring channel list update request. Already grabbing channel list.";
+        return;
+    }
+
+    if (m_channelListUrl.isEmpty())
+    {
+        qCritical() << "Failed to update channel list. No channel list URL set."
+                    << "If you'd like to use MultiMC's update system, please pass the channel "
+                        "list URL to CMake at compile time.";
+        return;
+    }
+
+    m_chanListLoading = true;
+    NetJob *job = new NetJob("Update System Channel List");
+    job->addNetAction(Net::Download::makeByteArray(QUrl(m_channelListUrl), &chanlistData));
+    connect(job, &NetJob::succeeded, [this, notifyNoUpdate]() { chanListDownloadFinished(notifyNoUpdate); });
+    QObject::connect(job, &NetJob::failed, this, &UpdateChecker::chanListDownloadFailed);
+    chanListJob.reset(job);
+    job->start();
 }
 
 void UpdateChecker::chanListDownloadFinished(bool notifyNoUpdate)
 {
-	chanListJob.reset();
-
-	QJsonParseError jsonError;
-	QJsonDocument jsonDoc = QJsonDocument::fromJson(chanlistData, &jsonError);
-	chanlistData.clear();
-	if (jsonError.error != QJsonParseError::NoError)
-	{
-		// TODO: Report errors to the user.
-		qCritical() << "Failed to parse channel list JSON:" << jsonError.errorString() << "at" << jsonError.offset;
-		m_chanListLoading = false;
-		return;
-	}
-
-	QJsonObject object = jsonDoc.object();
-
-	bool success = false;
-	int formatVersion = object.value("format_version").toVariant().toInt(&success);
-	if (formatVersion != CHANLIST_FORMAT || !success)
-	{
-		qCritical()
-			<< "Failed to check for updates. Channel list format version mismatch. We're using"
-			<< CHANLIST_FORMAT << "server has" << formatVersion;
-		m_chanListLoading = false;
-		return;
-	}
-
-	// Load channels into a temporary array.
-	QList<ChannelListEntry> loadedChannels;
-	QJsonArray channelArray = object.value("channels").toArray();
-	for (QJsonValue chanVal : channelArray)
-	{
-		QJsonObject channelObj = chanVal.toObject();
-		ChannelListEntry entry{channelObj.value("id").toVariant().toString(),
-							   channelObj.value("name").toVariant().toString(),
-							   channelObj.value("description").toVariant().toString(),
-							   channelObj.value("url").toVariant().toString()};
-		if (entry.id.isEmpty() || entry.name.isEmpty() || entry.url.isEmpty())
-		{
-			qCritical() << "Channel list entry with empty ID, name, or URL. Skipping.";
-			continue;
-		}
-		loadedChannels.append(entry);
-	}
-
-	// Swap  the channel list we just loaded into the object's channel list.
-	m_channels.swap(loadedChannels);
-
-	m_chanListLoading = false;
-	m_chanListLoaded = true;
-	qDebug() << "Successfully loaded UpdateChecker channel list.";
-
-	// If we're waiting to check for updates, do that now.
-	if (m_checkUpdateWaiting)
-		checkForUpdate(m_deferredUpdateChannel, notifyNoUpdate);
-
-	emit channelListLoaded();
+    chanListJob.reset();
+
+    QJsonParseError jsonError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(chanlistData, &jsonError);
+    chanlistData.clear();
+    if (jsonError.error != QJsonParseError::NoError)
+    {
+        // TODO: Report errors to the user.
+        qCritical() << "Failed to parse channel list JSON:" << jsonError.errorString() << "at" << jsonError.offset;
+        m_chanListLoading = false;
+        return;
+    }
+
+    QJsonObject object = jsonDoc.object();
+
+    bool success = false;
+    int formatVersion = object.value("format_version").toVariant().toInt(&success);
+    if (formatVersion != CHANLIST_FORMAT || !success)
+    {
+        qCritical()
+            << "Failed to check for updates. Channel list format version mismatch. We're using"
+            << CHANLIST_FORMAT << "server has" << formatVersion;
+        m_chanListLoading = false;
+        return;
+    }
+
+    // Load channels into a temporary array.
+    QList<ChannelListEntry> loadedChannels;
+    QJsonArray channelArray = object.value("channels").toArray();
+    for (QJsonValue chanVal : channelArray)
+    {
+        QJsonObject channelObj = chanVal.toObject();
+        ChannelListEntry entry{channelObj.value("id").toVariant().toString(),
+                               channelObj.value("name").toVariant().toString(),
+                               channelObj.value("description").toVariant().toString(),
+                               channelObj.value("url").toVariant().toString()};
+        if (entry.id.isEmpty() || entry.name.isEmpty() || entry.url.isEmpty())
+        {
+            qCritical() << "Channel list entry with empty ID, name, or URL. Skipping.";
+            continue;
+        }
+        loadedChannels.append(entry);
+    }
+
+    // Swap  the channel list we just loaded into the object's channel list.
+    m_channels.swap(loadedChannels);
+
+    m_chanListLoading = false;
+    m_chanListLoaded = true;
+    qDebug() << "Successfully loaded UpdateChecker channel list.";
+
+    // If we're waiting to check for updates, do that now.
+    if (m_checkUpdateWaiting)
+        checkForUpdate(m_deferredUpdateChannel, notifyNoUpdate);
+
+    emit channelListLoaded();
 }
 
 void UpdateChecker::chanListDownloadFailed(QString reason)
 {
-	m_chanListLoading = false;
-	qCritical() << QString("Failed to download channel list: %1").arg(reason);
-	emit channelListLoaded();
+    m_chanListLoading = false;
+    qCritical() << QString("Failed to download channel list: %1").arg(reason);
+    emit channelListLoaded();
 }
 
diff --git a/api/logic/updater/UpdateChecker.h b/api/logic/updater/UpdateChecker.h
index 4996da26..bb5013de 100644
--- a/api/logic/updater/UpdateChecker.h
+++ b/api/logic/updater/UpdateChecker.h
@@ -22,100 +22,100 @@
 
 class MULTIMC_LOGIC_EXPORT UpdateChecker : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 
 public:
-	UpdateChecker(QString channelListUrl, QString currentChannel, int currentBuild);
-	void checkForUpdate(QString updateChannel, bool notifyNoUpdate);
-
-	/*!
-	 * Causes the update checker to download the channel list from the URL specified in config.h (generated by CMake).
-	 * If this isn't called before checkForUpdate(), it will automatically be called.
-	 */
-	void updateChanList(bool notifyNoUpdate);
-
-	/*!
-	 * An entry in the channel list.
-	 */
-	struct ChannelListEntry
-	{
-		QString id;
-		QString name;
-		QString description;
-		QString url;
-	};
-
-	/*!
-	 * Returns a the current channel list.
-	 * If the channel list hasn't been loaded, this list will be empty.
-	 */
-	QList<ChannelListEntry> getChannelList() const;
-
-	/*!
-	 * Returns false if the channel list is empty.
-	 */
-	bool hasChannels() const;
+    UpdateChecker(QString channelListUrl, QString currentChannel, int currentBuild);
+    void checkForUpdate(QString updateChannel, bool notifyNoUpdate);
+
+    /*!
+     * Causes the update checker to download the channel list from the URL specified in config.h (generated by CMake).
+     * If this isn't called before checkForUpdate(), it will automatically be called.
+     */
+    void updateChanList(bool notifyNoUpdate);
+
+    /*!
+     * An entry in the channel list.
+     */
+    struct ChannelListEntry
+    {
+        QString id;
+        QString name;
+        QString description;
+        QString url;
+    };
+
+    /*!
+     * Returns a the current channel list.
+     * If the channel list hasn't been loaded, this list will be empty.
+     */
+    QList<ChannelListEntry> getChannelList() const;
+
+    /*!
+     * Returns false if the channel list is empty.
+     */
+    bool hasChannels() const;
 
 signals:
-	//! Signal emitted when an update is available. Passes the URL for the repo and the ID and name for the version.
-	void updateAvailable(GoUpdate::Status status);
+    //! Signal emitted when an update is available. Passes the URL for the repo and the ID and name for the version.
+    void updateAvailable(GoUpdate::Status status);
 
-	//! Signal emitted when the channel list finishes loading or fails to load.
-	void channelListLoaded();
+    //! Signal emitted when the channel list finishes loading or fails to load.
+    void channelListLoaded();
 
-	void noUpdateFound();
+    void noUpdateFound();
 
 private slots:
-	void updateCheckFinished(bool notifyNoUpdate);
-	void updateCheckFailed();
+    void updateCheckFinished(bool notifyNoUpdate);
+    void updateCheckFailed();
 
-	void chanListDownloadFinished(bool notifyNoUpdate);
-	void chanListDownloadFailed(QString reason);
+    void chanListDownloadFinished(bool notifyNoUpdate);
+    void chanListDownloadFailed(QString reason);
 
 private:
-	friend class UpdateCheckerTest;
-
-	NetJobPtr indexJob;
-	QByteArray indexData;
-	NetJobPtr chanListJob;
-	QByteArray chanlistData;
-
-	QString m_channelListUrl;
-
-	QList<ChannelListEntry> m_channels;
-
-	/*!
-	 * True while the system is checking for updates.
-	 * If checkForUpdate is called while this is true, it will be ignored.
-	 */
-	bool m_updateChecking = false;
-
-	/*!
-	 * True if the channel list has loaded.
-	 * If this is false, trying to check for updates will call updateChanList first.
-	 */
-	bool m_chanListLoaded = false;
-
-	/*!
-	 * Set to true while the channel list is currently loading.
-	 */
-	bool m_chanListLoading = false;
-
-	/*!
-	 * Set to true when checkForUpdate is called while the channel list isn't loaded.
-	 * When the channel list finishes loading, if this is true, the update checker will check for updates.
-	 */
-	bool m_checkUpdateWaiting = false;
-
-	/*!
-	 * if m_checkUpdateWaiting, this is the last used update channel
-	 */
-	QString m_deferredUpdateChannel;
-
-	int m_currentBuild = -1;
-	QString m_currentChannel;
-	QString m_currentRepoUrl;
-
-	QString m_newRepoUrl;
+    friend class UpdateCheckerTest;
+
+    NetJobPtr indexJob;
+    QByteArray indexData;
+    NetJobPtr chanListJob;
+    QByteArray chanlistData;
+
+    QString m_channelListUrl;
+
+    QList<ChannelListEntry> m_channels;
+
+    /*!
+     * True while the system is checking for updates.
+     * If checkForUpdate is called while this is true, it will be ignored.
+     */
+    bool m_updateChecking = false;
+
+    /*!
+     * True if the channel list has loaded.
+     * If this is false, trying to check for updates will call updateChanList first.
+     */
+    bool m_chanListLoaded = false;
+
+    /*!
+     * Set to true while the channel list is currently loading.
+     */
+    bool m_chanListLoading = false;
+
+    /*!
+     * Set to true when checkForUpdate is called while the channel list isn't loaded.
+     * When the channel list finishes loading, if this is true, the update checker will check for updates.
+     */
+    bool m_checkUpdateWaiting = false;
+
+    /*!
+     * if m_checkUpdateWaiting, this is the last used update channel
+     */
+    QString m_deferredUpdateChannel;
+
+    int m_currentBuild = -1;
+    QString m_currentChannel;
+    QString m_currentRepoUrl;
+
+    QString m_newRepoUrl;
 };
 
diff --git a/api/logic/updater/UpdateChecker_test.cpp b/api/logic/updater/UpdateChecker_test.cpp
index 16b21614..59f2a5a1 100644
--- a/api/logic/updater/UpdateChecker_test.cpp
+++ b/api/logic/updater/UpdateChecker_test.cpp
@@ -8,137 +8,137 @@ Q_DECLARE_METATYPE(UpdateChecker::ChannelListEntry)
 
 bool operator==(const UpdateChecker::ChannelListEntry &e1, const UpdateChecker::ChannelListEntry &e2)
 {
-	qDebug() << e1.url << "vs" << e2.url;
-	return e1.id == e2.id &&
-			e1.name == e2.name &&
-			e1.description == e2.description &&
-			e1.url == e2.url;
+    qDebug() << e1.url << "vs" << e2.url;
+    return e1.id == e2.id &&
+            e1.name == e2.name &&
+            e1.description == e2.description &&
+            e1.url == e2.url;
 }
 
 QDebug operator<<(QDebug dbg, const UpdateChecker::ChannelListEntry &c)
 {
-	dbg.nospace() << "ChannelListEntry(id=" << c.id << " name=" << c.name << " description=" << c.description << " url=" << c.url << ")";
-	return dbg.maybeSpace();
+    dbg.nospace() << "ChannelListEntry(id=" << c.id << " name=" << c.name << " description=" << c.description << " url=" << c.url << ")";
+    return dbg.maybeSpace();
 }
 
 class UpdateCheckerTest : public QObject
 {
-	Q_OBJECT
+    Q_OBJECT
 private
 slots:
-	void initTestCase()
-	{
-
-	}
-	void cleanupTestCase()
-	{
-
-	}
-
-	static QString findTestDataUrl(const char *file)
-	{
-		return QUrl::fromLocalFile(QFINDTESTDATA(file)).toString();
-	}
-	void tst_ChannelListParsing_data()
-	{
-		QTest::addColumn<QString>("channel");
-		QTest::addColumn<QString>("channelUrl");
-		QTest::addColumn<bool>("hasChannels");
-		QTest::addColumn<bool>("valid");
-		QTest::addColumn<QList<UpdateChecker::ChannelListEntry> >("result");
-
-		QTest::newRow("garbage")
-				<< QString()
-				<< findTestDataUrl("data/garbageChannels.json")
-				<< false
-				<< false
-				<< QList<UpdateChecker::ChannelListEntry>();
-		QTest::newRow("errors")
-				<< QString()
-				<< findTestDataUrl("data/errorChannels.json")
-				<< false
-				<< true
-				<< QList<UpdateChecker::ChannelListEntry>();
-		QTest::newRow("no channels")
-				<< QString()
-				<< findTestDataUrl("data/noChannels.json")
-				<< false
-				<< true
-				<< QList<UpdateChecker::ChannelListEntry>();
-		QTest::newRow("one channel")
-				<< QString("develop")
-				<< findTestDataUrl("data/oneChannel.json")
-				<< true
-				<< true
-				<< (QList<UpdateChecker::ChannelListEntry>() << UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", "http://example.org/stuff"});
-		QTest::newRow("several channels")
-				<< QString("develop")
-				<< findTestDataUrl("data/channels.json")
-				<< true
-				<< true
-				<< (QList<UpdateChecker::ChannelListEntry>()
-					<< UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", findTestDataUrl("data")}
-					<< UpdateChecker::ChannelListEntry{"stable", "Stable", "It's stable at least", findTestDataUrl("data")}
-					<< UpdateChecker::ChannelListEntry{"42", "The Channel", "This is the channel that is going to answer all of your questions", "https://dent.me/tea"});
-	}
-	void tst_ChannelListParsing()
-	{
-
-		QFETCH(QString, channel);
-		QFETCH(QString, channelUrl);
-		QFETCH(bool, hasChannels);
-		QFETCH(bool, valid);
-		QFETCH(QList<UpdateChecker::ChannelListEntry>, result);
-
-		UpdateChecker checker(channelUrl, channel, 0);
-
-		QSignalSpy channelListLoadedSpy(&checker, SIGNAL(channelListLoaded()));
-		QVERIFY(channelListLoadedSpy.isValid());
-
-		checker.updateChanList(false);
-
-		if (valid)
-		{
-			QVERIFY(channelListLoadedSpy.wait());
-			QCOMPARE(channelListLoadedSpy.size(), 1);
-		}
-		else
-		{
-			channelListLoadedSpy.wait();
-			QCOMPARE(channelListLoadedSpy.size(), 0);
-		}
-
-		QCOMPARE(checker.hasChannels(), hasChannels);
-		QCOMPARE(checker.getChannelList(), result);
-	}
-
-	void tst_UpdateChecking()
-	{
-		QString channel = "develop";
-		QString channelUrl = findTestDataUrl("data/channels.json");
-		int currentBuild = 2;
-
-		UpdateChecker checker(channelUrl, channel, currentBuild);
-
-		QSignalSpy updateAvailableSpy(&checker, SIGNAL(updateAvailable(GoUpdate::Status)));
-		QVERIFY(updateAvailableSpy.isValid());
-		QSignalSpy channelListLoadedSpy(&checker, SIGNAL(channelListLoaded()));
-		QVERIFY(channelListLoadedSpy.isValid());
-
-		checker.updateChanList(false);
-		QVERIFY(channelListLoadedSpy.wait());
-
-		qDebug() << "CWD:" << QDir::current().absolutePath();
-		checker.m_channels[0].url = findTestDataUrl("data/");
-		checker.checkForUpdate(channel, false);
-
-		QVERIFY(updateAvailableSpy.wait());
-
-		auto status = updateAvailableSpy.first().first().value<GoUpdate::Status>();
-		QCOMPARE(checker.m_channels[0].url, status.newRepoUrl);
-		QCOMPARE(3, status.newVersionId);
-		QCOMPARE(currentBuild, status.currentVersionId);
-	}
+    void initTestCase()
+    {
+
+    }
+    void cleanupTestCase()
+    {
+
+    }
+
+    static QString findTestDataUrl(const char *file)
+    {
+        return QUrl::fromLocalFile(QFINDTESTDATA(file)).toString();
+    }
+    void tst_ChannelListParsing_data()
+    {
+        QTest::addColumn<QString>("channel");
+        QTest::addColumn<QString>("channelUrl");
+        QTest::addColumn<bool>("hasChannels");
+        QTest::addColumn<bool>("valid");
+        QTest::addColumn<QList<UpdateChecker::ChannelListEntry> >("result");
+
+        QTest::newRow("garbage")
+                << QString()
+                << findTestDataUrl("data/garbageChannels.json")
+                << false
+                << false
+                << QList<UpdateChecker::ChannelListEntry>();
+        QTest::newRow("errors")
+                << QString()
+                << findTestDataUrl("data/errorChannels.json")
+                << false
+                << true
+                << QList<UpdateChecker::ChannelListEntry>();
+        QTest::newRow("no channels")
+                << QString()
+                << findTestDataUrl("data/noChannels.json")
+                << false
+                << true
+                << QList<UpdateChecker::ChannelListEntry>();
+        QTest::newRow("one channel")
+                << QString("develop")
+                << findTestDataUrl("data/oneChannel.json")
+                << true
+                << true
+                << (QList<UpdateChecker::ChannelListEntry>() << UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", "http://example.org/stuff"});
+        QTest::newRow("several channels")
+                << QString("develop")
+                << findTestDataUrl("data/channels.json")
+                << true
+                << true
+                << (QList<UpdateChecker::ChannelListEntry>()
+                    << UpdateChecker::ChannelListEntry{"develop", "Develop", "The channel called \"develop\"", findTestDataUrl("data")}
+                    << UpdateChecker::ChannelListEntry{"stable", "Stable", "It's stable at least", findTestDataUrl("data")}
+                    << UpdateChecker::ChannelListEntry{"42", "The Channel", "This is the channel that is going to answer all of your questions", "https://dent.me/tea"});
+    }
+    void tst_ChannelListParsing()
+    {
+
+        QFETCH(QString, channel);
+        QFETCH(QString, channelUrl);
+        QFETCH(bool, hasChannels);
+        QFETCH(bool, valid);
+        QFETCH(QList<UpdateChecker::ChannelListEntry>, result);
+
+        UpdateChecker checker(channelUrl, channel, 0);
+
+        QSignalSpy channelListLoadedSpy(&checker, SIGNAL(channelListLoaded()));
+        QVERIFY(channelListLoadedSpy.isValid());
+
+        checker.updateChanList(false);
+
+        if (valid)
+        {
+            QVERIFY(channelListLoadedSpy.wait());
+            QCOMPARE(channelListLoadedSpy.size(), 1);
+        }
+        else
+        {
+            channelListLoadedSpy.wait();
+            QCOMPARE(channelListLoadedSpy.size(), 0);
+        }
+
+        QCOMPARE(checker.hasChannels(), hasChannels);
+        QCOMPARE(checker.getChannelList(), result);
+    }
+
+    void tst_UpdateChecking()
+    {
+        QString channel = "develop";
+        QString channelUrl = findTestDataUrl("data/channels.json");
+        int currentBuild = 2;
+
+        UpdateChecker checker(channelUrl, channel, currentBuild);
+
+        QSignalSpy updateAvailableSpy(&checker, SIGNAL(updateAvailable(GoUpdate::Status)));
+        QVERIFY(updateAvailableSpy.isValid());
+        QSignalSpy channelListLoadedSpy(&checker, SIGNAL(channelListLoaded()));
+        QVERIFY(channelListLoadedSpy.isValid());
+
+        checker.updateChanList(false);
+        QVERIFY(channelListLoadedSpy.wait());
+
+        qDebug() << "CWD:" << QDir::current().absolutePath();
+        checker.m_channels[0].url = findTestDataUrl("data/");
+        checker.checkForUpdate(channel, false);
+
+        QVERIFY(updateAvailableSpy.wait());
+
+        auto status = updateAvailableSpy.first().first().value<GoUpdate::Status>();
+        QCOMPARE(checker.m_channels[0].url, status.newRepoUrl);
+        QCOMPARE(3, status.newVersionId);
+        QCOMPARE(currentBuild, status.currentVersionId);
+    }
 };
 
 QTEST_GUILESS_MAIN(UpdateCheckerTest)
diff --git a/api/logic/updater/testdata/1.json b/api/logic/updater/testdata/1.json
index 3dd189e5..7af7e52d 100644
--- a/api/logic/updater/testdata/1.json
+++ b/api/logic/updater/testdata/1.json
@@ -1,43 +1,43 @@
 {
-	"ApiVersion": 0,
-	"Id": 1,
-	"Name": "1.0.1",
-	"Files": [
-		{
-			"Path": "fileOne",
-			"Sources": [
-				{
-					"SourceType": "http",
-					"Url": "@TEST_DATA_URL@/fileOneA"
-				}
-			],
-			"Executable": true,
-			"Perms": 493,
-			"MD5": "9eb84090956c484e32cb6c08455a667b"
-		},
-		{
-			"Path": "fileTwo",
-			"Sources": [
-				{
-					"SourceType": "http",
-					"Url": "@TEST_DATA_URL@/fileTwo"
-				}
-			],
-			"Executable": false,
-			"Perms": 644,
-			"MD5": "38f94f54fa3eb72b0ea836538c10b043"
-		},
-		{
-			"Path": "fileThree",
-			"Sources": [
-				{
-					"SourceType": "http",
-					"Url": "@TEST_DATA_URL@/fileThree"
-				}
-			],
-			"Executable": false,
-			"Perms": "750",
-			"MD5": "f12df554b21e320be6471d7154130e70"
-		}
-	]
+    "ApiVersion": 0,
+    "Id": 1,
+    "Name": "1.0.1",
+    "Files": [
+        {
+            "Path": "fileOne",
+            "Sources": [
+                {
+                    "SourceType": "http",
+                    "Url": "@TEST_DATA_URL@/fileOneA"
+                }
+            ],
+            "Executable": true,
+            "Perms": 493,
+            "MD5": "9eb84090956c484e32cb6c08455a667b"
+        },
+        {
+            "Path": "fileTwo",
+            "Sources": [
+                {
+                    "SourceType": "http",
+                    "Url": "@TEST_DATA_URL@/fileTwo"
+                }
+            ],
+            "Executable": false,
+            "Perms": 644,
+            "MD5": "38f94f54fa3eb72b0ea836538c10b043"
+        },
+        {
+            "Path": "fileThree",
+            "Sources": [
+                {
+                    "SourceType": "http",
+                    "Url": "@TEST_DATA_URL@/fileThree"
+                }
+            ],
+            "Executable": false,
+            "Perms": "750",
+            "MD5": "f12df554b21e320be6471d7154130e70"
+        }
+    ]
 }
diff --git a/api/logic/updater/testdata/2.json b/api/logic/updater/testdata/2.json
index a7ba7029..96d430d5 100644
--- a/api/logic/updater/testdata/2.json
+++ b/api/logic/updater/testdata/2.json
@@ -1,31 +1,31 @@
 {
-	"ApiVersion": 0,
-	"Id": 1,
-	"Name": "1.0.1",
-	"Files": [
-		{
-			"Path": "fileOne",
-			"Sources": [
-				{
-					"SourceType": "http",
-					"Url": "@TEST_DATA_URL@/fileOneB"
-				}
-			],
-			"Executable": true,
-			"Perms": 493,
-			"MD5": "42915a71277c9016668cce7b82c6b577"
-		},
-		{
-			"Path": "fileTwo",
-			"Sources": [
-				{
-					"SourceType": "http",
-					"Url": "@TEST_DATA_URL@/fileTwo"
-				}
-			],
-			"Executable": false,
-			"Perms": 644,
-			"MD5": "38f94f54fa3eb72b0ea836538c10b043"
-		}
-	]
+    "ApiVersion": 0,
+    "Id": 1,
+    "Name": "1.0.1",
+    "Files": [
+        {
+            "Path": "fileOne",
+            "Sources": [
+                {
+                    "SourceType": "http",
+                    "Url": "@TEST_DATA_URL@/fileOneB"
+                }
+            ],
+            "Executable": true,
+            "Perms": 493,
+            "MD5": "42915a71277c9016668cce7b82c6b577"
+        },
+        {
+            "Path": "fileTwo",
+            "Sources": [
+                {
+                    "SourceType": "http",
+                    "Url": "@TEST_DATA_URL@/fileTwo"
+                }
+            ],
+            "Executable": false,
+            "Perms": 644,
+            "MD5": "38f94f54fa3eb72b0ea836538c10b043"
+        }
+    ]
 }
diff --git a/api/logic/updater/testdata/channels.json b/api/logic/updater/testdata/channels.json
index b46c64c8..5c6e42cb 100644
--- a/api/logic/updater/testdata/channels.json
+++ b/api/logic/updater/testdata/channels.json
@@ -1,23 +1,23 @@
 {
-	"format_version": 0,
-	"channels": [
-		{
-			"id": "develop",
-			"name": "Develop",
-			"description": "The channel called \"develop\"",
-			"url": "@TEST_DATA_URL@"
-		},
-		{
-			"id": "stable",
-			"name": "Stable",
-			"description": "It's stable at least",
-			"url": "@TEST_DATA_URL@"
-		},
-		{
-			"id": "42",
-			"name": "The Channel",
-			"description": "This is the channel that is going to answer all of your questions",
-			"url": "https://dent.me/tea"
-		}
-	]
+    "format_version": 0,
+    "channels": [
+        {
+            "id": "develop",
+            "name": "Develop",
+            "description": "The channel called \"develop\"",
+            "url": "@TEST_DATA_URL@"
+        },
+        {
+            "id": "stable",
+            "name": "Stable",
+            "description": "It's stable at least",
+            "url": "@TEST_DATA_URL@"
+        },
+        {
+            "id": "42",
+            "name": "The Channel",
+            "description": "This is the channel that is going to answer all of your questions",
+            "url": "https://dent.me/tea"
+        }
+    ]
 }
diff --git a/api/logic/updater/testdata/errorChannels.json b/api/logic/updater/testdata/errorChannels.json
index 333cd445..a2cb2165 100644
--- a/api/logic/updater/testdata/errorChannels.json
+++ b/api/logic/updater/testdata/errorChannels.json
@@ -1,23 +1,23 @@
 {
-	"format_version": 0,
-	"channels": [
-		{
-			"id": "",
-			"name": "Develop",
-			"description": "The channel called \"develop\"",
-			"url": "http://example.org/stuff"
-		},
-		{
-			"id": "stable",
-			"name": "",
-			"description": "It's stable at least",
-			"url": "ftp://username@host/path/to/stuff"
-		},
-		{
-			"id": "42",
-			"name": "The Channel",
-			"description": "This is the channel that is going to answer all of your questions",
-			"url": ""
-		}
-	]
+    "format_version": 0,
+    "channels": [
+        {
+            "id": "",
+            "name": "Develop",
+            "description": "The channel called \"develop\"",
+            "url": "http://example.org/stuff"
+        },
+        {
+            "id": "stable",
+            "name": "",
+            "description": "It's stable at least",
+            "url": "ftp://username@host/path/to/stuff"
+        },
+        {
+            "id": "42",
+            "name": "The Channel",
+            "description": "This is the channel that is going to answer all of your questions",
+            "url": ""
+        }
+    ]
 }
diff --git a/api/logic/updater/testdata/garbageChannels.json b/api/logic/updater/testdata/garbageChannels.json
index 1450fb9c..34437451 100644
--- a/api/logic/updater/testdata/garbageChannels.json
+++ b/api/logic/updater/testdata/garbageChannels.json
@@ -1,22 +1,22 @@
 {
-	"format_version": 0,
-	"channels": [
-		{
-			"id": "develop",
-			"name": "Develop",
-			"description": "The channel called \"develop\"",
-aa			"url": "http://example.org/stuff"
-		},
-a			"id": "stable",
-			"name": "Stable",
-			"description": "It's stable at least",
-			"url": "ftp://username@host/path/to/stuff"
-		},
-		{
-			"id": "42"f
-			"name": "The Channel",
-			"description": "This is the channel that is going to answer all of your questions",
-			"url": "https://dent.me/tea"
-		}
-	]
+    "format_version": 0,
+    "channels": [
+        {
+            "id": "develop",
+            "name": "Develop",
+            "description": "The channel called \"develop\"",
+aa            "url": "http://example.org/stuff"
+        },
+a            "id": "stable",
+            "name": "Stable",
+            "description": "It's stable at least",
+            "url": "ftp://username@host/path/to/stuff"
+        },
+        {
+            "id": "42"f
+            "name": "The Channel",
+            "description": "This is the channel that is going to answer all of your questions",
+            "url": "https://dent.me/tea"
+        }
+    ]
 }
diff --git a/api/logic/updater/testdata/index.json b/api/logic/updater/testdata/index.json
index 20ceb9f4..867bdcfb 100644
--- a/api/logic/updater/testdata/index.json
+++ b/api/logic/updater/testdata/index.json
@@ -1,9 +1,9 @@
 {
-	"ApiVersion": 0,
-	"Versions": [
-		{ "Id": 0, "Name": "1.0.0" },
-		{ "Id": 1, "Name": "1.0.1" },
-		{ "Id": 2, "Name": "1.0.2" },
-		{ "Id": 3, "Name": "1.0.3" }
-	]
+    "ApiVersion": 0,
+    "Versions": [
+        { "Id": 0, "Name": "1.0.0" },
+        { "Id": 1, "Name": "1.0.1" },
+        { "Id": 2, "Name": "1.0.2" },
+        { "Id": 3, "Name": "1.0.3" }
+    ]
 }
diff --git a/api/logic/updater/testdata/noChannels.json b/api/logic/updater/testdata/noChannels.json
index bbb2cb70..76988982 100644
--- a/api/logic/updater/testdata/noChannels.json
+++ b/api/logic/updater/testdata/noChannels.json
@@ -1,5 +1,5 @@
 {
-	"format_version": 0,
-	"channels": [
-	]
+    "format_version": 0,
+    "channels": [
+    ]
 }
diff --git a/api/logic/updater/testdata/oneChannel.json b/api/logic/updater/testdata/oneChannel.json
index 84727ac7..cc8ed255 100644
--- a/api/logic/updater/testdata/oneChannel.json
+++ b/api/logic/updater/testdata/oneChannel.json
@@ -1,11 +1,11 @@
 {
-	"format_version": 0,
-	"channels": [
-		{
-			"id": "develop",
-			"name": "Develop",
-			"description": "The channel called \"develop\"",
-			"url": "http://example.org/stuff"
-		}
-	]
+    "format_version": 0,
+    "channels": [
+        {
+            "id": "develop",
+            "name": "Develop",
+            "description": "The channel called \"develop\"",
+            "url": "http://example.org/stuff"
+        }
+    ]
 }
-- 
cgit