aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew <forkk@forkk.net>2013-12-15 15:01:34 -0600
committerAndrew <forkk@forkk.net>2013-12-15 15:01:34 -0600
commit9d8006b597aead06f1d51dacbdb346ebab3d5e8f (patch)
tree1f99ca1da321be32930198e3d72b2fc9d3bf53de
parent0ee8f90d40f5b3ddb177286c9066a4e59748c681 (diff)
parentb0e8037feb5b9d48defe6b8263d068f87bdb141c (diff)
downloadPrismLauncher-9d8006b597aead06f1d51dacbdb346ebab3d5e8f.tar.gz
PrismLauncher-9d8006b597aead06f1d51dacbdb346ebab3d5e8f.tar.bz2
PrismLauncher-9d8006b597aead06f1d51dacbdb346ebab3d5e8f.zip
Merge branch 'develop' of github.com:MultiMC/MultiMC5 into feature_news
Conflicts: CMakeLists.txt
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt27
-rw-r--r--MultiMC.cpp39
-rw-r--r--MultiMC.h2
-rw-r--r--depends/settings/CMakeLists.txt8
-rw-r--r--depends/util/CMakeLists.txt8
-rw-r--r--gui/MainWindow.cpp165
-rw-r--r--gui/dialogs/AboutDialog.ui276
-rw-r--r--gui/dialogs/AccountListDialog.cpp6
-rw-r--r--gui/dialogs/AccountListDialog.ui2
-rw-r--r--gui/dialogs/EditAccountDialog.ui4
-rw-r--r--gui/dialogs/InstanceSettings.ui4
-rw-r--r--gui/dialogs/LegacyModEditDialog.ui2
-rw-r--r--gui/dialogs/LwjglSelectDialog.ui2
-rw-r--r--gui/dialogs/OneSixModEditDialog.ui2
-rw-r--r--gui/dialogs/VersionSelectDialog.ui2
-rw-r--r--logic/BaseInstance.h2
-rw-r--r--logic/OneSixInstance.cpp13
-rw-r--r--logic/OneSixUpdate.cpp10
-rw-r--r--logic/auth/MojangAccount.cpp4
-rw-r--r--logic/auth/MojangAccount.h5
-rw-r--r--logic/auth/MojangAccountList.cpp64
-rw-r--r--logic/auth/MojangAccountList.h7
-rw-r--r--logic/auth/flows/AuthenticateTask.cpp6
-rw-r--r--logic/auth/flows/RefreshTask.cpp9
-rw-r--r--logic/lists/InstanceList.cpp21
-rw-r--r--logic/lists/InstanceList.h8
-rw-r--r--logic/net/ByteArrayDownload.cpp8
-rw-r--r--logic/net/CacheDownload.cpp14
-rw-r--r--logic/net/ForgeMirrors.cpp8
-rw-r--r--logic/net/ForgeXzDownload.cpp18
-rw-r--r--logic/net/MD5EtagDownload.cpp16
-rw-r--r--logic/net/NetAction.h23
-rw-r--r--logic/net/NetJob.h12
-rw-r--r--logic/net/PasteUpload.cpp2
-rw-r--r--logic/net/S3ListBucket.cpp175
-rw-r--r--logic/net/S3ListBucket.h57
-rw-r--r--main.cpp38
-rw-r--r--mmc_updater/src/tests/CMakeLists.txt2
-rw-r--r--tests/CMakeLists.txt82
-rw-r--r--tests/TestUtil.h31
-rw-r--r--tests/data/CMakeLists.txt4
-rwxr-xr-xtests/data/tst_userutils-test_createShortcut-unix6
-rw-r--r--tests/tst_pathutils.cpp76
-rw-r--r--tests/tst_userutils.cpp66
45 files changed, 796 insertions, 541 deletions
diff --git a/.gitignore b/.gitignore
index 597bbbec..a58d38f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ resources/CMakeFiles
resources/MultiMCLauncher.jar
*~
*.swp
+html/
# Ctags File
tags
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7880d0d1..f2cfc3ae 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,7 @@ IF(WIN32)
ENDIF()
project(MultiMC)
+enable_testing()
######## Set CMake options ########
SET(CMAKE_AUTOMOC ON)
@@ -304,8 +305,6 @@ logic/net/NetJob.h
logic/net/NetJob.cpp
logic/net/HttpMetaCache.h
logic/net/HttpMetaCache.cpp
-logic/net/S3ListBucket.h
-logic/net/S3ListBucket.cpp
logic/net/PasteUpload.h
logic/net/PasteUpload.cpp
logic/net/URLConstants.h
@@ -472,6 +471,15 @@ IF(WIN32)
)
ENDIF(WIN32)
+OPTION(MultiMC_CODE_COVERAGE "Compiles for code coverage" OFF)
+IF(MultiMC_CODE_COVERAGE)
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 --coverage")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0 --coverage")
+ENDIF(MultiMC_CODE_COVERAGE)
+
# Tell CMake that MultiMCLauncher.jar is generated.
SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/launcher/MultiMCLauncher.jar GENERATED)
SET_SOURCE_FILES_PROPERTIES(${PROJECT_BINARY_DIR}/depends/javacheck/JavaCheck.jar GENERATED)
@@ -482,14 +490,18 @@ CONFIGURE_FILE(generated.qrc.in generated.qrc)
QT5_ADD_RESOURCES(GENERATED_QRC ${CMAKE_CURRENT_BINARY_DIR}/generated.qrc)
QT5_ADD_RESOURCES(GRAPHICS_QRC graphics.qrc)
+# Add common library
+ADD_LIBRARY(MultiMC_common STATIC ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GENERATED_QRC} ${GRAPHICS_QRC})
+
# Add executable
-ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32
- ${MULTIMC_SOURCES} ${MULTIMC_UI} ${GRAPHICS_QRC} ${GENERATED_QRC} ${MULTIMC_RCS})
+ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 main.cpp ${MULTIMC_RCS})
# Link
-TARGET_LINK_LIBRARIES(MultiMC xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
+TARGET_LINK_LIBRARIES(MultiMC MultiMC_common)
+TARGET_LINK_LIBRARIES(MultiMC_common xz-embedded unpack200 quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
QT5_USE_MODULES(MultiMC Core Widgets Network Xml WebKit ${MultiMC_QT_ADDITIONAL_MODULES})
-ADD_DEPENDENCIES(MultiMC MultiMCLauncher JavaCheck)
+QT5_USE_MODULES(MultiMC_common Core Widgets Network Xml WebKit ${MultiMC_QT_ADDITIONAL_MODULES})
+ADD_DEPENDENCIES(MultiMC_common MultiMCLauncher JavaCheck)
################################ INSTALLATION AND PACKAGING ################################
@@ -648,3 +660,6 @@ ENDIF()
add_custom_target (translations DEPENDS ${QM_FILES})
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/translations)
+
+# Tests
+add_subdirectory(tests)
diff --git a/MultiMC.cpp b/MultiMC.cpp
index 52bf4cb9..12c37d2a 100644
--- a/MultiMC.cpp
+++ b/MultiMC.cpp
@@ -9,7 +9,6 @@
#include <QMessageBox>
#include <QStringList>
-#include "gui/MainWindow.h"
#include "gui/dialogs/VersionSelectDialog.h"
#include "logic/lists/InstanceList.h"
#include "logic/auth/MojangAccountList.h"
@@ -37,7 +36,7 @@
#include "config.h"
using namespace Util::Commandline;
-MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv),
+MultiMC::MultiMC(int &argc, char **argv, const QString &root) : QApplication(argc, argv),
m_version{VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_CHANNEL, VERSION_BUILD_TYPE}
{
setOrganizationName("MultiMC");
@@ -138,7 +137,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv),
}
// change directory
- QDir::setCurrent(args["dir"].toString());
+ QDir::setCurrent(args["dir"].toString().isEmpty() ?
+ (root.isEmpty() ? QDir::currentPath() : QDir::current().absoluteFilePath(root))
+ : args["dir"].toString());
// init the logger
initLogger();
@@ -480,37 +481,5 @@ QString MultiMC::getExitUpdatePath() const
return m_updateOnExitPath;
}
-int main_gui(MultiMC &app)
-{
- // show main window
- MainWindow mainWin;
- mainWin.restoreState(QByteArray::fromBase64(MMC->settings()->get("MainWindowState").toByteArray()));
- mainWin.restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("MainWindowGeometry").toByteArray()));
- mainWin.show();
- mainWin.checkSetDefaultJava();
- auto exitCode = app.exec();
-
- // Update if necessary.
- if (!app.getExitUpdatePath().isEmpty())
- app.installUpdates(app.getExitUpdatePath(), false);
-
- return exitCode;
-}
-
-int main(int argc, char *argv[])
-{
- // initialize Qt
- MultiMC app(argc, argv);
-
- switch (app.status())
- {
- case MultiMC::Initialized:
- return main_gui(app);
- case MultiMC::Failed:
- return 1;
- case MultiMC::Succeeded:
- return 0;
- }
-}
#include "MultiMC.moc"
diff --git a/MultiMC.h b/MultiMC.h
index fe6e0e76..775189b1 100644
--- a/MultiMC.h
+++ b/MultiMC.h
@@ -46,7 +46,7 @@ public:
};
public:
- MultiMC(int &argc, char **argv);
+ MultiMC(int &argc, char **argv, const QString &root = QString());
virtual ~MultiMC();
std::shared_ptr<SettingsObject> settings()
diff --git a/depends/settings/CMakeLists.txt b/depends/settings/CMakeLists.txt
index 3de1d792..154697f6 100644
--- a/depends/settings/CMakeLists.txt
+++ b/depends/settings/CMakeLists.txt
@@ -51,6 +51,14 @@ add_definitions(-DLIBSETTINGS_LIBRARY)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+IF(MultiMC_CODE_COVERAGE)
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 --coverage")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0 --coverage")
+ENDIF(MultiMC_CODE_COVERAGE)
+
add_library(libSettings STATIC ${LIBSETTINGS_SOURCES} ${LIBSETTINGS_HEADERS} ${LIBSETTINGS_HEADERS_PRIVATE})
qt5_use_modules(libSettings Core)
target_link_libraries(libSettings)
diff --git a/depends/util/CMakeLists.txt b/depends/util/CMakeLists.txt
index 5c87c644..db7d70e6 100644
--- a/depends/util/CMakeLists.txt
+++ b/depends/util/CMakeLists.txt
@@ -47,6 +47,14 @@ add_definitions(-DLIBUTIL_LIBRARY)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+IF(MultiMC_CODE_COVERAGE)
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage")
+ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 --coverage")
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -O0 --coverage")
+ENDIF(MultiMC_CODE_COVERAGE)
+
add_library(libUtil STATIC ${LIBUTIL_SOURCES})
# qt5_use_modules(libUtil Core Network)
qt5_use_modules(libUtil Core)
diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp
index 748728d6..3f086b36 100644
--- a/gui/MainWindow.cpp
+++ b/gui/MainWindow.cpp
@@ -20,7 +20,6 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"
-#include "keyring.h"
#include <QMenu>
#include <QMessageBox>
@@ -179,14 +178,15 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
statusBar()->addPermanentWidget(m_statusRight, 0);
// Add "manage accounts" button, right align
- QWidget* spacer = new QWidget();
+ QWidget *spacer = new QWidget();
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->mainToolBar->addWidget(spacer);
accountMenu = new QMenu(this);
manageAccountsAction = new QAction(tr("Manage Accounts"), this);
manageAccountsAction->setCheckable(false);
- connect(manageAccountsAction, SIGNAL(triggered(bool)), this, SLOT(on_actionManageAccounts_triggered()));
+ connect(manageAccountsAction, SIGNAL(triggered(bool)), this,
+ SLOT(on_actionManageAccounts_triggered()));
repopulateAccountsMenu();
@@ -195,7 +195,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
accountMenuButton->setMenu(accountMenu);
accountMenuButton->setPopupMode(QToolButton::InstantPopup);
accountMenuButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- accountMenuButton->setIcon(QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio));
+ accountMenuButton->setIcon(
+ QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio));
QWidgetAction *accountMenuButtonAction = new QWidgetAction(this);
accountMenuButtonAction->setDefaultWidget(accountMenuButton);
@@ -203,26 +204,28 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
ui->mainToolBar->addAction(accountMenuButtonAction);
// Update the menu when the active account changes.
- // Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit. Template hell sucks...
- connect(MMC->accounts().get(), &MojangAccountList::activeAccountChanged, [this] { activeAccountChanged(); });
- connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this] { repopulateAccountsMenu(); });
+ // Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit.
+ // Template hell sucks...
+ connect(MMC->accounts().get(), &MojangAccountList::activeAccountChanged, [this]
+ { activeAccountChanged(); });
+ connect(MMC->accounts().get(), &MojangAccountList::listChanged, [this]
+ { repopulateAccountsMenu(); });
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
// TODO: Nicer way to iterate?
- for(int i = 0; i < accounts->count(); i++)
+ for (int i = 0; i < accounts->count(); i++)
{
MojangAccountPtr account = accounts->at(i);
- if(account != nullptr)
+ if (account != nullptr)
{
auto job = new NetJob("Startup player skins: " + account->username());
- for(AccountProfile profile : account->profiles())
+ for (AccountProfile profile : account->profiles())
{
auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png");
auto action = CacheDownload::make(
- QUrl("http://" + URLConstants::SKINS_BASE + profile.name + ".png"),
- meta);
+ QUrl("http://" + URLConstants::SKINS_BASE + profile.name + ".png"), meta);
job->addNetAction(action);
meta->stale = true;
}
@@ -249,9 +252,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
// set up the updater object.
auto updater = MMC->updateChecker();
- QObject::connect(updater.get(), &UpdateChecker::updateAvailable, this, &MainWindow::updateAvailable);
+ QObject::connect(updater.get(), &UpdateChecker::updateAvailable, this,
+ &MainWindow::updateAvailable);
// if automatic update checks are allowed, start one.
- if(MMC->settings()->get("AutoUpdate").toBool())
+ if (MMC->settings()->get("AutoUpdate").toBool())
on_actionCheckUpdate_triggered();
}
@@ -325,7 +329,7 @@ void MainWindow::repopulateAccountsMenu()
QAction *action = new QAction(profile.name, this);
action->setData(account->username());
action->setCheckable(true);
- if(active_username == account->username())
+ if (active_username == account->username())
{
action->setChecked(true);
}
@@ -343,7 +347,7 @@ void MainWindow::repopulateAccountsMenu()
action->setCheckable(true);
action->setIcon(QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio));
action->setData("");
- if(active_username.isEmpty())
+ if (active_username.isEmpty())
{
action->setChecked(true);
}
@@ -360,10 +364,11 @@ void MainWindow::repopulateAccountsMenu()
*/
void MainWindow::changeActiveAccount()
{
- QAction* sAction = (QAction*) sender();
+ 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;
+ if (sAction->data().type() != QVariant::Type::String)
+ return;
QVariant data = sAction->data();
QString id = "";
@@ -394,7 +399,8 @@ void MainWindow::activeAccountChanged()
}
// Set the icon to the "no account" icon.
- accountMenuButton->setIcon(QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio));
+ accountMenuButton->setIcon(
+ QPixmap(":/icons/toolbar/noaccount").scaled(48, 48, Qt::KeepAspectRatio));
}
bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
@@ -430,26 +436,28 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
void MainWindow::updateAvailable(QString repo, QString versionName, int versionId)
{
UpdateDialog dlg;
- UpdateAction action = (UpdateAction) dlg.exec();
- switch(action)
+ UpdateAction action = (UpdateAction)dlg.exec();
+ switch (action)
{
- case UPDATE_LATER:
- QLOG_INFO() << "Update will be installed later.";
- break;
- case UPDATE_NOW:
- downloadUpdates(repo, versionId);
- break;
- case UPDATE_ONEXIT:
- downloadUpdates(repo, versionId, true);
- break;
+ case UPDATE_LATER:
+ QLOG_INFO() << "Update will be installed later.";
+ break;
+ case UPDATE_NOW:
+ downloadUpdates(repo, versionId);
+ break;
+ case UPDATE_ONEXIT:
+ downloadUpdates(repo, versionId, true);
+ break;
}
}
void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit)
{
QLOG_INFO() << "Downloading updates.";
- // TODO: If the user chooses to update on exit, we should download updates in the background.
- // Doing so is a bit complicated, because we'd have to make sure it finished downloading before actually exiting MultiMC.
+ // TODO: If the user chooses to update on exit, we should download updates in the
+ // background.
+ // Doing so is a bit complicated, because we'd have to make sure it finished downloading
+ // before actually exiting MultiMC.
ProgressDialog updateDlg(this);
DownloadUpdateTask updateTask(repo, versionId, &updateDlg);
// If the task succeeds, install the updates.
@@ -525,36 +533,44 @@ void MainWindow::on_actionAddInstance_triggered()
{
errorMsg += "An instance with the given directory name already exists.";
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
- break;
+ return;
}
case InstanceFactory::CantCreateDir:
{
errorMsg += "Failed to create the instance directory.";
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
- break;
+ return;
}
default:
{
errorMsg += QString("Unknown instance loader error %1").arg(error);
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
- break;
+ return;
}
}
- std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
- MojangAccountPtr account = accounts->activeAccount();
- if(account.get() != nullptr && account->accountStatus() != NotVerified)
+ if (MMC->accounts()->anyAccountIsValid())
{
ProgressDialog loadDialog(this);
auto update = newInstance->doUpdate(false);
- connect(update.get(), &Task::failed , [this](QString reason) {
+ connect(update.get(), &Task::failed, [this](QString reason)
+ {
QString error = QString("Instance load failed: %1").arg(reason);
- CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)->show();
+ CustomMessageBox::selectable(this, tr("Error"), error, QMessageBox::Warning)
+ ->show();
});
loadDialog.exec(update.get());
}
+ else
+ {
+ CustomMessageBox::selectable(
+ this, tr("Error"),
+ tr("MultiMC cannot download Minecraft or update instances unless you have at least "
+ "one account added.\nPlease add your Mojang or Minecraft account."),
+ QMessageBox::Warning)->show();
+ }
}
void MainWindow::on_actionCopyInstance_triggered()
@@ -629,8 +645,14 @@ void MainWindow::on_actionChangeInstGroup_triggered()
bool ok = false;
QString name(m_selectedInstance->group());
- name = QInputDialog::getText(this, tr("Group name"), tr("Enter a new group name."),
- QLineEdit::Normal, name, &ok);
+ auto groups = MMC->instances()->getGroups();
+ groups.insert(0, "");
+ groups.sort(Qt::CaseInsensitive);
+ int foo = groups.indexOf(name);
+
+ name = QInputDialog::getItem(this, tr("Group name"), tr("Enter a new group name."), groups,
+ foo, true, &ok);
+ name = name.simplified();
if (ok)
m_selectedInstance->setGroupPost(name);
}
@@ -814,9 +836,11 @@ void MainWindow::doLaunch()
if (accounts->count() <= 0)
{
// 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?"),
+ 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 (reply == QMessageBox::Yes)
@@ -829,7 +853,7 @@ void MainWindow::doLaunch()
{
// If no default account is set, ask the user which one to use.
AccountSelectDialog selectDialog(tr("Which account would you like to use?"),
- AccountSelectDialog::GlobalDefaultCheckbox, this);
+ AccountSelectDialog::GlobalDefaultCheckbox, this);
selectDialog.exec();
@@ -846,7 +870,7 @@ void MainWindow::doLaunch()
return;
// do the login. if the account has an access token, try to refresh it first.
- if(account->accountStatus() != NotVerified)
+ if (account->accountStatus() != NotVerified)
{
// We'll need to validate the access token to make sure the account is still logged in.
ProgressDialog progDialog(this);
@@ -855,7 +879,7 @@ void MainWindow::doLaunch()
progDialog.exec(task.get());
auto status = account->accountStatus();
- if(status != NotVerified)
+ if (status != NotVerified)
{
updateInstance(m_selectedInstance, account);
}
@@ -863,20 +887,22 @@ void MainWindow::doLaunch()
account->downgrade();
return;
}
- if (loginWithPassword(account, tr("Your account is currently not logged in. Please enter your password to log in again.")))
+ if (loginWithPassword(account, tr("Your account is currently not logged in. Please enter "
+ "your password to log in again.")))
updateInstance(m_selectedInstance, account);
}
-bool MainWindow::loginWithPassword(MojangAccountPtr account, const QString& errorMsg)
+bool MainWindow::loginWithPassword(MojangAccountPtr account, const QString &errorMsg)
{
EditAccountDialog passDialog(errorMsg, this, EditAccountDialog::PasswordField);
if (passDialog.exec() == QDialog::Accepted)
{
- // To refresh the token, we just create an authenticate task with the given account and the user's password.
+ // To refresh the token, we just create an authenticate task with the given account and
+ // the user's password.
ProgressDialog progDialog(this);
auto task = account->login(passDialog.password());
progDialog.exec(task.get());
- if(task->successful())
+ if (task->successful())
return true;
else
{
@@ -887,21 +913,20 @@ bool MainWindow::loginWithPassword(MojangAccountPtr account, const QString& erro
return false;
}
-void MainWindow::updateInstance(BaseInstance* instance, MojangAccountPtr account)
+void MainWindow::updateInstance(BaseInstance *instance, MojangAccountPtr account)
{
bool only_prepare = account->accountStatus() != Online;
auto updateTask = instance->doUpdate(only_prepare);
if (!updateTask)
{
launchInstance(instance, account);
+ return;
}
- else
- {
- ProgressDialog tDialog(this);
- connect(updateTask.get(), &Task::succeeded, [this, instance, account] { launchInstance(instance, account); });
- connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
- tDialog.exec(updateTask.get());
- }
+ ProgressDialog tDialog(this);
+ connect(updateTask.get(), &Task::succeeded, [this, instance, account]
+ { launchInstance(instance, account); });
+ connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
+ tDialog.exec(updateTask.get());
}
void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account)
@@ -989,13 +1014,31 @@ void MainWindow::on_actionChangeInstMCVersion_triggered()
this, tr("Are you sure?"),
tr("This will remove any library/version customization you did previously. "
"This includes things like Forge install and similar."),
- QMessageBox::Warning, QMessageBox::Ok, QMessageBox::Abort)->exec();
+ QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Abort,
+ QMessageBox::Abort)->exec();
if (result != QMessageBox::Ok)
return;
}
m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor());
}
+ if (!MMC->accounts()->anyAccountIsValid())
+ {
+ CustomMessageBox::selectable(
+ this, tr("Error"),
+ tr("MultiMC cannot download Minecraft or update instances unless you have at least "
+ "one account added.\nPlease add your Mojang or Minecraft account."),
+ QMessageBox::Warning)->show();
+ return;
+ }
+ auto updateTask = m_selectedInstance->doUpdate(false /*only_prepare*/);
+ if (!updateTask)
+ {
+ return;
+ }
+ ProgressDialog tDialog(this);
+ connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
+ tDialog.exec(updateTask.get());
}
void MainWindow::on_actionChangeInstLWJGLVersion_triggered()
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index f674eb61..7b91ebc8 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>637</width>
+ <width>706</width>
<height>579</height>
</rect>
</property>
@@ -17,7 +17,7 @@
</size>
</property>
<property name="windowTitle">
- <string>Dialog</string>
+ <string>About MultiMC</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@@ -95,13 +95,16 @@
</item>
<item>
<widget class="QToolBox" name="toolBox">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
<widget class="QWidget" name="aboutPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>619</width>
- <height>329</height>
+ <width>688</width>
+ <height>313</height>
</rect>
</property>
<attribute name="label">
@@ -159,8 +162,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>619</width>
- <height>329</height>
+ <width>688</width>
+ <height>313</height>
</rect>
</property>
<attribute name="label">
@@ -176,7 +179,7 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-r