diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index e817d50d..f8904267 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "osutils.h" #include "userutils.h" @@ -172,35 +173,50 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); ui->mainToolBar->addWidget(spacer); - actionManageAccounts = new QToolButton(this); - actionManageAccounts->setToolTip(tr("Manage your Mojang or Minecraft accounts.")); - actionManageAccounts->setObjectName("actionManageAccounts"); - actionManageAccounts->setText(tr("Manage accounts")); - actionManageAccounts->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - actionManageAccounts->setLayoutDirection(Qt::RightToLeft); + accountMenu = new QMenu(this); + manageAccountsAction = new QAction(tr("Manage accounts"), this); + manageAccountsAction->setCheckable(false); + connect(manageAccountsAction, SIGNAL(triggered(bool)), this, SLOT(on_actionManageAccounts_triggered())); - MojangAccountPtr account = MMC->accounts()->activeAccount(); - if(account != nullptr) + repopulateAccountsMenu(); + + accountMenuButton = new QToolButton(this); + accountMenuButton->setText(tr("Accounts")); + accountMenuButton->setMenu(accountMenu); + accountMenuButton->setPopupMode(QToolButton::InstantPopup); + accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + accountMenuButton->setLayoutDirection(Qt::RightToLeft); + + QWidgetAction *accountMenuButtonAction = new QWidgetAction(this); + accountMenuButtonAction->setDefaultWidget(accountMenuButton); + + ui->mainToolBar->addAction(accountMenuButtonAction); + + std::shared_ptr accounts = MMC->accounts(); + + // TODO: Nicer way to iterate? + for(int i = 0; i < accounts->count(); i++) { - auto job = new NetJob("Startup player skins: " + account->username()); - - for(AccountProfile profile : account->profiles()) + MojangAccountPtr account = accounts->at(i); + if(account != nullptr) { - auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png"); - auto action = CacheDownload::make( - QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"), - meta); - job->addNetAction(action); - meta->stale = true; + auto job = new NetJob("Startup player skins: " + account->username()); + + for(AccountProfile profile : account->profiles()) + { + auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png"); + auto action = CacheDownload::make( + QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"), + meta); + job->addNetAction(action); + meta->stale = true; + } + + connect(job, SIGNAL(succeeded()), SLOT(activeAccountChanged())); + job->start(); } - - connect(job, SIGNAL(succeeded()), SLOT(activeAccountChanged())); - job->start(); } - connect(actionManageAccounts, SIGNAL(clicked()), this, SLOT(on_actionManageAccounts_triggered())); - ui->mainToolBar->addWidget(actionManageAccounts); - // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. { @@ -233,18 +249,113 @@ MainWindow::~MainWindow() delete assets_downloader; } + +void MainWindow::repopulateAccountsMenu() +{ + accountMenu->clear(); + + std::shared_ptr accounts = MMC->accounts(); + MojangAccountPtr active_account = accounts->activeAccount(); + + QString active_username = ""; + if(active_account != nullptr) + { + active_username = accounts->activeAccount()->username(); + } + + if(accounts->count() <= 0) + { + QAction *action = new QAction(tr("No accounts added!"), this); + action->setEnabled(false); + accountMenu->addAction(action); + + accountMenu->addSeparator(); + } + else + { + // TODO: Nicer way to iterate? + for(int i = 0; i < accounts->count(); i++) + { + MojangAccountPtr account = accounts->at(i); + + // Styling hack + QAction *section = new QAction(account->username(), this); + section->setEnabled(false); + accountMenu->addAction(section); + + for(AccountProfile profile : account->profiles()) + { + QAction *action = new QAction(profile.name(), this); + action->setData(account->username()); + action->setCheckable(true); + if(active_username == account->username()) + { + action->setChecked(true); + } + + action->setIcon(SkinUtils::getFaceFromCache(profile.name())); + accountMenu->addAction(action); + connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount())); + } + + accountMenu->addSeparator(); + } + } + + QAction *action = new QAction(tr("No default"), this); + action->setCheckable(true); + action->setData(""); + if(active_username.isEmpty()) + { + action->setChecked(true); + } + + accountMenu->addAction(action); + connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount())); + + accountMenu->addSeparator(); + accountMenu->addAction(manageAccountsAction); +} + +/* + * Assumes the sender is a QAction + */ +void MainWindow::changeActiveAccount() +{ + QAction* sAction = (QAction*) sender(); + // Profile's associated Mojang username + // Will need to change when profiles are properly implemented + if(sAction->data().type() != QVariant::Type::String) return; + + QVariant data = sAction->data(); + QString id = ""; + if(!data.isNull()) + { + id = data.toString(); + } + + MMC->accounts()->setActiveAccount(id); + + activeAccountChanged(); +} + void MainWindow::activeAccountChanged() { + repopulateAccountsMenu(); + MojangAccountPtr account = MMC->accounts()->activeAccount(); - if(account != nullptr) + if(account != nullptr && account->username() != "") { const AccountProfile *profile = account->currentProfile(); if(profile != nullptr) { - actionManageAccounts->setIcon(SkinUtils::getFaceFromCache(profile->name())); + accountMenuButton->setIcon(SkinUtils::getFaceFromCache(profile->name())); + return; } } + + accountMenuButton->setIcon(QIcon()); } bool MainWindow::eventFilter(QObject *obj, QEvent *ev) diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 4e20d7cb..4191e590 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -148,6 +148,10 @@ slots: void activeAccountChanged(); + void changeActiveAccount(); + + void repopulateAccountsMenu(); + protected: bool eventFilter(QObject *obj, QEvent *ev); void setCatBackground(bool enabled); @@ -170,5 +174,7 @@ private: QLabel *m_statusLeft; QLabel *m_statusRight; - QToolButton *actionManageAccounts; + QMenu *accountMenu; + QToolButton *accountMenuButton; + QAction *manageAccountsAction; }; diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp index 5feed13d..29f3838d 100644 --- a/gui/dialogs/AccountListDialog.cpp +++ b/gui/dialogs/AccountListDialog.cpp @@ -92,6 +92,8 @@ void AccountListDialog::on_setDefaultBtn_clicked() void AccountListDialog::on_noDefaultBtn_clicked() { m_accounts->setActiveAccount(""); + + emit activeAccountChanged(); } void AccountListDialog::on_closeBtnBox_rejected() @@ -138,6 +140,9 @@ void AccountListDialog::onLoginComplete() // Add the authenticated account to the accounts list. MojangAccountPtr account = m_authTask->getMojangAccount(); m_accounts->addAccount(account); + + emit activeAccountChanged(); + //ui->listView->update(); // Grab associated player skins diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp index a30ef4ab..c6dce836 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/lists/MojangAccountList.cpp @@ -100,8 +100,10 @@ void MojangAccountList::setActiveAccount(const QString& username) else { for (MojangAccountPtr account : m_accounts) + { if (account->username() == username) m_activeAccount = username; + } } endResetModel(); onListChanged(); @@ -113,7 +115,9 @@ void MojangAccountList::onListChanged() if (m_autosave) // TODO: Alert the user if this fails. saveList(); - emit listChanged(); + + // TODO: stop this getting called from setActiveAccount + //emit listChanged(); }