From b89c1ddc80f013ac9ee99f38b8add3d74b33d405 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 29 Oct 2024 21:51:05 -0400 Subject: [PATCH] Show unsaved changes warning for map list and layout-only edits --- include/core/map.h | 2 +- include/core/maplayout.h | 2 +- include/project.h | 3 +++ src/core/map.cpp | 2 +- src/core/maplayout.cpp | 2 +- src/mainwindow.cpp | 16 ++++------------ src/project.cpp | 25 +++++++++++++++++++++++-- src/ui/maplistmodels.cpp | 1 + 8 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index 66aa0008..acc52d90 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -101,7 +101,7 @@ public: QUndoStack editHistory; void modify(); void clean(); - bool hasUnsavedChanges(); + bool hasUnsavedChanges() const; void pruneEditHistory(); private: diff --git a/include/core/maplayout.h b/include/core/maplayout.h index cdd3b5d6..b617002f 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -104,7 +104,7 @@ public: void clearBorderCache(); void cacheBorder(); - bool hasUnsavedChanges(); + bool hasUnsavedChanges() const; bool layoutBlockChanged(int i, const Blockdata &cache); diff --git a/include/project.h b/include/project.h index 07d6dcab..39c492bb 100644 --- a/include/project.h +++ b/include/project.h @@ -144,6 +144,9 @@ public: int appendMapsec(QString name); + bool hasUnsavedChanges(); + bool hasUnsavedDataChanges = false; + QSet getTopLevelMapFields(); bool loadMapData(Map*); bool readMapLayouts(); diff --git a/src/core/map.cpp b/src/core/map.cpp index 8067b9a7..2a7d96dc 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -256,7 +256,7 @@ void Map::clean() { this->hasUnsavedDataChanges = false; } -bool Map::hasUnsavedChanges() { +bool Map::hasUnsavedChanges() const { return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile; } diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 9e283e26..34033ac5 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -418,6 +418,6 @@ QPixmap Layout::getLayoutItemPixmap() { return this->layoutItem ? this->layoutItem->pixmap() : QPixmap(); } -bool Layout::hasUnsavedChanges() { +bool Layout::hasUnsavedChanges() const { return !this->editHistory.isClean(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6e0f9185..9bac433a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1427,6 +1427,8 @@ void MainWindow::mapListAddGroup() { // TODO: Pull this all out into a custom window. Connect that to an action in the main menu as well. // (or, re-use the new map dialog with some tweaks) +// TODO: This needs to take the same default settings you would get for a new map (tilesets, dimensions, etc.) +// and initialize it with the same fill settings (default metatile/collision/elevation, default border) void MainWindow::mapListAddLayout() { if (!editor || !editor->project) return; @@ -1458,7 +1460,6 @@ void MainWindow::mapListAddLayout() { errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); QString errorMessage; - // TODO: Select default tilesets QComboBox *primaryCombo = new QComboBox(&dialog); primaryCombo->addItems(this->editor->project->primaryTilesetLabels); QComboBox *secondaryCombo = new QComboBox(&dialog); @@ -1642,6 +1643,7 @@ void MainWindow::onNewMapCreated() { logInfo(QString("Created a new map named %1.").arg(newMapName)); + // TODO: Creating a new map shouldn't be automatically saved editor->project->saveMap(newMap); editor->project->saveAllDataStructures(); @@ -3496,17 +3498,7 @@ bool MainWindow::closeProject() { if (!isProjectOpen()) return true; - // Check loaded maps for unsaved changes - // TODO: This needs to check for unsaved changes in layouts too. - bool unsavedChanges = false; - for (auto map : editor->project->mapCache.values()) { - if (map && map->hasUnsavedChanges()) { - unsavedChanges = true; - break; - } - } - - if (unsavedChanges) { + if (this->editor->project->hasUnsavedChanges()) { QMessageBox::StandardButton result = QMessageBox::question( this, "porymap", "The project has been modified, save changes?", QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); diff --git a/src/project.cpp b/src/project.cpp index 314503f4..e7a9beeb 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -484,7 +484,7 @@ bool Project::loadMapLayout(Map* map) { return false; } - if (map->hasUnsavedChanges() || map->layout->hasUnsavedChanges()) { + if (map->hasUnsavedChanges()) { return true; } else { return loadLayout(map->layout); @@ -1463,6 +1463,7 @@ void Project::saveAllDataStructures() { saveMapConstantsHeader(); saveWildMonData(); saveConfig(); + this->hasUnsavedDataChanges = false; } void Project::saveConfig() { @@ -2293,7 +2294,6 @@ QString Project::getEmptyMapsecName() { // This function assumes a valid and unique name. // Will return the new index. -// TODO: We're not currently tracking map/layout agonstic changes like this as unsaved, so there's no warning if you close the project after doing this. int Project::appendMapsec(QString name) { const QString emptyMapsecName = getEmptyMapsecName(); int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey(); @@ -2308,6 +2308,7 @@ int Project::appendMapsec(QString name) { this->mapSectionNameToValue[name] = newMapsecValue; this->mapSectionValueToName[newMapsecValue] = name; + this->hasUnsavedDataChanges = true; return newMapsecValue; } @@ -2993,3 +2994,23 @@ void Project::applyParsedLimits() { projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1); projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1); } + +bool Project::hasUnsavedChanges() { + if (this->hasUnsavedDataChanges) + return true; + + // Check layouts for unsaved changes + for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) { + auto map = i.value(); + if (map && map->hasUnsavedChanges()) + return true; + } + + // Check loaded maps for unsaved changes + for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) { + auto layout = i.value(); + if (layout && layout->hasUnsavedChanges()) + return true; + } + return false; +} diff --git a/src/ui/maplistmodels.cpp b/src/ui/maplistmodels.cpp index e9fbaa1f..46297892 100644 --- a/src/ui/maplistmodels.cpp +++ b/src/ui/maplistmodels.cpp @@ -214,6 +214,7 @@ void MapGroupModel::updateProject() { this->project->mapGroups = mapGroups; this->project->groupedMapNames = groupedMapNames; this->project->mapNames = mapNames; + this->project->hasUnsavedDataChanges = true; } QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) {