Show unsaved changes warning for map list and layout-only edits

This commit is contained in:
GriffinR 2024-10-29 21:51:05 -04:00
parent 785ac958a5
commit b89c1ddc80
8 changed files with 35 additions and 18 deletions

View file

@ -101,7 +101,7 @@ public:
QUndoStack editHistory; QUndoStack editHistory;
void modify(); void modify();
void clean(); void clean();
bool hasUnsavedChanges(); bool hasUnsavedChanges() const;
void pruneEditHistory(); void pruneEditHistory();
private: private:

View file

@ -104,7 +104,7 @@ public:
void clearBorderCache(); void clearBorderCache();
void cacheBorder(); void cacheBorder();
bool hasUnsavedChanges(); bool hasUnsavedChanges() const;
bool layoutBlockChanged(int i, const Blockdata &cache); bool layoutBlockChanged(int i, const Blockdata &cache);

View file

@ -144,6 +144,9 @@ public:
int appendMapsec(QString name); int appendMapsec(QString name);
bool hasUnsavedChanges();
bool hasUnsavedDataChanges = false;
QSet<QString> getTopLevelMapFields(); QSet<QString> getTopLevelMapFields();
bool loadMapData(Map*); bool loadMapData(Map*);
bool readMapLayouts(); bool readMapLayouts();

View file

@ -256,7 +256,7 @@ void Map::clean() {
this->hasUnsavedDataChanges = false; this->hasUnsavedDataChanges = false;
} }
bool Map::hasUnsavedChanges() { bool Map::hasUnsavedChanges() const {
return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile; return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile;
} }

View file

@ -418,6 +418,6 @@ QPixmap Layout::getLayoutItemPixmap() {
return this->layoutItem ? this->layoutItem->pixmap() : QPixmap(); return this->layoutItem ? this->layoutItem->pixmap() : QPixmap();
} }
bool Layout::hasUnsavedChanges() { bool Layout::hasUnsavedChanges() const {
return !this->editHistory.isClean(); return !this->editHistory.isClean();
} }

View file

@ -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. // 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) // (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() { void MainWindow::mapListAddLayout() {
if (!editor || !editor->project) return; if (!editor || !editor->project) return;
@ -1458,7 +1460,6 @@ void MainWindow::mapListAddLayout() {
errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }"); errorMessageLabel->setStyleSheet("QLabel { background-color: rgba(255, 0, 0, 25%) }");
QString errorMessage; QString errorMessage;
// TODO: Select default tilesets
QComboBox *primaryCombo = new QComboBox(&dialog); QComboBox *primaryCombo = new QComboBox(&dialog);
primaryCombo->addItems(this->editor->project->primaryTilesetLabels); primaryCombo->addItems(this->editor->project->primaryTilesetLabels);
QComboBox *secondaryCombo = new QComboBox(&dialog); QComboBox *secondaryCombo = new QComboBox(&dialog);
@ -1642,6 +1643,7 @@ void MainWindow::onNewMapCreated() {
logInfo(QString("Created a new map named %1.").arg(newMapName)); 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->saveMap(newMap);
editor->project->saveAllDataStructures(); editor->project->saveAllDataStructures();
@ -3496,17 +3498,7 @@ bool MainWindow::closeProject() {
if (!isProjectOpen()) if (!isProjectOpen())
return true; return true;
// Check loaded maps for unsaved changes if (this->editor->project->hasUnsavedChanges()) {
// 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) {
QMessageBox::StandardButton result = QMessageBox::question( QMessageBox::StandardButton result = QMessageBox::question(
this, "porymap", "The project has been modified, save changes?", this, "porymap", "The project has been modified, save changes?",
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);

View file

@ -484,7 +484,7 @@ bool Project::loadMapLayout(Map* map) {
return false; return false;
} }
if (map->hasUnsavedChanges() || map->layout->hasUnsavedChanges()) { if (map->hasUnsavedChanges()) {
return true; return true;
} else { } else {
return loadLayout(map->layout); return loadLayout(map->layout);
@ -1463,6 +1463,7 @@ void Project::saveAllDataStructures() {
saveMapConstantsHeader(); saveMapConstantsHeader();
saveWildMonData(); saveWildMonData();
saveConfig(); saveConfig();
this->hasUnsavedDataChanges = false;
} }
void Project::saveConfig() { void Project::saveConfig() {
@ -2293,7 +2294,6 @@ QString Project::getEmptyMapsecName() {
// This function assumes a valid and unique name. // This function assumes a valid and unique name.
// Will return the new index. // 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) { int Project::appendMapsec(QString name) {
const QString emptyMapsecName = getEmptyMapsecName(); const QString emptyMapsecName = getEmptyMapsecName();
int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey(); int newMapsecValue = mapSectionValueToName.isEmpty() ? 0 : mapSectionValueToName.lastKey();
@ -2308,6 +2308,7 @@ int Project::appendMapsec(QString name) {
this->mapSectionNameToValue[name] = newMapsecValue; this->mapSectionNameToValue[name] = newMapsecValue;
this->mapSectionValueToName[newMapsecValue] = name; this->mapSectionValueToName[newMapsecValue] = name;
this->hasUnsavedDataChanges = true;
return newMapsecValue; return newMapsecValue;
} }
@ -2993,3 +2994,23 @@ void Project::applyParsedLimits() {
projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1); projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1);
projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 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;
}

View file

@ -214,6 +214,7 @@ void MapGroupModel::updateProject() {
this->project->mapGroups = mapGroups; this->project->mapGroups = mapGroups;
this->project->groupedMapNames = groupedMapNames; this->project->groupedMapNames = groupedMapNames;
this->project->mapNames = mapNames; this->project->mapNames = mapNames;
this->project->hasUnsavedDataChanges = true;
} }
QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) { QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) {