Browse Source

Launcher fixes for mod filesystem (#860)

* Show submods as disabled if parent mod is disabled
* [845] disable button for local mods
Fixes for #812 #851 #852
Nordsoft91 3 years ago
parent
commit
205bb09880

+ 30 - 3
launcher/modManager/cmodlist.cpp

@@ -92,6 +92,11 @@ bool CModEntry::isUpdateable() const
 	return false;
 }
 
+bool CModEntry::isEssential() const
+{
+	return getValue("storedLocaly").toBool();
+}
+
 bool CModEntry::isInstalled() const
 {
 	return !localData.isEmpty();
@@ -152,6 +157,10 @@ QVariantMap CModList::copyField(QVariantMap data, QString from, QString to)
 	return renamed;
 }
 
+void CModList::reloadRepositories()
+{
+}
+
 void CModList::resetRepositories()
 {
 	repositories.clear();
@@ -176,7 +185,7 @@ void CModList::modChanged(QString modID)
 {
 }
 
-static QVariant getValue(QVariantMap input, QString path)
+static QVariant getValue(QVariant input, QString path)
 {
 	if(path.size() > 1)
 	{
@@ -184,7 +193,7 @@ static QVariant getValue(QVariantMap input, QString path)
 		QString remainder = "/" + path.section('/', 2, -1);
 
 		entryName.remove(0, 1);
-		return getValue(input.value(entryName).toMap(), remainder);
+		return getValue(input.toMap().value(entryName), remainder);
 	}
 	else
 	{
@@ -208,11 +217,29 @@ CModEntry CModList::getMod(QString modname) const
 	}
 	else
 	{
-		if(conf.canConvert<QVariantMap>())
+		if(!conf.toMap().isEmpty())
+		{
 			settings = conf.toMap();
+			if(settings.value("active").isNull())
+				settings["active"] = true; // default
+		}
 		else
 			settings.insert("active", conf);
 	}
+	
+	if(settings["active"].toBool())
+	{
+		QString rootPath = path.section('/', 0, 1);
+		if(path != rootPath)
+		{
+			conf = getValue(modSettings, rootPath);
+			const auto confMap = conf.toMap();
+			if(!conf.isNull() && !confMap["active"].isNull() && !confMap["active"].toBool())
+			{
+				settings = confMap;
+			}
+		}
+	}
 
 	for(auto entry : repositories)
 	{

+ 3 - 0
launcher/modManager/cmodlist.h

@@ -49,6 +49,8 @@ public:
 	bool isUpdateable() const;
 	// installed
 	bool isInstalled() const;
+	// vcmi essential files
+	bool isEssential() const;
 
 	// see ModStatus enum
 	int getModStatus() const;
@@ -74,6 +76,7 @@ class CModList
 
 public:
 	virtual void resetRepositories();
+	virtual void reloadRepositories();
 	virtual void addRepository(QVariantMap data);
 	virtual void setLocalModList(QVariantMap data);
 	virtual void setModSettings(QVariant data);

+ 6 - 0
launcher/modManager/cmodlistmodel_moc.cpp

@@ -160,6 +160,12 @@ QVariant CModListModel::headerData(int section, Qt::Orientation orientation, int
 	return QVariant();
 }
 
+void CModListModel::reloadRepositories()
+{
+	beginResetModel();
+	endResetModel();
+}
+
 void CModListModel::resetRepositories()
 {
 	beginResetModel();

+ 1 - 0
launcher/modManager/cmodlistmodel_moc.h

@@ -61,6 +61,7 @@ public:
 
 	/// CModListContainer overrides
 	void resetRepositories() override;
+	void reloadRepositories() override;
 	void addRepository(QVariantMap data) override;
 	void modChanged(QString modID) override;
 

+ 6 - 3
launcher/modManager/cmodlistview_moc.cpp

@@ -310,10 +310,10 @@ void CModListView::selectMod(const QModelIndex & index)
 		// Block buttons if action is not allowed at this time
 		// TODO: automate handling of some of these cases instead of forcing player
 		// to resolve all conflicts manually.
-		ui->disableButton->setEnabled(!hasDependentMods);
+		ui->disableButton->setEnabled(!hasDependentMods && !mod.isEssential());
 		ui->enableButton->setEnabled(!hasBlockingMods && !hasInvalidDeps);
 		ui->installButton->setEnabled(!hasInvalidDeps);
-		ui->uninstallButton->setEnabled(!hasDependentMods);
+		ui->uninstallButton->setEnabled(!hasDependentMods && !mod.isEssential());
 		ui->updateButton->setEnabled(!hasInvalidDeps && !hasDependentMods);
 
 		loadScreenshots();
@@ -522,6 +522,9 @@ void CModListView::downloadFile(QString file, QString url, QString description)
 
 		connect(dlManager, SIGNAL(finished(QStringList,QStringList,QStringList)),
 			this, SLOT(downloadFinished(QStringList,QStringList,QStringList)));
+		
+		
+		connect(modModel, &CModListModel::dataChanged, filterModel, &QAbstractItemModel::dataChanged);
 
 
 		QString progressBarFormat = "Downloading %s%. %p% (%v KB out of %m KB) finished";
@@ -658,7 +661,7 @@ void CModListView::installMods(QStringList archives)
 		auto mod = modModel->getMod(modName);
 		if(mod.isInstalled() && !mod.getValue("keepDisabled").toBool())
 		{
-			if(manager->enableMod(modName))
+			if(mod.isDisabled() && manager->enableMod(modName))
 			{
 				for(QString child : modModel->getChildren(modName))
 					enableMod(child);

+ 15 - 12
launcher/modManager/cmodmanager.cpp

@@ -74,6 +74,7 @@ void CModManager::loadMods()
 	CModHandler handler;
 	handler.loadMods();
 	auto installedMods = handler.getAllMods();
+	localMods.clear();
 
 	for(auto modname : installedMods)
 	{
@@ -82,6 +83,13 @@ void CModManager::loadMods()
 		{
 			boost::filesystem::path name = *CResourceHandler::get()->getResourceName(resID);
 			auto mod = JsonUtils::JsonFromFile(pathToQString(name));
+			if(!name.is_absolute())
+			{
+				auto json = JsonUtils::toJson(mod);
+				json["storedLocaly"].Bool() = true;
+				mod = JsonUtils::toVariant(json);
+			}
+			
 			localMods.insert(QString::fromUtf8(modname.c_str()).toLower(), mod);
 		}
 	}
@@ -269,12 +277,10 @@ bool CModManager::doInstallMod(QString modname, QString archivePath)
 	QString upperLevel = modDirName.section('/', 0, 0);
 	if(upperLevel != modDirName)
 		removeModDir(destDir + upperLevel);
-
-	QVariantMap json = JsonUtils::JsonFromFile(destDir + modname + "/mod.json").toMap();
-
-	localMods.insert(modname, json);
-	modList->setLocalModList(localMods);
-	modList->modChanged(modname);
+	
+	CResourceHandler::get("initial")->updateFilteredFiles([](const std::string &) { return true; });
+	loadMods();
+	modList->reloadRepositories();
 
 	return true;
 }
@@ -288,16 +294,13 @@ bool CModManager::doUninstallMod(QString modname)
 	if(!QDir(modDir).exists())
 		return addError(modname, "Data with this mod was not found");
 
-	if(!localMods.contains(modname))
-		return addError(modname, "Data with this mod was not found");
-
 	QDir modFullDir(modDir);
 	if(!removeModDir(modDir))
 		return addError(modname, "Mod is located in protected directory, plase remove it manually:\n" + modFullDir.absolutePath());
 
-	localMods.remove(modname);
-	modList->setLocalModList(localMods);
-	modList->modChanged(modname);
+	CResourceHandler::get("initial")->updateFilteredFiles([](const std::string &){ return true; });
+	loadMods();
+	modList->reloadRepositories();
 
 	return true;
 }

+ 5 - 4
lib/filesystem/CFilesystemLoader.cpp

@@ -16,9 +16,10 @@
 namespace bfs = boost::filesystem;
 
 CFilesystemLoader::CFilesystemLoader(std::string _mountPoint, bfs::path baseDirectory, size_t depth, bool initial):
-    baseDirectory(std::move(baseDirectory)),
-    mountPoint(std::move(_mountPoint)),
-    fileList(listFiles(mountPoint, depth, initial))
+	baseDirectory(std::move(baseDirectory)),
+	mountPoint(std::move(_mountPoint)),
+	fileList(listFiles(mountPoint, depth, initial)),
+	recursiveDepth(depth)
 {
 	logGlobal->trace("File system loaded, %d files found", fileList.size());
 }
@@ -52,7 +53,7 @@ void CFilesystemLoader::updateFilteredFiles(std::function<bool(const std::string
 {
 	if (filter(mountPoint))
 	{
-		fileList = listFiles(mountPoint, 1, false);
+		fileList = listFiles(mountPoint, recursiveDepth, false);
 	}
 }
 

+ 2 - 0
lib/filesystem/CFilesystemLoader.h

@@ -45,6 +45,8 @@ private:
 	boost::filesystem::path baseDirectory;
 
 	std::string mountPoint;
+	
+	size_t recursiveDepth;
 
 	/** A list of files in the directory
 	 * key = ResourceID for resource loader