From a9a0b65358b3799746fa9c8e1aa879e0b59ef526 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 18 Nov 2013 12:58:03 -0600 Subject: [PATCH] Implement loading accounts from list. --- MultiMC.cpp | 6 +++ MultiMC.h | 7 +++ gui/dialogs/AccountListDialog.cpp | 7 ++- gui/dialogs/AccountListDialog.h | 5 +- logic/auth/MojangAccount.h | 20 +++++-- logic/lists/MojangAccountList.cpp | 89 +++++++++++++++++++++++++++++++ logic/lists/MojangAccountList.h | 14 +++++ 7 files changed, 141 insertions(+), 7 deletions(-) diff --git a/MultiMC.cpp b/MultiMC.cpp index 1c70fb54b..ae1401a6a 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -10,6 +10,7 @@ #include "gui/MainWindow.h" #include "gui/dialogs/VersionSelectDialog.h" #include "logic/lists/InstanceList.h" +#include "logic/lists/MojangAccountList.h" #include "logic/lists/IconList.h" #include "logic/lists/LwjglVersionList.h" #include "logic/lists/MinecraftVersionList.h" @@ -146,6 +147,11 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) connect(InstDirSetting, SIGNAL(settingChanged(const Setting &, QVariant)), m_instances.get(), SLOT(on_InstFolderChanged(const Setting &, QVariant))); + // and accounts + m_accounts.reset(new MojangAccountList(this)); + QLOG_INFO() << "Loading accounts..."; + m_accounts->loadList(); + // init the http meta cache initHttpMetaCache(); diff --git a/MultiMC.h b/MultiMC.h index cd4a5f7de..dba923b1e 100644 --- a/MultiMC.h +++ b/MultiMC.h @@ -13,6 +13,7 @@ class LWJGLVersionList; class HttpMetaCache; class SettingsObject; class InstanceList; +class MojangAccountList; class IconList; class QNetworkAccessManager; class ForgeVersionList; @@ -57,6 +58,11 @@ public: return m_instances; } + std::shared_ptr accounts() + { + return m_accounts; + } + std::shared_ptr icons(); Status status() @@ -101,6 +107,7 @@ private: std::shared_ptr m_mmc_translator; std::shared_ptr m_settings; std::shared_ptr m_instances; + std::shared_ptr m_accounts; std::shared_ptr m_icons; std::shared_ptr m_qnam; std::shared_ptr m_metacache; diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp index 86d34de84..5a73cb185 100644 --- a/gui/dialogs/AccountListDialog.cpp +++ b/gui/dialogs/AccountListDialog.cpp @@ -23,13 +23,16 @@ #include #include +#include + AccountListDialog::AccountListDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AccountListDialog) { ui->setupUi(this); - ui->listView->setModel(&m_accounts); + m_accounts = MMC->accounts(); + ui->listView->setModel(m_accounts.get()); } AccountListDialog::~AccountListDialog() @@ -84,7 +87,7 @@ void AccountListDialog::onLoginComplete() { // Add the authenticated account to the accounts list. MojangAccountPtr account = m_authTask->getMojangAccount(); - m_accounts.addAccount(account); + m_accounts->addAccount(account); //ui->listView->update(); } diff --git a/gui/dialogs/AccountListDialog.h b/gui/dialogs/AccountListDialog.h index 442834efa..57c8b460b 100644 --- a/gui/dialogs/AccountListDialog.h +++ b/gui/dialogs/AccountListDialog.h @@ -17,6 +17,8 @@ #include +#include + #include "logic/lists/MojangAccountList.h" namespace Ui { @@ -44,8 +46,7 @@ slots: void on_closedBtnBox_rejected(); protected: - // Temporarily putting this here... - MojangAccountList m_accounts; + std::shared_ptr m_accounts; AuthenticateTask* m_authTask; diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index a38cb8f75..35261d65e 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -18,9 +18,16 @@ #include #include #include +#include #include +class MojangAccount; + +typedef std::shared_ptr MojangAccountPtr; +Q_DECLARE_METATYPE(MojangAccountPtr) + + /** * Class that represents a profile within someone's Mojang account. * @@ -71,6 +78,16 @@ public: */ MojangAccount(const MojangAccount& other, QObject* parent); + /** + * 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(); + /** * This MojangAccount's username. May be an email address if the account is migrated. @@ -130,6 +147,3 @@ protected: ProfileList m_profiles; // List of available profiles. }; -typedef std::shared_ptr MojangAccountPtr; -Q_DECLARE_METATYPE(MojangAccountPtr) - diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp index d309d63a3..40f0ea26c 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/lists/MojangAccountList.cpp @@ -14,8 +14,23 @@ */ #include "logic/lists/MojangAccountList.h" + +#include +#include +#include +#include +#include +#include +#include + +#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 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 ce16d70d6..37c928deb 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.