diff --git a/MultiMC.cpp b/MultiMC.cpp index 25c53185..3d62f76e 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -37,6 +37,9 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) initTranslations(); + // Don't quit on hiding the last window + this->setQuitOnLastWindowClosed(false); + // Print app header std::cout << "MultiMC 5" << std::endl; std::cout << "(c) 2013 MultiMC Contributors" << std::endl << std::endl; @@ -158,6 +161,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv) m_status = MultiMC::Failed; return; } + m_status = MultiMC::Initialized; } diff --git a/gui/consolewindow.cpp b/gui/consolewindow.cpp index deeedd65..6ed4a0ec 100644 --- a/gui/consolewindow.cpp +++ b/gui/consolewindow.cpp @@ -14,7 +14,7 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) : { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - connect(mcproc, SIGNAL(ended()), this, SLOT(onEnded())); + connect(mcproc, SIGNAL(ended(BaseInstance*)), this, SLOT(onEnded(BaseInstance*))); } ConsoleWindow::~ConsoleWindow() @@ -109,9 +109,14 @@ void ConsoleWindow::on_btnKillMinecraft_clicked() r_u_sure.close(); } -void ConsoleWindow::onEnded() +void ConsoleWindow::onEnded(BaseInstance *instance) { ui->btnKillMinecraft->setEnabled(false); - // TODO: Check why this doesn't work - if (!proc->exitCode()) this->close(); + + // TODO: Might need an option to forcefully close, even on an error + if(instance->settings().get("AutoCloseConsole").toBool()) + { + // TODO: Check why this doesn't work + if (!proc->exitCode()) this->close(); + } } diff --git a/gui/consolewindow.h b/gui/consolewindow.h index 6a6c9e50..e8790c92 100644 --- a/gui/consolewindow.h +++ b/gui/consolewindow.h @@ -49,7 +49,7 @@ public slots: private slots: void on_closeButton_clicked(); void on_btnKillMinecraft_clicked(); - void onEnded(); + void onEnded(BaseInstance *instance); protected: void closeEvent(QCloseEvent *); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index cce16a93..46fd5bd7 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -155,6 +155,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // FIXME: stop using POINTERS everywhere connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad())); + m_statusLeft = new QLabel(tr("Instance type"), this); + m_statusRight = new QLabel(tr("Assets information"), this); + m_statusRight->setAlignment(Qt::AlignRight); + statusBar()->addPermanentWidget(m_statusLeft, 1); + statusBar()->addPermanentWidget(m_statusRight, 0); + // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. { @@ -168,6 +174,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi MMC->lwjgllist()->loadList(); } assets_downloader = new OneSixAssets(); + connect(assets_downloader, SIGNAL(indexStarted()), SLOT(assetsIndexStarted())); + connect(assets_downloader, SIGNAL(filesStarted()), SLOT(assetsFilesStarted())); + connect(assets_downloader, SIGNAL(filesProgress(int, int, int)), SLOT(assetsFilesProgress(int, int, int))); + connect(assets_downloader, SIGNAL(failed()), SLOT(assetsFailed())); + connect(assets_downloader, SIGNAL(finished()), SLOT(assetsFinished())); assets_downloader->start(); } } @@ -433,6 +444,7 @@ void MainWindow::closeEvent(QCloseEvent *event) // settings->getConfig().setValue("MainWindowGeometry", saveGeometry()); // settings->getConfig().setValue("MainWindowState", saveState()); QMainWindow::closeEvent(event); + QApplication::exit(); } /* void MainWindow::on_instanceView_customContextMenuRequested(const QPoint &pos) @@ -630,11 +642,18 @@ void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response) this->hide(); } + console = new ConsoleWindow(proc); - console->show(); + connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, SLOT(write(QString, MessageLevel::Enum))); - connect(proc, SIGNAL(ended()), this, SLOT(instanceEnded())); + connect(proc, SIGNAL(ended(BaseInstance*)), this, SLOT(instanceEnded(BaseInstance*))); + + if (instance->settings().get("ShowConsole").toBool()) + { + console->show(); + } + proc->setLogin(response.username, response.session_id); proc->launch(); } @@ -747,8 +766,7 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & m_selectedInstance->menuActionEnabled("actionEditInstMods")); ui->actionChangeInstMCVersion->setEnabled( m_selectedInstance->menuActionEnabled("actionChangeInstMCVersion")); - statusBar()->clearMessage(); - statusBar()->showMessage(m_selectedInstance->getStatusbarDescription()); + m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); auto ico = MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); } @@ -784,10 +802,15 @@ void MainWindow::on_actionEditInstNotes_triggered() } } -void MainWindow::instanceEnded() +void MainWindow::instanceEnded(BaseInstance *instance) { this->show(); ui->actionLaunchInstance->setEnabled(m_selectedInstance); + + if (instance->settings().get("AutoCloseConsole").toBool()) + { + console->close(); + } } void MainWindow::checkSetDefaultJava() @@ -822,18 +845,48 @@ void MainWindow::checkSetDefaultJava() vselect.setResizeOn(2); vselect.exec(); - if (!vselect.selectedVersion()) + if (vselect.selectedVersion()) + java = std::dynamic_pointer_cast(vselect.selectedVersion()); + else { QMessageBox::warning(this, tr("Invalid version selected"), tr("You didn't select a valid Java version, so MultiMC will " "select the default. " "You can change this in the settings dialog.")); - JavaUtils ju; java = ju.GetDefaultJava(); } - - java = std::dynamic_pointer_cast(vselect.selectedVersion()); - MMC->settings()->set("JavaPath", java->path); + if(java) + MMC->settings()->set("JavaPath", java->path); + else + MMC->settings()->set("JavaPath", QString("java")); } } + +void MainWindow::assetsIndexStarted() +{ + m_statusRight->setText(tr("Checking assets...")); +} + +void MainWindow::assetsFilesStarted() +{ + m_statusRight->setText(tr("Downloading assets...")); +} + +void MainWindow::assetsFilesProgress(int succeeded, int failed, int total) +{ + QString status = tr("Downloading assets: %1 / %2").arg(succeeded + failed).arg(total); + if(failed > 0) status += tr(" (%1 failed)").arg(failed); + status += tr("..."); + m_statusRight->setText(status); +} + +void MainWindow::assetsFailed() +{ + m_statusRight->setText(tr("Failed to update assets.")); +} + +void MainWindow::assetsFinished() +{ + m_statusRight->setText(tr("Assets up to date.")); +} diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 4490d474..6715acbb 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -112,10 +112,16 @@ private slots: void on_actionChangeInstLWJGLVersion_triggered(); - void instanceEnded(); + void instanceEnded(BaseInstance *instance); void on_actionInstanceSettings_triggered(); + void assetsIndexStarted(); + void assetsFilesStarted(); + void assetsFilesProgress(int, int, int); + void assetsFailed(); + void assetsFinished(); + public slots: void instanceActivated(QModelIndex); @@ -150,6 +156,9 @@ private: LoginResponse m_activeLogin; Task *m_versionLoadTask; + + QLabel *m_statusLeft; + QLabel *m_statusRight; }; #endif // MAINWINDOW_H diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 06b7a1f1..ff122628 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -138,7 +138,7 @@ void MinecraftProcess::finish(int code, ExitStatus status) } } m_instance->cleanupAfterRun(); - emit ended(); + emit ended(m_instance); } void MinecraftProcess::killMinecraft() @@ -193,4 +193,4 @@ MessageLevel::Enum MinecraftProcess::getLevel(const QString &line, MessageLevel: if (line.contains("[DEBUG]")) level = MessageLevel::Debug; return level; -} \ No newline at end of file +} diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h index a1dfa23f..812559d5 100644 --- a/logic/MinecraftProcess.h +++ b/logic/MinecraftProcess.h @@ -67,7 +67,7 @@ signals: /** * @brief emitted when mc has finished and the PostLaunchCommand was run */ - void ended(); + void ended(BaseInstance*); /** * @brief emitted when we want to log something diff --git a/logic/OneSixAssets.cpp b/logic/OneSixAssets.cpp index 6aa0a207..ff19a86b 100644 --- a/logic/OneSixAssets.cpp +++ b/logic/OneSixAssets.cpp @@ -67,6 +67,8 @@ void OneSixAssets::fetchXMLFinished() QString fprefix ( "assets/" ); nuke_whitelist.clear(); + emit filesStarted(); + auto firstJob = index_job->first(); QByteArray ba = std::dynamic_pointer_cast(firstJob)->m_data; @@ -84,6 +86,7 @@ void OneSixAssets::fetchXMLFinished() DownloadJob *job = new DownloadJob("Assets"); connect ( job, SIGNAL(succeeded()), SLOT(downloadFinished()) ); connect ( job, SIGNAL(failed()), SIGNAL(failed()) ); + connect ( job, SIGNAL(filesProgress(int, int, int)), SIGNAL(filesProgress(int, int, int)) ); auto metacache = MMC->metacache(); @@ -130,14 +133,15 @@ void OneSixAssets::fetchXMLFinished() emit finished(); } } + void OneSixAssets::start() { auto job = new DownloadJob("Assets index"); job->addByteArrayDownload(QUrl ( "http://s3.amazonaws.com/Minecraft.Resources/" )); connect ( job, SIGNAL(succeeded()), SLOT ( fetchXMLFinished() ) ); + emit indexStarted(); index_job.reset ( job ); job->start(); } - #include "OneSixAssets.moc" diff --git a/logic/OneSixAssets.h b/logic/OneSixAssets.h index 58618c88..6c6f2c36 100644 --- a/logic/OneSixAssets.h +++ b/logic/OneSixAssets.h @@ -10,6 +10,9 @@ class OneSixAssets : public QObject signals: void failed(); void finished(); + void indexStarted(); + void filesStarted(); + void filesProgress(int, int, int); public slots: void fetchXMLFinished(); diff --git a/logic/net/DownloadJob.cpp b/logic/net/DownloadJob.cpp index fa3e655e..38716a02 100644 --- a/logic/net/DownloadJob.cpp +++ b/logic/net/DownloadJob.cpp @@ -56,6 +56,8 @@ void DownloadJob::partSucceeded(int index) num_succeeded++; QLOG_INFO() << m_job_name.toLocal8Bit() << "progress:" << num_succeeded << "/" << downloads.size(); + emit filesProgress(num_succeeded, num_failed, downloads.size()); + if (num_failed + num_succeeded == downloads.size()) { if (num_failed) @@ -78,6 +80,7 @@ void DownloadJob::partFailed(int index) { QLOG_ERROR() << "Part" << index << "failed 3 times (" << downloads[index]->m_url << ")"; num_failed++; + emit filesProgress(num_succeeded, num_failed, downloads.size()); if (num_failed + num_succeeded == downloads.size()) { QLOG_ERROR() << m_job_name.toLocal8Bit() << "failed."; diff --git a/logic/net/DownloadJob.h b/logic/net/DownloadJob.h index 91b014ad..cc2a1d59 100644 --- a/logic/net/DownloadJob.h +++ b/logic/net/DownloadJob.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "Download.h" #include "ByteArrayDownload.h" #include "FileDownload.h" @@ -57,12 +58,13 @@ public: signals: void started(); void progress(qint64 current, qint64 total); + void filesProgress(int, int, int); void succeeded(); void failed(); public slots: virtual void start(); private slots: - void partProgress(int index, qint64 bytesReceived, qint64 bytesTotal);; + void partProgress(int index, qint64 bytesReceived, qint64 bytesTotal); void partSucceeded(int index); void partFailed(int index); private: diff --git a/logic/net/LoginTask.cpp b/logic/net/LoginTask.cpp index 4098783b..5717aa9f 100644 --- a/logic/net/LoginTask.cpp +++ b/logic/net/LoginTask.cpp @@ -213,14 +213,16 @@ void LoginTask::yggdrasilLogin() clientToken.remove('{'); clientToken.remove('}'); // create the request - QString requestConstent; - requestConstent += "{"; - requestConstent += " \"agent\":{\"name\":\"Minecraft\",\"version\":1},\n"; - requestConstent += " \"username\":\"" + uInfo.username + "\",\n"; - requestConstent += " \"password\":\"" + uInfo.password + "\",\n"; - requestConstent += " \"clientToken\":\"" + clientToken + "\"\n"; - requestConstent += "}"; - netReply = worker->post(netRequest, requestConstent.toUtf8()); + QJsonObject root; + QJsonObject agent; + agent.insert("name", QString("Minecraft")); + agent.insert("version", QJsonValue(1)); + root.insert("agent", agent); + root.insert("username", uInfo.username); + root.insert("password", uInfo.password); + root.insert("clientToken", clientToken); + QJsonDocument requestDoc(root); + netReply = worker->post(netRequest, requestDoc.toJson()); } /*