QmlDesigner: Add UniqueName class

The class is used for generating a unique name anywhere in QmlDesigner
codebase. The role of this class is generation of next candidate name
when name is not unique. Actual checking of name uniqueness is provided
as a function param.

Also applied the new UniqueName on 1 usecase in
ContentLibraryUserModel::getUniqueLib3DQmlName

Change-Id: I777aeef7c269bed7d999695cf5fcee6a5576222b
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2024-05-13 14:13:03 +03:00
parent cf614eca91
commit 21f00445be
4 changed files with 82 additions and 8 deletions

View File

@@ -46,10 +46,10 @@ add_qtc_library(QmlDesignerUtils STATIC
hdrimage.cpp hdrimage.h
ktximage.cpp ktximage.h
imageutils.cpp imageutils.h
uniquename.cpp uniquename.h
qmldesignerutils_global.h
)
target_compile_options(QmlDesignerUtils PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,Clang,GNU>:-Wno-error=maybe-uninitialized>)
target_compile_options(QmlDesignerUtils PUBLIC $<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-unneeded-internal-declaration>)

View File

@@ -16,6 +16,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <utils/uniquename.h>
#include <QFileInfo>
#include <QJsonArray>
@@ -314,13 +315,9 @@ QString ContentLibraryUserModel::getUniqueLib3DQmlName(const QString &defaultNam
baseQml[0] = baseQml.at(0).toUpper();
baseQml.prepend("My");
QString uniqueQml = baseQml;
int counter = 1;
while (itemQmls.contains(uniqueQml)) {
uniqueQml = QString("%1%2").arg(uniqueQml).arg(counter);
++counter;
}
QString uniqueQml = UniqueName::get(baseQml, [&] (const QString &name) {
return !itemQmls.contains(name);
});
return uniqueQml + ".qml";
}

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "uniquename.h"
#include <QRegularExpression>
namespace QmlDesigner {
/**
* @brief Gets a unique name from a give name
* @param oldName input name
* @param predicate function to check if the name is unique. Retuns true if name is unique
* @return a unique name
*/
// static
QString UniqueName::get(const QString &oldName, std::function<bool(const QString &)> predicate)
{
QString newName = oldName;
while (!predicate(newName))
newName = nextName(newName);
return newName;
}
// static
QString UniqueName::nextName(const QString &oldName)
{
static QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
QString uniqueName = oldName;
// if the name ends with a number, increment it
QRegularExpressionMatch match = rgx.match(uniqueName);
if (match.hasMatch()) { // ends with a number
QString numStr = match.captured(0);
int num = match.captured(0).toInt();
// get number of padding zeros, ex: for "005" = 2
int nPaddingZeros = 0;
for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros);
++num;
// if the incremented number's digits increased, decrease the padding zeros
if (std::fmod(std::log10(num), 1.0) == 0)
--nPaddingZeros;
uniqueName = oldName.mid(0, match.capturedStart())
+ QString('0').repeated(nPaddingZeros)
+ QString::number(num);
} else {
uniqueName = oldName + '1';
}
return uniqueName;
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,19 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <QString>
namespace QmlDesigner {
class UniqueName
{
public:
static QString get(const QString &oldName, std::function<bool(const QString &)> predicate);
private:
static QString nextName(const QString &oldName);
};
} // namespace QmlDesigner