mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-25 00:37:24 +02:00
Merge pull request #5108 from IvanSavenko/preset_import
[1.6.1?] Mod preset import/export
This commit is contained in:
@ -857,6 +857,12 @@ void CModListView::installMods(QStringList archives)
|
|||||||
modNames.push_back(modName);
|
modNames.push_back(modName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!activatingPreset.isEmpty())
|
||||||
|
{
|
||||||
|
modStateModel->activatePreset(activatingPreset);
|
||||||
|
activatingPreset.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// uninstall old version of mod, if installed
|
// uninstall old version of mod, if installed
|
||||||
for(QString mod : modNames)
|
for(QString mod : modNames)
|
||||||
{
|
{
|
||||||
@ -1147,3 +1153,25 @@ QString CModListView::getActivePreset() const
|
|||||||
{
|
{
|
||||||
return modStateModel->getActivePreset();
|
return modStateModel->getActivePreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode CModListView::exportCurrentPreset() const
|
||||||
|
{
|
||||||
|
return modStateModel->exportCurrentPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CModListView::importPreset(const JsonNode & data)
|
||||||
|
{
|
||||||
|
const auto & [presetName, modList] = modStateModel->importPreset(data);
|
||||||
|
|
||||||
|
if (modList.empty())
|
||||||
|
{
|
||||||
|
modStateModel->activatePreset(presetName);
|
||||||
|
modStateModel->reloadLocalState();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activatingPreset = presetName;
|
||||||
|
for (const auto & modID : modList)
|
||||||
|
doInstallMod(modID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,6 +37,7 @@ class CModListView : public QWidget
|
|||||||
CModFilterModel * filterModel;
|
CModFilterModel * filterModel;
|
||||||
CDownloadManager * dlManager;
|
CDownloadManager * dlManager;
|
||||||
JsonNode accumulatedRepositoryData;
|
JsonNode accumulatedRepositoryData;
|
||||||
|
QString activatingPreset;
|
||||||
|
|
||||||
QStringList enqueuedModDownloads;
|
QStringList enqueuedModDownloads;
|
||||||
|
|
||||||
@ -97,17 +98,16 @@ public:
|
|||||||
QStringList getUpdateableMods();
|
QStringList getUpdateableMods();
|
||||||
|
|
||||||
void createNewPreset(const QString & presetName);
|
void createNewPreset(const QString & presetName);
|
||||||
|
|
||||||
void deletePreset(const QString & presetName);
|
void deletePreset(const QString & presetName);
|
||||||
|
|
||||||
void activatePreset(const QString & presetName);
|
void activatePreset(const QString & presetName);
|
||||||
|
|
||||||
void renamePreset(const QString & oldPresetName, const QString & newPresetName);
|
void renamePreset(const QString & oldPresetName, const QString & newPresetName);
|
||||||
|
|
||||||
QStringList getAllPresets() const;
|
QStringList getAllPresets() const;
|
||||||
|
|
||||||
QString getActivePreset() const;
|
QString getActivePreset() const;
|
||||||
|
|
||||||
|
JsonNode exportCurrentPreset() const;
|
||||||
|
void importPreset(const JsonNode & data);
|
||||||
|
|
||||||
/// returns true if mod is currently enabled
|
/// returns true if mod is currently enabled
|
||||||
bool isModEnabled(const QString & modName);
|
bool isModEnabled(const QString & modName);
|
||||||
|
|
||||||
|
@ -157,3 +157,16 @@ QString ModStateModel::getActivePreset() const
|
|||||||
{
|
{
|
||||||
return QString::fromStdString(modManager->getActivePreset());
|
return QString::fromStdString(modManager->getActivePreset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode ModStateModel::exportCurrentPreset() const
|
||||||
|
{
|
||||||
|
return modManager->exportCurrentPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<QString, QStringList> ModStateModel::importPreset(const JsonNode & data)
|
||||||
|
{
|
||||||
|
std::tuple<QString, QStringList> result;
|
||||||
|
const auto & [presetName, modList] = modManager->importPreset(data);
|
||||||
|
|
||||||
|
return {QString::fromStdString(presetName), stringListStdToQt(modList)};
|
||||||
|
}
|
||||||
|
@ -57,4 +57,7 @@ public:
|
|||||||
|
|
||||||
QStringList getAllPresets() const;
|
QStringList getAllPresets() const;
|
||||||
QString getActivePreset() const;
|
QString getActivePreset() const;
|
||||||
|
|
||||||
|
JsonNode exportCurrentPreset() const;
|
||||||
|
std::tuple<QString, QStringList> importPreset(const JsonNode & data);
|
||||||
};
|
};
|
||||||
|
@ -44,12 +44,41 @@ StartGameTab::StartGameTab(QWidget * parent)
|
|||||||
refreshState();
|
refreshState();
|
||||||
|
|
||||||
ui->buttonGameResume->setVisible(false); // TODO: implement
|
ui->buttonGameResume->setVisible(false); // TODO: implement
|
||||||
ui->buttonPresetExport->setVisible(false); // TODO: implement
|
|
||||||
ui->buttonPresetImport->setVisible(false); // TODO: implement
|
|
||||||
|
|
||||||
#ifndef ENABLE_EDITOR
|
#ifndef ENABLE_EDITOR
|
||||||
ui->buttonGameEditor->hide();
|
ui->buttonGameEditor->hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto clipboard = QGuiApplication::clipboard();
|
||||||
|
|
||||||
|
connect(clipboard, SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartGameTab::clipboardDataChanged()
|
||||||
|
{
|
||||||
|
ui->buttonPresetExport->setIcon(QIcon{});// reset icon, if any
|
||||||
|
|
||||||
|
auto clipboard = QGuiApplication::clipboard();
|
||||||
|
QString clipboardText = clipboard->text().trimmed();
|
||||||
|
|
||||||
|
if (clipboardText.isEmpty())
|
||||||
|
{
|
||||||
|
ui->buttonPresetImport->setEnabled(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this *may* be json, try parsing it
|
||||||
|
if (clipboardText.startsWith('{'))
|
||||||
|
{
|
||||||
|
QByteArray presetBytes(clipboardText.toUtf8());
|
||||||
|
const JsonNode presetJson(reinterpret_cast<const std::byte*>(presetBytes.data()), presetBytes.size(), "preset in clipboard");
|
||||||
|
bool presetValid = !presetJson["name"].String().empty() && !presetJson["mods"].Vector().empty();
|
||||||
|
|
||||||
|
ui->buttonPresetImport->setEnabled(presetValid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ui->buttonPresetImport->setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartGameTab::~StartGameTab()
|
StartGameTab::~StartGameTab()
|
||||||
@ -72,6 +101,8 @@ void StartGameTab::refreshState()
|
|||||||
refreshTranslation(getMainWindow()->getTranslationStatus());
|
refreshTranslation(getMainWindow()->getTranslationStatus());
|
||||||
refreshPresets();
|
refreshPresets();
|
||||||
refreshMods();
|
refreshMods();
|
||||||
|
|
||||||
|
clipboardDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartGameTab::refreshPresets()
|
void StartGameTab::refreshPresets()
|
||||||
@ -363,12 +394,22 @@ void StartGameTab::on_buttonMissingCampaignsHelp_clicked()
|
|||||||
|
|
||||||
void StartGameTab::on_buttonPresetExport_clicked()
|
void StartGameTab::on_buttonPresetExport_clicked()
|
||||||
{
|
{
|
||||||
// TODO
|
JsonNode presetJson = getMainWindow()->getModView()->exportCurrentPreset();
|
||||||
|
QString presetString = QString::fromStdString(presetJson.toCompactString());
|
||||||
|
QGuiApplication::clipboard()->setText(presetString);
|
||||||
|
|
||||||
|
ui->buttonPresetExport->setIcon(QIcon{":/icons/mod-enabled.png"});
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartGameTab::on_buttonPresetImport_clicked()
|
void StartGameTab::on_buttonPresetImport_clicked()
|
||||||
{
|
{
|
||||||
// TODO
|
QString presetString = QGuiApplication::clipboard()->text();
|
||||||
|
QByteArray presetBytes(presetString.toUtf8());
|
||||||
|
JsonNode presetJson(reinterpret_cast<const std::byte*>(presetBytes.data()), presetBytes.size(), "imported preset");
|
||||||
|
|
||||||
|
getMainWindow()->getModView()->importPreset(presetJson);
|
||||||
|
getMainWindow()->switchToModsTab();
|
||||||
|
refreshPresets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartGameTab::on_buttonPresetNew_clicked()
|
void StartGameTab::on_buttonPresetNew_clicked()
|
||||||
|
@ -65,19 +65,14 @@ private slots:
|
|||||||
void on_buttonMissingVideoHelp_clicked();
|
void on_buttonMissingVideoHelp_clicked();
|
||||||
void on_buttonMissingFilesHelp_clicked();
|
void on_buttonMissingFilesHelp_clicked();
|
||||||
void on_buttonMissingCampaignsHelp_clicked();
|
void on_buttonMissingCampaignsHelp_clicked();
|
||||||
|
|
||||||
void on_buttonPresetExport_clicked();
|
void on_buttonPresetExport_clicked();
|
||||||
|
|
||||||
void on_buttonPresetImport_clicked();
|
void on_buttonPresetImport_clicked();
|
||||||
|
|
||||||
void on_buttonPresetNew_clicked();
|
void on_buttonPresetNew_clicked();
|
||||||
|
|
||||||
void on_buttonPresetDelete_clicked();
|
void on_buttonPresetDelete_clicked();
|
||||||
|
|
||||||
void on_comboBoxModPresets_currentTextChanged(const QString &arg1);
|
void on_comboBoxModPresets_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
void on_buttonPresetRename_clicked();
|
void on_buttonPresetRename_clicked();
|
||||||
|
|
||||||
|
void clipboardDataChanged();
|
||||||
private:
|
private:
|
||||||
Ui::StartGameTab * ui;
|
Ui::StartGameTab * ui;
|
||||||
};
|
};
|
||||||
|
@ -207,7 +207,12 @@ const JsonNode & ModsPresetState::getActivePresetConfig() const
|
|||||||
|
|
||||||
TModList ModsPresetState::getActiveRootMods() const
|
TModList ModsPresetState::getActiveRootMods() const
|
||||||
{
|
{
|
||||||
const JsonNode & modsToActivateJson = getActivePresetConfig()["mods"];
|
return getRootMods(getActivePreset());
|
||||||
|
}
|
||||||
|
|
||||||
|
TModList ModsPresetState::getRootMods(const std::string & presetName) const
|
||||||
|
{
|
||||||
|
const JsonNode & modsToActivateJson = modConfig["presets"][presetName]["mods"];
|
||||||
auto modsToActivate = modsToActivateJson.convertTo<std::vector<TModID>>();
|
auto modsToActivate = modsToActivateJson.convertTo<std::vector<TModID>>();
|
||||||
if (!vstd::contains(modsToActivate, ModScope::scopeBuiltin()))
|
if (!vstd::contains(modsToActivate, ModScope::scopeBuiltin()))
|
||||||
modsToActivate.push_back(ModScope::scopeBuiltin());
|
modsToActivate.push_back(ModScope::scopeBuiltin());
|
||||||
@ -385,6 +390,33 @@ std::string ModsPresetState::getActivePreset() const
|
|||||||
return modConfig["activePreset"].String();
|
return modConfig["activePreset"].String();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode ModsPresetState::exportCurrentPreset() const
|
||||||
|
{
|
||||||
|
JsonNode data = getActivePresetConfig();
|
||||||
|
std::string presetName = getActivePreset();
|
||||||
|
|
||||||
|
data["name"] = JsonNode(presetName);
|
||||||
|
|
||||||
|
vstd::erase_if(data["settings"].Struct(), [&](const auto & pair){
|
||||||
|
return !vstd::contains(data["mods"].Vector(), JsonNode(pair.first));
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ModsPresetState::importPreset(const JsonNode & newConfig)
|
||||||
|
{
|
||||||
|
std::string importedPresetName = newConfig["name"].String();
|
||||||
|
|
||||||
|
if (importedPresetName.empty())
|
||||||
|
throw std::runtime_error("Attempt to import invalid preset");
|
||||||
|
|
||||||
|
modConfig["presets"][importedPresetName] = newConfig;
|
||||||
|
modConfig["presets"][importedPresetName].Struct().erase("name");
|
||||||
|
|
||||||
|
return importedPresetName;
|
||||||
|
}
|
||||||
|
|
||||||
ModsStorage::ModsStorage(const std::vector<TModID> & modsToLoad, const JsonNode & repositoryList)
|
ModsStorage::ModsStorage(const std::vector<TModID> & modsToLoad, const JsonNode & repositoryList)
|
||||||
{
|
{
|
||||||
JsonNode coreModConfig(JsonPath::builtin("config/gameConfig.json"));
|
JsonNode coreModConfig(JsonPath::builtin("config/gameConfig.json"));
|
||||||
@ -796,4 +828,28 @@ std::string ModManager::getActivePreset() const
|
|||||||
return modsPreset->getActivePreset();
|
return modsPreset->getActivePreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode ModManager::exportCurrentPreset() const
|
||||||
|
{
|
||||||
|
return modsPreset->exportCurrentPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<std::string, TModList> ModManager::importPreset(const JsonNode & data)
|
||||||
|
{
|
||||||
|
std::string presetName = modsPreset->importPreset(data);
|
||||||
|
|
||||||
|
TModList requiredMods = modsPreset->getRootMods(presetName);
|
||||||
|
TModList installedMods = modsState->getInstalledMods();
|
||||||
|
|
||||||
|
TModList missingMods;
|
||||||
|
for (const auto & modID : requiredMods)
|
||||||
|
{
|
||||||
|
if (!vstd::contains(installedMods, modID))
|
||||||
|
missingMods.push_back(modID);
|
||||||
|
}
|
||||||
|
|
||||||
|
modsPreset->saveConfigurationState();
|
||||||
|
|
||||||
|
return {presetName, missingMods};
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -58,6 +58,12 @@ public:
|
|||||||
std::vector<std::string> getAllPresets() const;
|
std::vector<std::string> getAllPresets() const;
|
||||||
std::string getActivePreset() const;
|
std::string getActivePreset() const;
|
||||||
|
|
||||||
|
JsonNode exportCurrentPreset() const;
|
||||||
|
|
||||||
|
/// Imports preset from provided json
|
||||||
|
/// Returns name of imported preset on success
|
||||||
|
std::string importPreset(const JsonNode & data);
|
||||||
|
|
||||||
void setModActive(const TModID & modName, bool isActive);
|
void setModActive(const TModID & modName, bool isActive);
|
||||||
|
|
||||||
void addRootMod(const TModID & modName);
|
void addRootMod(const TModID & modName);
|
||||||
@ -72,6 +78,8 @@ public:
|
|||||||
|
|
||||||
/// Returns list of currently active root mods (non-submod)
|
/// Returns list of currently active root mods (non-submod)
|
||||||
TModList getActiveRootMods() const;
|
TModList getActiveRootMods() const;
|
||||||
|
/// Returns list of root mods present in specified preset
|
||||||
|
TModList getRootMods(const std::string & presetName) const;
|
||||||
|
|
||||||
/// Returns list of all known settings (submods) for a specified mod
|
/// Returns list of all known settings (submods) for a specified mod
|
||||||
std::map<TModID, bool> getModSettings(const TModID & modID) const;
|
std::map<TModID, bool> getModSettings(const TModID & modID) const;
|
||||||
@ -155,6 +163,12 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> getAllPresets() const;
|
std::vector<std::string> getAllPresets() const;
|
||||||
std::string getActivePreset() const;
|
std::string getActivePreset() const;
|
||||||
|
|
||||||
|
JsonNode exportCurrentPreset() const;
|
||||||
|
|
||||||
|
/// Imports preset from provided json
|
||||||
|
/// Returns name of imported preset and list of mods that must be installed to activate preset
|
||||||
|
std::tuple<std::string, TModList> importPreset(const JsonNode & data);
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
Reference in New Issue
Block a user