瀏覽代碼

Merge pull request #2723 from Nordsoft91/versions-fix

Launcher & lib versions unification
Nordsoft91 2 年之前
父節點
當前提交
9af73c2212

+ 23 - 65
launcher/modManager/cmodlist.cpp

@@ -14,54 +14,7 @@
 #include "../../lib/JsonNode.h"
 #include "../../lib/filesystem/CFileInputStream.h"
 #include "../../lib/GameConstants.h"
-
-namespace
-{
-bool isCompatible(const QString & verMin, const QString & verMax)
-{
-	QVersionNumber vcmiVersion(VCMI_VERSION_MAJOR,
-							   VCMI_VERSION_MINOR,
-							   VCMI_VERSION_PATCH);
-	
-	auto versionMin = QVersionNumber::fromString(verMin);
-	auto versionMax = QVersionNumber::fromString(verMax);
-	
-	auto buildVersion = [](QVersionNumber & ver)
-	{
-		const int maxSections = 3; // versions consist from up to 3 sections, major.minor.patch
-
-		if(ver.segmentCount() < maxSections)
-		{
-			auto segments = ver.segments();
-			for(int i = segments.size(); i < maxSections; ++i)
-				segments.append(0);
-			ver = QVersionNumber(segments);
-		}
-	};
-
-	if(!versionMin.isNull())
-	{
-		buildVersion(versionMin);
-		if(vcmiVersion < versionMin)
-			return false;
-	}
-	
-	if(!versionMax.isNull())
-	{
-		buildVersion(versionMax);
-		if(vcmiVersion > versionMax)
-			return false;
-	}
-	return true;
-}
-}
-
-bool CModEntry::compareVersions(QString lesser, QString greater)
-{
-	auto versionLesser = QVersionNumber::fromString(lesser);
-	auto versionGreater = QVersionNumber::fromString(greater);
-	return versionLesser < versionGreater;
-}
+#include "../../lib/modding/CModVersion.h"
 
 QString CModEntry::sizeToString(double size)
 {
@@ -110,18 +63,24 @@ bool CModEntry::isUpdateable() const
 	if(!isInstalled())
 		return false;
 
-	QString installedVer = localData["installedVersion"].toString();
-	QString availableVer = repository["latestVersion"].toString();
+	auto installedVer = localData["installedVersion"].toString().toStdString();
+	auto availableVer = repository["latestVersion"].toString().toStdString();
 
-	if(compareVersions(installedVer, availableVer))
-		return true;
-	return false;
+	return (CModVersion::fromString(installedVer) < CModVersion::fromString(availableVer));
+}
+
+bool isCompatible(const QVariantMap & compatibility)
+{
+	auto compatibleMin = CModVersion::fromString(compatibility["min"].toString().toStdString());
+	auto compatibleMax = CModVersion::fromString(compatibility["max"].toString().toStdString());
+
+	return (compatibleMin.isNull() || CModVersion::GameVersion().compatible(compatibleMin, true, true))
+			&& (compatibleMax.isNull() || compatibleMax.compatible(CModVersion::GameVersion(), true, true));
 }
 
 bool CModEntry::isCompatible() const
 {
-	auto compatibility = localData["compatibility"].toMap();
-	return ::isCompatible(compatibility["min"].toString(), compatibility["max"].toString());
+	return ::isCompatible(localData["compatibility"].toMap());
 }
 
 bool CModEntry::isEssential() const
@@ -186,10 +145,10 @@ QVariant CModEntry::getValueImpl(QString value, bool localized) const
 	if(repository.contains(value) && localData.contains(value))
 	{
 		// value is present in both repo and locally installed. Select one from latest version
-		QString installedVer = localData["installedVersion"].toString();
-		QString availableVer = repository["latestVersion"].toString();
+		auto installedVer = localData["installedVersion"].toString().toStdString();
+		auto availableVer = repository["latestVersion"].toString().toStdString();
 
-		useRepositoryData = compareVersions(installedVer, availableVer);
+		useRepositoryData = CModVersion::fromString(installedVer) < CModVersion::fromString(availableVer);
 	}
 
 	auto & storage = useRepositoryData ? repository : localData;
@@ -310,10 +269,8 @@ CModEntry CModList::getMod(QString modname) const
 
 	if(settings.value("active").toBool())
 	{
-		auto compatibility = local.value("compatibility").toMap();
-		if(compatibility["min"].isValid() || compatibility["max"].isValid())
-			if(!isCompatible(compatibility["min"].toString(), compatibility["max"].toString()))
-				settings["active"] = false;
+		if(!::isCompatible(local.value("compatibility").toMap()))
+			settings["active"] = false;
 	}
 
 	for(auto entry : repositories)
@@ -322,10 +279,11 @@ CModEntry CModList::getMod(QString modname) const
 		if(repoVal.isValid())
 		{
 			auto repoValMap = repoVal.toMap();
-			auto compatibility = repoValMap["compatibility"].toMap();
-			if(isCompatible(compatibility["min"].toString(), compatibility["max"].toString()))
+			if(::isCompatible(repoValMap["compatibility"].toMap()))
 			{
-				if(repo.empty() || CModEntry::compareVersions(repo["version"].toString(), repoValMap["version"].toString()))
+				if(repo.empty()
+					|| CModVersion::fromString(repo["version"].toString().toStdString())
+					 < CModVersion::fromString(repoValMap["version"].toString().toStdString()))
 				{
 					//take valid download link and screenshots before assignment
 					auto download = repo.value("download");

+ 0 - 3
launcher/modManager/cmodlist.h

@@ -74,9 +74,6 @@ public:
 	QVariant getValue(QString value) const;
 	QVariant getBaseValue(QString value) const;
 
-	// returns true if less < greater comparing versions section by section
-	static bool compareVersions(QString lesser, QString greater);
-
 	static QString sizeToString(double size);
 };
 

+ 2 - 1
launcher/modManager/cmodlistview_moc.cpp

@@ -25,6 +25,7 @@
 
 #include "../../lib/CConfigHandler.h"
 #include "../../lib/Languages.h"
+#include "../../lib/modding/CModVersion.h"
 
 void CModListView::setupModModel()
 {
@@ -191,7 +192,7 @@ QString CModListView::genChangelogText(CModEntry & mod)
 
 	std::sort(versions.begin(), versions.end(), [](QString lesser, QString greater)
 	{
-		return CModEntry::compareVersions(lesser, greater);
+		return CModVersion::fromString(lesser.toStdString()) < CModVersion::fromString(greater.toStdString());
 	});
 	std::reverse(versions.begin(), versions.end());
 

+ 35 - 7
lib/modding/CModVersion.cpp

@@ -20,9 +20,9 @@ CModVersion CModVersion::GameVersion()
 
 CModVersion CModVersion::fromString(std::string from)
 {
-	int major = 0;
-	int minor = 0;
-	int patch = 0;
+	int major = Any;
+	int minor = Any;
+	int patch = Any;
 	try
 	{
 		auto pointPos = from.find('.');
@@ -45,19 +45,47 @@ CModVersion CModVersion::fromString(std::string from)
 
 std::string CModVersion::toString() const
 {
-	return std::to_string(major) + '.' + std::to_string(minor) + '.' + std::to_string(patch);
+	std::string res;
+	if(major != Any)
+	{
+		res += std::to_string(major);
+		if(minor != Any)
+		{
+			res += '.' + std::to_string(minor);
+			if(patch != Any)
+				res += '.' + std::to_string(patch);
+		}
+	}
+	return res;
 }
 
 bool CModVersion::compatible(const CModVersion & other, bool checkMinor, bool checkPatch) const
 {
+	bool doCheckMinor = checkMinor && minor != Any && other.minor != Any;
+	bool doCheckPatch = checkPatch && patch != Any && other.patch != Any;
+	
+	assert(!doCheckPatch || (doCheckPatch && doCheckMinor));
+		
 	return  (major == other.major &&
-			(!checkMinor || minor >= other.minor) &&
-			(!checkPatch || minor > other.minor || (minor == other.minor && patch >= other.patch)));
+			(!doCheckMinor || minor >= other.minor) &&
+			(!doCheckPatch || minor > other.minor || (minor == other.minor && patch >= other.patch)));
 }
 
 bool CModVersion::isNull() const
 {
-	return major == 0 && minor == 0 && patch == 0;
+	return major == Any;
+}
+
+bool operator < (const CModVersion & lesser, const CModVersion & greater)
+{
+	//specific is "greater" than non-specific, that's why do not check for Any value
+	if(lesser.major == greater.major)
+	{
+		if(lesser.minor == greater.minor)
+			return lesser.patch < greater.patch;
+		return lesser.minor < greater.minor;
+	}
+	return lesser.major < greater.major;
 }
 
 VCMI_LIB_NAMESPACE_END

+ 7 - 3
lib/modding/CModVersion.h

@@ -20,9 +20,11 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 struct DLL_LINKAGE CModVersion
 {
-	int major = 0;
-	int minor = 0;
-	int patch = 0;
+	static const int Any = -1;
+	
+	int major = Any;
+	int minor = Any;
+	int patch = Any;
 
 	CModVersion() = default;
 	CModVersion(int mj, int mi, int p): major(mj), minor(mi), patch(p) {}
@@ -42,4 +44,6 @@ struct DLL_LINKAGE CModVersion
 	}
 };
 
+DLL_LINKAGE bool operator < (const CModVersion & lesser, const CModVersion & greater);
+
 VCMI_LIB_NAMESPACE_END