Initial FTB support. Allows "tracking" of FTB instances.

This commit is contained in:
Jan Dalheimer 2013-12-20 14:47:26 +01:00 committed by Petr Mrázek
parent 34a3fedf7b
commit 82c87aa06f
16 changed files with 644 additions and 68 deletions

View File

@ -361,6 +361,12 @@ logic/ForgeInstaller.cpp
logic/NostalgiaInstance.h
logic/NostalgiaInstance.cpp
# FTB
logic/OneSixFTBInstance.h
logic/OneSixFTBInstance.cpp
logic/LegacyFTBInstance.h
logic/LegacyFTBInstance.cpp
# Lists
logic/lists/InstanceList.h
logic/lists/InstanceList.cpp
@ -385,6 +391,8 @@ logic/EnabledItemFilter.cpp
logic/tasks/ProgressProvider.h
logic/tasks/Task.h
logic/tasks/Task.cpp
logic/tasks/SequentialTask.h
logic/tasks/SequentialTask.cpp
# Utilities
logic/JavaChecker.h

View File

@ -313,6 +313,55 @@ void MultiMC::initGlobalSettings()
m_settings->registerSetting(new Setting("UseDevBuilds", false));
m_settings->registerSetting(new Setting("AutoUpdate", true));
// FTB
m_settings->registerSetting(new Setting("TrackFTBInstances", false));
m_settings->registerSetting(new Setting("FTBLauncherRoot",
#ifdef Q_OS_LINUX
QDir::home().absoluteFilePath(".ftblauncher")
#elif defined(Q_OS_WIN32)
PathCombine(QDir::homePath(), "AppData/Roaming/ftblauncher")
#elif defined(Q_OS_MAC)
PathCombine(QDir::homePath(), "Library/Application Support/ftblauncher")
#endif
));
m_settings->registerSetting(new Setting("FTBRoot"));
if (m_settings->get("FTBRoot").isNull())
{
QString ftbRoot;
QFile f(QDir(m_settings->get("FTBLauncherRoot").toString()).absoluteFilePath("ftblaunch.cfg"));
QLOG_INFO() << "Attempting to read" << f.fileName();
if (f.open(QFile::ReadOnly))
{
const QString data = QString::fromLatin1(f.readAll());
QRegularExpression exp("installPath=(.*)");
ftbRoot = QDir::cleanPath(exp.match(data).captured(1));
#ifdef Q_OS_WIN32
if (!ftbRoot.isEmpty())
{
if (ftbRoot.at(0).isLetter() && ftbRoot.size() > 1 && ftbRoot.at(1) == '/')
{
ftbRoot.remove(1, 1);
}
}
#endif
if (ftbRoot.isEmpty())
{
QLOG_INFO() << "Failed to get FTB root path";
}
else
{
QLOG_INFO() << "FTB is installed at" << ftbRoot;
m_settings->set("FTBRoot", ftbRoot);
}
}
else
{
QLOG_WARN() << "Couldn't open" << f.fileName() << ":" << f.errorString();
QLOG_WARN() << "This is perfectly normal if you don't have FTB installed";
}
}
// Folders
m_settings->registerSetting(new Setting("InstanceDir", "instances"));
m_settings->registerSetting(new Setting("CentralModsDir", "mods"));

View File

@ -60,6 +60,32 @@ void SettingsDialog::updateCheckboxStuff()
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
}
void SettingsDialog::on_ftbLauncherBrowseBtn_clicked()
{
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Launcher Directory"),
ui->ftbLauncherBox->text());
QString cooked_dir = NormalizePath(raw_dir);
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
{
ui->ftbLauncherBox->setText(cooked_dir);
}
}
void SettingsDialog::on_ftbBrowseBtn_clicked()
{
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("FTB Directory"),
ui->ftbBox->text());
QString cooked_dir = NormalizePath(raw_dir);
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
if (!cooked_dir.isEmpty() && QDir(cooked_dir).exists())
{
ui->ftbBox->setText(cooked_dir);
}
}
void SettingsDialog::on_instDirBrowseBtn_clicked()
{
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Directory"),
@ -135,6 +161,11 @@ void SettingsDialog::applySettings(SettingsObject *s)
// Updates
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
// FTB
s->set("TrackFTBInstances", ui->trackFtbBox->isChecked());
s->set("FTBLauncherRoot", ui->ftbLauncherBox->text());
s->set("FTBRoot", ui->ftbBox->text());
// Folders
// TODO: Offer to move instances to new instance folder.
s->set("InstanceDir", ui->instDirTextBox->text());
@ -185,6 +216,11 @@ void SettingsDialog::loadSettings(SettingsObject *s)
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
ui->devBuildsCheckBox->setChecked(s->get("UseDevBuilds").toBool());
// FTB
ui->trackFtbBox->setChecked(s->get("TrackFTBInstances").toBool());
ui->ftbLauncherBox->setText(s->get("FTBLauncherRoot").toString());
ui->ftbBox->setText(s->get("FTBRoot").toString());
// Folders
ui->instDirTextBox->setText(s->get("InstanceDir").toString());
ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());

View File

@ -45,6 +45,10 @@ protected:
private
slots:
void on_ftbLauncherBrowseBtn_clicked();
void on_ftbBrowseBtn_clicked();
void on_instDirBrowseBtn_clicked();
void on_modsDirBrowseBtn_clicked();

View File

@ -95,6 +95,87 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>FTB</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="2">
<widget class="QPushButton" name="ftbLauncherBrowseBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>28</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Launcher:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="ftbLauncherBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="trackFtbBox">
<property name="text">
<string>Track FTB instances</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="ftbBox"/>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="ftbBrowseBtn">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>28</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Files:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="foldersBox">
<property name="title">

View File

@ -20,7 +20,9 @@
#include "BaseInstance.h"
#include "LegacyInstance.h"
#include "LegacyFTBInstance.h"
#include "OneSixInstance.h"
#include "OneSixFTBInstance.h"
#include "NostalgiaInstance.h"
#include "BaseVersion.h"
#include "MinecraftVersion.h"
@ -60,6 +62,14 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
{
inst = new NostalgiaInstance(instDir, m_settings, this);
}
else if (inst_type == "LegacyFTB")
{
inst = new LegacyFTBInstance(instDir, m_settings, this);
}
else if (inst_type == "OneSixFTB")
{
inst = new OneSixFTBInstance(instDir, m_settings, this);
}
else
{
return InstanceFactory::UnknownLoadError;
@ -69,7 +79,8 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
InstanceFactory::InstCreateError InstanceFactory::createInstance(BaseInstance *&inst,
BaseVersionPtr version,
const QString &instDir)
const QString &instDir,
const InstType type)
{
QDir rootDir(instDir);
@ -85,32 +96,63 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(BaseInstance *&
auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg"));
m_settings->registerSetting(new Setting("InstanceType", "Legacy"));
switch (mcVer->type)
if (type == NormalInst)
{
case MinecraftVersion::Legacy:
m_settings->set("InstanceType", "Legacy");
inst = new LegacyInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
case MinecraftVersion::OneSix:
m_settings->set("InstanceType", "OneSix");
inst = new OneSixInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
case MinecraftVersion::Nostalgia:
m_settings->set("InstanceType", "Nostalgia");
inst = new NostalgiaInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
default:
switch (mcVer->type)
{
case MinecraftVersion::Legacy:
m_settings->set("InstanceType", "Legacy");
inst = new LegacyInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
case MinecraftVersion::OneSix:
m_settings->set("InstanceType", "OneSix");
inst = new OneSixInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
case MinecraftVersion::Nostalgia:
m_settings->set("InstanceType", "Nostalgia");
inst = new NostalgiaInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
default:
{
delete m_settings;
return InstanceFactory::NoSuchVersion;
}
}
}
else if (type == FTBInstance)
{
switch (mcVer->type)
{
case MinecraftVersion::Legacy:
m_settings->set("InstanceType", "LegacyFTB");
inst = new LegacyFTBInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
case MinecraftVersion::OneSix:
m_settings->set("InstanceType", "OneSixFTB");
inst = new OneSixFTBInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
inst->setShouldUseCustomBaseJar(false);
break;
default:
{
delete m_settings;
return InstanceFactory::NoSuchVersion;
}
}
}
else
{
delete m_settings;
return InstanceFactory::NoSuchVersion;
}
}
// FIXME: really, how do you even know?
return InstanceFactory::NoCreateError;

View File

@ -55,18 +55,25 @@ public:
CantCreateDir
};
enum InstType
{
NormalInst,
FTBInstance
};
/*!
* \brief Creates a stub instance
*
* \param inst Pointer to store the created instance in.
* \param inst Game version to use for the instance
* \param version Game version to use for the instance
* \param instDir The new instance's directory.
* \param type The type of instance to create
* \return An InstCreateError error code.
* - InstExists if the given instance directory is already an instance.
* - CantCreateDir if the given instance directory cannot be created.
*/
InstCreateError createInstance(BaseInstance *&inst, BaseVersionPtr version,
const QString &instDir);
const QString &instDir, const InstType type = NormalInst);
/*!
* \brief Creates a copy of an existing instance with a new name

View File

@ -0,0 +1,16 @@
#include "LegacyFTBInstance.h"
LegacyFTBInstance::LegacyFTBInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) :
LegacyInstance(rootDir, settings, parent)
{
}
QString LegacyFTBInstance::getStatusbarDescription()
{
return "Legacy FTB: " + intendedVersionId();
}
bool LegacyFTBInstance::menuActionEnabled(QString action_name) const
{
return false;
}

13
logic/LegacyFTBInstance.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "LegacyInstance.h"
class LegacyFTBInstance : public LegacyInstance
{
Q_OBJECT
public:
explicit LegacyFTBInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent = 0);
virtual QString getStatusbarDescription();
virtual bool menuActionEnabled(QString action_name) const;
};

111
logic/OneSixFTBInstance.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "OneSixFTBInstance.h"
#include "OneSixVersion.h"
#include "OneSixLibrary.h"
#include "tasks/SequentialTask.h"
#include "ForgeInstaller.h"
#include "lists/ForgeVersionList.h"
#include "MultiMC.h"
class OneSixFTBInstanceForge : public Task
{
Q_OBJECT
public:
explicit OneSixFTBInstanceForge(const QString &version, OneSixFTBInstance *inst, QObject *parent = 0) :
Task(parent), instance(inst), version("Forge " + version)
{
}
void executeTask()
{
for (int i = 0; i < MMC->forgelist()->count(); ++i)
{
if (MMC->forgelist()->at(i)->name() == version)
{
forgeVersion = std::dynamic_pointer_cast<ForgeVersion>(MMC->forgelist()->at(i));
break;
}
}
if (!forgeVersion)
return;
entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename);
if (entry->stale)
{
setStatus(tr("Downloading Forge..."));
fjob = new NetJob("Forge download");
fjob->addNetAction(CacheDownload::make(forgeVersion->installer_url, entry));
connect(fjob, &NetJob::failed, [this](){emitFailed(m_failReason);});
connect(fjob, &NetJob::succeeded, this, &OneSixFTBInstanceForge::installForge);
connect(fjob, &NetJob::progress, [this](qint64 c, qint64 total){ setProgress(100 * c / total); });
fjob->start();
}
else
{
installForge();
}
}
private
slots:
void installForge()
{
setStatus(tr("Installing Forge..."));
QString forgePath = entry->getFullPath();
ForgeInstaller forge(forgePath, forgeVersion->universal_url);
if (!instance->reloadFullVersion())
{
emitFailed(tr("Couldn't load the version config"));
return;
}
if (!forge.apply(instance->getFullVersion()))
{
emitFailed(tr("Couldn't install Forge"));
return;
}
emitSucceeded();
}
private:
OneSixFTBInstance *instance;
QString version;
ForgeVersionPtr forgeVersion;
MetaEntryPtr entry;
NetJob *fjob;
};
OneSixFTBInstance::OneSixFTBInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) :
OneSixInstance(rootDir, settings, parent)
{
QFile f(QDir(minecraftRoot()).absoluteFilePath("pack.json"));
if (f.open(QFile::ReadOnly))
{
QString data = QString::fromUtf8(f.readAll());
QRegularExpressionMatch match = QRegularExpression("net.minecraftforge:minecraftforge:[\\.\\d]*").match(data);
m_forge.reset(new OneSixLibrary(match.captured()));
m_forge->finalize();
}
}
QString OneSixFTBInstance::getStatusbarDescription()
{
return "OneSix FTB: " + intendedVersionId();
}
bool OneSixFTBInstance::menuActionEnabled(QString action_name) const
{
return false;
}
std::shared_ptr<Task> OneSixFTBInstance::doUpdate(bool only_prepare)
{
std::shared_ptr<SequentialTask> task;
task.reset(new SequentialTask(this));
if (!MMC->forgelist()->isLoaded())
{
task->addTask(std::shared_ptr<Task>(MMC->forgelist()->getLoadTask()));
}
task->addTask(OneSixInstance::doUpdate(only_prepare));
task->addTask(std::shared_ptr<Task>(new OneSixFTBInstanceForge(m_forge->version(), this, this)));
return task;
}
#include "OneSixFTBInstance.moc"

20
logic/OneSixFTBInstance.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "OneSixInstance.h"
class OneSixLibrary;
class OneSixFTBInstance : public OneSixInstance
{
Q_OBJECT
public:
explicit OneSixFTBInstance(const QString &rootDir, SettingsObject *settings,
QObject *parent = 0);
virtual QString getStatusbarDescription();
virtual bool menuActionEnabled(QString action_name) const;
virtual std::shared_ptr<Task> doUpdate(bool only_prepare) override;
private:
std::shared_ptr<OneSixLibrary> m_forge;
};

View File

@ -159,6 +159,7 @@ ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task()
void ForgeListLoadTask::executeTask()
{
setStatus(tr("Fetching Forge version list"));
auto job = new NetJob("Version index");
// we do not care if the version is stale or not.
auto forgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "list.json");

View File

@ -22,11 +22,14 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QXmlStreamReader>
#include <QRegularExpression>
#include <pathutils.h>
#include "MultiMC.h"
#include "logic/lists/InstanceList.h"
#include "logic/lists/IconList.h"
#include "logic/lists/MinecraftVersionList.h"
#include "logic/BaseInstance.h"
#include "logic/InstanceFactory.h"
#include "logger/QsLog.h"
@ -42,6 +45,8 @@ InstanceList::InstanceList(const QString &instDir, QObject *parent)
{
QDir::current().mkpath(m_instDir);
}
connect(MMC->minecraftlist().get(), &MinecraftVersionList::modelReset, this, &InstanceList::loadList);
}
InstanceList::~InstanceList()
@ -285,57 +290,87 @@ InstanceList::InstListError InstanceList::loadList()
beginResetModel();
m_instances.clear();
QDir dir(m_instDir);
QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable,
QDirIterator::FollowSymlinks);
while (iter.hasNext())
{
QString subDir = iter.next();
if (!QFileInfo(PathCombine(subDir, "instance.cfg")).exists())
continue;
BaseInstance *instPtr = NULL;
auto &loader = InstanceFactory::get();
auto error = loader.loadInstance(instPtr, subDir);
if (error != InstanceFactory::NoLoadError && error != InstanceFactory::NotAnInstance)
QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable,
QDirIterator::FollowSymlinks);
while (iter.hasNext())
{
QString errorMsg = QString("Failed to load instance %1: ")
.arg(QFileInfo(subDir).baseName())
.toUtf8();
QString subDir = iter.next();
if (!QFileInfo(PathCombine(subDir, "instance.cfg")).exists())
continue;
switch (error)
{
default:
errorMsg += QString("Unknown instance loader error %1").arg(error);
break;
}
QLOG_ERROR() << errorMsg.toUtf8();
BaseInstance *instPtr = NULL;
auto error = InstanceFactory::get().loadInstance(instPtr, subDir);
continueProcessInstance(instPtr, error, subDir, groupMap);
}
else if (!instPtr)
}
if (MMC->settings()->get("TrackFTBInstances").toBool() && MMC->minecraftlist()->isLoaded())
{
QDir dir = QDir(MMC->settings()->get("FTBLauncherRoot").toString());
QDir dataDir = QDir(MMC->settings()->get("FTBRoot").toString());
if (!dir.exists())
{
QLOG_ERROR() << QString("Error loading instance %1. Instance loader returned null.")
.arg(QFileInfo(subDir).baseName())
.toUtf8();
QLOG_INFO() << "The FTB launcher directory specified does not exist. Please check your settings.";
}
else if (!dataDir.exists())
{
QLOG_INFO() << "The FTB directory specified does not exist. Please check your settings";
}
else
{
std::shared_ptr<BaseInstance> inst(instPtr);
auto iter = groupMap.find(inst->id());
if (iter != groupMap.end())
dir.cd("ModPacks");
QFile f(dir.absoluteFilePath("modpacks.xml"));
if (f.open(QFile::ReadOnly))
{
inst->setGroupInitial((*iter));
QXmlStreamReader reader(&f);
while (!reader.atEnd())
{
switch (reader.readNext())
{
case QXmlStreamReader::StartElement:
{
if (reader.name() == "modpack")
{
QXmlStreamAttributes attrs = reader.attributes();
const QDir instanceDir = QDir(dataDir.absoluteFilePath(attrs.value("dir").toString()));
if (instanceDir.exists())
{
const QString name = attrs.value("name").toString();
const QString iconKey = attrs.value("logo").toString().remove(QRegularExpression("\\..*"));
const QString mcVersion = attrs.value("mcVersion").toString();
const QString notes = attrs.value("description").toString();
QLOG_DEBUG() << dir.absoluteFilePath(attrs.value("logo").toString());
MMC->icons()->addIcon(iconKey, iconKey, dir.absoluteFilePath(attrs.value("dir").toString() + QDir::separator() + attrs.value("logo").toString()), true);
BaseInstance *instPtr = NULL;
auto error = InstanceFactory::get().createInstance(instPtr, MMC->minecraftlist()->findVersion(mcVersion), instanceDir.absolutePath(), InstanceFactory::FTBInstance);
if (instPtr && error == InstanceFactory::NoCreateError)
{
instPtr->setGroupInitial("FTB");
instPtr->setName(name);
instPtr->setIconKey(iconKey);
instPtr->setIntendedVersionId(mcVersion);
instPtr->setNotes(notes);
}
continueProcessInstance(instPtr, error, instanceDir, groupMap);
}
}
break;
}
case QXmlStreamReader::EndElement:
break;
case QXmlStreamReader::Characters:
break;
default:
break;
}
}
}
QLOG_INFO() << "Loaded instance " << inst->name();
inst->setParent(this);
m_instances.append(inst);
connect(instPtr, SIGNAL(propertiesChanged(BaseInstance *)), this,
SLOT(propertiesChanged(BaseInstance *)));
connect(instPtr, SIGNAL(groupChanged()), this, SLOT(groupChanged()));
connect(instPtr, SIGNAL(nuked(BaseInstance *)), this,
SLOT(instanceNuked(BaseInstance *)));
}
}
endResetModel();
emit dataIsInvalid();
return NoError;
@ -409,6 +444,46 @@ int InstanceList::getInstIndex(BaseInstance *inst) const
return -1;
}
void InstanceList::continueProcessInstance(BaseInstance *instPtr, const int error, const QDir &dir, QMap<QString, QString> &groupMap)
{
if (error != InstanceFactory::NoLoadError && error != InstanceFactory::NotAnInstance)
{
QString errorMsg = QString("Failed to load instance %1: ")
.arg(QFileInfo(dir.absolutePath()).baseName())
.toUtf8();
switch (error)
{
default:
errorMsg += QString("Unknown instance loader error %1").arg(error);
break;
}
QLOG_ERROR() << errorMsg.toUtf8();
}
else if (!instPtr)
{
QLOG_ERROR() << QString("Error loading instance %1. Instance loader returned null.")
.arg(QFileInfo(dir.absolutePath()).baseName())
.toUtf8();
}
else
{
auto iter = groupMap.find(instPtr->id());
if (iter != groupMap.end())
{
instPtr->setGroupInitial((*iter));
}
QLOG_INFO() << "Loaded instance " << instPtr->name();
instPtr->setParent(this);
m_instances.append(std::shared_ptr<BaseInstance>(instPtr));
connect(instPtr, SIGNAL(propertiesChanged(BaseInstance *)), this,
SLOT(propertiesChanged(BaseInstance *)));
connect(instPtr, SIGNAL(groupChanged()), this, SLOT(groupChanged()));
connect(instPtr, SIGNAL(nuked(BaseInstance *)), this,
SLOT(instanceNuked(BaseInstance *)));
}
}
void InstanceList::instanceNuked(BaseInstance *inst)
{
int i = getInstIndex(inst);

View File

@ -25,6 +25,8 @@
class BaseInstance;
class QDir;
class InstanceList : public QAbstractListModel
{
Q_OBJECT
@ -65,11 +67,6 @@ public:
return m_instDir;
}
/*!
* \brief Loads the instance list. Triggers notifications.
*/
InstListError loadList();
/*!
* \brief Get the instance at index
*/
@ -108,6 +105,11 @@ public
slots:
void on_InstFolderChanged(const Setting &setting, QVariant value);
/*!
* \brief Loads the instance list. Triggers notifications.
*/
InstListError loadList();
private
slots:
void propertiesChanged(BaseInstance *inst);
@ -117,6 +119,8 @@ slots:
private:
int getInstIndex(BaseInstance *inst) const;
void continueProcessInstance(BaseInstance *instPtr, const int error, const QDir &dir, QMap<QString, QString> &groupMap);
protected:
QString m_instDir;
QList<InstancePtr> m_instances;

View File

@ -0,0 +1,77 @@
#include "SequentialTask.h"
SequentialTask::SequentialTask(QObject *parent) :
Task(parent), m_currentIndex(-1)
{
}
QString SequentialTask::getStatus() const
{
if (m_queue.isEmpty() || m_currentIndex >= m_queue.size())
{
return QString();
}
return m_queue.at(m_currentIndex)->getStatus();
}
void SequentialTask::getProgress(qint64 &current, qint64 &total)
{
current = 0;
total = 0;
for (int i = 0; i < m_queue.size(); ++i)
{
qint64 subCurrent, subTotal;
m_queue.at(i)->getProgress(subCurrent, subTotal);
current += subCurrent;
total += subTotal;
}
}
void SequentialTask::addTask(std::shared_ptr<Task> task)
{
m_queue.append(task);
}
void SequentialTask::executeTask()
{
m_currentIndex = -1;
startNext();
}
void SequentialTask::startNext()
{
if (m_currentIndex != -1)
{
std::shared_ptr<Task> previous = m_queue[m_currentIndex];
disconnect(previous.get(), 0, this, 0);
}
m_currentIndex++;
if (m_queue.isEmpty() || m_currentIndex >= m_queue.size())
{
emitSucceeded();
return;
}
std::shared_ptr<Task> next = m_queue[m_currentIndex];
connect(next.get(), SIGNAL(failed(QString)), this, SLOT(subTaskFailed(QString)));
connect(next.get(), SIGNAL(status(QString)), this, SLOT(subTaskStatus(QString)));
connect(next.get(), SIGNAL(progress(qint64,qint64)), this, SLOT(subTaskProgress()));
connect(next.get(), SIGNAL(succeeded()), this, SLOT(startNext()));
next->start();
emit status(getStatus());
}
void SequentialTask::subTaskFailed(const QString &msg)
{
emitFailed(msg);
}
void SequentialTask::subTaskStatus(const QString &msg)
{
setStatus(msg);
}
void SequentialTask::subTaskProgress()
{
qint64 current, total;
getProgress(current, total);
setProgress(100 * current / total);
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "Task.h"
#include <QQueue>
#include <memory>
class SequentialTask : public Task
{
Q_OBJECT
public:
explicit SequentialTask(QObject *parent = 0);
virtual QString getStatus() const;
virtual void getProgress(qint64 &current, qint64 &total);
void addTask(std::shared_ptr<Task> task);
protected:
void executeTask();
private
slots:
void startNext();
void subTaskFailed(const QString &msg);
void subTaskStatus(const QString &msg);
void subTaskProgress();
private:
QQueue<std::shared_ptr<Task> > m_queue;
int m_currentIndex;
};