NOISSUE Granular instance reload

This commit is contained in:
Petr Mrázek
2016-10-03 00:55:54 +02:00
parent bbe139dce5
commit d66fdcd4cc
28 changed files with 1507 additions and 1005 deletions

View File

@@ -95,9 +95,23 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
connect(m_instance.get(), &BaseInstance::runningStatusChanged,
this, &InstanceWindow::on_RunningState_changed);
}
// set up instance destruction detection
{
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
}
show();
}
void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus)
{
if(newStatus == BaseInstance::Status::Gone)
{
m_doNotSave = true;
close();
}
}
void InstanceWindow::setKillButton(bool kill)
{
if(kill)
@@ -145,18 +159,25 @@ void InstanceWindow::on_closeButton_clicked()
void InstanceWindow::closeEvent(QCloseEvent *event)
{
bool proceed = true;
if(!m_doNotSave)
{
proceed &= m_container->requestClose(event);
}
if(!proceed)
{
return;
}
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
if(m_container->requestClose(event))
emit isClosing();
event->accept();
if(m_shouldQuit)
{
emit isClosing();
event->accept();
if(m_shouldQuit)
{
// this needs to be delayed so we don't do horrible things
QMetaObject::invokeMethod(MMC, "quit", Qt::QueuedConnection);
}
// this needs to be delayed so we don't do horrible things
QMetaObject::invokeMethod(MMC, "quit", Qt::QueuedConnection);
}
}

View File

@@ -55,6 +55,7 @@ slots:
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
void on_RunningState_changed(bool running);
void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus);
protected:
void closeEvent(QCloseEvent *) override;
@@ -67,6 +68,7 @@ private:
unique_qobject_ptr<LaunchController> m_launchController;
InstancePtr m_instance;
bool m_shouldQuit = false;
bool m_doNotSave = false;
PageContainer *m_container = nullptr;
QPushButton *m_closeButton = nullptr;
QPushButton *m_killButton = nullptr;

View File

@@ -88,6 +88,8 @@
#include "dialogs/EditAccountDialog.h"
#include "dialogs/NotificationDialog.h"
#include "dialogs/ExportInstanceDialog.h"
#include <FolderInstanceProvider.h>
#include <InstanceImportTask.h>
class MainWindow::Ui
{
@@ -996,26 +998,6 @@ void MainWindow::setCatBackground(bool enabled)
}
}
static QFileInfo findRecursive(const QString &dir, const QString &name)
{
for (const auto info : QDir(dir).entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files, QDir::DirsLast))
{
if (info.isFile() && info.fileName() == name)
{
return info;
}
else if (info.isDir())
{
const QFileInfo res = findRecursive(info.absoluteFilePath(), name);
if (res.isFile() && res.exists())
{
return res;
}
}
}
return QFileInfo();
}
// FIXME: eliminate, should not be needed
void MainWindow::waitForMinecraftVersions()
{
@@ -1028,147 +1010,50 @@ void MainWindow::waitForMinecraftVersions()
}
}
InstancePtr MainWindow::instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url)
void MainWindow::runModalTask(Task *task)
{
InstancePtr newInstance;
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
QString instDirName = FS::DirNameFromString(instName, instancesDir);
QString instDir = FS::PathCombine(instancesDir, instDirName);
QString archivePath;
if (url.isLocalFile())
{
archivePath = url.toLocalFile();
}
else
{
const QString path = url.host() + '/' + url.path();
auto entry = ENV.metacache()->resolveEntry("general", path);
entry->setStale(true);
NetJob job(tr("Modpack download"));
job.addNetAction(Net::Download::makeCached(url, entry));
// FIXME: possibly causes endless loop problems
ProgressDialog dlDialog(this);
job.setStatus(tr("Downloading modpack:\n%1").arg(url.toString()));
if (dlDialog.execWithTask(&job) != QDialog::Accepted)
connect(task, &Task::failed, [this](QString reason)
{
return nullptr;
}
archivePath = entry->getFullPath();
}
QTemporaryDir extractTmpDir;
QDir extractDir(extractTmpDir.path());
qDebug() << "Attempting to create instance from" << archivePath;
if (MMCZip::extractDir(archivePath, extractDir.absolutePath()).isEmpty())
{
CustomMessageBox::selectable(this, tr("Error"), tr("Failed to extract modpack"), QMessageBox::Warning)->show();
return nullptr;
}
const QFileInfo instanceCfgFile = findRecursive(extractDir.absolutePath(), "instance.cfg");
if (!instanceCfgFile.isFile() || !instanceCfgFile.exists())
{
CustomMessageBox::selectable(this, tr("Error"), tr("Archive does not contain instance.cfg"))->show();
return nullptr;
}
if (!FS::copy(instanceCfgFile.absoluteDir().absolutePath(), instDir)())
{
CustomMessageBox::selectable(this, tr("Error"), tr("Unable to copy instance"))->show();
return nullptr;
}
auto error = MMC->instances()->loadInstance(newInstance, instDir);
QString errorMsg = tr("Failed to load instance %1: ").arg(instDirName);
switch (error)
{
case InstanceList::UnknownLoadError:
errorMsg += tr("Unkown error");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
return nullptr;
case InstanceList::NotAnInstance:
errorMsg += tr("Not an instance");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
return nullptr;
default:
break;
}
newInstance->setName(instName);
if (instIcon != "default")
{
newInstance->setIconKey(instIcon);
}
else
{
instIcon = newInstance->iconKey();
auto importIconPath = FS::PathCombine(newInstance->instanceRoot(), instIcon + ".png");
if (QFile::exists(importIconPath))
{
// import icon
auto iconList = MMC->icons();
// FIXME: check if the file is OK before removing the existing one...
if (iconList->iconFileExists(instIcon))
{
// FIXME: ask if icon should be overwritten. Show difference in the question dialog.
iconList->deleteIcon(instIcon);
}
iconList->installIcons({importIconPath});
}
}
newInstance->setGroupInitial(instGroup);
// reset time played on import... because packs.
newInstance->resetTimePlayed();
MMC->instances()->add(InstancePtr(newInstance));
MMC->instances()->saveGroupList();
finalizeInstance(newInstance);
return newInstance;
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
});
ProgressDialog loadDialog(this);
loadDialog.setSkipButton(true, tr("Abort"));
loadDialog.execWithTask(task);
}
InstancePtr MainWindow::instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version)
void MainWindow::instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url)
{
InstancePtr newInstance;
std::unique_ptr<Task> task(MMC->folderProvider()->zipImportTask(url, instName, instGroup, instIcon));
runModalTask(task.get());
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
QString instDirName = FS::DirNameFromString(instName, instancesDir);
QString instDir = FS::PathCombine(instancesDir, instDirName);
auto error = MMC->instances()->createInstance(newInstance, version, instDir);
QString errorMsg = tr("Failed to create instance %1: ").arg(instDirName);
switch (error)
{
case InstanceList::NoCreateError:
break;
// FIXME: handle instance selection after creation
// finalizeInstance(newInstance);
}
case InstanceList::InstExists:
{
errorMsg += tr("An instance with the given directory name already exists.");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
return nullptr;
}
void MainWindow::instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version)
{
std::unique_ptr<Task> task(MMC->folderProvider()->creationTask(version, instName, instGroup, instIcon));
runModalTask(task.get());
case InstanceList::CantCreateDir:
{
errorMsg += tr("Failed to create the instance directory.");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
return nullptr;
}
// FIXME: handle instance selection after creation
// finalizeInstance(newInstance);
}
default:
{
errorMsg += tr("Unknown instance loader error %1").arg(error);
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
return nullptr;
}
}
newInstance->setName(instName);
newInstance->setIconKey(instIcon);
newInstance->setGroupInitial(instGroup);
MMC->instances()->add(InstancePtr(newInstance));
MMC->instances()->saveGroupList();
finalizeInstance(newInstance);
return newInstance;
void MainWindow::on_actionCopyInstance_triggered()
{
if (!m_selectedInstance)
return;
CopyInstanceDialog copyInstDlg(m_selectedInstance, this);
if (!copyInstDlg.exec())
return;
std::unique_ptr<Task> task(MMC->folderProvider()->copyTask(m_selectedInstance, copyInstDlg.instName(), copyInstDlg.instGroup(),
copyInstDlg.iconKey(), copyInstDlg.shouldCopySaves()));
runModalTask(task.get());
// FIXME: handle instance selection after creation
// finalizeInstance(newInstance);
}
void MainWindow::finalizeInstance(InstancePtr inst)
@@ -1251,56 +1136,6 @@ void MainWindow::on_actionDISCORD_triggered()
DesktopServices::openUrl(QUrl("https://discord.gg/0k2zsXGNHs0fE4Wm"));
}
void MainWindow::on_actionCopyInstance_triggered()
{
if (!m_selectedInstance)
return;
CopyInstanceDialog copyInstDlg(m_selectedInstance, this);
if (!copyInstDlg.exec())
return;
QString instancesDir = MMC->settings()->get("InstanceDir").toString();
QString instDirName = FS::DirNameFromString(copyInstDlg.instName(), instancesDir);
QString instDir = FS::PathCombine(instancesDir, instDirName);
bool copySaves = copyInstDlg.shouldCopySaves();
InstancePtr newInstance;
auto error = MMC->instances()->copyInstance(newInstance, m_selectedInstance, instDir, copySaves);
QString errorMsg = tr("Failed to create instance %1: ").arg(instDirName);
switch (error)
{
case InstanceList::NoCreateError:
newInstance->setName(copyInstDlg.instName());
newInstance->setIconKey(copyInstDlg.iconKey());
MMC->instances()->add(newInstance);
newInstance->setGroupPost(copyInstDlg.instGroup());
return;
case InstanceList::InstExists:
{
errorMsg += tr("An instance with the given directory name already exists.");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
break;
}
case InstanceList::CantCreateDir:
{
errorMsg += tr("Failed to create the instance directory.");
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
break;
}
default:
{
errorMsg += tr("Unknown instance loader error %1").arg(error);
CustomMessageBox::selectable(this, tr("Error"), errorMsg, QMessageBox::Warning)->show();
break;
}
}
}
void MainWindow::on_actionChangeInstIcon_triggered()
{
if (!m_selectedInstance)
@@ -1386,7 +1221,7 @@ void MainWindow::on_actionViewInstanceFolder_triggered()
void MainWindow::on_actionRefresh_triggered()
{
MMC->instances()->loadList();
MMC->instances()->loadList(true);
}
void MainWindow::on_actionViewCentralModsFolder_triggered()

View File

@@ -170,8 +170,9 @@ private:
void setSelectedInstanceById(const QString &id);
void waitForMinecraftVersions();
InstancePtr instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
InstancePtr instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
void runModalTask(Task *task);
void instanceFromVersion(QString instName, QString instGroup, QString instIcon, BaseVersionPtr version);
void instanceFromZipPack(QString instName, QString instGroup, QString instIcon, QUrl url);
void finalizeInstance(InstancePtr inst);
void launch(InstancePtr instance, bool online = true, BaseProfilerFactory *profiler = nullptr);

View File

@@ -25,6 +25,9 @@
#include <QStyleFactory>
#include "InstanceList.h"
#include "FolderInstanceProvider.h"
#include "minecraft/ftb/FTBInstanceProvider.h"
#include <minecraft/auth/MojangAccountList.h>
#include "icons/IconList.h"
//FIXME: get rid of this
@@ -261,10 +264,13 @@ MultiMC::MultiMC(int &argc, char **argv, bool test_mode) : QApplication(argc, ar
<< "Your instance path contains \'!\' and this is known to cause java problems";
}
m_instances.reset(new InstanceList(m_settings, InstDirSetting->get().toString(), this));
m_instanceFolder = new FolderInstanceProvider(m_settings, instDir);
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instanceFolder, &FolderInstanceProvider::on_InstFolderChanged);
m_instances->addInstanceProvider(m_instanceFolder);
m_instances->addInstanceProvider(new FTBInstanceProvider(m_settings));
qDebug() << "Loading Instances...";
m_instances->loadList();
connect(InstDirSetting.get(), SIGNAL(SettingChanged(const Setting &, QVariant)),
m_instances.get(), SLOT(on_InstFolderChanged(const Setting &, QVariant)));
m_instances->loadList(true);
// and accounts
m_accounts.reset(new MojangAccountList(this));
@@ -1007,7 +1013,7 @@ void MultiMC::onExit()
{
if(m_instances)
{
m_instances->saveGroupList();
// m_instances->saveGroupList();
}
ENV.destroy();
if(logFile)

View File

@@ -7,6 +7,7 @@
#include <QIcon>
#include <QDateTime>
#include <updater/GoUpdate.h>
class FolderInstanceProvider;
class GenericPageProvider;
class QFile;
@@ -91,6 +92,11 @@ public:
return m_instances;
}
FolderInstanceProvider * folderProvider()
{
return m_instanceFolder;
}
std::shared_ptr<IconList> icons()
{
return m_icons;
@@ -164,6 +170,7 @@ private:
std::shared_ptr<QTranslator> m_mmc_translator;
std::shared_ptr<SettingsObject> m_settings;
std::shared_ptr<InstanceList> m_instances;
FolderInstanceProvider * m_instanceFolder;
std::shared_ptr<IconList> m_icons;
std::shared_ptr<UpdateChecker> m_updateChecker;
std::shared_ptr<MojangAccountList> m_accounts;