diff --git a/CHANGELOG.md b/CHANGELOG.md index b9bf5d3f..bdbafdf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project somewhat adheres to [Semantic Versioning](https://semver.org/sp - Fix `Edit > Clear Map Entries` in the Region Map Editor not saving the applied changes. - Fix `Edit > Undo/Redo` appearing enabled even when they don't do anything. - Fix `Help > Open Manual` being disabled when no project is open. +- Fix new tilesets potentially overwriting data in an existing directory. - Fix exported images on macOS using a different color space than in Porymap. - Fix some `INCBIN` statements not being parsed correctly. - Fix excessive logging if Porymap fails to monitor all map files. diff --git a/include/core/utility.h b/include/core/utility.h index ad8ce825..07b52a70 100644 --- a/include/core/utility.h +++ b/include/core/utility.h @@ -19,6 +19,7 @@ namespace Util { QString toStylesheetString(const QFont &font); void show(QWidget *w); QColorSpace toColorSpace(int colorSpaceInt); + QString mkpath(const QString& dirPath); } #endif // UTILITY_H diff --git a/src/core/utility.cpp b/src/core/utility.cpp index 1c48f830..93e2206f 100644 --- a/src/core/utility.cpp +++ b/src/core/utility.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // Sometimes we want to sort names alphabetically to make them easier to find in large combo box lists. // QStringList::sort (as of writing) can only sort numbers in lexical order, which has an undesirable @@ -145,3 +146,17 @@ QColorSpace Util::toColorSpace(int colorSpaceInt) { return QColorSpace(); } } + +// Creates a directory named 'dirPath', including any non-existent parent directories. Returns an error message, if any. +// If 'dirPath' already exists it's considered an error unless the directory has no files. +QString Util::mkpath(const QString& dirPath) { + if (!QDir::root().mkpath(dirPath)) { + return QString("Failed to create directory '%1'").arg(dirPath); + } + QDir dir(dirPath); + QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); + if (!files.isEmpty()) { + return QString("Directory '%1' already exists and is not empty").arg(dirPath); + } + return QString(); +} diff --git a/src/project.cpp b/src/project.cpp index aea178a5..d53e9cb9 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1569,17 +1569,14 @@ Tileset *Project::createNewTileset(QString name, bool secondary, bool checkerboa // Create tileset directories const QString fullDirectoryPath = QString("%1/%2").arg(this->root).arg(tileset->getExpectedDir()); - QDir directory; - if (!directory.mkpath(fullDirectoryPath)) { - logError(QString("Failed to create directory '%1' for new tileset '%2'").arg(fullDirectoryPath).arg(tileset->name)); - delete tileset; - return nullptr; - } const QString palettesPath = fullDirectoryPath + "/palettes"; - if (!directory.mkpath(palettesPath)) { - logError(QString("Failed to create palettes directory '%1' for new tileset '%2'").arg(palettesPath).arg(tileset->name)); - delete tileset; - return nullptr; + for (const auto& dir : {fullDirectoryPath, palettesPath}) { + QString error = Util::mkpath(dir); + if (!error.isEmpty()) { + logError(QString("Failed to create tileset '%1': %2.").arg(tileset->name).arg(error)); + delete tileset; + return nullptr; + } } tileset->tilesImagePath = fullDirectoryPath + "/tiles.png";