diff --git a/include/config.h b/include/config.h index ab625498..a8979e96 100644 --- a/include/config.h +++ b/include/config.h @@ -2,6 +2,7 @@ #define CONFIG_H #include +#include enum MapSortOrder { Group = 0, @@ -9,23 +10,23 @@ enum MapSortOrder { Layout = 2, }; -class KeyValueConfigBase +class KeyValueConfigBase : public QObject { public: void save(); void load(); virtual ~KeyValueConfigBase(); protected: - QString configFilename; + virtual QString getConfigFilepath() = 0; virtual void parseConfigKeyValue(QString key, QString value) = 0; virtual QMap getKeyValueMap() = 0; + virtual void onNewConfigFileCreated() = 0; }; class PorymapConfig: public KeyValueConfigBase { public: PorymapConfig() { - this->configFilename = "porymap.cfg"; this->recentProject = ""; this->recentMap = ""; this->mapSortOrder = MapSortOrder::Group; @@ -40,8 +41,10 @@ public: MapSortOrder getMapSortOrder(); bool getPrettyCursors(); protected: + QString getConfigFilepath(); void parseConfigKeyValue(QString key, QString value); QMap getKeyValueMap(); + void onNewConfigFileCreated() {} private: QString recentProject; QString recentMap; @@ -51,4 +54,30 @@ private: extern PorymapConfig porymapConfig; +enum BaseGameVersion { + pokeruby, + pokeemerald, +}; + +class ProjectConfig: public KeyValueConfigBase +{ +public: + ProjectConfig() { + this->baseGameVersion = BaseGameVersion::pokeemerald; + } + void setBaseGameVersion(BaseGameVersion baseGameVersion); + BaseGameVersion getBaseGameVersion(); + void setProjectDir(QString projectDir); +protected: + QString getConfigFilepath(); + void parseConfigKeyValue(QString key, QString value); + QMap getKeyValueMap(); + void onNewConfigFileCreated(); +private: + BaseGameVersion baseGameVersion; + QString projectDir; +}; + +extern ProjectConfig projectConfig; + #endif // CONFIG_H diff --git a/src/config.cpp b/src/config.cpp index cf8c76d1..be0612fa 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -2,7 +2,12 @@ #include "log.h" #include #include +#include +#include +#include #include +#include +#include #include #include @@ -11,17 +16,19 @@ KeyValueConfigBase::~KeyValueConfigBase() { } void KeyValueConfigBase::load() { - QFile file(this->configFilename); + QFile file(this->getConfigFilepath()); if (!file.exists()) { if (!file.open(QIODevice::WriteOnly)) { - logError(QString("Could not create config file '%1'").arg(this->configFilename)); + logError(QString("Could not create config file '%1'").arg(this->getConfigFilepath())); } else { file.close(); + this->onNewConfigFileCreated(); + this->save(); } } if (!file.open(QIODevice::ReadOnly)) { - logError(QString("Could not open config file '%1': ").arg(this->configFilename) + file.errorString()); + logError(QString("Could not open config file '%1': ").arg(this->getConfigFilepath()) + file.errorString()); } QTextStream in(&file); @@ -40,7 +47,7 @@ void KeyValueConfigBase::load() { QRegularExpressionMatch match = re.match(line); if (!match.hasMatch()) { - logWarn(QString("Invalid config line in %1: '%2'").arg(this->configFilename).arg(line)); + logWarn(QString("Invalid config line in %1: '%2'").arg(this->getConfigFilepath()).arg(line)); continue; } @@ -57,12 +64,12 @@ void KeyValueConfigBase::save() { text += QString("%1=%2\n").arg(it.key()).arg(it.value()); } - QFile file(this->configFilename); + QFile file(this->getConfigFilepath()); if (file.open(QIODevice::WriteOnly)) { file.write(text.toUtf8()); file.close(); } else { - logError(QString("Could not open config file '%1' for writing: ").arg(this->configFilename) + file.errorString()); + logError(QString("Could not open config file '%1' for writing: ").arg(this->getConfigFilepath()) + file.errorString()); } } @@ -80,6 +87,11 @@ const QMap mapSortOrderReverseMap = { PorymapConfig porymapConfig; +QString PorymapConfig::getConfigFilepath() { + // porymap config file is in the same directory as porymap itself. + return "porymap.cfg"; +} + void PorymapConfig::parseConfigKeyValue(QString key, QString value) { if (key == "recent_project") { this->recentProject = value; @@ -97,10 +109,10 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) { this->mapSortOrder = mapSortOrderReverseMap.value(sortOrder); } else { this->mapSortOrder = MapSortOrder::Group; - logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.")); + logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value)); } } else { - logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->configFilename).arg(key)); + logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); } } @@ -148,3 +160,80 @@ MapSortOrder PorymapConfig::getMapSortOrder() { bool PorymapConfig::getPrettyCursors() { return this->prettyCursors; } + +const QMap baseGameVersionMap = { + {BaseGameVersion::pokeruby, "pokeruby"}, + {BaseGameVersion::pokeemerald, "pokeemerald"}, +}; + +const QMap baseGameVersionReverseMap = { + {"pokeruby", BaseGameVersion::pokeruby}, + {"pokeemerald", BaseGameVersion::pokeemerald}, +}; + +ProjectConfig projectConfig; + +QString ProjectConfig::getConfigFilepath() { + // porymap config file is in the same directory as porymap itself. + return QDir(this->projectDir).filePath("porymap.project.cfg");; +} + +void ProjectConfig::parseConfigKeyValue(QString key, QString value) { + if (key == "base_game_version") { + QString baseGameVersion = value.toLower(); + if (baseGameVersionReverseMap.contains(baseGameVersion)) { + this->baseGameVersion = baseGameVersionReverseMap.value(baseGameVersion); + } else { + this->baseGameVersion = BaseGameVersion::pokeemerald; + logWarn(QString("Invalid config value for base_game_version: '%1'. Must be 'pokeruby' or 'pokeemerald'.").arg(value)); + } + } else { + logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); + } +} + +QMap ProjectConfig::getKeyValueMap() { + QMap map; + map.insert("base_game_version", baseGameVersionMap.value(this->baseGameVersion)); + return map; +} + +void ProjectConfig::onNewConfigFileCreated() { + QString dirName = QDir(this->projectDir).dirName().toLower(); + if (baseGameVersionReverseMap.contains(dirName)) { + this->baseGameVersion = baseGameVersionReverseMap.value(dirName); + logInfo(QString("Auto-detected base_game_version as '%1'").arg(dirName)); + } else { + QDialog dialog(nullptr, Qt::WindowTitleHint); + dialog.setWindowTitle("Project Configuration"); + dialog.setWindowModality(Qt::NonModal); + + QFormLayout form(&dialog); + + QComboBox *baseGameVersionComboBox = new QComboBox(); + baseGameVersionComboBox->addItem("pokeruby", BaseGameVersion::pokeruby); + baseGameVersionComboBox->addItem("pokeemerald", BaseGameVersion::pokeemerald); + form.addRow(new QLabel("Game Version"), baseGameVersionComboBox); + + QDialogButtonBox buttonBox(QDialogButtonBox::Ok, Qt::Horizontal, &dialog); + connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); + form.addRow(&buttonBox); + + if (dialog.exec() == QDialog::Accepted) { + this->baseGameVersion = static_cast(baseGameVersionComboBox->currentData().toInt()); + } + } +} + +void ProjectConfig::setProjectDir(QString projectDir) { + this->projectDir = projectDir; +} + +void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) { + this->baseGameVersion = baseGameVersion; + this->save(); +} + +BaseGameVersion ProjectConfig::getBaseGameVersion() { + return this->baseGameVersion; +} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c9903d9f..e28859be 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -196,6 +196,9 @@ bool MainWindow::openProject(QString dir) { this->statusBar()->showMessage(QString("Opening project %1").arg(dir)); bool success = true; + projectConfig.setProjectDir(dir); + projectConfig.load(); + bool already_open = isProjectOpen() && (editor->project->root == dir); if (!already_open) { editor->project = new Project;