From a9a0b65358b3799746fa9c8e1aa879e0b59ef526 Mon Sep 17 00:00:00 2001
From: Andrew <forkk@forkk.net>
Date: Mon, 18 Nov 2013 12:58:03 -0600
Subject: Implement loading accounts from list.

---
 logic/lists/MojangAccountList.cpp | 89 +++++++++++++++++++++++++++++++++++++++
 logic/lists/MojangAccountList.h   | 14 ++++++
 2 files changed, 103 insertions(+)

(limited to 'logic/lists')

diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp
index d309d63a..40f0ea26 100644
--- a/logic/lists/MojangAccountList.cpp
+++ b/logic/lists/MojangAccountList.cpp
@@ -14,8 +14,23 @@
  */
 
 #include "logic/lists/MojangAccountList.h"
+
+#include <QIODevice>
+#include <QFile>
+#include <QTextStream>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonParseError>
+
+#include "logger/QsLog.h"
+
 #include "logic/auth/MojangAccount.h"
 
+#define DEFAULT_ACCOUNT_LIST_FILE "accounts.json"
+
+#define ACCOUNT_LIST_FORMAT_VERSION 1
+
 MojangAccountList::MojangAccountList(QObject *parent) : QAbstractListModel(parent)
 {
 }
@@ -144,3 +159,77 @@ void MojangAccountList::updateListData(QList<MojangAccountPtr> versions)
 	m_accounts = versions;
 	endResetModel();
 }
+
+bool MojangAccountList::loadList(const QString& filePath)
+{
+	QString path = filePath;
+	if (path.isEmpty()) path = DEFAULT_ACCOUNT_LIST_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::ReadOnly))
+	{
+		QLOG_ERROR() << "Failed to read the account list file (" << path << ").";
+		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)
+	{
+		QLOG_ERROR() << 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())
+	{
+		QLOG_ERROR() << "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 = "accountlist-old.json";
+		QLOG_WARN() << "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)
+		{
+			m_accounts.append(account);
+		}
+		else
+		{
+			QLOG_WARN() << "Failed to load an account.";
+		}
+	}
+	endResetModel();
+	
+	return true;
+}
+
diff --git a/logic/lists/MojangAccountList.h b/logic/lists/MojangAccountList.h
index ce16d70d..37c928de 100644
--- a/logic/lists/MojangAccountList.h
+++ b/logic/lists/MojangAccountList.h
@@ -80,6 +80,20 @@ public:
 	 */
 	virtual MojangAccountPtr findAccount(const QString &username);
 
+	/*!
+	 * \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="");
+
 signals:
 	/*!
 	 * Signal emitted to indicate that the account list has changed.
-- 
cgit v1.2.3