From e5b4dee1c05d0d6ebc0d7b2dd802b93cb8765e63 Mon Sep 17 00:00:00 2001
From: Jan Dalheimer <jan@dalheimer.de>
Date: Fri, 14 Mar 2014 19:51:56 +0100
Subject: Move version stuff to the model and reimplement reordering

---
 logic/OneSixVersionBuilder.cpp |  13 ++--
 logic/VersionFinal.cpp         | 153 ++++++++++++++++++++++++++++++++++++++---
 logic/VersionFinal.h           |  16 ++++-
 3 files changed, 163 insertions(+), 19 deletions(-)

(limited to 'logic')

diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp
index 8eacbce4..35d01a46 100644
--- a/logic/OneSixVersionBuilder.cpp
+++ b/logic/OneSixVersionBuilder.cpp
@@ -58,13 +58,15 @@ void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
 
 void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external)
 {
-	m_version->clear();
+	m_version->versionFiles.clear();
 
 	QDir root(m_instance->instanceRoot());
 	QDir patches(root.absoluteFilePath("patches/"));
 
 	// if we do external files, do just those.
 	if (!external.isEmpty())
+	{
+		int externalOrder = -1;
 		for (auto fileName : external)
 		{
 			QLOG_INFO() << "Reading" << fileName;
@@ -72,11 +74,12 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
 				parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
 			file->name = QFileInfo(fileName).fileName();
 			file->fileId = "org.multimc.external." + file->name;
+			file->order = (externalOrder += 1);
 			file->version = QString();
 			file->mcVersion = QString();
-			file->applyTo(m_version);
 			m_version->versionFiles.append(file);
 		}
+	}
 	// else, if there's custom json, we just do that.
 	else if (QFile::exists(root.absoluteFilePath("custom.json")))
 	{
@@ -85,8 +88,8 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
 		file->name = "custom.json";
 		file->filename = "custom.json";
 		file->fileId = "org.multimc.custom.json";
+		file->order = -1;
 		file->version = QString();
-		file->applyTo(m_version);
 		m_version->versionFiles.append(file);
 		// QObject::tr("The version descriptors of this instance are not compatible with the
 		// current version of MultiMC"));
@@ -101,9 +104,9 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
 			auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false);
 			file->name = "Minecraft";
 			file->fileId = "org.multimc.version.json";
+			file->order = -1;
 			file->version = m_instance->intendedVersionId();
 			file->mcVersion = m_instance->intendedVersionId();
-			file->applyTo(m_version);
 			m_version->versionFiles.append(file);
 			// QObject::tr("Error while applying %1. Please check MultiMC-0.log for more
 			// info.").arg(root.absoluteFilePath("version.json")));
@@ -128,9 +131,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
 			}
 			for (auto order : files.keys())
 			{
-				QLOG_DEBUG() << "Applying file with order" << order;
 				auto &filePair = files[order];
-				filePair.second->applyTo(m_version);
 				m_version->versionFiles.append(filePair.second);
 			}
 		} while (0);
diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp
index a057ecdd..2901fcf9 100644
--- a/logic/VersionFinal.cpp
+++ b/logic/VersionFinal.cpp
@@ -17,8 +17,20 @@
 
 #include <QDebug>
 #include <QFile>
+#include <QDir>
 
 #include "OneSixVersionBuilder.h"
+#include "OneSixInstance.h"
+
+template <typename A, typename B> QMap<A, B> invert(const QMap<B, A> &in)
+{
+	QMap<A, B> out;
+	for (auto it = in.begin(); it != in.end(); ++it)
+	{
+		out.insert(it.value(), it.key());
+	}
+	return out;
+}
 
 VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent)
 	: QAbstractListModel(parent), m_instance(instance)
@@ -31,12 +43,12 @@ bool VersionFinal::reload(const bool onlyVanilla, const QStringList &external)
 	//FIXME: source of epic failure.
 	beginResetModel();
 	OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external);
+	reapply(true);
 	endResetModel();
 }
 
 void VersionFinal::clear()
 {
-	beginResetModel();
 	id.clear();
 	time.clear();
 	releaseTime.clear();
@@ -48,8 +60,6 @@ void VersionFinal::clear()
 	mainClass.clear();
 	libraries.clear();
 	tweakers.clear();
-	versionFiles.clear();
-	endResetModel();
 }
 
 bool VersionFinal::canRemove(const int index) const
@@ -60,6 +70,14 @@ bool VersionFinal::canRemove(const int index) const
 	}
 	return false;
 }
+bool VersionFinal::remove(const int index)
+{
+	if (canRemove(index))
+	{
+		return QFile::remove(versionFiles.at(index)->filename);
+	}
+	return false;
+}
 
 QString VersionFinal::versionFileId(const int index) const
 {
@@ -69,14 +87,16 @@ QString VersionFinal::versionFileId(const int index) const
 	}
 	return versionFiles.at(index)->fileId;
 }
-
-bool VersionFinal::remove(const int index)
+VersionFilePtr VersionFinal::versionFile(const QString &id)
 {
-	if (canRemove(index))
+	for (auto file : versionFiles)
 	{
-		return QFile::remove(versionFiles.at(index)->filename);
+		if (file->fileId == id)
+		{
+			return file;
+		}
 	}
-	return false;
+	return 0;
 }
 
 QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
@@ -91,7 +111,6 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
 	}
 	return output;
 }
-
 QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs()
 {
 	QList<std::shared_ptr<OneSixLibrary> > output;
@@ -144,7 +163,6 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
 	}
 	return QVariant();
 }
-
 QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int role) const
 {
 	if (orientation == Qt::Horizontal)
@@ -164,7 +182,6 @@ QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int
 	}
 	return QVariant();
 }
-
 Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const
 {
 	if (!index.isValid())
@@ -181,3 +198,117 @@ int VersionFinal::columnCount(const QModelIndex &parent) const
 {
 	return 2;
 }
+
+bool VersionFinal::isCustom()
+{
+	return QDir(m_instance->instanceRoot()).exists("custom.json");
+}
+bool VersionFinal::revertToBase()
+{
+	return QDir(m_instance->instanceRoot()).remove("custom.json");
+}
+
+QMap<QString, int> VersionFinal::getExistingOrder() const
+{
+
+	QMap<QString, int> order;
+	// default
+	{
+		for (auto file : versionFiles)
+		{
+			order.insert(file->fileId, file->order);
+		}
+	}
+	// overriden
+	{
+		QMap<QString, int> overridenOrder = OneSixVersionBuilder::readOverrideOrders(m_instance);
+		for (auto id : order.keys())
+		{
+			if (overridenOrder.contains(id))
+			{
+				order[id] = overridenOrder[id];
+			}
+		}
+	}
+	return order;
+}
+
+void VersionFinal::move(const int index, const MoveDirection direction)
+{
+	int theirIndex;
+	if (direction == MoveUp)
+	{
+		theirIndex = index - 1;
+	}
+	else
+	{
+		theirIndex = index + 1;
+	}
+	if (theirIndex < 0 || theirIndex >= versionFiles.size())
+	{
+		return;
+	}
+	const QString ourId = versionFileId(index);
+	const QString theirId = versionFileId(theirIndex);
+	if (ourId.isNull() || ourId.startsWith("org.multimc.") ||
+			theirId.isNull() || theirId.startsWith("org.multimc."))
+	{
+		return;
+	}
+
+	VersionFilePtr we = versionFiles[index];
+	VersionFilePtr them = versionFiles[theirIndex];
+	if (!we || !them)
+	{
+		return;
+	}
+	beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex);
+	versionFiles.replace(theirIndex, we);
+	versionFiles.replace(index, them);
+	endMoveRows();
+
+	auto order = getExistingOrder();
+	order[ourId] = theirIndex;
+	order[theirId] = index;
+
+	if (!OneSixVersionBuilder::writeOverrideOrders(order, m_instance))
+	{
+		throw MMCError(tr("Couldn't save the new order"));
+	}
+	else
+	{
+		reapply();
+	}
+}
+void VersionFinal::resetOrder()
+{
+	QDir(m_instance->instanceRoot()).remove("order.json");
+	reapply();
+}
+
+void VersionFinal::reapply(const bool alreadyReseting)
+{
+	if (!alreadyReseting)
+	{
+		beginResetModel();
+	}
+
+	clear();
+
+	auto existingOrders = getExistingOrder();
+	QList<int> orders = existingOrders.values();
+	std::sort(orders.begin(), orders.end());
+	QList<VersionFilePtr> newVersionFiles;
+	for (auto order : orders)
+	{
+		auto file = versionFile(existingOrders.key(order));
+		newVersionFiles.append(file);
+		file->applyTo(this);
+	}
+	versionFiles.swap(newVersionFiles);
+
+	if (!alreadyReseting)
+	{
+		endResetModel();
+	}
+}
diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h
index 99fd5ff0..fcffb3c3 100644
--- a/logic/VersionFinal.h
+++ b/logic/VersionFinal.h
@@ -41,12 +41,22 @@ public:
 	bool reload(const bool onlyVanilla = false, const QStringList &external = QStringList());
 	void clear();
 
-	void dump() const;
-
 	bool canRemove(const int index) const;
 
 	QString versionFileId(const int index) const;
 
+	// does this instance have an all overriding custom.json
+	bool isCustom();
+	// remove custom.json
+	bool revertToBase();
+
+	enum MoveDirection { MoveUp, MoveDown };
+	void move(const int index, const MoveDirection direction);
+	void resetOrder();
+
+	// clears and reapplies all version files
+	void reapply(const bool alreadyReseting = false);
+
 public
 slots:
 	bool remove(const int index);
@@ -120,7 +130,9 @@ public:
 	// QList<Rule> rules;
 
 	QList<VersionFilePtr> versionFiles;
+	VersionFilePtr versionFile(const QString &id);
 
 private:
 	OneSixInstance *m_instance;
+	QMap<QString, int> getExistingOrder() const;
 };
-- 
cgit v1.2.3


From e95619fa67239b709522a66b8bb7403bb7b84098 Mon Sep 17 00:00:00 2001
From: Jan Dalheimer <jan@dalheimer.de>
Date: Fri, 14 Mar 2014 20:48:57 +0100
Subject: Pull in BaseInstaller related changes from quickmod

---
 logic/BaseInstaller.h         |   6 +++
 logic/ForgeInstaller.cpp      | 105 ++++++++++++++++++++++++++++++++++++++++--
 logic/ForgeInstaller.h        |   5 +-
 logic/LiteLoaderInstaller.cpp |  68 ++++++++++++++++++++++++++-
 logic/LiteLoaderInstaller.h   |   5 +-
 5 files changed, 182 insertions(+), 7 deletions(-)

(limited to 'logic')

diff --git a/logic/BaseInstaller.h b/logic/BaseInstaller.h
index c572e004..d59833cc 100644
--- a/logic/BaseInstaller.h
+++ b/logic/BaseInstaller.h
@@ -20,6 +20,10 @@
 class OneSixInstance;
 class QDir;
 class QString;
+class QObject;
+class ProgressProvider;
+class BaseVersion;
+typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
 
 class BaseInstaller
 {
@@ -31,6 +35,8 @@ public:
 	virtual bool add(OneSixInstance *to);
 	virtual bool remove(OneSixInstance *from);
 
+	virtual ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
+
 protected:
 	virtual QString id() const = 0;
 	QString filename(const QString &root) const;
diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp
index 6f238c21..48bfb8a3 100644
--- a/logic/ForgeInstaller.cpp
+++ b/logic/ForgeInstaller.cpp
@@ -24,17 +24,24 @@
 #include <QRegularExpression>
 #include <QRegularExpressionMatch>
 #include "MultiMC.h"
+#include "tasks/Task.h"
 #include "OneSixInstance.h"
+#include "lists/ForgeVersionList.h"
+#include "gui/dialogs/ProgressDialog.h"
 
 #include <QJsonDocument>
 #include <QJsonArray>
 #include <QSaveFile>
 #include <QCryptographicHash>
 
-ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
+ForgeInstaller::ForgeInstaller()
+	: BaseInstaller()
+{
+}
+void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl)
 {
 	std::shared_ptr<VersionFinal> newVersion;
-	m_universal_url = universal_url;
+	m_universal_url = universalUrl;
 
 	QuaZip zip(filename);
 	if (!zip.open(QuaZip::mdUnzip))
@@ -111,7 +118,6 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
 	m_forge_version = newVersion;
 	realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
 }
-
 bool ForgeInstaller::add(OneSixInstance *to)
 {
 	if (!BaseInstaller::add(to))
@@ -226,3 +232,96 @@ bool ForgeInstaller::add(OneSixInstance *to)
 
 	return true;
 }
+
+class ForgeInstallTask : public Task
+{
+	Q_OBJECT
+public:
+	ForgeInstallTask(ForgeInstaller *installer, OneSixInstance *instance, BaseVersionPtr version, QObject *parent = 0)
+		: Task(parent), m_installer(installer), m_instance(instance), m_version(version)
+	{
+	}
+
+protected:
+	void executeTask() override
+	{
+		{
+			setStatus(tr("Installing forge..."));
+			ForgeVersionPtr forgeVersion =
+				std::dynamic_pointer_cast<ForgeVersion>(m_version);
+			if (!forgeVersion)
+			{
+				emitFailed(tr("Unknown error occured"));
+				return;
+			}
+			auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename);
+			if (entry->stale)
+			{
+				NetJob *fjob = new NetJob("Forge download");
+				fjob->addNetAction(CacheDownload::make(forgeVersion->installer_url, entry));
+				connect(fjob, &NetJob::progress, [this](qint64 current, qint64 total){setProgress(100 * current / qMax((qint64)1, total));});
+				connect(fjob, &NetJob::status, [this](const QString &msg){setStatus(msg);});
+				connect(fjob, &NetJob::failed, [this](){emitFailed(tr("Failure to download forge"));});
+				connect(fjob, &NetJob::succeeded, [this, entry, forgeVersion]()
+				{
+					if (!install(entry, forgeVersion))
+					{
+						QLOG_ERROR() << "Failure installing forge";
+						emitFailed(tr("Failure to install forge"));
+					}
+					else
+					{
+						reload();
+					}
+				});
+			}
+			else
+			{
+				if (!install(entry, forgeVersion))
+				{
+					QLOG_ERROR() << "Failure installing forge";
+					emitFailed(tr("Failure to install forge"));
+				}
+				else
+				{
+					reload();
+				}
+			}
+		}
+	}
+
+	bool install(const std::shared_ptr<MetaEntry> &entry, const ForgeVersionPtr &forgeVersion)
+	{
+		QString forgePath = entry->getFullPath();
+		m_installer->prepare(forgePath, forgeVersion->universal_url);
+		return m_installer->add(m_instance);
+	}
+	void reload()
+	{
+		try
+		{
+			m_instance->reloadVersion();
+			emitSucceeded();
+		}
+		catch (MMCError &e)
+		{
+			emitFailed(e.cause());
+		}
+		catch (...)
+		{
+			emitFailed(tr("Failed to load the version description file for reasons unknown."));
+		}
+	}
+
+private:
+	ForgeInstaller *m_installer;
+	OneSixInstance *m_instance;
+	BaseVersionPtr m_version;
+};
+
+ProgressProvider *ForgeInstaller::createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent)
+{
+	return new ForgeInstallTask(this, instance, version, parent);
+}
+
+#include "ForgeInstaller.moc"
diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h
index df029f38..05cc994b 100644
--- a/logic/ForgeInstaller.h
+++ b/logic/ForgeInstaller.h
@@ -25,12 +25,15 @@ class VersionFinal;
 class ForgeInstaller : public BaseInstaller
 {
 public:
-	ForgeInstaller(QString filename, QString universal_url);
+	ForgeInstaller();
 
+	void prepare(const QString &filename, const QString &universalUrl);
 	bool add(OneSixInstance *to) override;
 
 	QString id() const override { return "net.minecraftforge"; }
 
+	ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override;
+
 private:
 	// the version, read from the installer
 	std::shared_ptr<VersionFinal> m_forge_version;
diff --git a/logic/LiteLoaderInstaller.cpp b/logic/LiteLoaderInstaller.cpp
index bb4b07ca..99cc5643 100644
--- a/logic/LiteLoaderInstaller.cpp
+++ b/logic/LiteLoaderInstaller.cpp
@@ -23,12 +23,17 @@
 #include "VersionFinal.h"
 #include "OneSixLibrary.h"
 #include "OneSixInstance.h"
+#include "MultiMC.h"
+#include "lists/LiteLoaderVersionList.h"
 
-LiteLoaderInstaller::LiteLoaderInstaller(LiteLoaderVersionPtr version)
-	: BaseInstaller(), m_version(version)
+LiteLoaderInstaller::LiteLoaderInstaller() : BaseInstaller()
 {
 }
 
+void LiteLoaderInstaller::prepare(LiteLoaderVersionPtr version)
+{
+	m_version = version;
+}
 bool LiteLoaderInstaller::add(OneSixInstance *to)
 {
 	if (!BaseInstaller::add(to))
@@ -84,3 +89,62 @@ bool LiteLoaderInstaller::add(OneSixInstance *to)
 
 	return true;
 }
+
+class LiteLoaderInstallTask : public Task
+{
+	Q_OBJECT
+public:
+	LiteLoaderInstallTask(LiteLoaderInstaller *installer, OneSixInstance *instance,
+						  BaseVersionPtr version, QObject *parent)
+		: Task(parent), m_installer(installer), m_instance(instance), m_version(version)
+	{
+	}
+
+protected:
+	void executeTask() override
+	{
+		LiteLoaderVersionPtr liteloaderVersion =
+			std::dynamic_pointer_cast<LiteLoaderVersion>(m_version);
+		if (!liteloaderVersion)
+		{
+			return;
+		}
+		m_installer->prepare(liteloaderVersion);
+		if (!m_installer->add(m_instance))
+		{
+			emitFailed(tr("For reasons unknown, the LiteLoader installation failed. Check your "
+						  "MultiMC log files for details."));
+		}
+		else
+		{
+			try
+			{
+				m_instance->reloadVersion();
+				emitSucceeded();
+			}
+			catch (MMCError &e)
+			{
+				emitFailed(e.cause());
+			}
+			catch (...)
+			{
+				emitFailed(
+					tr("Failed to load the version description file for reasons unknown."));
+			}
+		}
+	}
+
+private:
+	LiteLoaderInstaller *m_installer;
+	OneSixInstance *m_instance;
+	BaseVersionPtr m_version;
+};
+
+ProgressProvider *LiteLoaderInstaller::createInstallTask(OneSixInstance *instance,
+														 BaseVersionPtr version,
+														 QObject *parent)
+{
+	return new LiteLoaderInstallTask(this, instance, version, parent);
+}
+
+#include "LiteLoaderInstaller.moc"
diff --git a/logic/LiteLoaderInstaller.h b/logic/LiteLoaderInstaller.h
index 2e0de64a..3ab5acb2 100644
--- a/logic/LiteLoaderInstaller.h
+++ b/logic/LiteLoaderInstaller.h
@@ -25,10 +25,13 @@
 class LiteLoaderInstaller : public BaseInstaller
 {
 public:
-	LiteLoaderInstaller(LiteLoaderVersionPtr version);
+	LiteLoaderInstaller();
 
+	void prepare(LiteLoaderVersionPtr version);
 	bool add(OneSixInstance *to) override;
 
+	ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override;
+
 private:
 	virtual QString id() const override
 	{
-- 
cgit v1.2.3


From 42a85def60036a5788a9dd862d0c6f835b62337c Mon Sep 17 00:00:00 2001
From: Jan Dalheimer <jan@dalheimer.de>
Date: Fri, 14 Mar 2014 21:18:17 +0100
Subject: Get rid of one reloadInstanceVersion

---
 logic/VersionFinal.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'logic')

diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp
index 2901fcf9..d0e85c15 100644
--- a/logic/VersionFinal.cpp
+++ b/logic/VersionFinal.cpp
@@ -72,9 +72,13 @@ bool VersionFinal::canRemove(const int index) const
 }
 bool VersionFinal::remove(const int index)
 {
-	if (canRemove(index))
+	if (canRemove(index) && QFile::remove(versionFiles.at(index)->filename))
 	{
-		return QFile::remove(versionFiles.at(index)->filename);
+		beginResetModel();
+		versionFiles.removeAt(index);
+		reapply(true);
+		endResetModel();
+		return true;
 	}
 	return false;
 }
-- 
cgit v1.2.3