Version filtering and general related code sanitization.

Version list dialog has alternating row background set.
Nostalgia versions, based on OneSix.
This commit is contained in:
Petr Mrázek 2013-08-11 18:58:24 +02:00
parent e5dc113bfc
commit 7e78a422e8
24 changed files with 254 additions and 431 deletions

View File

@ -47,6 +47,9 @@ OneSixUpdate.h
OneSixVersion.h OneSixVersion.h
VersionFactory.h VersionFactory.h
# Nostalgia
NostalgiaInstance.h
# Lists # Lists
lists/InstanceList.h lists/InstanceList.h
lists/InstVersionList.h lists/InstVersionList.h
@ -61,8 +64,6 @@ tasks/LoginTask.h
SET(LIBINST_SOURCES SET(LIBINST_SOURCES
# Base classes and infrastructure # Base classes and infrastructure
InstanceVersion.cpp
MinecraftVersion.cpp
InstanceFactory.cpp InstanceFactory.cpp
BaseUpdate.cpp BaseUpdate.cpp
BaseInstance.cpp BaseInstance.cpp
@ -83,6 +84,9 @@ OneSixVersion.cpp
OneSixUpdate.cpp OneSixUpdate.cpp
VersionFactory.cpp VersionFactory.cpp
# Nostalgia
NostalgiaInstance.cpp
# Lists # Lists
lists/InstanceList.cpp lists/InstanceList.cpp
lists/InstVersionList.cpp lists/InstVersionList.cpp

View File

@ -21,7 +21,9 @@
#include "BaseInstance.h" #include "BaseInstance.h"
#include "LegacyInstance.h" #include "LegacyInstance.h"
#include "OneSixInstance.h" #include "OneSixInstance.h"
#include "NostalgiaInstance.h"
#include "InstanceVersion.h" #include "InstanceVersion.h"
#include "MinecraftVersion.h"
#include "inifile.h" #include "inifile.h"
#include <inisettingsobject.h> #include <inisettingsobject.h>
@ -54,6 +56,10 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
{ {
inst = new OneSixInstance(instDir, m_settings, this); inst = new OneSixInstance(instDir, m_settings, this);
} }
else if(inst_type == "Nostalgia")
{
inst = new NostalgiaInstance(instDir, m_settings, this);
}
else else
{ {
return InstanceFactory::UnknownLoadError; return InstanceFactory::UnknownLoadError;
@ -62,7 +68,7 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
} }
InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*& inst, const InstVersion* version, const QString& instDir ) InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*& inst, InstVersionPtr version, const QString& instDir )
{ {
QDir rootDir(instDir); QDir rootDir(instDir);
@ -71,14 +77,37 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance( BaseInstance*&
{ {
return InstanceFactory::CantCreateDir; return InstanceFactory::CantCreateDir;
} }
auto mcVer = version.dynamicCast<MinecraftVersion>();
if(!mcVer)
return InstanceFactory::NoSuchVersion;
auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg")); auto m_settings = new INISettingsObject(PathCombine(instDir, "instance.cfg"));
m_settings->registerSetting(new Setting("InstanceType", "Legacy")); m_settings->registerSetting(new Setting("InstanceType", "Legacy"));
m_settings->set("InstanceType", "OneSix");
inst = new OneSixInstance(instDir, m_settings, this); switch(mcVer->type)
inst->setIntendedVersionId(version->descriptor()); {
case MinecraftVersion::Legacy:
m_settings->set("InstanceType", "Legacy");
inst = new LegacyInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor);
break;
case MinecraftVersion::OneSix:
m_settings->set("InstanceType", "OneSix");
inst = new OneSixInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor);
break;
case MinecraftVersion::Nostalgia:
m_settings->set("InstanceType", "Nostalgia");
inst = new NostalgiaInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor);
break;
default:
{
delete m_settings;
return InstanceFactory::NoSuchVersion;
}
}
//FIXME: really, how do you even know? //FIXME: really, how do you even know?
return InstanceFactory::NoCreateError; return InstanceFactory::NoCreateError;
} }

View File

@ -20,6 +20,7 @@
#include <QList> #include <QList>
#include "libmmc_config.h" #include "libmmc_config.h"
#include "InstanceVersion.h"
class InstVersion; class InstVersion;
class BaseInstance; class BaseInstance;
@ -46,6 +47,7 @@ public:
enum InstCreateError enum InstCreateError
{ {
NoCreateError = 0, NoCreateError = 0,
NoSuchVersion,
UnknownCreateError, UnknownCreateError,
InstExists, InstExists,
CantCreateDir CantCreateDir
@ -60,7 +62,7 @@ public:
* - InstExists if the given instance directory is already an instance. * - InstExists if the given instance directory is already an instance.
* - CantCreateDir if the given instance directory cannot be created. * - CantCreateDir if the given instance directory cannot be created.
*/ */
InstCreateError createInstance(BaseInstance *&inst, const InstVersion * version, const QString &instDir); InstCreateError createInstance(BaseInstance *&inst, InstVersionPtr version, const QString &instDir);
/*! /*!
* \brief Loads an instance from the given directory. * \brief Loads an instance from the given directory.

View File

@ -1,67 +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 "InstanceVersion.h"
#include "lists/InstVersionList.h"
InstVersion::InstVersion(const QString &descriptor,
const QString &name,
qint64 timestamp,
InstVersionList *parent) :
QObject(parent), m_descriptor(descriptor), m_name(name), m_timestamp(timestamp)
{
}
InstVersion::InstVersion(const InstVersion &other, QObject *parent) :
QObject(parent ? parent : other.parent()),
m_descriptor(other.descriptor()), m_name(other.name()), m_timestamp(other.timestamp())
{
}
InstVersionList *InstVersion::versionList() const
{
// Parent should *always* be either an InstVersionList or NULL.
if (!parent() || !parent()->inherits("InstVersionList"))
return NULL;
else
return (InstVersionList *)parent();
}
bool InstVersion::isLessThan(const InstVersion &other) const
{
return timestamp() < other.timestamp();
}
bool InstVersion::isGreaterThan(const InstVersion &other) const
{
return timestamp() > other.timestamp();
}
QString InstVersion::descriptor() const
{
return m_descriptor;
}
QString InstVersion::name() const
{
return m_name;
}
qint64 InstVersion::timestamp() const
{
return m_timestamp;
}

View File

@ -14,108 +14,56 @@
*/ */
#pragma once #pragma once
#include <QObject>
#include "libmmc_config.h" #include "libmmc_config.h"
#include <QSharedPointer>
class InstVersionList;
/*! /*!
* An abstract base class for instance versions. * An abstract base class for versions.
* InstVersions hold information about versions such as their names, identifiers,
* types, etc.
*/ */
class LIBMULTIMC_EXPORT InstVersion : public QObject struct LIBMULTIMC_EXPORT InstVersion
{ {
Q_OBJECT
/*!
* A string used to identify this version in config files.
* This should be unique within the version list or shenanigans will occur.
*/
Q_PROPERTY(QString descriptor READ descriptor CONSTANT)
/*!
* The name of this version as it is displayed to the user.
* For example: "1.5.1"
*/
Q_PROPERTY(QString name READ name)
/*!
* The name of this version's type as it is displayed to the user.
* For example: "Latest Version", "Snapshot", or "MCNostalgia"
*/
Q_PROPERTY(QString typeName READ typeName)
/*!
* Gets the version's timestamp.
* This is primarily used for sorting versions in a list.
*/
Q_PROPERTY(qint64 timestamp READ timestamp)
public:
/*!
* \brief Constructs a new InstVersion with the given parent.
* The parent *must* be the InstVersionList that contains this InstVersion.
* The InstVersion will be added to the list immediately after being created.
*/
explicit InstVersion(const QString &descriptor,
const QString &name,
qint64 timestamp,
InstVersionList *parent = 0);
/*!
* Copy constructor.
* If the 'parent' parameter is not NULL, sets this version's parent to the
* specified object, rather than setting it to the same parent as the version
* we're copying from.
* \param other The version to copy.
* \param parent If not NULL, will be set as the new version object's parent.
*/
InstVersion(const InstVersion &other, QObject *parent = 0);
virtual QString descriptor() const;
virtual QString name() const;
virtual QString typeName() const = 0;
virtual qint64 timestamp() const;
virtual InstVersionList *versionList() const;
/*!
* Creates a copy of this version with a different parent.
* \param newParent The parent QObject of the copy.
* \return A new, identical copy of this version with the given parent set.
*/
virtual InstVersion *copyVersion(InstVersionList *newParent) const = 0;
/*! /*!
* Checks if this version is less (older) than the given version. * Checks if this version is less (older) than the given version.
* \param other The version to compare this one to. * \param other The version to compare this one to.
* \return True if this version is older than the given version. * \return True if this version is older than the given version.
*/ */
virtual bool isLessThan(const InstVersion &other) const; virtual bool operator<(const InstVersion &rhs) const
{
return timestamp < rhs.timestamp;
}
/*! /*!
* Checks if this version is greater (newer) than the given version. * Checks if this version is greater (newer) than the given version.
* \param other The version to compare this one to. * \param other The version to compare this one to.
* \return True if this version is newer than the given version. * \return True if this version is newer than the given version.
*/ */
virtual bool isGreaterThan(const InstVersion &other) const; virtual bool operator>( const InstVersion& rhs ) const
{
return timestamp > rhs.timestamp;
}
/*! /*!
* \sa shouldSortBefore() * A string used to identify this version in config files.
* This should be unique within the version list or shenanigans will occur.
*/ */
virtual bool operator<(const InstVersion &rhs) { return isLessThan(rhs); } QString descriptor;
/*! /*!
* \sa shouldSortAfter() * The name of this version as it is displayed to the user.
* For example: "1.5.1"
*/ */
virtual bool operator>(const InstVersion &rhs) { return isGreaterThan(rhs); } QString name;
/*!
* Gets the version's timestamp.
* This is primarily used for sorting versions in a list.
*/
qint64 timestamp;
protected: virtual QString typeString() const
QString m_descriptor; {
QString m_name; return "InstVersion";
qint64 m_timestamp; }
}; };
typedef QSharedPointer<InstVersion> InstVersionPtr;
Q_DECLARE_METATYPE( InstVersionPtr )

View File

@ -1,93 +0,0 @@
/* Copyright 2013 Andrew Okin
*
* 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 "MinecraftVersion.h"
MinecraftVersion::MinecraftVersion(QString descriptor,
QString name,
qint64 timestamp,
QString dlUrl,
QString etag,
InstVersionList *parent) :
InstVersion(descriptor, name, timestamp, parent), m_dlUrl(dlUrl), m_etag(etag)
{
}
QString MinecraftVersion::descriptor() const
{
return m_descriptor;
}
QString MinecraftVersion::name() const
{
return m_name;
}
QString MinecraftVersion::typeName() const
{
switch (versionType())
{
case OldSnapshot:
return "Snapshot";
case Stable:
return "Stable";
case CurrentStable:
return "Current Stable";
case Snapshot:
return "Snapshot";
case Nostalgia:
return "Nostalgia";
default:
return QString("Unknown Type %1").arg(versionType());
}
}
qint64 MinecraftVersion::timestamp() const
{
return m_timestamp;
}
MinecraftVersion::VersionType MinecraftVersion::versionType() const
{
return m_type;
}
void MinecraftVersion::setVersionType(MinecraftVersion::VersionType typeName)
{
m_type = typeName;
}
QString MinecraftVersion::downloadURL() const
{
return m_dlUrl;
}
QString MinecraftVersion::etag() const
{
return m_etag;
}
InstVersion *MinecraftVersion::copyVersion(InstVersionList *newParent) const
{
MinecraftVersion *version = new MinecraftVersion(
descriptor(), name(), timestamp(), downloadURL(), etag(), newParent);
version->setVersionType(versionType());
return version;
}

View File

@ -18,50 +18,61 @@
#include "libmmc_config.h" #include "libmmc_config.h"
#include "InstanceVersion.h" #include "InstanceVersion.h"
#include <QStringList>
class LIBMULTIMC_EXPORT MinecraftVersion : public InstVersion struct LIBMULTIMC_EXPORT MinecraftVersion : public InstVersion
{ {
Q_OBJECT // From InstVersion:
/*
QString m_descriptor;
QString m_name;
qint64 m_timestamp;
*/
public:
explicit MinecraftVersion(QString descriptor,
QString name,
qint64 timestamp,
QString dlUrl,
QString etag,
InstVersionList *parent = 0);
static InstVersion *mcnVersion(QString rawName, QString niceName);
enum VersionType
{
OldSnapshot,
Stable,
CurrentStable,
Snapshot,
Nostalgia
};
virtual QString descriptor() const;
virtual QString name() const;
virtual QString typeName() const;
virtual qint64 timestamp() const;
virtual VersionType versionType() const;
virtual void setVersionType(VersionType typeName);
virtual QString downloadURL() const;
virtual QString etag() const;
virtual InstVersion *copyVersion(InstVersionList *newParent) const;
private:
/// The URL that this version will be downloaded from. maybe. /// The URL that this version will be downloaded from. maybe.
QString m_dlUrl; QString download_url;
/// ETag/MD5 Used to verify the integrity of the downloaded minecraft.jar.
QString m_etag;
/// This version's type. Used internally to identify what kind of version this is. /// This version's type. Used internally to identify what kind of version this is.
VersionType m_type; enum VersionType
{
OneSix,
Legacy,
Nostalgia
} type;
/// is this the latest version?
bool is_latest = false;
/// is this a snapshot?
bool is_snapshot = false;
virtual QString typeString() const
{
QStringList pre_final;
if(is_latest == true)
{
pre_final.append("Latest");
}
switch (type)
{
case OneSix:
pre_final.append("OneSix");
break;
case Legacy:
pre_final.append("Legacy");
break;
case Nostalgia:
pre_final.append("Nostalgia");
break;
default:
pre_final.append(QString("Type(%1)").arg(type));
break;
}
if(is_snapshot == true)
{
pre_final.append("Snapshot");
}
return pre_final.join(' ');
}
}; };

View File

@ -0,0 +1,12 @@
#include "NostalgiaInstance.h"
NostalgiaInstance::NostalgiaInstance ( const QString& rootDir, SettingsObject* settings, QObject* parent )
: OneSixInstance ( rootDir, settings, parent )
{
}
/*
ADD MORE
IF REQUIRED
*/

View File

@ -0,0 +1,10 @@
#pragma once
#include "OneSixInstance.h"
class LIBMULTIMC_EXPORT NostalgiaInstance : public OneSixInstance
{
Q_OBJECT
public:
explicit NostalgiaInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0);
};

View File

@ -39,7 +39,7 @@ void OneSixUpdate::executeTask()
{ {
QString intendedVersion = m_inst->intendedVersionId(); QString intendedVersion = m_inst->intendedVersionId();
// Get a pointer to the version object that corresponds to the instance's version. // Get a pointer to the version object that corresponds to the instance's version.
targetVersion = (MinecraftVersion *)MinecraftVersionList::getMainList().findVersion(intendedVersion); targetVersion = MinecraftVersionList::getMainList().findVersion(intendedVersion).dynamicCast<MinecraftVersion>();
if(targetVersion == nullptr) if(targetVersion == nullptr)
{ {
// don't do anything if it was invalid // don't do anything if it was invalid
@ -62,7 +62,7 @@ void OneSixUpdate::versionFileStart()
setStatus("Getting the version files from Mojang."); setStatus("Getting the version files from Mojang.");
QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/");
urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; urlstr += targetVersion->descriptor + "/" + targetVersion->descriptor + ".json";
auto dljob = DownloadJob::create(QUrl(urlstr)); auto dljob = DownloadJob::create(QUrl(urlstr));
specificVersionDownloadJob.reset(new JobList()); specificVersionDownloadJob.reset(new JobList());
specificVersionDownloadJob->add(dljob); specificVersionDownloadJob->add(dljob);
@ -77,7 +77,7 @@ void OneSixUpdate::versionFileFinished()
JobPtr firstJob = specificVersionDownloadJob->getFirstJob(); JobPtr firstJob = specificVersionDownloadJob->getFirstJob();
auto DlJob = firstJob.dynamicCast<DownloadJob>(); auto DlJob = firstJob.dynamicCast<DownloadJob>();
QString version_id = targetVersion->descriptor(); QString version_id = targetVersion->descriptor;
QString inst_dir = m_inst->rootDir(); QString inst_dir = m_inst->rootDir();
// save the version file in $instanceId/version.json // save the version file in $instanceId/version.json
{ {

View File

@ -50,7 +50,7 @@ private:
JobListQueue download_queue; JobListQueue download_queue;
// target version, determined during this task // target version, determined during this task
MinecraftVersion *targetVersion; QSharedPointer<MinecraftVersion> targetVersion;
}; };

View File

@ -181,12 +181,6 @@ public:
/// the list of libs - both active and inactive, native and java /// the list of libs - both active and inactive, native and java
QList<QSharedPointer<Library> > libraries; QList<QSharedPointer<Library> > libraries;
/**
* is this actually a legacy version? if so, none of the other stuff here will be ever used.
* added by FullVersionFactory
*/
bool isLegacy;
/* /*
FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. FIXME: add support for those rules here? Looks like a pile of quick hacks to me though.
@ -211,7 +205,6 @@ public:
FullVersion() FullVersion()
{ {
minimumLauncherVersion = 0xDEADBEEF; minimumLauncherVersion = 0xDEADBEEF;
isLegacy = false;
} }
QList<QSharedPointer<Library> > getActiveNormalLibs(); QList<QSharedPointer<Library> > getActiveNormalLibs();

View File

@ -49,10 +49,6 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
{ {
fullVersion->id = root.value("id").toString(); fullVersion->id = root.value("id").toString();
// if it's on our legacy list, it's legacy
if(legacyWhitelist.contains(fullVersion->id))
fullVersion->isLegacy = true;
fullVersion->mainClass = root.value("mainClass").toString(); fullVersion->mainClass = root.value("mainClass").toString();
auto procArgsValue = root.value("processArguments"); auto procArgsValue = root.value("processArguments");
if(procArgsValue.isString()) if(procArgsValue.isString())
@ -62,7 +58,6 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
if(toCompare == "legacy") if(toCompare == "legacy")
{ {
fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}"; fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}";
fullVersion->isLegacy = true;
} }
else if(toCompare == "username_session") else if(toCompare == "username_session")
{ {
@ -83,11 +78,7 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
auto minecraftTypeValue = root.value("type"); auto minecraftTypeValue = root.value("type");
if(minecraftTypeValue.isString()) if(minecraftTypeValue.isString())
{ {
QString copy = fullVersion->type = minecraftTypeValue.toString(); fullVersion->type = minecraftTypeValue.toString();
if(copy == "old_aplha" || copy == "old_beta")
{
fullVersion->isLegacy = true;
}
} }
fullVersion->releaseTime = root.value("releaseTime").toString(); fullVersion->releaseTime = root.value("releaseTime").toString();
@ -117,7 +108,7 @@ QSharedPointer<FullVersion> FullVersionFactory::parse4(QJsonObject root, QShared
auto urlVal = libObj.value("url"); auto urlVal = libObj.value("url");
if(urlVal.isString()) if(urlVal.isString())
{ {
library->setBaseUrl(nameVal.toString()); library->setBaseUrl(urlVal.toString());
} }
// Extract excludes (if any) // Extract excludes (if any)
@ -201,6 +192,4 @@ QSharedPointer<FullVersion> FullVersionFactory::parse(QByteArray data)
FullVersionFactory::FullVersionFactory() FullVersionFactory::FullVersionFactory()
{ {
m_error = FullVersionFactory::AllOK; m_error = FullVersionFactory::AllOK;
legacyWhitelist.append("1.5.1");
legacyWhitelist.append("1.5.2");
} }

View File

@ -21,5 +21,4 @@ public:
private: private:
QSharedPointer<FullVersion> parse4(QJsonObject root, QSharedPointer<FullVersion> product); QSharedPointer<FullVersion> parse4(QJsonObject root, QSharedPointer<FullVersion> product);
QList<QSharedPointer<Rule> > parse4rules(QJsonObject & baseObj); QList<QSharedPointer<Rule> > parse4rules(QJsonObject & baseObj);
QStringList legacyWhitelist;
}; };

View File

@ -21,20 +21,20 @@ InstVersionList::InstVersionList(QObject *parent) :
{ {
} }
const InstVersion *InstVersionList::findVersion(const QString &descriptor) InstVersionPtr InstVersionList::findVersion( const QString& descriptor )
{ {
for (int i = 0; i < count(); i++) for (int i = 0; i < count(); i++)
{ {
if (at(i)->descriptor() == descriptor) if (at(i)->descriptor == descriptor)
return at(i); return at(i);
} }
return NULL; return InstVersionPtr();
} }
const InstVersion *InstVersionList::getLatestStable() const InstVersionPtr InstVersionList::getLatestStable() const
{ {
if (count() <= 0) if (count() <= 0)
return NULL; return InstVersionPtr();
else else
return at(0); return at(0);
} }
@ -48,7 +48,7 @@ QVariant InstVersionList::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
const InstVersion *version = at(index.row()); InstVersionPtr version = at(index.row());
switch (role) switch (role)
{ {
@ -56,23 +56,23 @@ QVariant InstVersionList::data(const QModelIndex &index, int role) const
switch (index.column()) switch (index.column())
{ {
case NameColumn: case NameColumn:
return version->name(); return version->name;
case TypeColumn: case TypeColumn:
return version->typeName(); return version->typeString();
case TimeColumn: case TimeColumn:
return version->timestamp(); return version->timestamp;
default: default:
return QVariant(); return QVariant();
} }
case Qt::ToolTipRole: case Qt::ToolTipRole:
return version->descriptor(); return version->descriptor;
case VersionPointerRole: case VersionPointerRole:
return qVariantFromValue((void *) version); return qVariantFromValue(version);
default: default:
return QVariant(); return QVariant();

View File

@ -18,10 +18,11 @@
#include <QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QSharedPointer>
#include "libmmc_config.h" #include "libmmc_config.h"
#include "InstanceVersion.h"
class InstVersion;
class Task; class Task;
/*! /*!
@ -71,7 +72,7 @@ public:
virtual bool isLoaded() = 0; virtual bool isLoaded() = 0;
//! Gets the version at the given index. //! Gets the version at the given index.
virtual const InstVersion *at(int i) const = 0; virtual const InstVersionPtr at(int i) const = 0;
//! Returns the number of versions in the list. //! Returns the number of versions in the list.
virtual int count() const = 0; virtual int count() const = 0;
@ -90,14 +91,14 @@ public:
* \return A const pointer to the version with the given descriptor. NULL if * \return A const pointer to the version with the given descriptor. NULL if
* one doesn't exist. * one doesn't exist.
*/ */
virtual const InstVersion *findVersion(const QString &descriptor); virtual InstVersionPtr findVersion(const QString &descriptor);
/*! /*!
* \brief Gets the latest stable version of this instance type. * \brief Gets the latest stable version of this instance type.
* This is the version that will be selected by default. * This is the version that will be selected by default.
* By default, this is simply the first version in the list. * By default, this is simply the first version in the list.
*/ */
virtual const InstVersion *getLatestStable() const; virtual InstVersionPtr getLatestStable() const;
/*! /*!
* Sorts the version list. * Sorts the version list.
@ -117,5 +118,5 @@ protected slots:
* then copies the versions and sets their parents correctly. * then copies the versions and sets their parents correctly.
* \param versions List of versions whose parents should be set. * \param versions List of versions whose parents should be set.
*/ */
virtual void updateListData(QList<InstVersion *> versions) = 0; virtual void updateListData(QList<InstVersionPtr > versions) = 0;
}; };

View File

@ -52,7 +52,7 @@ bool MinecraftVersionList::isLoaded()
return m_loaded; return m_loaded;
} }
const InstVersion *MinecraftVersionList::at(int i) const const InstVersionPtr MinecraftVersionList::at(int i) const
{ {
return m_vlist.at(i); return m_vlist.at(i);
} }
@ -62,28 +62,11 @@ int MinecraftVersionList::count() const
return m_vlist.count(); return m_vlist.count();
} }
void MinecraftVersionList::printToStdOut() const bool cmpVersions(InstVersionPtr first, InstVersionPtr second)
{ {
qDebug() << "---------------- Version List ----------------"; const InstVersion & left = *first;
const InstVersion & right = *second;
for (int i = 0; i < m_vlist.count(); i++) return left > right;
{
MinecraftVersion *version = qobject_cast<MinecraftVersion *>(m_vlist.at(i));
if (!version)
continue;
qDebug() << "Version " << version->name();
qDebug() << "\tDownload: " << version->downloadURL();
qDebug() << "\tTimestamp: " << version->timestamp();
qDebug() << "\tType: " << version->typeName();
qDebug() << "----------------------------------------------";
}
}
bool cmpVersions(const InstVersion *first, const InstVersion *second)
{
return !first->isLessThan(*second);
} }
void MinecraftVersionList::sort() void MinecraftVersionList::sort()
@ -93,16 +76,17 @@ void MinecraftVersionList::sort()
endResetModel(); endResetModel();
} }
InstVersion *MinecraftVersionList::getLatestStable() const InstVersionPtr MinecraftVersionList::getLatestStable() const
{ {
for (int i = 0; i < m_vlist.length(); i++) for (int i = 0; i < m_vlist.length(); i++)
{ {
if (((MinecraftVersion *)m_vlist.at(i))->versionType() == MinecraftVersion::CurrentStable) auto ver = m_vlist.at(i).dynamicCast<MinecraftVersion>();
if (ver->is_latest && !ver->is_snapshot)
{ {
return m_vlist.at(i); return m_vlist.at(i);
} }
} }
return NULL; return InstVersionPtr();
} }
MinecraftVersionList &MinecraftVersionList::getMainList() MinecraftVersionList &MinecraftVersionList::getMainList()
@ -110,32 +94,12 @@ MinecraftVersionList &MinecraftVersionList::getMainList()
return mcVList; return mcVList;
} }
void MinecraftVersionList::updateListData(QList<InstVersion *> versions) void MinecraftVersionList::updateListData(QList<InstVersionPtr > versions)
{ {
// First, we populate a temporary list with the copies of the versions.
QList<InstVersion *> tempList;
for (int i = 0; i < versions.length(); i++)
{
InstVersion *version = versions[i]->copyVersion(this);
Q_ASSERT(version != NULL);
tempList.append(version);
}
// Now we swap the temporary list into the actual version list.
// This applies our changes to the version list immediately and still gives us
// access to the old version list so that we can delete the objects in it and
// free their memory. By doing this, we cause the version list to update as
// quickly as possible.
beginResetModel(); beginResetModel();
m_vlist.swap(tempList); m_vlist = versions;
m_loaded = true; m_loaded = true;
endResetModel(); endResetModel();
// We called swap, so all the data that was in the version list previously is now in
// tempList (and vice-versa). Now we just free the memory.
while (!tempList.isEmpty())
delete tempList.takeFirst();
// NOW SORT!! // NOW SORT!!
sort(); sort();
} }
@ -160,6 +124,25 @@ MCVListLoadTask::MCVListLoadTask(MinecraftVersionList *vlist)
m_list = vlist; m_list = vlist;
m_currentStable = NULL; m_currentStable = NULL;
vlistReply = nullptr; vlistReply = nullptr;
legacyWhitelist.insert("1.5.2");
legacyWhitelist.insert("1.5.1");
legacyWhitelist.insert("1.5");
legacyWhitelist.insert("1.4.7");
legacyWhitelist.insert("1.4.6");
legacyWhitelist.insert("1.4.5");
legacyWhitelist.insert("1.4.4");
legacyWhitelist.insert("1.4.2");
legacyWhitelist.insert("1.3.2");
legacyWhitelist.insert("1.3.1");
legacyWhitelist.insert("1.2.5");
legacyWhitelist.insert("1.2.4");
legacyWhitelist.insert("1.2.3");
legacyWhitelist.insert("1.2.2");
legacyWhitelist.insert("1.2.1");
legacyWhitelist.insert("1.1");
legacyWhitelist.insert("1.0.1");
legacyWhitelist.insert("1.0.0");
// TODO: consider adding betas here too (whatever the legacy launcher supports)
} }
MCVListLoadTask::~MCVListLoadTask() MCVListLoadTask::~MCVListLoadTask()
@ -232,8 +215,12 @@ void MCVListLoadTask::list_downloaded()
} }
QJsonArray versions = root.value("versions").toArray(); QJsonArray versions = root.value("versions").toArray();
QList<InstVersionPtr > tempList;
for (int i = 0; i < versions.count(); i++) for (int i = 0; i < versions.count(); i++)
{ {
bool is_snapshot = false;
bool is_latest = false;
// Load the version info. // Load the version info.
if(!versions[i].isObject()) if(!versions[i].isObject())
{ {
@ -257,50 +244,53 @@ void MCVListLoadTask::list_downloaded()
//FIXME: log this somewhere //FIXME: log this somewhere
continue; continue;
} }
// Parse the type. // Parse the type.
MinecraftVersion::VersionType versionType; MinecraftVersion::VersionType versionType;
// OneSix or Legacy. use filter to determine type
if (versionTypeStr == "release") if (versionTypeStr == "release")
{ {
// Check if this version is the current stable version. versionType = legacyWhitelist.contains(versionID)?MinecraftVersion::Legacy:MinecraftVersion::OneSix;
if (versionID == latestReleaseID) is_latest = (versionID == latestReleaseID);
versionType = MinecraftVersion::CurrentStable; is_snapshot = false;
else
versionType = MinecraftVersion::Stable;
} }
else if(versionTypeStr == "snapshot") else if(versionTypeStr == "snapshot") // It's a snapshot... yay
{ {
versionType = MinecraftVersion::Snapshot; versionType = legacyWhitelist.contains(versionID)?MinecraftVersion::Legacy:MinecraftVersion::OneSix;
is_latest = (versionID == latestSnapshotID);
is_snapshot = true;
} }
else if(versionTypeStr == "old_beta" || versionTypeStr == "old_alpha") else if(versionTypeStr == "old_alpha")
{ {
versionType = MinecraftVersion::Nostalgia; versionType = MinecraftVersion::Nostalgia;
is_latest = false;
is_snapshot = false;
}
else if(versionTypeStr == "old_beta")
{
versionType = MinecraftVersion::Legacy;
is_latest = false;
is_snapshot = false;
} }
else else
{ {
//FIXME: log this somewhere //FIXME: log this somewhere
continue; continue;
} }
//FIXME: detect if snapshots are old or not
// Get the download URL. // Get the download URL.
QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/"; QString dlUrl = QString(MCVLIST_URLBASE) + versionID + "/";
// Now, we construct the version object and add it to the list. // Now, we construct the version object and add it to the list.
MinecraftVersion *mcVersion = new MinecraftVersion(versionID, versionID, versionTime.toMSecsSinceEpoch(),dlUrl, ""); QSharedPointer<MinecraftVersion> mcVersion(new MinecraftVersion());
mcVersion->setVersionType(versionType); mcVersion->name = mcVersion->descriptor = versionID;
mcVersion->timestamp = versionTime.toMSecsSinceEpoch();
mcVersion->download_url = dlUrl;
mcVersion->is_latest = is_latest;
mcVersion->is_snapshot = is_snapshot;
mcVersion->type = versionType;
tempList.append(mcVersion); tempList.append(mcVersion);
} }
m_list->updateListData(tempList); m_list->updateListData(tempList);
// Once that's finished, we can delete the versions in our temp list.
while (!tempList.isEmpty())
delete tempList.takeFirst();
#ifdef PRINT_VERSIONS
m_list->printToStdOut();
#endif
emitSucceeded(); emitSucceeded();
return; return;
} }

View File

@ -17,6 +17,8 @@
#include <QObject> #include <QObject>
#include <QList> #include <QList>
#include <QSet>
#include <QSharedPointer>
#include "InstVersionList.h" #include "InstVersionList.h"
#include "tasks/Task.h" #include "tasks/Task.h"
@ -36,12 +38,11 @@ public:
virtual Task *getLoadTask(); virtual Task *getLoadTask();
virtual bool isLoaded(); virtual bool isLoaded();
virtual const InstVersion *at(int i) const; virtual const InstVersionPtr at(int i) const;
virtual int count() const; virtual int count() const;
virtual void printToStdOut() const;
virtual void sort(); virtual void sort();
virtual InstVersion *getLatestStable() const; virtual InstVersionPtr getLatestStable() const;
/*! /*!
* Gets the main version list instance. * Gets the main version list instance.
@ -50,12 +51,12 @@ public:
protected: protected:
QList<InstVersion *>m_vlist; QList<InstVersionPtr > m_vlist;
bool m_loaded; bool m_loaded;
protected slots: protected slots:
virtual void updateListData(QList<InstVersion *> versions); virtual void updateListData(QList<InstVersionPtr > versions);
}; };
class MCVListLoadTask : public Task class MCVListLoadTask : public Task
@ -76,10 +77,8 @@ protected:
bool loadFromVList(); bool loadFromVList();
QNetworkReply *vlistReply; QNetworkReply *vlistReply;
MinecraftVersionList *m_list; MinecraftVersionList *m_list;
QList<InstVersion *> tempList; //! < List of loaded versions
MinecraftVersion *m_currentStable; MinecraftVersion *m_currentStable;
QSet<QString> legacyWhitelist;
}; };

View File

@ -534,7 +534,7 @@ void MainWindow::on_actionChangeInstMCVersion_triggered()
VersionSelectDialog vselect(inst->versionList(), this); VersionSelectDialog vselect(inst->versionList(), this);
if (vselect.exec() && vselect.selectedVersion()) if (vselect.exec() && vselect.selectedVersion())
{ {
inst->setIntendedVersionId(vselect.selectedVersion()->descriptor()); inst->setIntendedVersionId(vselect.selectedVersion()->descriptor);
} }
} }

View File

@ -37,8 +37,6 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::NewInstanceDialog) ui(new Ui::NewInstanceDialog)
{ {
m_selectedVersion = NULL;
ui->setupUi(this); ui->setupUi(this);
resize(minimumSizeHint()); resize(minimumSizeHint());
layout()->setSizeConstraint(QLayout::SetFixedSize); layout()->setSizeConstraint(QLayout::SetFixedSize);
@ -64,17 +62,16 @@ NewInstanceDialog::~NewInstanceDialog()
void NewInstanceDialog::updateDialogState() void NewInstanceDialog::updateDialogState()
{ {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled( ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty() && m_selectedVersion);
!instName().isEmpty() && m_selectedVersion);
} }
void NewInstanceDialog::setSelectedVersion(const InstVersion *version) void NewInstanceDialog::setSelectedVersion(InstVersionPtr version)
{ {
m_selectedVersion = version; m_selectedVersion = version;
if (m_selectedVersion) if (m_selectedVersion)
{ {
ui->versionTextBox->setText(version->name()); ui->versionTextBox->setText(version->name);
} }
else else
{ {
@ -94,7 +91,7 @@ QString NewInstanceDialog::iconKey() const
return InstIconKey; return InstIconKey;
} }
const InstVersion *NewInstanceDialog::selectedVersion() const InstVersionPtr NewInstanceDialog::selectedVersion() const
{ {
return m_selectedVersion; return m_selectedVersion;
} }
@ -105,7 +102,7 @@ void NewInstanceDialog::on_btnChangeVersion_clicked()
vselect.exec(); vselect.exec();
if (vselect.result() == QDialog::Accepted) if (vselect.result() == QDialog::Accepted)
{ {
const InstVersion *version = vselect.selectedVersion(); InstVersionPtr version = vselect.selectedVersion();
if (version) if (version)
setSelectedVersion(version); setSelectedVersion(version);
} }

View File

@ -17,9 +17,7 @@
#define NEWINSTANCEDIALOG_H #define NEWINSTANCEDIALOG_H
#include <QDialog> #include <QDialog>
#include "InstanceVersion.h"
class InstanceTypeInterface;
class InstVersion;
namespace Ui { namespace Ui {
class NewInstanceDialog; class NewInstanceDialog;
@ -35,13 +33,13 @@ public:
void updateDialogState(); void updateDialogState();
void setSelectedVersion(const InstVersion *version); void setSelectedVersion(InstVersionPtr version);
void loadVersionList(); void loadVersionList();
QString instName() const; QString instName() const;
QString iconKey() const; QString iconKey() const;
const InstVersion *selectedVersion() const; InstVersionPtr selectedVersion() const;
private slots: private slots:
void on_btnChangeVersion_clicked(); void on_btnChangeVersion_clicked();
@ -51,7 +49,7 @@ private slots:
private: private:
Ui::NewInstanceDialog *ui; Ui::NewInstanceDialog *ui;
const InstVersion *m_selectedVersion; InstVersionPtr m_selectedVersion;
QString InstIconKey; QString InstIconKey;
}; };

View File

@ -68,13 +68,11 @@ void VersionSelectDialog::loadList()
taskDlg->exec(loadTask); taskDlg->exec(loadTask);
} }
const InstVersion *VersionSelectDialog::selectedVersion() const InstVersionPtr VersionSelectDialog::selectedVersion() const
{ {
const InstVersion *versionPtr = (const InstVersion *) auto currentIndex = ui->listView->selectionModel()->currentIndex();
m_proxyModel->data(ui->listView->selectionModel()->currentIndex(), auto variant = m_proxyModel->data(currentIndex, InstVersionList::VersionPointerRole);
InstVersionList::VersionPointerRole).value<void *>(); return variant.value<InstVersionPtr>();
return versionPtr;
} }
void VersionSelectDialog::on_refreshButton_clicked() void VersionSelectDialog::on_refreshButton_clicked()

View File

@ -19,9 +19,9 @@
#include <QDialog> #include <QDialog>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <InstanceVersion.h>
class InstVersionList; class InstVersionList;
class InstVersion;
namespace Ui namespace Ui
{ {
@ -41,7 +41,7 @@ public:
//! Starts a task that loads the list. //! Starts a task that loads the list.
void loadList(); void loadList();
const InstVersion *selectedVersion() const; InstVersionPtr selectedVersion() const;
private slots: private slots:
void on_refreshButton_clicked(); void on_refreshButton_clicked();

View File

@ -19,6 +19,9 @@
<property name="horizontalScrollBarPolicy"> <property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum> <enum>Qt::ScrollBarAlwaysOff</enum>
</property> </property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated"> <property name="rootIsDecorated">
<bool>false</bool> <bool>false</bool>
</property> </property>