summaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/MainWindow.cpp161
-rw-r--r--gui/MainWindow.h26
-rw-r--r--gui/MainWindow.ui9
-rw-r--r--gui/dialogs/AccountListDialog.cpp112
-rw-r--r--gui/dialogs/AccountListDialog.h63
-rw-r--r--gui/dialogs/AccountListDialog.ui93
6 files changed, 354 insertions, 110 deletions
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index b8766d9a..6ae41f50 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -57,6 +57,7 @@
#include "gui/dialogs/IconPickerDialog.h"
#include "gui/dialogs/EditNotesDialog.h"
#include "gui/dialogs/CopyInstanceDialog.h"
+#include "gui/dialogs/AccountListDialog.h"
#include "gui/ConsoleWindow.h"
@@ -84,11 +85,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
ui->setupUi(this);
setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString()));
- // Set the selected instance to null
- m_selectedInstance = nullptr;
- // Set active instance to null.
- m_activeInst = nullptr;
-
// OSX magic.
setUnifiedTitleAndToolBarOnMac(true);
@@ -428,6 +424,12 @@ void MainWindow::on_actionSettings_triggered()
proxymodel->sort(0);
}
+void MainWindow::on_actionManageAccounts_triggered()
+{
+ AccountListDialog dialog(this);
+ dialog.exec();
+}
+
void MainWindow::on_actionReportBug_triggered()
{
openWebPage(QUrl("http://multimc.myjetbrains.com/youtrack/dashboard#newissue=yes"));
@@ -538,11 +540,7 @@ void MainWindow::instanceActivated(QModelIndex index)
NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this);
- bool autoLogin = inst->settings().get("AutoLogin").toBool();
- if (autoLogin)
- doAutoLogin();
- else
- doLogin();
+ doLogin();
}
void MainWindow::on_actionLaunchInstance_triggered()
@@ -554,106 +552,74 @@ void MainWindow::on_actionLaunchInstance_triggered()
}
}
-void MainWindow::doAutoLogin()
+void MainWindow::doLogin(const QString &errorMsg)
{
if (!m_selectedInstance)
return;
- Keyring *k = Keyring::instance();
- QStringList accounts = k->getStoredAccounts("minecraft");
-
- if (!accounts.isEmpty())
+ // Find an account to use.
+ std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
+ MojangAccountPtr account = accounts->activeAccount();
+ if (accounts->count() <= 0)
{
- QString username = accounts[0];
- QString password = k->getPassword("minecraft", username);
+ // Tell the user they need to log in at least one account in order to play.
+ auto reply = CustomMessageBox::selectable(this, tr("No Accounts"),
+ tr("In order to play Minecraft, you must have at least one Mojang or Minecraft account logged in to MultiMC."
+ "Would you like to open the account manager to add an account now?"),
+ QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
- if (!password.isEmpty())
- {
- QLOG_INFO() << "Automatically logging in with stored account: " << username;
- m_activeInst = m_selectedInstance;
- doLogin(username, password);
- }
- else
+ if (reply == QMessageBox::Yes)
{
- QLOG_ERROR() << "Auto login set for account, but no password was found: "
- << username;
- doLogin(tr("Auto login attempted, but no password is stored."));
+ // Open the account manager.
+ on_actionManageAccounts_triggered();
}
}
- else
+ else if (account.get() == nullptr)
{
- QLOG_ERROR() << "Auto login set but no accounts were stored.";
- doLogin(tr("Auto login attempted, but no accounts are stored."));
- }
-}
-
-void MainWindow::doLogin(QString username, QString password)
-{
- PasswordLogin uInfo{username, password};
-
- ProgressDialog *tDialog = new ProgressDialog(this);
- LoginTask *loginTask = new LoginTask(uInfo, tDialog);
- connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection);
- connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection);
-
- tDialog->exec(loginTask);
-}
-
-void MainWindow::doLogin(const QString &errorMsg)
-{
- if (!m_selectedInstance)
- return;
+ // Tell the user they need to log in at least one account in order to play.
+ auto reply = CustomMessageBox::selectable(this, tr("No Account Selected"),
+ tr("You don't have an account selected as an active account."
+ "Would you like to open the account manager to select one now?"),
+ QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
- LoginDialog *loginDlg = new LoginDialog(this, errorMsg);
- if (!m_selectedInstance->lastLaunch())
- loginDlg->forceOnline();
-
- loginDlg->exec();
- if (loginDlg->result() == QDialog::Accepted)
- {
- if (loginDlg->isOnline())
+ if (reply == QMessageBox::Yes)
{
- m_activeInst = m_selectedInstance;
- doLogin(loginDlg->getUsername(), loginDlg->getPassword());
- }
- else
- {
- QString user = loginDlg->getUsername();
- if (user.length() == 0)
- user = QString("Player");
- m_activeLogin = {user, QString("Offline"), user, QString()};
- m_activeInst = m_selectedInstance;
- launchInstance(m_activeInst, m_activeLogin);
+ // Open the account manager.
+ on_actionManageAccounts_triggered();
}
}
+ else
+ {
+ // We'll need to validate the access token to make sure the account is still logged in.
+ // TODO: Do that ^
+
+ prepareLaunch(m_selectedInstance, account);
+ }
}
-void MainWindow::onLoginComplete()
+void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account)
{
- if (!m_activeInst)
- return;
- LoginTask *task = (LoginTask *)QObject::sender();
- m_activeLogin = task->getResult();
-
- Task *updateTask = m_activeInst->doUpdate();
+ Task *updateTask = instance->doUpdate();
if (!updateTask)
{
- launchInstance(m_activeInst, m_activeLogin);
+ launchInstance(instance, account);
}
else
{
ProgressDialog tDialog(this);
- connect(updateTask, SIGNAL(succeeded()), SLOT(onGameUpdateComplete()));
+ connect(updateTask, &Task::succeeded, [this, instance, account] { launchInstance(instance, account); });
connect(updateTask, SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
tDialog.exec(updateTask);
delete updateTask;
}
- auto job = new NetJob("Player skin: " + m_activeLogin.player_name);
+ QString playerName = account->currentProfile()->name();
- auto meta = MMC->metacache()->resolveEntry("skins", m_activeLogin.player_name + ".png");
+ auto job = new NetJob("Player skin: " + playerName);
+
+ auto meta = MMC->metacache()->resolveEntry("skins", playerName + ".png");
auto action = CacheDownload::make(
- QUrl("http://skins.minecraft.net/MinecraftSkins/" + m_activeLogin.player_name + ".png"),
+ QUrl("http://skins.minecraft.net/MinecraftSkins/" + playerName + ".png"),
meta);
job->addNetAction(action);
meta->stale = true;
@@ -678,12 +644,12 @@ void MainWindow::onLoginComplete()
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
QJsonObject mappings = root.value("mappings").toObject();
- QJsonArray usernames = mappings.value(m_activeLogin.username).toArray();
+ QJsonArray usernames = mappings.value(account->username()).toArray();
- if (!usernames.contains(m_activeLogin.player_name))
+ if (!usernames.contains(playerName))
{
- usernames.prepend(m_activeLogin.player_name);
- mappings[m_activeLogin.username] = usernames;
+ usernames.prepend(playerName);
+ mappings[account->username()] = usernames;
root["mappings"] = mappings;
jsonDoc.setObject(root);
@@ -693,22 +659,12 @@ void MainWindow::onLoginComplete()
}
}
-void MainWindow::onGameUpdateComplete()
-{
- launchInstance(m_activeInst, m_activeLogin);
-}
-
-void MainWindow::onGameUpdateError(QString error)
-{
- CustomMessageBox::selectable(this, tr("Error updating instance"), error,
- QMessageBox::Warning)->show();
-}
-
-void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response)
+void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account)
{
Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL");
+ Q_ASSERT_X(account.get() != nullptr, "launchInstance", "account is NULL");
- proc = instance->prepareForLaunch(response);
+ proc = instance->prepareForLaunch(account);
if (!proc)
return;
@@ -717,10 +673,19 @@ void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response)
console = new ConsoleWindow(proc);
connect(console, SIGNAL(isClosing()), this, SLOT(instanceEnded()));
- proc->setLogin(response.username, response.session_id);
+ // I think this will work...
+ QString username = account->username();
+ QString session_id = account->accessToken();
+ proc->setLogin(username, session_id);
proc->launch();
}
+void MainWindow::onGameUpdateError(QString error)
+{
+ CustomMessageBox::selectable(this, tr("Error updating instance"), error,
+ QMessageBox::Warning)->show();
+}
+
void MainWindow::taskStart()
{
// Nothing to do here yet.
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index b1678f76..3b8d4668 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -22,6 +22,8 @@
#include "logic/net/LoginTask.h"
#include "logic/BaseInstance.h"
+#include "logic/auth/MojangAccount.h"
+
class QToolButton;
class LabeledToolButton;
class QLabel;
@@ -80,6 +82,8 @@ slots:
void on_actionSettings_triggered();
+ void on_actionManageAccounts_triggered();
+
void on_actionReportBug_triggered();
void on_actionNews_triggered();
@@ -103,12 +107,18 @@ slots:
void on_actionEditInstNotes_triggered();
void doLogin(const QString &errorMsg = "");
- void doLogin(QString username, QString password);
- void doAutoLogin();
- void onLoginComplete();
+ /*!
+ * Launches the given instance with the given account.
+ * This function assumes that the given account has a valid, usable access token.
+ */
+ void launchInstance(BaseInstance* instance, MojangAccountPtr account);
+
+ /*!
+ * Prepares the given instance for launch with the given account.
+ */
+ void prepareLaunch(BaseInstance* instance, MojangAccountPtr account);
- void onGameUpdateComplete();
void onGameUpdateError(QString error);
void taskStart();
@@ -136,8 +146,6 @@ slots:
void startTask(Task *task);
- void launchInstance(BaseInstance *inst, LoginResponse response);
-
protected:
bool eventFilter(QObject *obj, QEvent *ev);
void setCatBackground(bool enabled);
@@ -155,12 +163,6 @@ private:
BaseInstance *m_selectedInstance;
- // A pointer to the instance we are actively doing stuff with.
- // This is set when the user launches an instance and is used to refer to that
- // instance throughout the launching process.
- BaseInstance *m_activeInst;
- LoginResponse m_activeLogin;
-
Task *m_versionLoadTask;
QLabel *m_statusLeft;
diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui
index 6f70fc98..f76d4d4e 100644
--- a/gui/MainWindow.ui
+++ b/gui/MainWindow.ui
@@ -70,6 +70,7 @@
<addaction name="separator"/>
<addaction name="actionCheckUpdate"/>
<addaction name="actionSettings"/>
+ <addaction name="actionManageAccounts"/>
<addaction name="separator"/>
<addaction name="actionReportBug"/>
<addaction name="actionNews"/>
@@ -465,6 +466,14 @@
<string>Add a new instance.</string>
</property>
</action>
+ <action name="actionManageAccounts">
+ <property name="text">
+ <string>Manage Accounts</string>
+ </property>
+ <property name="toolTip">
+ <string>Manage your Mojang or Minecraft accounts.</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp
new file mode 100644
index 00000000..c685c164
--- /dev/null
+++ b/gui/dialogs/AccountListDialog.cpp
@@ -0,0 +1,112 @@
+/* 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 <QItemSelectionModel>
+
+#include <logger/QsLog.h>
+
+#include <logic/auth/AuthenticateTask.h>
+
+#include <gui/dialogs/LoginDialog.h>
+#include <gui/dialogs/ProgressDialog.h>
+
+#include <MultiMC.h>
+
+AccountListDialog::AccountListDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::AccountListDialog)
+{
+ ui->setupUi(this);
+
+ m_accounts = MMC->accounts();
+ // TODO: Make the "Active?" column show checkboxes or radio buttons.
+ ui->listView->setModel(m_accounts.get());
+}
+
+AccountListDialog::~AccountListDialog()
+{
+ delete ui;
+}
+
+
+void AccountListDialog::on_addAccountBtn_clicked()
+{
+ doLogin("Please log in to add your account.");
+}
+
+void AccountListDialog::on_rmAccountBtn_clicked()
+{
+ QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
+ if (selection.size() > 0)
+ {
+ QModelIndex selected = selection.first();
+ m_accounts->removeAccount(selected);
+ }
+}
+
+void AccountListDialog::on_editAccountBtn_clicked()
+{
+ // TODO
+}
+
+void AccountListDialog::on_setActiveBtn_clicked()
+{
+ QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
+ if (selection.size() > 0)
+ {
+ QModelIndex selected = selection.first();
+ MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
+ m_accounts->setActiveAccount(account->username());
+ }
+}
+
+void AccountListDialog::on_closeBtnBox_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..17a50bec
--- /dev/null
+++ b/gui/dialogs/AccountListDialog.h
@@ -0,0 +1,63 @@
+/* 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 <QDialog>
+
+#include <memory>
+
+#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();
+
+ void on_setActiveBtn_clicked();
+
+ // This will be sent when the "close" button is clicked.
+ void on_closeBtnBox_rejected();
+
+protected:
+ std::shared_ptr<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..2872b368
--- /dev/null
+++ b/gui/dialogs/AccountListDialog.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AccountListDialog</class>
+ <widget class="QDialog" name="AccountListDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="welcomeLabel">
+ <property name="text">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Welcome! If you're new here, you can click the &amp;quot;Add&amp;quot; button to add your Mojang or Minecraft account.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QTreeView" name="listView"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="manageAcctsBtnBox">
+ <item>
+ <widget class="QPushButton" name="addAccountBtn">
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="editAccountBtn">
+ <property name="text">
+ <string>&amp;Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="rmAccountBtn">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="buttonSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="setActiveBtn">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the currently selected account as the active account. The active account is the account that is used to log in (unless it is overridden in an instance-specific setting).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>&amp;Set Active</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="closeBtnBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>