Browse Source

Implemented preset management for Start Game tab

Ivan Savenko 10 months ago
parent
commit
0fde7942d2

+ 31 - 0
launcher/modManager/cmodlistview_moc.cpp

@@ -1076,3 +1076,34 @@ void CModListView::on_allModsView_doubleClicked(const QModelIndex &index)
 		return;
 	}
 }
+
+void CModListView::createNewPreset(const QString & presetName)
+{
+	modStateModel->createNewPreset(presetName);
+}
+
+void CModListView::deletePreset(const QString & presetName)
+{
+	modStateModel->deletePreset(presetName);
+}
+
+void CModListView::activatePreset(const QString & presetName)
+{
+	modStateModel->activatePreset(presetName);
+	modStateModel->reloadLocalState();
+}
+
+void CModListView::renamePreset(const QString & oldPresetName, const QString & newPresetName)
+{
+	modStateModel->renamePreset(oldPresetName, newPresetName);
+}
+
+QStringList CModListView::getAllPresets() const
+{
+	return modStateModel->getAllPresets();
+}
+
+QString CModListView::getActivePreset() const
+{
+	return modStateModel->getActivePreset();
+}

+ 12 - 0
launcher/modManager/cmodlistview_moc.h

@@ -94,6 +94,18 @@ public:
 	/// finds all mods that can be updated
 	QStringList getUpdateableMods();
 
+	void createNewPreset(const QString & presetName);
+
+	void deletePreset(const QString & presetName);
+
+	void activatePreset(const QString & presetName);
+
+	void renamePreset(const QString & oldPresetName, const QString & newPresetName);
+
+	QStringList getAllPresets() const;
+
+	QString getActivePreset() const;
+
 	/// returns true if mod is currently enabled
 	bool isModEnabled(const QString & modName);
 

+ 31 - 0
launcher/modManager/modstatemodel.cpp

@@ -128,3 +128,34 @@ QString ModStateModel::getTopParent(QString modname) const
 	else
 		return "";
 }
+
+void ModStateModel::createNewPreset(const QString & presetName)
+{
+	modManager->createNewPreset(presetName.toStdString());
+}
+
+void ModStateModel::deletePreset(const QString & presetName)
+{
+	modManager->deletePreset(presetName.toStdString());
+}
+
+void ModStateModel::activatePreset(const QString & presetName)
+{
+	modManager->activatePreset(presetName.toStdString());
+}
+
+void ModStateModel::renamePreset(const QString & oldPresetName, const QString & newPresetName)
+{
+	modManager->renamePreset(oldPresetName.toStdString(), newPresetName.toStdString());
+}
+
+QStringList ModStateModel::getAllPresets() const
+{
+	auto result = modManager->getAllPresets();
+	return stringListStdToQt(result);
+}
+
+QString ModStateModel::getActivePreset() const
+{
+	return QString::fromStdString(modManager->getActivePreset());
+}

+ 8 - 0
launcher/modManager/modstatemodel.h

@@ -49,4 +49,12 @@ public:
 
 	bool isSubmod(QString modname);
 	QString getTopParent(QString modname) const;
+
+	void createNewPreset(const QString & presetName);
+	void deletePreset(const QString & presetName);
+	void activatePreset(const QString & presetName);
+	void renamePreset(const QString & oldPresetName, const QString & newPresetName);
+
+	QStringList getAllPresets() const;
+	QString getActivePreset() const;
 };

+ 75 - 5
launcher/startGame/StartGameTab.cpp

@@ -23,6 +23,8 @@ StartGameTab::StartGameTab(QWidget * parent)
 	refreshState();
 
 	ui->buttonGameResume->setVisible(false); // TODO: implement
+	ui->buttonPresetExport->setVisible(false); // TODO: implement
+	ui->buttonPresetImport->setVisible(false); // TODO: implement
 }
 
 StartGameTab::~StartGameTab()
@@ -41,11 +43,23 @@ MainWindow * StartGameTab::getMainWindow()
 void StartGameTab::refreshState()
 {
 	refreshGameData();
-	refreshUpdateStatus(EGameUpdateStatus::NOT_CHECKED);//TODO
+	refreshUpdateStatus(EGameUpdateStatus::NOT_CHECKED);//TODO - follow automatic check on startup setting
 	refreshTranslation(getMainWindow()->getTranslationStatus());
+	refreshPresets();
 	refreshMods();
 }
 
+void StartGameTab::refreshPresets()
+{
+	QSignalBlocker blocker(ui->comboBoxModPresets);
+
+	QStringList allPresets = getMainWindow()->getModView()->getAllPresets();
+	ui->comboBoxModPresets->clear();
+	ui->comboBoxModPresets->addItems(allPresets);
+	ui->comboBoxModPresets->setCurrentText(getMainWindow()->getModView()->getActivePreset());
+	ui->buttonPresetDelete->setVisible(allPresets.size() > 1);
+}
+
 void StartGameTab::refreshGameData()
 {
 	// Some players are using pirated version of the game with some of the files missing
@@ -121,12 +135,17 @@ void StartGameTab::refreshMods()
 
 void StartGameTab::refreshUpdateStatus(EGameUpdateStatus status)
 {
+	QString availableVersion; // TODO
+
 	ui->labelTitleEngine->setText("VCMI " VCMI_VERSION_STRING);
 	ui->buttonUpdateCheck->setVisible(status == EGameUpdateStatus::NOT_CHECKED);
 	ui->labelUpdateNotFound->setVisible(status == EGameUpdateStatus::NO_UPDATE);
 	ui->labelUpdateAvailable->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
 	ui->buttonOpenChangelog->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
 	ui->buttonOpenDownloads->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
+
+	if (status == EGameUpdateStatus::UPDATE_AVAILABLE)
+		ui->labelUpdateAvailable->setText(tr("Update to %1 available").arg(availableVersion));
 }
 
 void StartGameTab::on_buttonGameStart_clicked()
@@ -204,8 +223,10 @@ void StartGameTab::on_buttonUpdateMods_clicked()
 {
 	QStringList updateableMods = getMainWindow()->getModView()->getUpdateableMods();
 
+	getMainWindow()->switchToModsTab();
+
 	for (const auto & modName : updateableMods)
-		getMainWindow()->getModView()->doInstallMod(modName);
+		getMainWindow()->getModView()->doUpdateMod(modName);
 }
 
 void StartGameTab::on_buttonHelpImportFiles_clicked()
@@ -248,7 +269,7 @@ void StartGameTab::on_buttonUpdateModsHelp_clicked()
 	QString message = tr(
 		"A new version of some of the mods that you have installed is now available in mod repository. "
 		"Use this option to automatically update all your mods to latest version.\n\n"
-		"WARNING: IN some cases, updated versions of mods may not be compatible with your existing saves. "
+		"WARNING: In some cases, updated versions of mods may not be compatible with your existing saves. "
 		"You many want to postpone mod update until you finish any of your ongoing games."
 		);
 
@@ -324,10 +345,59 @@ void StartGameTab::on_buttonPresetImport_clicked()
 
 void StartGameTab::on_buttonPresetNew_clicked()
 {
-	// TODO
+	bool ok;
+	QString presetName = QInputDialog::getText(
+		this,
+		ui->buttonPresetNew->text(),
+		tr("Enter preset name:"),
+		QLineEdit::Normal,
+		QString(),
+		&ok);
+
+	if (ok && !presetName.isEmpty())
+	{
+		getMainWindow()->getModView()->createNewPreset(presetName);
+		getMainWindow()->getModView()->activatePreset(presetName);
+		refreshPresets();
+	}
 }
 
 void StartGameTab::on_buttonPresetDelete_clicked()
 {
-	// TODO
+	QString activePresetBefore = getMainWindow()->getModView()->getActivePreset();
+	QStringList allPresets = getMainWindow()->getModView()->getAllPresets();
+
+	allPresets.removeAll(activePresetBefore);
+	if (!allPresets.empty())
+	{
+		getMainWindow()->getModView()->activatePreset(allPresets.front());
+		getMainWindow()->getModView()->deletePreset(activePresetBefore);
+		refreshPresets();
+	}
+}
+
+void StartGameTab::on_comboBoxModPresets_currentTextChanged(const QString &presetName)
+{
+	getMainWindow()->getModView()->activatePreset(presetName);
 }
+
+void StartGameTab::on_buttonPresetRename_clicked()
+{
+	QString currentName = getMainWindow()->getModView()->getActivePreset();
+
+	bool ok;
+	QString newName = QInputDialog::getText(
+		this,
+		ui->buttonPresetNew->text(),
+		tr("Rename preset '%1' to:").arg(currentName),
+		QLineEdit::Normal,
+		currentName,
+		&ok);
+
+	if (ok && !newName.isEmpty())
+	{
+		getMainWindow()->getModView()->renamePreset(currentName, newName);
+		refreshPresets();
+	}
+}
+

+ 5 - 0
launcher/startGame/StartGameTab.h

@@ -30,6 +30,7 @@ class StartGameTab : public QWidget
 	void refreshUpdateStatus(EGameUpdateStatus status);
 	void refreshTranslation(ETranslationStatus status);
 	void refreshMods();
+	void refreshPresets();
 	void refreshGameData();
 
 public:
@@ -64,6 +65,10 @@ private slots:
 
 	void on_buttonPresetDelete_clicked();
 
+	void on_comboBoxModPresets_currentTextChanged(const QString &arg1);
+
+	void on_buttonPresetRename_clicked();
+
 private:
 	Ui::StartGameTab * ui;
 };

+ 35 - 16
launcher/startGame/StartGameTab.ui

@@ -26,11 +26,11 @@
          <rect>
           <x>0</x>
           <y>0</y>
-          <width>240</width>
-          <height>222</height>
+          <width>226</width>
+          <height>234</height>
          </rect>
         </property>
-        <layout class="QGridLayout" name="gridLayout" rowstretch="1,0,0,0,0,0,0">
+        <layout class="QGridLayout" name="gridLayout" rowstretch="1,0,0,0,0,0,0,0,0">
          <item row="3" column="0">
           <widget class="QPushButton" name="buttonPresetImport">
            <property name="minimumSize">
@@ -50,7 +50,7 @@
            </property>
           </widget>
          </item>
-         <item row="6" column="0">
+         <item row="8" column="0">
           <spacer name="verticalSpacer">
            <property name="orientation">
             <enum>Qt::Vertical</enum>
@@ -63,8 +63,8 @@
            </property>
           </spacer>
          </item>
-         <item row="2" column="0">
-          <widget class="QPushButton" name="buttonPresetExport">
+         <item row="6" column="0">
+          <widget class="QPushButton" name="buttonPresetRename">
            <property name="minimumSize">
             <size>
              <width>0</width>
@@ -78,8 +78,29 @@
             </size>
            </property>
            <property name="text">
-            <string>Export to Clipboard</string>
+            <string>Rename Current Preset</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="0">
+          <widget class="QComboBox" name="comboBoxModPresets">
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>30</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>30</height>
+            </size>
            </property>
+           <item>
+            <property name="text">
+             <string>Current Preset</string>
+            </property>
+           </item>
           </widget>
          </item>
          <item row="4" column="0">
@@ -101,8 +122,8 @@
            </property>
           </widget>
          </item>
-         <item row="0" column="0">
-          <widget class="QComboBox" name="comboBoxModPresets">
+         <item row="2" column="0">
+          <widget class="QPushButton" name="buttonPresetExport">
            <property name="minimumSize">
             <size>
              <width>0</width>
@@ -115,14 +136,12 @@
              <height>30</height>
             </size>
            </property>
-           <item>
-            <property name="text">
-             <string>Current Preset</string>
-            </property>
-           </item>
+           <property name="text">
+            <string>Export to Clipboard</string>
+           </property>
           </widget>
          </item>
-         <item row="5" column="0">
+         <item row="7" column="0">
           <widget class="QPushButton" name="buttonPresetDelete">
            <property name="minimumSize">
             <size>
@@ -580,7 +599,7 @@
             </size>
            </property>
            <property name="text">
-            <string>Update to %1 available</string>
+            <string/>
            </property>
            <property name="wordWrap">
             <bool>true</bool>

+ 89 - 0
lib/modding/ModManager.cpp

@@ -326,6 +326,61 @@ void ModsPresetState::saveConfigurationState() const
 	file << modConfig.toCompactString();
 }
 
+void ModsPresetState::createNewPreset(const std::string & presetName)
+{
+	if (modConfig["presets"][presetName].isNull())
+		modConfig["presets"][presetName]["mods"].Vector().emplace_back("vcmi");
+}
+
+void ModsPresetState::deletePreset(const std::string & presetName)
+{
+	if (modConfig["presets"].Struct().size() < 2)
+		throw std::runtime_error("Unable to delete last preset!");
+
+	modConfig["presets"].Struct().erase(presetName);
+}
+
+void ModsPresetState::activatePreset(const std::string & presetName)
+{
+	if (modConfig["presets"].Struct().count(presetName) == 0)
+		throw std::runtime_error("Unable to activate non-exinsting preset!");
+
+	modConfig["activePreset"].String() = presetName;
+}
+
+void ModsPresetState::renamePreset(const std::string & oldPresetName, const std::string & newPresetName)
+{
+	if (oldPresetName == newPresetName)
+		throw std::runtime_error("Unable to rename preset to the same name!");
+
+	if (modConfig["presets"].Struct().count(oldPresetName) == 0)
+		throw std::runtime_error("Unable to rename non-existing last preset!");
+
+	if (modConfig["presets"].Struct().count(newPresetName) != 0)
+		throw std::runtime_error("Unable to rename preset - preset with such name already exists!");
+
+	modConfig["presets"][newPresetName] = modConfig["presets"][oldPresetName];
+	modConfig["presets"].Struct().erase(oldPresetName);
+
+	if (modConfig["activePreset"].String() == oldPresetName)
+		modConfig["activePreset"].String() = newPresetName;
+}
+
+std::vector<std::string> ModsPresetState::getAllPresets() const
+{
+	std::vector<std::string> presets;
+
+	for (const auto & preset : modConfig["presets"].Struct())
+		presets.push_back(preset.first);
+
+	return presets;
+}
+
+std::string ModsPresetState::getActivePreset() const
+{
+	return modConfig["activePreset"].String();
+}
+
 ModsStorage::ModsStorage(const std::vector<TModID> & modsToLoad, const JsonNode & repositoryList)
 {
 	JsonNode coreModConfig(JsonPath::builtin("config/gameConfig.json"));
@@ -703,4 +758,38 @@ void ModDependenciesResolver::tryAddMods(TModList modsToResolve, const ModsStora
 	brokenMods.insert(brokenMods.end(), modsToResolve.begin(), modsToResolve.end());
 }
 
+void ModManager::createNewPreset(const std::string & presetName)
+{
+	modsPreset->createNewPreset(presetName);
+	modsPreset->saveConfigurationState();
+}
+
+void ModManager::deletePreset(const std::string & presetName)
+{
+	modsPreset->deletePreset(presetName);
+	modsPreset->saveConfigurationState();
+}
+
+void ModManager::activatePreset(const std::string & presetName)
+{
+	modsPreset->activatePreset(presetName);
+	modsPreset->saveConfigurationState();
+}
+
+void ModManager::renamePreset(const std::string & oldPresetName, const std::string & newPresetName)
+{
+	modsPreset->renamePreset(oldPresetName, newPresetName);
+	modsPreset->saveConfigurationState();
+}
+
+std::vector<std::string> ModManager::getAllPresets() const
+{
+	return modsPreset->getAllPresets();
+}
+
+std::string ModManager::getActivePreset() const
+{
+	return modsPreset->getActivePreset();
+}
+
 VCMI_LIB_NAMESPACE_END

+ 16 - 0
lib/modding/ModManager.h

@@ -50,6 +50,14 @@ class ModsPresetState : boost::noncopyable
 public:
 	ModsPresetState();
 
+	void createNewPreset(const std::string & presetName);
+	void deletePreset(const std::string & presetName);
+	void activatePreset(const std::string & presetName);
+	void renamePreset(const std::string & oldPresetName, const std::string & newPresetName);
+
+	std::vector<std::string> getAllPresets() const;
+	std::string getActivePreset() const;
+
 	void setModActive(const TModID & modName, bool isActive);
 
 	void addRootMod(const TModID & modName);
@@ -139,6 +147,14 @@ public:
 
 	void tryEnableMods(const TModList & modList);
 	void tryDisableMod(const TModID & modName);
+
+	void createNewPreset(const std::string & presetName);
+	void deletePreset(const std::string & presetName);
+	void activatePreset(const std::string & presetName);
+	void renamePreset(const std::string & oldPresetName, const std::string & newPresetName);
+
+	std::vector<std::string> getAllPresets() const;
+	std::string getActivePreset() const;
 };
 
 VCMI_LIB_NAMESPACE_END