summaryrefslogtreecommitdiffstats
path: root/logic/lists
diff options
context:
space:
mode:
Diffstat (limited to 'logic/lists')
-rw-r--r--logic/lists/ForgeVersionList.cpp205
-rw-r--r--logic/lists/ForgeVersionList.h14
-rw-r--r--logic/lists/IconList.cpp271
-rw-r--r--logic/lists/IconList.h54
-rw-r--r--logic/lists/InstanceList.cpp226
-rw-r--r--logic/lists/InstanceList.h16
-rw-r--r--logic/lists/JavaVersionList.cpp13
-rw-r--r--logic/lists/JavaVersionList.h1
-rw-r--r--logic/lists/MinecraftVersionList.cpp2
9 files changed, 388 insertions, 414 deletions
diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp
index b5e421af..56eca744 100644
--- a/logic/lists/ForgeVersionList.cpp
+++ b/logic/lists/ForgeVersionList.cpp
@@ -15,6 +15,7 @@
#include "ForgeVersionList.h"
#include <logic/net/NetJob.h>
+#include <logic/net/URLConstants.h>
#include "MultiMC.h"
#include <QtNetwork>
@@ -23,8 +24,6 @@
#include "logger/QsLog.h"
-#define JSON_URL "http://files.minecraftforge.net/minecraftforge/json"
-
ForgeVersionList::ForgeVersionList(QObject *parent) : BaseVersionList(parent)
{
}
@@ -159,44 +158,43 @@ ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task()
void ForgeListLoadTask::executeTask()
{
+ setStatus(tr("Fetching Forge version lists..."));
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");
+ auto gradleForgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "json");
// verify by poking the server.
forgeListEntry->stale = true;
+ gradleForgeListEntry->stale = true;
+
+ job->addNetAction(listDownload = CacheDownload::make(QUrl(URLConstants::FORGE_LEGACY_URL),
+ forgeListEntry));
+ job->addNetAction(gradleListDownload = CacheDownload::make(
+ QUrl(URLConstants::FORGE_GRADLE_URL), gradleForgeListEntry));
+
+ connect(listDownload.get(), SIGNAL(failed(int)), SLOT(listFailed()));
+ connect(gradleListDownload.get(), SIGNAL(failed(int)), SLOT(gradleListFailed()));
- job->addNetAction(CacheDownload::make(QUrl(JSON_URL), forgeListEntry));
listJob.reset(job);
- connect(listJob.get(), SIGNAL(succeeded()), SLOT(list_downloaded()));
- connect(listJob.get(), SIGNAL(failed()), SLOT(list_failed()));
+ connect(listJob.get(), SIGNAL(succeeded()), SLOT(listDownloaded()));
connect(listJob.get(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64)));
listJob->start();
}
-void ForgeListLoadTask::list_failed()
-{
- auto DlJob = listJob->first();
- auto reply = DlJob->m_reply;
- if (reply)
- {
- QLOG_ERROR() << "Getting forge version list failed: " << reply->errorString();
- }
- else
- QLOG_ERROR() << "Getting forge version list failed for reasons unknown.";
-}
-
-void ForgeListLoadTask::list_downloaded()
+bool ForgeListLoadTask::parseForgeList(QList<BaseVersionPtr> &out)
{
QByteArray data;
{
- auto DlJob = listJob->first();
- auto filename = std::dynamic_pointer_cast<CacheDownload>(DlJob)->m_target_path;
+ auto dlJob = listDownload;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
QFile listFile(filename);
if (!listFile.open(QIODevice::ReadOnly))
- return;
+ {
+ return false;
+ }
data = listFile.readAll();
- DlJob.reset();
+ dlJob.reset();
}
QJsonParseError jsonError;
@@ -205,13 +203,13 @@ void ForgeListLoadTask::list_downloaded()
if (jsonError.error != QJsonParseError::NoError)
{
emitFailed("Error parsing version list JSON:" + jsonError.errorString());
- return;
+ return false;
}
if (!jsonDoc.isObject())
{
- emitFailed("Error parsing version list JSON: jsonDoc is not an object");
- return;
+ emitFailed("Error parsing version list JSON: JSON root is not an object");
+ return false;
}
QJsonObject root = jsonDoc.object();
@@ -221,11 +219,10 @@ void ForgeListLoadTask::list_downloaded()
{
emitFailed(
"Error parsing version list JSON: version list object is missing 'builds' array");
- return;
+ return false;
}
QJsonArray builds = root.value("builds").toArray();
- QList<BaseVersionPtr> tempList;
for (int i = 0; i < builds.count(); i++)
{
// Load the version info.
@@ -246,7 +243,9 @@ void ForgeListLoadTask::list_downloaded()
for (int j = 0; j < files.count(); j++)
{
if (!files[j].isObject())
+ {
continue;
+ }
QJsonObject file = files[j].toObject();
buildtype = file.value("buildtype").toString();
if ((buildtype == "client" || buildtype == "universal") && !valid)
@@ -262,7 +261,9 @@ void ForgeListLoadTask::list_downloaded()
{
QString ext = file.value("ext").toString();
if (ext.isEmpty())
+ {
continue;
+ }
changelog_url = file.value("url").toString();
}
else if (buildtype == "installer")
@@ -282,15 +283,161 @@ void ForgeListLoadTask::list_downloaded()
fVersion->jobbuildver = jobbuildver;
fVersion->mcver = mcver;
if (installer_filename.isEmpty())
+ {
fVersion->filename = filename;
+ }
else
+ {
fVersion->filename = installer_filename;
+ }
fVersion->m_buildnr = build_nr;
- tempList.append(fVersion);
+ out.append(fVersion);
+ }
+ }
+
+ return true;
+}
+
+bool ForgeListLoadTask::parseForgeGradleList(QList<BaseVersionPtr> &out)
+{
+ QByteArray data;
+ {
+ auto dlJob = gradleListDownload;
+ auto filename = std::dynamic_pointer_cast<CacheDownload>(dlJob)->m_target_path;
+ QFile listFile(filename);
+ if (!listFile.open(QIODevice::ReadOnly))
+ {
+ return false;
+ }
+ data = listFile.readAll();
+ dlJob.reset();
+ }
+
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
+
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ emitFailed("Error parsing gradle version list JSON:" + jsonError.errorString());
+ return false;
+ }
+
+ if (!jsonDoc.isObject())
+ {
+ emitFailed("Error parsing gradle version list JSON: JSON root is not an object");
+ return false;
+ }
+
+ QJsonObject root = jsonDoc.object();
+
+ // we probably could hard code these, but it might still be worth doing it this way
+ const QString webpath = root.value("webpath").toString();
+ const QString artifact = root.value("artifact").toString();
+
+ QJsonObject numbers = root.value("number").toObject();
+ for (auto it = numbers.begin(); it != numbers.end(); ++it)
+ {
+ QJsonObject number = it.value().toObject();
+ std::shared_ptr<ForgeVersion> fVersion(new ForgeVersion());
+ fVersion->m_buildnr = number.value("build").toDouble();
+ fVersion->jobbuildver = number.value("version").toString();
+ fVersion->mcver = number.value("mcversion").toString();
+ fVersion->filename = "";
+ QString filename, installer_filename;
+ QJsonArray files = number.value("files").toArray();
+ for (auto fIt = files.begin(); fIt != files.end(); ++fIt)
+ {
+ // TODO with gradle we also get checksums, use them
+ QJsonArray file = (*fIt).toArray();
+ if (file.size() < 3)
+ {
+ continue;
+ }
+ if (file.at(1).toString() == "installer")
+ {
+ fVersion->installer_url = QString("%1/%2-%3/%4-%2-%3-installer.%5").arg(
+ webpath, fVersion->mcver, fVersion->jobbuildver, artifact,
+ file.at(0).toString());
+ installer_filename = QString("%1-%2-%3-installer.%4").arg(
+ artifact, fVersion->mcver, fVersion->jobbuildver, file.at(0).toString());
+ }
+ else if (file.at(1).toString() == "universal")
+ {
+ fVersion->universal_url = QString("%1/%2-%3/%4-%2-%3-universal.%5").arg(
+ webpath, fVersion->mcver, fVersion->jobbuildver, artifact,
+ file.at(0).toString());
+ filename = QString("%1-%2-%3-universal.%4").arg(
+ artifact, fVersion->mcver, fVersion->jobbuildver, file.at(0).toString());
+ }
+ else if (file.at(1).toString() == "changelog")
+ {
+ fVersion->changelog_url = QString("%1/%2-%3/%4-%2-%3-changelog.%5").arg(
+ webpath, fVersion->mcver, fVersion->jobbuildver, artifact,
+ file.at(0).toString());
+ }
+ }
+ if (fVersion->installer_url.isEmpty() && fVersion->universal_url.isEmpty())
+ {
+ continue;
}
+ fVersion->filename = fVersion->installer_url.isEmpty() ? filename : installer_filename;
+ out.append(fVersion);
}
- m_list->updateListData(tempList);
+
+ return true;
+}
+
+void ForgeListLoadTask::listDownloaded()
+{
+ QList<BaseVersionPtr> list;
+ bool ret = true;
+ if (!parseForgeList(list))
+ {
+ ret = false;
+ }
+ if (!parseForgeGradleList(list))
+ {
+ ret = false;
+ }
+
+ if (!ret)
+ {
+ return;
+ }
+
+ qSort(list.begin(), list.end(), [](const BaseVersionPtr & p1, const BaseVersionPtr & p2)
+ {
+ // TODO better comparison (takes major/minor/build number into account)
+ return p1->name() > p2->name();
+ });
+
+ m_list->updateListData(list);
emitSucceeded();
return;
}
+
+void ForgeListLoadTask::listFailed()
+{
+ auto reply = listDownload->m_reply;
+ if (reply)
+ {
+ QLOG_ERROR() << "Getting forge version list failed: " << reply->errorString();
+ }
+ else
+ {
+ QLOG_ERROR() << "Getting forge version list failed for reasons unknown.";
+ }
+}
+void ForgeListLoadTask::gradleListFailed()
+{
+ auto reply = gradleListDownload->m_reply;
+ if (reply)
+ {
+ QLOG_ERROR() << "Getting forge version list failed: " << reply->errorString();
+ }
+ else
+ {
+ QLOG_ERROR() << "Getting forge version list failed for reasons unknown.";
+ }
+}
diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h
index bf9e87b2..924084ae 100644
--- a/logic/lists/ForgeVersionList.h
+++ b/logic/lists/ForgeVersionList.h
@@ -80,7 +80,7 @@ public:
protected:
QList<BaseVersionPtr> m_vlist;
- bool m_loaded;
+ bool m_loaded = false;
protected
slots:
@@ -98,10 +98,18 @@ public:
protected
slots:
- void list_downloaded();
- void list_failed();
+ void listDownloaded();
+ void listFailed();
+ void gradleListFailed();
protected:
NetJobPtr listJob;
ForgeVersionList *m_list;
+
+ CacheDownloadPtr listDownload;
+ CacheDownloadPtr gradleListDownload;
+
+private:
+ bool parseForgeList(QList<BaseVersionPtr> &out);
+ bool parseForgeGradleList(QList<BaseVersionPtr> &out);
};
diff --git a/logic/lists/IconList.cpp b/logic/lists/IconList.cpp
deleted file mode 100644
index ecfb8c3c..00000000
--- a/logic/lists/IconList.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "IconList.h"
-#include <pathutils.h>
-#include <QMap>
-#include <QEventLoop>
-#include <QDir>
-#include <QMimeData>
-#include <QUrl>
-#define MAX_SIZE 1024
-
-struct entry
-{
- QString key;
- QString name;
- QIcon icon;
- bool is_builtin;
- QString filename;
-};
-
-class Private : public QObject
-{
- Q_OBJECT
-public:
- QMap<QString, int> index;
- QVector<entry> icons;
- Private()
- {
- }
-};
-
-IconList::IconList() : QAbstractListModel(), d(new Private())
-{
- QDir instance_icons(":/icons/instances/");
- auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
- for (auto file_info : file_info_list)
- {
- QString key = file_info.baseName();
- addIcon(key, key, file_info.absoluteFilePath(), true);
- }
-
- // FIXME: get from settings
- ensureFolderPathExists("icons");
- QDir user_icons("icons");
- file_info_list = user_icons.entryInfoList(QDir::Files, QDir::Name);
- for (auto file_info : file_info_list)
- {
- QString filename = file_info.absoluteFilePath();
- QString key = file_info.baseName();
- addIcon(key, key, filename);
- }
-}
-
-IconList::~IconList()
-{
- delete d;
- d = nullptr;
-}
-
-QStringList IconList::mimeTypes() const
-{
- QStringList types;
- types << "text/uri-list";
- return types;
-}
-Qt::DropActions IconList::supportedDropActions() const
-{
- return Qt::CopyAction;
-}
-
-bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
- const QModelIndex &parent)
-{
- if (action == Qt::IgnoreAction)
- return true;
- // check if the action is supported
- if (!data || !(action & supportedDropActions()))
- return false;
-
- // files dropped from outside?
- if (data->hasUrls())
- {
- /*
- bool was_watching = is_watching;
- if(was_watching)
- stopWatching();
- */
- auto urls = data->urls();
- QStringList iconFiles;
- for (auto url : urls)
- {
- // only local files may be dropped...
- if (!url.isLocalFile())
- continue;
- iconFiles += url.toLocalFile();
- }
- installIcons(iconFiles);
- /*
- if(was_watching)
- startWatching();
- */
- return true;
- }
- return false;
-}
-
-Qt::ItemFlags IconList::flags(const QModelIndex &index) const
-{
- Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
- if (index.isValid())
- return Qt::ItemIsDropEnabled | defaultFlags;
- else
- return Qt::ItemIsDropEnabled | defaultFlags;
-}
-
-QVariant IconList::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid())
- return QVariant();
-
- int row = index.row();
-
- if (row < 0 || row >= d->icons.size())
- return QVariant();
-
- switch (role)
- {
- case Qt::DecorationRole:
- return d->icons[row].icon;
- case Qt::DisplayRole:
- return d->icons[row].name;
- case Qt::UserRole:
- return d->icons[row].key;
- default:
- return QVariant();
- }
-}
-
-int IconList::rowCount(const QModelIndex &parent) const
-{
- return d->icons.size();
-}
-
-void IconList::installIcons(QStringList iconFiles)
-{
- for (QString file : iconFiles)
- {
- QFileInfo fileinfo(file);
- if (!fileinfo.isReadable() || !fileinfo.isFile())
- continue;
- QString target = PathCombine("icons", fileinfo.fileName());
-
- QString suffix = fileinfo.suffix();
- if (suffix != "jpeg" && suffix != "png" && suffix != "jpg")
- continue;
-
- if (!QFile::copy(file, target))
- continue;
-
- QString key = fileinfo.baseName();
- addIcon(key, key, target);
- }
-}
-
-bool IconList::deleteIcon(QString key)
-{
- int iconIdx = getIconIndex(key);
- if (iconIdx == -1)
- return false;
- auto &iconEntry = d->icons[iconIdx];
- if (iconEntry.is_builtin)
- return false;
- if (QFile::remove(iconEntry.filename))
- {
- beginRemoveRows(QModelIndex(), iconIdx, iconIdx);
- d->icons.remove(iconIdx);
- reindex();
- endRemoveRows();
- }
- return true;
-}
-
-bool IconList::addIcon(QString key, QString name, QString path, bool is_builtin)
-{
- auto iter = d->index.find(key);
- if (iter != d->index.end())
- {
- if (d->icons[*iter].is_builtin)
- return false;
-
- QIcon icon(path);
- if (icon.isNull())
- return false;
-
- auto &oldOne = d->icons[*iter];
-
- if (!QFile::remove(oldOne.filename))
- return false;
-
- // replace the icon
- oldOne = {key, name, icon, is_builtin, path};
- dataChanged(index(*iter), index(*iter));
- return true;
- }
- else
- {
- QIcon icon(path);
- if (icon.isNull())
- return false;
-
- // add a new icon
- beginInsertRows(QModelIndex(), d->icons.size(), d->icons.size());
- d->icons.push_back({key, name, icon, is_builtin, path});
- d->index[key] = d->icons.size() - 1;
- endInsertRows();
- return true;
- }
-}
-
-void IconList::reindex()
-{
- d->index.clear();
- int i = 0;
- for (auto &iter : d->icons)
- {
- d->index[iter.key] = i;
- i++;
- }
-}
-
-QIcon IconList::getIcon(QString key)
-{
- int icon_index = getIconIndex(key);
-
- if (icon_index != -1)
- return d->icons[icon_index].icon;
-
- // Fallback for icons that don't exist.
- icon_index = getIconIndex("infinity");
-
- if (icon_index != -1)
- return d->icons[icon_index].icon;
- return QIcon();
-}
-
-int IconList::getIconIndex(QString key)
-{
- if (key == "default")
- key = "infinity";
-
- auto iter = d->index.find(key);
- if (iter != d->index.end())
- return *iter;
-
- return -1;
-}
-
-#include "IconList.moc" \ No newline at end of file
diff --git a/logic/lists/IconList.h b/logic/lists/IconList.h
deleted file mode 100644
index 40ad043b..00000000
--- a/logic/lists/IconList.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright 2013 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <QMutex>
-#include <QAbstractListModel>
-#include <QtGui/QIcon>
-
-class Private;
-
-class IconList : public QAbstractListModel
-{
-public:
- IconList();
- virtual ~IconList();
-
- QIcon getIcon(QString key);
- int getIconIndex(QString key);
-
- virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
-
- bool addIcon(QString key, QString name, QString path, bool is_builtin = false);
- bool deleteIcon(QString key);
-
- virtual QStringList mimeTypes() const;
- virtual Qt::DropActions supportedDropActions() const;
- virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
- const QModelIndex &parent);
- virtual Qt::ItemFlags flags(const QModelIndex &index) const;
-
- void installIcons(QStringList iconFiles);
-
-private:
- // hide copy constructor
- IconList(const IconList &) = delete;
- // hide assign op
- IconList &operator=(const IconList &) = delete;
- void reindex();
- Private *d;
-};
diff --git a/logic/lists/InstanceList.cpp b/logic/lists/InstanceList.cpp
index 15fd10ba..48a2865a 100644
--- a/logic/lists/InstanceList.cpp
+++ b/logic/lists/InstanceList.cpp
@@ -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/icons/IconList.h"
+#include "logic/lists/MinecraftVersionList.h"
#include "logic/BaseInstance.h"
#include "logic/InstanceFactory.h"
#include "logger/QsLog.h"
@@ -42,6 +45,9 @@ InstanceList::InstanceList(const QString &instDir, QObject *parent)
{
QDir::current().mkpath(m_instDir);
}
+
+ connect(MMC->minecraftlist().get(), &MinecraftVersionList::modelReset, this,
+ &InstanceList::loadList);
}
InstanceList::~InstanceList()
@@ -276,66 +282,155 @@ void InstanceList::loadGroupList(QMap<QString, QString> &groupMap)
}
}
-InstanceList::InstListError InstanceList::loadList()
+struct FTBRecord
{
- // load the instance groups
- QMap<QString, QString> groupMap;
- loadGroupList(groupMap);
+ QString dir;
+ QString name;
+ QString logo;
+ QString mcVersion;
+ QString description;
+};
+
+void InstanceList::loadForgeInstances(QMap<QString, QString> groupMap)
+{
+ QList<FTBRecord> records;
+ QDir dir = QDir(MMC->settings()->get("FTBLauncherRoot").toString());
+ QDir dataDir = QDir(MMC->settings()->get("FTBRoot").toString());
+ if (!dir.exists())
+ {
+ QLOG_INFO() << "The FTB launcher directory specified does not exist. Please check your "
+ "settings.";
+ return;
+ }
+ else if (!dataDir.exists())
+ {
+ QLOG_INFO() << "The FTB directory specified does not exist. Please check your settings";
+ return;
+ }
- beginResetModel();
+ dir.cd("ModPacks");
+ QFile f(dir.absoluteFilePath("modpacks.xml"));
+ if (!f.open(QFile::ReadOnly))
+ return;
- m_instances.clear();
- QDir dir(m_instDir);
- QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable,
- QDirIterator::FollowSymlinks);
- while (iter.hasNext())
+ // read the FTB packs XML.
+ QXmlStreamReader reader(&f);
+ while (!reader.atEnd())
{
- QString subDir = iter.next();
- if (!QFileInfo(PathCombine(subDir, "instance.cfg")).exists())
+ switch (reader.readNext())
+ {
+ case QXmlStreamReader::StartElement:
+ {
+ if (reader.name() == "modpack")
+ {
+ QXmlStreamAttributes attrs = reader.attributes();
+ FTBRecord record;
+ record.dir = attrs.value("dir").toString();
+ record.name = attrs.value("name").toString();
+ record.logo = attrs.value("logo").toString();
+ record.mcVersion = attrs.value("mcVersion").toString();
+ record.description = attrs.value("description").toString();
+ records.append(record);
+ }
+ break;
+ }
+ case QXmlStreamReader::EndElement:
+ break;
+ case QXmlStreamReader::Characters:
+ break;
+ default:
+ break;
+ }
+ }
+ f.close();
+
+ // process the records we acquired.
+ for (auto record : records)
+ {
+ auto instanceDir = dataDir.absoluteFilePath(record.dir);
+ auto templateDir = dir.absoluteFilePath(record.dir);
+ if (!QFileInfo(instanceDir).exists())
+ {
continue;
+ }
- BaseInstance *instPtr = NULL;
- auto &loader = InstanceFactory::get();
- auto error = loader.loadInstance(instPtr, subDir);
+ QString iconKey = record.logo;
+ iconKey.remove(QRegularExpression("\\..*"));
+ MMC->icons()->addIcon(iconKey, iconKey, PathCombine(templateDir, record.logo),
+ MMCIcon::Transient);
- if (error != InstanceFactory::NoLoadError && error != InstanceFactory::NotAnInstance)
+ if (!QFileInfo(PathCombine(instanceDir, "instance.cfg")).exists())
{
- QString errorMsg = QString("Failed to load instance %1: ")
- .arg(QFileInfo(subDir).baseName())
- .toUtf8();
-
- switch (error)
+ BaseInstance *instPtr = NULL;
+ auto &factory = InstanceFactory::get();
+ auto version = MMC->minecraftlist()->findVersion(record.mcVersion);
+ if (!version)
{
- default:
- errorMsg += QString("Unknown instance loader error %1").arg(error);
- break;
+ QLOG_ERROR() << "Can't load instance " << instanceDir
+ << " because minecraft version " << record.mcVersion
+ << " can't be resolved.";
+ continue;
}
- QLOG_ERROR() << errorMsg.toUtf8();
+ auto error = factory.createInstance(instPtr, version, instanceDir,
+ InstanceFactory::FTBInstance);
+
+ if (!instPtr || error != InstanceFactory::NoCreateError)
+ continue;
+
+ instPtr->setGroupInitial("FTB");
+ instPtr->setName(record.name);
+ instPtr->setIconKey(iconKey);
+ instPtr->setIntendedVersionId(record.mcVersion);
+ instPtr->setNotes(record.description);
+ continueProcessInstance(instPtr, error, instanceDir, groupMap);
}
- else if (!instPtr)
+ else
{
- QLOG_ERROR() << QString("Error loading instance %1. Instance loader returned null.")
- .arg(QFileInfo(subDir).baseName())
- .toUtf8();
+ BaseInstance *instPtr = NULL;
+ auto error = InstanceFactory::get().loadInstance(instPtr, instanceDir);
+ if (!instPtr || error != InstanceFactory::NoCreateError)
+ continue;
+ instPtr->setGroupInitial("FTB");
+ instPtr->setName(record.name);
+ instPtr->setIconKey(iconKey);
+ if (instPtr->intendedVersionId() != record.mcVersion)
+ instPtr->setIntendedVersionId(record.mcVersion);
+ instPtr->setNotes(record.description);
+ continueProcessInstance(instPtr, error, instanceDir, groupMap);
}
- else
+ }
+}
+
+InstanceList::InstListError InstanceList::loadList()
+{
+ // load the instance groups
+ QMap<QString, QString> groupMap;
+ loadGroupList(groupMap);
+
+ beginResetModel();
+
+ m_instances.clear();
+
+ {
+ QDirIterator iter(m_instDir, QDir::Dirs | QDir::NoDot | QDir::NoDotDot | QDir::Readable,
+ QDirIterator::FollowSymlinks);
+ while (iter.hasNext())
{
- std::shared_ptr<BaseInstance> inst(instPtr);
- auto iter = groupMap.find(inst->id());
- if (iter != groupMap.end())
- {
- inst->setGroupInitial((*iter));
- }
- 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 *)));
+ QString subDir = iter.next();
+ if (!QFileInfo(PathCombine(subDir, "instance.cfg")).exists())
+ continue;
+
+ BaseInstance *instPtr = NULL;
+ auto error = InstanceFactory::get().loadInstance(instPtr, subDir);
+ continueProcessInstance(instPtr, error, subDir, groupMap);
}
}
+
+ if (MMC->settings()->get("TrackFTBInstances").toBool())
+ {
+ loadForgeInstances(groupMap);
+ }
+
endResetModel();
emit dataIsInvalid();
return NoError;
@@ -409,6 +504,47 @@ 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);
diff --git a/logic/lists/InstanceList.h b/logic/lists/InstanceList.h
index f23b7763..0ce808e5 100644
--- a/logic/lists/InstanceList.h
+++ b/logic/lists/InstanceList.h
@@ -25,6 +25,8 @@
class BaseInstance;
+class QDir;
+
class InstanceList : public QAbstractListModel
{
Q_OBJECT
@@ -66,11 +68,6 @@ public:
}
/*!
- * \brief Loads the instance list. Triggers notifications.
- */
- InstListError loadList();
-
- /*!
* \brief Get the instance at index
*/
InstancePtr at(int i) const
@@ -108,6 +105,12 @@ public
slots:
void on_InstFolderChanged(const Setting &setting, QVariant value);
+ /*!
+ * \brief Loads the instance list. Triggers notifications.
+ */
+ InstListError loadList();
+ void loadForgeInstances(QMap<QString, QString> groupMap);
+
private
slots:
void propertiesChanged(BaseInstance *inst);
@@ -117,6 +120,9 @@ 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;
diff --git a/logic/lists/JavaVersionList.cpp b/logic/lists/JavaVersionList.cpp
index d2f0972c..e8c5acd0 100644
--- a/logic/lists/JavaVersionList.cpp
+++ b/logic/lists/JavaVersionList.cpp
@@ -172,14 +172,14 @@ JavaListLoadTask::~JavaListLoadTask()
void JavaListLoadTask::executeTask()
{
- setStatus("Detecting Java installations...");
+ setStatus(tr("Detecting Java installations..."));
JavaUtils ju;
QList<QString> candidate_paths = ju.FindJavaPaths();
- auto job = new JavaCheckerJob("Java detection");
- connect(job, SIGNAL(finished(QList<JavaCheckResult>)), this, SLOT(javaCheckerFinished(QList<JavaCheckResult>)));
- connect(job, SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int)));
+ m_job = std::shared_ptr<JavaCheckerJob>(new JavaCheckerJob("Java detection"));
+ connect(m_job.get(), SIGNAL(finished(QList<JavaCheckResult>)), this, SLOT(javaCheckerFinished(QList<JavaCheckResult>)));
+ connect(m_job.get(), SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int)));
QLOG_DEBUG() << "Probing the following Java paths: ";
for(QString candidate : candidate_paths)
@@ -188,10 +188,10 @@ void JavaListLoadTask::executeTask()
auto candidate_checker = new JavaChecker();
candidate_checker->path = candidate;
- job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
+ m_job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
}
- job->start();
+ m_job->start();
}
void JavaListLoadTask::checkerProgress(int current, int total)
@@ -203,6 +203,7 @@ void JavaListLoadTask::checkerProgress(int current, int total)
void JavaListLoadTask::javaCheckerFinished(QList<JavaCheckResult> results)
{
QList<JavaVersionPtr> candidates;
+ m_job.reset();
QLOG_DEBUG() << "Found the following valid Java installations:";
for(JavaCheckResult result : results)
diff --git a/logic/lists/JavaVersionList.h b/logic/lists/JavaVersionList.h
index 879b2480..e6cc8e5f 100644
--- a/logic/lists/JavaVersionList.h
+++ b/logic/lists/JavaVersionList.h
@@ -90,6 +90,7 @@ public slots:
void checkerProgress(int current, int total);
protected:
+ std::shared_ptr<JavaCheckerJob> m_job;
JavaVersionList *m_list;
JavaVersion *m_currentRecommended;
};
diff --git a/logic/lists/MinecraftVersionList.cpp b/logic/lists/MinecraftVersionList.cpp
index 523b81ac..91f86df0 100644
--- a/logic/lists/MinecraftVersionList.cpp
+++ b/logic/lists/MinecraftVersionList.cpp
@@ -139,7 +139,7 @@ MCVListLoadTask::~MCVListLoadTask()
void MCVListLoadTask::executeTask()
{
- setStatus("Loading instance version list...");
+ setStatus(tr("Loading instance version list..."));
auto worker = MMC->qnam();
vlistReply = worker->get(QNetworkRequest(QUrl("http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + "versions.json")));
connect(vlistReply, SIGNAL(finished()), this, SLOT(list_downloaded()));