diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ff3aafe..343f6ac8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,8 @@ gui/dialogs/EditNotesDialog.h gui/dialogs/EditNotesDialog.cpp gui/dialogs/CustomMessageBox.h gui/dialogs/CustomMessageBox.cpp +gui/dialogs/AccountListDialog.h +gui/dialogs/AccountListDialog.cpp # GUI - widgets gui/widgets/InstanceDelegate.h @@ -323,6 +325,8 @@ logic/lists/ForgeVersionList.h logic/lists/ForgeVersionList.cpp logic/lists/JavaVersionList.h logic/lists/JavaVersionList.cpp +logic/lists/MojangAccountList.h +logic/lists/MojangAccountList.cpp # misc model/view logic/EnabledItemFilter.h @@ -363,6 +367,7 @@ gui/dialogs/IconPickerDialog.ui gui/dialogs/LegacyModEditDialog.ui gui/dialogs/OneSixModEditDialog.ui gui/dialogs/EditNotesDialog.ui +gui/dialogs/AccountListDialog.ui # Widgets/other gui/widgets/MCModInfoFrame.ui diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp new file mode 100644 index 00000000..86d34de8 --- /dev/null +++ b/gui/dialogs/AccountListDialog.cpp @@ -0,0 +1,90 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AccountListDialog.h" +#include "ui_AccountListDialog.h" + +#include + +#include + +#include +#include + +AccountListDialog::AccountListDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::AccountListDialog) +{ + ui->setupUi(this); + + ui->listView->setModel(&m_accounts); +} + +AccountListDialog::~AccountListDialog() +{ + delete ui; +} + + +void AccountListDialog::on_addAccountBtn_clicked() +{ + doLogin("Please log in to add your account."); +} + +void AccountListDialog::on_rmAccountBtn_clicked() +{ + // TODO +} + +void AccountListDialog::on_editAccountBtn_clicked() +{ + // TODO +} + +void AccountListDialog::on_closedBtnBox_rejected() +{ + close(); +} + +void AccountListDialog::doLogin(const QString& errMsg) +{ + // TODO: We can use the login dialog for this for now, but we'll have to make something better for it eventually. + LoginDialog loginDialog(this); + loginDialog.exec(); + + if (loginDialog.result() == QDialog::Accepted) + { + QString username(loginDialog.getUsername()); + QString password(loginDialog.getPassword()); + + MojangAccountPtr account = MojangAccountPtr(new MojangAccount(username)); + + ProgressDialog* progDialog = new ProgressDialog(this); + m_authTask = new AuthenticateTask(account, password, progDialog); + connect(m_authTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection); + connect(m_authTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection); + progDialog->exec(m_authTask); + //delete m_authTask; + } +} + +void AccountListDialog::onLoginComplete() +{ + // Add the authenticated account to the accounts list. + MojangAccountPtr account = m_authTask->getMojangAccount(); + m_accounts.addAccount(account); + //ui->listView->update(); +} + diff --git a/gui/dialogs/AccountListDialog.h b/gui/dialogs/AccountListDialog.h new file mode 100644 index 00000000..442834ef --- /dev/null +++ b/gui/dialogs/AccountListDialog.h @@ -0,0 +1,60 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "logic/lists/MojangAccountList.h" + +namespace Ui { +class AccountListDialog; +} + +class AuthenticateTask; + +class AccountListDialog : public QDialog +{ +Q_OBJECT +public: + explicit AccountListDialog(QWidget *parent = 0); + ~AccountListDialog(); + +public +slots: + void on_addAccountBtn_clicked(); + + void on_rmAccountBtn_clicked(); + + void on_editAccountBtn_clicked(); + + // This will be sent when the "close" button is clicked. + void on_closedBtnBox_rejected(); + +protected: + // Temporarily putting this here... + MojangAccountList m_accounts; + + AuthenticateTask* m_authTask; + +protected +slots: + void doLogin(const QString& errMsg=""); + void onLoginComplete(); + +private: + Ui::AccountListDialog *ui; +}; + diff --git a/gui/dialogs/AccountListDialog.ui b/gui/dialogs/AccountListDialog.ui new file mode 100644 index 00000000..034985a9 --- /dev/null +++ b/gui/dialogs/AccountListDialog.ui @@ -0,0 +1,83 @@ + + + AccountListDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + <html><head/><body><p>Welcome! If you're new here, you can click the &quot;Add&quot; button to add your Mojang or Minecraft account.</p></body></html> + + + true + + + + + + + + + + + + + + &Add + + + + + + + &Edit + + + + + + + &Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + QDialogButtonBox::Close + + + + + + + + diff --git a/logic/auth/AuthenticateTask.cpp b/logic/auth/AuthenticateTask.cpp index db4b0d92..a9c2c03f 100644 --- a/logic/auth/AuthenticateTask.cpp +++ b/logic/auth/AuthenticateTask.cpp @@ -26,7 +26,7 @@ #include "logger/QsLog.h" -AuthenticateTask::AuthenticateTask(MojangAccount* account, const QString& password, QObject* parent) : +AuthenticateTask::AuthenticateTask(MojangAccountPtr account, const QString& password, QObject* parent) : YggdrasilTask(account, parent), m_password(password) { } diff --git a/logic/auth/AuthenticateTask.h b/logic/auth/AuthenticateTask.h index 4169ad5f..54a6b79a 100644 --- a/logic/auth/AuthenticateTask.h +++ b/logic/auth/AuthenticateTask.h @@ -29,7 +29,7 @@ class AuthenticateTask : public YggdrasilTask { Q_OBJECT public: - AuthenticateTask(MojangAccount* account, const QString& password, QObject* parent=0); + AuthenticateTask(MojangAccountPtr account, const QString& password, QObject* parent=0); protected: virtual QJsonObject getRequestContent() const; diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index 8856047e..936046fb 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -41,6 +41,16 @@ MojangAccount::MojangAccount(const QString& username, const QString& clientToken m_currentProfile = -1; } +MojangAccount::MojangAccount(const MojangAccount& other, QObject* parent) +{ + m_username = other.username(); + m_clientToken = other.clientToken(); + m_accessToken = other.accessToken(); + + m_profiles = other.m_profiles; + m_currentProfile = other.m_currentProfile; +} + QString MojangAccount::username() const { diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index c5a26736..a38cb8f7 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -19,6 +19,7 @@ #include #include +#include /** * Class that represents a profile within someone's Mojang account. @@ -65,6 +66,11 @@ public: */ explicit MojangAccount(const QString& username, const QString& clientToken, const QString& accessToken, QObject* parent = 0); + /** + * Constructs a new MojangAccount matching the given account. + */ + MojangAccount(const MojangAccount& other, QObject* parent); + /** * This MojangAccount's username. May be an email address if the account is migrated. @@ -124,3 +130,6 @@ protected: ProfileList m_profiles; // List of available profiles. }; +typedef std::shared_ptr MojangAccountPtr; +Q_DECLARE_METATYPE(MojangAccountPtr) + diff --git a/logic/auth/YggdrasilTask.cpp b/logic/auth/YggdrasilTask.cpp index a023b07e..39dfb749 100644 --- a/logic/auth/YggdrasilTask.cpp +++ b/logic/auth/YggdrasilTask.cpp @@ -25,7 +25,7 @@ #include #include -YggdrasilTask::YggdrasilTask(MojangAccount* account, QObject* parent) : Task(parent) +YggdrasilTask::YggdrasilTask(MojangAccountPtr account, QObject* parent) : Task(parent) { m_error = nullptr; m_account = account; @@ -175,7 +175,7 @@ YggdrasilTask::Error *YggdrasilTask::getError() const return this->m_error; } -MojangAccount* YggdrasilTask::getMojangAccount() const +MojangAccountPtr YggdrasilTask::getMojangAccount() const { return this->m_account; } diff --git a/logic/auth/YggdrasilTask.h b/logic/auth/YggdrasilTask.h index 64632d44..6aebae16 100644 --- a/logic/auth/YggdrasilTask.h +++ b/logic/auth/YggdrasilTask.h @@ -20,8 +20,7 @@ #include #include - -class MojangAccount; +#include "logic/auth/MojangAccount.h" class QNetworkReply; @@ -33,7 +32,7 @@ class YggdrasilTask : public Task { Q_OBJECT public: - explicit YggdrasilTask(MojangAccount* account, QObject* parent=0); + explicit YggdrasilTask(MojangAccountPtr account, QObject* parent=0); ~YggdrasilTask(); /** @@ -61,7 +60,7 @@ public: /** * Gets the Mojang account that this task is operating on. */ - virtual MojangAccount* getMojangAccount() const; + virtual MojangAccountPtr getMojangAccount() const; /** * Returns a pointer to a YggdrasilTask::Error object if an error has occurred. @@ -117,7 +116,7 @@ protected: */ virtual QString getStateMessage(const State state) const; - MojangAccount* m_account; + MojangAccountPtr m_account; QNetworkReply* m_netReply; diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp new file mode 100644 index 00000000..d309d63a --- /dev/null +++ b/logic/lists/MojangAccountList.cpp @@ -0,0 +1,146 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "logic/lists/MojangAccountList.h" +#include "logic/auth/MojangAccount.h" + +MojangAccountList::MojangAccountList(QObject *parent) : QAbstractListModel(parent) +{ +} + +MojangAccountPtr MojangAccountList::findAccount(const QString &username) +{ + for (int i = 0; i < count(); i++) + { + MojangAccountPtr account = at(i); + if (account->username() == username) + return account; + } + return MojangAccountPtr(); +} + + +const MojangAccountPtr MojangAccountList::at(int i) const +{ + return MojangAccountPtr(m_accounts.at(i)); +} + +void MojangAccountList::addAccount(const MojangAccountPtr account) +{ + beginResetModel(); + m_accounts.append(account); + endResetModel(); +} + +void MojangAccountList::removeAccount(const QString& username) +{ + beginResetModel(); + for (auto account : m_accounts) + { + if (account->username() == username) + { + m_accounts.removeOne(account); + return; + } + } + endResetModel(); +} + + +int MojangAccountList::count() const +{ + 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); + + default: + return QVariant(); + } +} + +QVariant MojangAccountList::headerData(int section, Qt::Orientation orientation, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + switch (section) + { + case NameColumn: + return "Name"; + + default: + return QVariant(); + } + + case Qt::ToolTipRole: + switch (section) + { + case NameColumn: + return "The name of the version."; + + default: + return QVariant(); + } + + default: + return QVariant(); + } +} + +int MojangAccountList::rowCount(const QModelIndex &parent) const +{ + // Return count + return count(); +} + +int MojangAccountList::columnCount(const QModelIndex &parent) const +{ + return 1; +} + +void MojangAccountList::updateListData(QList versions) +{ + beginResetModel(); + m_accounts = versions; + endResetModel(); +} diff --git a/logic/lists/MojangAccountList.h b/logic/lists/MojangAccountList.h new file mode 100644 index 00000000..ce16d70d --- /dev/null +++ b/logic/lists/MojangAccountList.h @@ -0,0 +1,109 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#include "logic/auth/MojangAccount.h" + + +/*! + * \brief List of available Mojang accounts. + * This should be loaded in the background by MultiMC on startup. + * + * This class also inherits from QAbstractListModel. Methods from that + * class determine how this list shows up in a list view. Said methods + * all have a default implementation, but they can be overridden by subclasses to + * change the behavior of the list. + */ +class MojangAccountList : public QAbstractListModel +{ + Q_OBJECT +public: + enum ModelRoles + { + PointerRole = 0x34B1CB48 + }; + + enum VListColumns + { + // TODO: Add icon column. + // First column - Name + NameColumn = 0, + }; + + 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; + + /*! + * 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); + + /*! + * \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); + +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(); + +protected: + QList m_accounts; + +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 versions); +}; +