QmlDesigner: Add UniqueName::getpath()

Also relevant tweaks in the same class

Change-Id: I59ca0839a28478028b8aa36b9df500f29d831b90
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2024-05-14 00:16:50 +03:00
parent f7a39ed57b
commit 5bf8845c42
4 changed files with 52 additions and 25 deletions

View File

@@ -154,20 +154,15 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
QString AssetsLibraryModel::addNewFolder(const QString &folderPath) QString AssetsLibraryModel::addNewFolder(const QString &folderPath)
{ {
Utils::FilePath dir = Utils::FilePath::fromString(folderPath); Utils::FilePath uniqueDirPath = Utils::FilePath::fromString(UniqueName::getPath(folderPath));
Utils::FilePath parentDir = dir.parentDir();
QString uniqueFolderName = UniqueName::get(dir.fileName(), [&] (const QString &folderName) { auto res = uniqueDirPath.ensureWritableDir();
return !parentDir.pathAppended(folderName).exists();
});
auto res = parentDir.pathAppended(uniqueFolderName).ensureWritableDir();
if (!res.has_value()) { if (!res.has_value()) {
qWarning() << __FUNCTION__ << res.error(); qWarning() << __FUNCTION__ << res.error();
return {}; return {};
} }
return uniqueFolderName; return uniqueDirPath.path();
} }
bool AssetsLibraryModel::urlPathExistsInModel(const QUrl &url) const bool AssetsLibraryModel::urlPathExistsInModel(const QUrl &url) const

View File

@@ -176,13 +176,9 @@ void AssetsLibraryWidget::deleteSelectedAssets()
QString AssetsLibraryWidget::getUniqueEffectPath(const QString &parentFolder, const QString &effectName) QString AssetsLibraryWidget::getUniqueEffectPath(const QString &parentFolder, const QString &effectName)
{ {
QString effectsDir = ModelNodeOperations::getEffectsDefaultDirectory(parentFolder); QString effectsDir = ModelNodeOperations::getEffectsDefaultDirectory(parentFolder);
QString effectPathTemplate = effectsDir + QLatin1String("/%1.qep"); QString effectPath = QLatin1String("%1/%2.qep").arg(effectsDir, effectName);
QString uniqueName = UniqueName::get(effectName, [&] (const QString &name) { return UniqueName::getPath(effectPath);
return !QFile::exists(effectPathTemplate.arg(name));
});
return effectPathTemplate.arg(uniqueName);
} }
bool AssetsLibraryWidget::createNewEffect(const QString &effectPath, bool openInEffectComposer) bool AssetsLibraryWidget::createNewEffect(const QString &effectPath, bool openInEffectComposer)

View File

@@ -3,17 +3,22 @@
#include "uniquename.h" #include "uniquename.h"
#include <QFileInfo>
#include <QRegularExpression> #include <QRegularExpression>
namespace QmlDesigner { namespace QmlDesigner {
/** /**
* @brief Gets a unique name from a give name * @brief Generates a unique name based on the provided name.
* @param oldName input name *
* @param predicate function to check if the name is unique. Retuns true if name is unique * This method iteratively generates a name by appending suffixes until a unique name is found.
* @return a unique name * The uniqueness of the generated name is determined by the provided predicate function.
*
* @param oldName The original name to be made unique.
* @param predicate A function that checks if a name is unique. Returns true if the name is unique,
* false otherwise.
* @return A unique name derived from the provided name.
*/ */
// static
QString UniqueName::get(const QString &oldName, std::function<bool(const QString &)> predicate) QString UniqueName::get(const QString &oldName, std::function<bool(const QString &)> predicate)
{ {
QString newName = oldName; QString newName = oldName;
@@ -23,29 +28,59 @@ QString UniqueName::get(const QString &oldName, std::function<bool(const QString
return newName; return newName;
} }
// static /**
* @brief Generates a unique path based on the provided path. If the path belongs to a file, the
* filename or if it's a directory, the directory name will be adjusted to ensure uniqueness.
*
* This method appends a numerical suffix (or increment it if it exists) to the filename or
* directory name if necessary to make it unique.
*
* @param path The original path to be made unique.
* @return A unique path derived from the provided path.
*/
QString UniqueName::getPath(const QString &path)
{
// Remove the trailing slash if it exists (otherwise QFileInfo::path() returns empty)
QString adjustedPath = path;
if (adjustedPath.endsWith('/'))
adjustedPath.chop(1);
QFileInfo fileInfo = QFileInfo(adjustedPath);
QString baseName = fileInfo.baseName();
QString suffix = fileInfo.completeSuffix();
if (!suffix.isEmpty())
suffix.prepend('.');
QString parentDir = fileInfo.path();
QString pathTemplate = parentDir + "/%1" + suffix;
QString uniqueBaseName = UniqueName::get(baseName, [&] (const QString &currName) {
return !QFileInfo::exists(pathTemplate.arg(currName));
});
return pathTemplate.arg(uniqueBaseName);
}
QString UniqueName::nextName(const QString &oldName) QString UniqueName::nextName(const QString &oldName)
{ {
static QRegularExpression rgx("\\d+$"); // matches a number at the end of a string static QRegularExpression rgx("\\d+$"); // match a number at the end of a string
QString uniqueName = oldName; QString uniqueName = oldName;
// if the name ends with a number, increment it // if the name ends with a number, increment it
QRegularExpressionMatch match = rgx.match(uniqueName); QRegularExpressionMatch match = rgx.match(uniqueName);
if (match.hasMatch()) { // ends with a number if (match.hasMatch()) { // ends with a number
QString numStr = match.captured(0); QString numStr = match.captured(0);
int num = match.captured(0).toInt(); int num = numStr.toInt() + 1;
// get number of padding zeros, ex: for "005" = 2 // get number of padding zeros, ex: for "005" = 2
int nPaddingZeros = 0; int nPaddingZeros = 0;
for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros); for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros);
++num;
// if the incremented number's digits increased, decrease the padding zeros // if the incremented number's digits increased, decrease the padding zeros
if (std::fmod(std::log10(num), 1.0) == 0) if (std::fmod(std::log10(num), 1.0) == 0)
--nPaddingZeros; --nPaddingZeros;
uniqueName = oldName.mid(0, match.capturedStart()) uniqueName = oldName.left(match.capturedStart())
+ QString('0').repeated(nPaddingZeros) + QString('0').repeated(nPaddingZeros)
+ QString::number(num); + QString::number(num);
} else { } else {

View File

@@ -11,6 +11,7 @@ class UniqueName
{ {
public: public:
static QString get(const QString &oldName, std::function<bool(const QString &)> predicate); static QString get(const QString &oldName, std::function<bool(const QString &)> predicate);
static QString getPath(const QString &oldName);
private: private:
static QString nextName(const QString &oldName); static QString nextName(const QString &oldName);