diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index a8085bfd5..4ecd9060a 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/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(); +} diff --git a/launcher/modManager/cmodlistview_moc.h b/launcher/modManager/cmodlistview_moc.h index 41be3221d..c0c589290 100644 --- a/launcher/modManager/cmodlistview_moc.h +++ b/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); diff --git a/launcher/modManager/modstatemodel.cpp b/launcher/modManager/modstatemodel.cpp index be4bc5627..9bcfa2863 100644 --- a/launcher/modManager/modstatemodel.cpp +++ b/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()); +} diff --git a/launcher/modManager/modstatemodel.h b/launcher/modManager/modstatemodel.h index 08bf1935f..168da5dfe 100644 --- a/launcher/modManager/modstatemodel.h +++ b/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; }; diff --git a/launcher/startGame/StartGameTab.cpp b/launcher/startGame/StartGameTab.cpp index 41dec18cf..c3dbc0074 100644 --- a/launcher/startGame/StartGameTab.cpp +++ b/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(); + } +} + diff --git a/launcher/startGame/StartGameTab.h b/launcher/startGame/StartGameTab.h index 9ca2d0799..3503f726c 100644 --- a/launcher/startGame/StartGameTab.h +++ b/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; }; diff --git a/launcher/startGame/StartGameTab.ui b/launcher/startGame/StartGameTab.ui index 28a5acfa7..813ec31ed 100644 --- a/launcher/startGame/StartGameTab.ui +++ b/launcher/startGame/StartGameTab.ui @@ -26,11 +26,11 @@ 0 0 - 240 - 222 + 226 + 234 - + @@ -50,7 +50,7 @@ - + Qt::Vertical @@ -63,8 +63,8 @@ - - + + 0 @@ -78,26 +78,7 @@ - Export to Clipboard - - - - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - Create New Preset + Rename Current Preset @@ -122,7 +103,45 @@ - + + + + + 0 + 30 + + + + + 16777215 + 30 + + + + Create New Preset + + + + + + + + 0 + 30 + + + + + 16777215 + 30 + + + + Export to Clipboard + + + + @@ -580,7 +599,7 @@ - Update to %1 available + true diff --git a/lib/modding/ModManager.cpp b/lib/modding/ModManager.cpp index f18452def..a117eff2c 100644 --- a/lib/modding/ModManager.cpp +++ b/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 ModsPresetState::getAllPresets() const +{ + std::vector 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 & 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 ModManager::getAllPresets() const +{ + return modsPreset->getAllPresets(); +} + +std::string ModManager::getActivePreset() const +{ + return modsPreset->getActivePreset(); +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/modding/ModManager.h b/lib/modding/ModManager.h index 2acdb90a6..616e2632d 100644 --- a/lib/modding/ModManager.h +++ b/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 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 getAllPresets() const; + std::string getActivePreset() const; }; VCMI_LIB_NAMESPACE_END