monitor files for changes
- add fileWatcher to project that monitors changes to most files (except map and layout json files) - add config setting whether to monitor files for changes (monitor_files)
This commit is contained in:
parent
6026266afd
commit
96a870552e
5 changed files with 84 additions and 7 deletions
|
@ -41,6 +41,7 @@ public:
|
|||
this->metatilesZoom = 30;
|
||||
this->showPlayerView = false;
|
||||
this->showCursorTile = true;
|
||||
this->monitorFiles = true;
|
||||
this->regionMapDimensions = QSize(32, 20);
|
||||
this->theme = "default";
|
||||
}
|
||||
|
@ -53,6 +54,7 @@ public:
|
|||
void setMetatilesZoom(int zoom);
|
||||
void setShowPlayerView(bool enabled);
|
||||
void setShowCursorTile(bool enabled);
|
||||
void setMonitorFiles(bool monitor);
|
||||
void setRegionMapDimensions(int width, int height);
|
||||
void setTheme(QString theme);
|
||||
QString getRecentProject();
|
||||
|
@ -64,6 +66,7 @@ public:
|
|||
int getMetatilesZoom();
|
||||
bool getShowPlayerView();
|
||||
bool getShowCursorTile();
|
||||
bool getMonitorFiles();
|
||||
QSize getRegionMapDimensions();
|
||||
QString getTheme();
|
||||
protected:
|
||||
|
@ -87,6 +90,7 @@ private:
|
|||
int metatilesZoom;
|
||||
bool showPlayerView;
|
||||
bool showCursorTile;
|
||||
bool monitorFiles;
|
||||
QSize regionMapDimensions;
|
||||
QString theme;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QPair>
|
||||
#include <QStandardItem>
|
||||
#include <QVariant>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
static QString NONE_MAP_CONSTANT = "MAP_NONE";
|
||||
static QString NONE_MAP_NAME = "None";
|
||||
|
@ -61,6 +62,7 @@ public:
|
|||
QMap<int, QString> metatileBehaviorMapInverse;
|
||||
QMap<QString, QString> facingDirections;
|
||||
ParseUtil parser;
|
||||
QFileSystemWatcher fileWatcher;
|
||||
|
||||
void set_root(QString);
|
||||
|
||||
|
|
|
@ -157,6 +157,12 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for show_cursor_tile: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if (key == "monitor_files") {
|
||||
bool ok;
|
||||
this->showCursorTile = value.toInt(&ok);
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for monitor_files: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if (key == "region_map_dimensions") {
|
||||
bool ok1, ok2;
|
||||
QStringList dims = value.split("x");
|
||||
|
@ -190,6 +196,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
|||
map.insert("metatiles_zoom", QString("%1").arg(this->metatilesZoom));
|
||||
map.insert("show_player_view", this->showPlayerView ? "1" : "0");
|
||||
map.insert("show_cursor_tile", this->showCursorTile ? "1" : "0");
|
||||
map.insert("monitor_files", this->monitorFiles ? "1" : "0");
|
||||
map.insert("region_map_dimensions", QString("%1x%2").arg(this->regionMapDimensions.width())
|
||||
.arg(this->regionMapDimensions.height()));
|
||||
map.insert("theme", this->theme);
|
||||
|
@ -233,6 +240,11 @@ void PorymapConfig::setPrettyCursors(bool enabled) {
|
|||
this->save();
|
||||
}
|
||||
|
||||
void PorymapConfig::setMonitorFiles(bool monitor) {
|
||||
this->monitorFiles = monitor;
|
||||
this->save();
|
||||
}
|
||||
|
||||
void PorymapConfig::setGeometry(QByteArray windowGeometry_, QByteArray windowState_, QByteArray mapSplitterState_,
|
||||
QByteArray eventsSlpitterState_, QByteArray mainSplitterState_) {
|
||||
this->windowGeometry = windowGeometry_;
|
||||
|
@ -315,6 +327,10 @@ bool PorymapConfig::getShowCursorTile() {
|
|||
return this->showCursorTile;
|
||||
}
|
||||
|
||||
bool PorymapConfig::getMonitorFiles() {
|
||||
return this->monitorFiles;
|
||||
}
|
||||
|
||||
QSize PorymapConfig::getRegionMapDimensions() {
|
||||
return this->regionMapDimensions;
|
||||
}
|
||||
|
|
|
@ -301,6 +301,27 @@ bool MainWindow::openProject(QString dir) {
|
|||
if (!already_open) {
|
||||
editor->closeProject();
|
||||
editor->project = new Project;
|
||||
QObject::connect(&editor->project->fileWatcher, &QFileSystemWatcher::fileChanged, [this](QString changed){
|
||||
QMessageBox notice(this);
|
||||
notice.setText("File Changed");
|
||||
notice.setInformativeText(QString("The file %1 has changed on disk. Would you like to reload the project?")
|
||||
.arg(changed.remove(editor->project->root + "/")));
|
||||
notice.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
|
||||
notice.setIcon(QMessageBox::Question);
|
||||
|
||||
QCheckBox showAgainCheck("Do not ask again.");
|
||||
notice.setCheckBox(&showAgainCheck);
|
||||
|
||||
int choice = notice.exec();
|
||||
if (choice == QMessageBox::Yes) {
|
||||
on_action_Reload_Project_triggered();
|
||||
} else if (choice == QMessageBox::No) {
|
||||
if (showAgainCheck.isChecked()) {
|
||||
porymapConfig.setMonitorFiles(false);
|
||||
this->editor->project->fileWatcher.blockSignals(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
editor->project->set_root(dir);
|
||||
success = loadDataStructures()
|
||||
&& populateMapList()
|
||||
|
|
|
@ -514,6 +514,7 @@ bool Project::readMapLayouts() {
|
|||
mapLayoutsTable.clear();
|
||||
|
||||
QString layoutsFilepath = QString("%1/data/layouts/layouts.json").arg(root);
|
||||
fileWatcher.addPath(layoutsFilepath);
|
||||
QJsonDocument layoutsDoc;
|
||||
if (!parser.tryParseJsonFile(&layoutsDoc, layoutsFilepath)) {
|
||||
logError(QString("Failed to read map layouts from %1").arg(layoutsFilepath));
|
||||
|
@ -1738,6 +1739,7 @@ bool Project::readWildMonData() {
|
|||
}
|
||||
|
||||
QString wildMonJsonFilepath = QString("%1/src/data/wild_encounters.json").arg(root);
|
||||
fileWatcher.addPath(wildMonJsonFilepath);
|
||||
QJsonDocument wildMonsJsonDoc;
|
||||
if (!parser.tryParseJsonFile(&wildMonsJsonDoc, wildMonJsonFilepath)) {
|
||||
logError(QString("Failed to read wild encounters from %1").arg(wildMonJsonFilepath));
|
||||
|
@ -1806,6 +1808,7 @@ bool Project::readMapGroups() {
|
|||
mapGroups->clear();
|
||||
|
||||
QString mapGroupsFilepath = QString("%1/data/maps/map_groups.json").arg(root);
|
||||
fileWatcher.addPath(mapGroupsFilepath);
|
||||
QJsonDocument mapGroupsDoc;
|
||||
if (!parser.tryParseJsonFile(&mapGroupsDoc, mapGroupsFilepath)) {
|
||||
logError(QString("Failed to read map groups from %1").arg(mapGroupsFilepath));
|
||||
|
@ -1975,7 +1978,9 @@ QMap<QString, QStringList> Project::getTilesetLabels() {
|
|||
bool Project::readTilesetProperties() {
|
||||
QStringList definePrefixes;
|
||||
definePrefixes << "NUM_";
|
||||
QMap<QString, int> defines = parser.readCDefines("include/fieldmap.h", definePrefixes);
|
||||
QString filename = "include/fieldmap.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> defines = parser.readCDefines(filename, definePrefixes);
|
||||
|
||||
auto it = defines.find("NUM_TILES_IN_PRIMARY");
|
||||
if (it != defines.end()) {
|
||||
|
@ -2034,6 +2039,7 @@ bool Project::readRegionMapSections() {
|
|||
|
||||
QStringList prefixes = (QStringList() << "MAPSEC_");
|
||||
QString filename = "include/constants/region_map_sections.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->mapSectionNameToValue = parser.readCDefines(filename, prefixes);
|
||||
if (this->mapSectionNameToValue.isEmpty()) {
|
||||
logError(QString("Failed to read region map sections from %1.").arg(filename));
|
||||
|
@ -2050,6 +2056,7 @@ bool Project::readHealLocations() {
|
|||
dataQualifiers.clear();
|
||||
flyableMaps.clear();
|
||||
QString filename = "src/data/heal_locations.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QString text = parser.readTextFile(root + "/" + filename);
|
||||
text.replace(QRegularExpression("//.*?(\r\n?|\n)|/\\*.*?\\*/", QRegularExpression::DotMatchesEverythingOption), "");
|
||||
|
||||
|
@ -2097,6 +2104,7 @@ bool Project::readItemNames() {
|
|||
itemNames->clear();
|
||||
QStringList prefixes = (QStringList() << "ITEM_");
|
||||
QString filename = "include/constants/items.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, itemNames);
|
||||
if (itemNames->isEmpty()) {
|
||||
logError(QString("Failed to read item constants from %1").arg(filename));
|
||||
|
@ -2109,6 +2117,7 @@ bool Project::readFlagNames() {
|
|||
flagNames->clear();
|
||||
QStringList prefixes = (QStringList() << "FLAG_");
|
||||
QString filename = "include/constants/flags.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, flagNames);
|
||||
if (flagNames->isEmpty()) {
|
||||
logError(QString("Failed to read flag constants from %1").arg(filename));
|
||||
|
@ -2121,6 +2130,7 @@ bool Project::readVarNames() {
|
|||
varNames->clear();
|
||||
QStringList prefixes = (QStringList() << "VAR_");
|
||||
QString filename = "include/constants/vars.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, varNames);
|
||||
if (varNames->isEmpty()) {
|
||||
logError(QString("Failed to read var constants from %1").arg(filename));
|
||||
|
@ -2133,6 +2143,7 @@ bool Project::readMovementTypes() {
|
|||
movementTypes->clear();
|
||||
QStringList prefixes = (QStringList() << "MOVEMENT_TYPE_");
|
||||
QString filename = "include/constants/event_object_movement.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, movementTypes);
|
||||
if (movementTypes->isEmpty()) {
|
||||
logError(QString("Failed to read movement type constants from %1").arg(filename));
|
||||
|
@ -2143,6 +2154,7 @@ bool Project::readMovementTypes() {
|
|||
|
||||
bool Project::readInitialFacingDirections() {
|
||||
QString filename = "src/event_object_movement.c";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
facingDirections = parser.readNamedIndexCArray(filename, "gInitialMovementTypeFacingDirections");
|
||||
if (facingDirections.isEmpty()) {
|
||||
logError(QString("Failed to read initial movement type facing directions from %1").arg(filename));
|
||||
|
@ -2155,6 +2167,7 @@ bool Project::readMapTypes() {
|
|||
mapTypes->clear();
|
||||
QStringList prefixes = (QStringList() << "MAP_TYPE_");
|
||||
QString filename = "include/constants/map_types.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, mapTypes);
|
||||
if (mapTypes->isEmpty()) {
|
||||
logError(QString("Failed to read map type constants from %1").arg(filename));
|
||||
|
@ -2167,6 +2180,7 @@ bool Project::readMapBattleScenes() {
|
|||
mapBattleScenes->clear();
|
||||
QStringList prefixes = (QStringList() << "MAP_BATTLE_SCENE_");
|
||||
QString filename = "include/constants/map_types.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted("include/constants/map_types.h", prefixes, mapBattleScenes);
|
||||
if (mapBattleScenes->isEmpty()) {
|
||||
logError(QString("Failed to read map battle scene constants from %1").arg(filename));
|
||||
|
@ -2179,6 +2193,7 @@ bool Project::readWeatherNames() {
|
|||
weatherNames->clear();
|
||||
QStringList prefixes = (QStringList() << "\\bWEATHER_");
|
||||
QString filename = "include/constants/weather.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, weatherNames);
|
||||
if (weatherNames->isEmpty()) {
|
||||
logError(QString("Failed to read weather constants from %1").arg(filename));
|
||||
|
@ -2191,6 +2206,7 @@ bool Project::readCoordEventWeatherNames() {
|
|||
coordEventWeatherNames->clear();
|
||||
QStringList prefixes = (QStringList() << "COORD_EVENT_WEATHER_");
|
||||
QString filename = "include/constants/weather.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, coordEventWeatherNames);
|
||||
if (coordEventWeatherNames->isEmpty()) {
|
||||
logError(QString("Failed to read coord event weather constants from %1").arg(filename));
|
||||
|
@ -2203,6 +2219,7 @@ bool Project::readSecretBaseIds() {
|
|||
secretBaseIds->clear();
|
||||
QStringList prefixes = (QStringList() << "SECRET_BASE_[A-Za-z0-9_]*_[0-9]+");
|
||||
QString filename = "include/constants/secret_bases.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, secretBaseIds);
|
||||
if (secretBaseIds->isEmpty()) {
|
||||
logError(QString("Failed to read secret base id constants from %1").arg(filename));
|
||||
|
@ -2215,6 +2232,7 @@ bool Project::readBgEventFacingDirections() {
|
|||
bgEventFacingDirections->clear();
|
||||
QStringList prefixes = (QStringList() << "BG_EVENT_PLAYER_FACING_");
|
||||
QString filename = "include/constants/event_bg.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, bgEventFacingDirections);
|
||||
if (bgEventFacingDirections->isEmpty()) {
|
||||
logError(QString("Failed to read bg event facing direction constants from %1").arg(filename));
|
||||
|
@ -2227,6 +2245,7 @@ bool Project::readTrainerTypes() {
|
|||
trainerTypes->clear();
|
||||
QStringList prefixes = (QStringList() << "TRAINER_TYPE_");
|
||||
QString filename = "include/constants/trainer_types.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
parser.readCDefinesSorted(filename, prefixes, trainerTypes);
|
||||
if (trainerTypes->isEmpty()) {
|
||||
logError(QString("Failed to read trainer type constants from %1").arg(filename));
|
||||
|
@ -2241,6 +2260,7 @@ bool Project::readMetatileBehaviors() {
|
|||
|
||||
QStringList prefixes = (QStringList() << "MB_");
|
||||
QString filename = "include/constants/metatile_behaviors.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->metatileBehaviorMap = parser.readCDefines(filename, prefixes);
|
||||
if (this->metatileBehaviorMap.isEmpty()) {
|
||||
logError(QString("Failed to read metatile behaviors from %1.").arg(filename));
|
||||
|
@ -2256,7 +2276,9 @@ bool Project::readMetatileBehaviors() {
|
|||
QStringList Project::getSongNames() {
|
||||
QStringList songDefinePrefixes;
|
||||
songDefinePrefixes << "SE_" << "MUS_";
|
||||
QMap<QString, int> songDefines = parser.readCDefines("include/constants/songs.h", songDefinePrefixes);
|
||||
QString filename = "include/constants/songs.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> songDefines = parser.readCDefines(filename, songDefinePrefixes);
|
||||
QStringList names = songDefines.keys();
|
||||
this->defaultSong = names.value(0, "MUS_DUMMY");
|
||||
|
||||
|
@ -2267,7 +2289,9 @@ QMap<QString, int> Project::getEventObjGfxConstants() {
|
|||
QStringList eventObjGfxPrefixes;
|
||||
eventObjGfxPrefixes << "OBJ_EVENT_GFX_";
|
||||
|
||||
QMap<QString, int> constants = parser.readCDefines("include/constants/event_objects.h", eventObjGfxPrefixes);
|
||||
QString filename = "include/constants/event_objects.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> constants = parser.readCDefines(filename, eventObjGfxPrefixes);
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
@ -2275,7 +2299,9 @@ QMap<QString, int> Project::getEventObjGfxConstants() {
|
|||
bool Project::readMiscellaneousConstants() {
|
||||
miscConstants.clear();
|
||||
if (projectConfig.getEncounterJsonActive()) {
|
||||
QMap<QString, int> pokemonDefines = parser.readCDefines("include/constants/pokemon.h", QStringList() << "MIN_" << "MAX_");
|
||||
QString filename = "include/constants/pokemon.h";
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> pokemonDefines = parser.readCDefines(filename, QStringList() << "MIN_" << "MAX_");
|
||||
miscConstants.insert("max_level_define", pokemonDefines.value("MAX_LEVEL") > pokemonDefines.value("MIN_LEVEL") ? pokemonDefines.value("MAX_LEVEL") : 100);
|
||||
miscConstants.insert("min_level_define", pokemonDefines.value("MIN_LEVEL") < pokemonDefines.value("MAX_LEVEL") ? pokemonDefines.value("MIN_LEVEL") : 1);
|
||||
}
|
||||
|
@ -2322,6 +2348,11 @@ void Project::loadEventPixmaps(QList<Event*> objects) {
|
|||
|
||||
QMap<QString, int> constants = getEventObjGfxConstants();
|
||||
|
||||
fileWatcher.addPaths(QStringList() << root + "/" + "src/data/object_events/object_event_graphics_info_pointers.h"
|
||||
<< root + "/" + "src/data/object_events/object_event_graphics_info.h"
|
||||
<< root + "/" + "src/data/object_events/object_event_pic_tables.h"
|
||||
<< root + "/" + "src/data/object_events/object_event_graphics.h");
|
||||
|
||||
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray("src/data/object_events/object_event_graphics_info_pointers.h", "gObjectEventGraphicsInfoPointers");
|
||||
|
||||
for (Event *object : objects) {
|
||||
|
@ -2383,10 +2414,13 @@ void Project::loadEventPixmaps(QList<Event*> objects) {
|
|||
|
||||
bool Project::readSpeciesIconPaths() {
|
||||
speciesToIconPath.clear();
|
||||
QString filename = "src/pokemon_icon.c";
|
||||
QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(filename, "gMonIconTable");
|
||||
QString srcfilename = "src/pokemon_icon.c";
|
||||
QString incfilename = "src/data/graphics/pokemon.h";
|
||||
fileWatcher.addPath(root + "/" + srcfilename);
|
||||
fileWatcher.addPath(root + "/" + incfilename);
|
||||
QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(srcfilename, "gMonIconTable");
|
||||
for (QString species : monIconNames.keys()) {
|
||||
QString path = parser.readCIncbin("src/data/graphics/pokemon.h", monIconNames.value(species));
|
||||
QString path = parser.readCIncbin(incfilename, monIconNames.value(species));
|
||||
speciesToIconPath.insert(species, root + "/" + path.replace("4bpp", "png"));
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue