Initial FTB support. Allows "tracking" of FTB instances.
This commit is contained in:
		
				
					committed by
					
						
						Petr Mrázek
					
				
			
			
				
	
			
			
			
						parent
						
							34a3fedf7b
						
					
				
				
					commit
					82c87aa06f
				
			@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								MultiMC.cpp
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								MultiMC.cpp
									
									
									
									
									
								
							@@ -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"));
 | 
			
		||||
 
 | 
			
		||||
@@ -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());
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,10 @@ protected:
 | 
			
		||||
 | 
			
		||||
private
 | 
			
		||||
slots:
 | 
			
		||||
	void on_ftbLauncherBrowseBtn_clicked();
 | 
			
		||||
 | 
			
		||||
	void on_ftbBrowseBtn_clicked();
 | 
			
		||||
 | 
			
		||||
	void on_instDirBrowseBtn_clicked();
 | 
			
		||||
 | 
			
		||||
	void on_modsDirBrowseBtn_clicked();
 | 
			
		||||
 
 | 
			
		||||
@@ -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">
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								logic/LegacyFTBInstance.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								logic/LegacyFTBInstance.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										13
									
								
								logic/LegacyFTBInstance.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										111
									
								
								logic/OneSixFTBInstance.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										20
									
								
								logic/OneSixFTBInstance.h
									
									
									
									
									
										Normal 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;
 | 
			
		||||
};
 | 
			
		||||
@@ -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");
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										77
									
								
								logic/tasks/SequentialTask.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								logic/tasks/SequentialTask.cpp
									
									
									
									
									
										Normal 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 ¤t, 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								logic/tasks/SequentialTask.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								logic/tasks/SequentialTask.h
									
									
									
									
									
										Normal 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 ¤t, 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;
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user