diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 5d34810d438..87f6e9c66d1 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -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 $<$:-Wno-error=maybe-uninitialized>) target_compile_options(QmlDesignerUtils PUBLIC $<$:-Wno-unneeded-internal-declaration>) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index efee2224452..3e40b9c12c5 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -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"; } diff --git a/src/plugins/qmldesigner/utils/uniquename.cpp b/src/plugins/qmldesigner/utils/uniquename.cpp new file mode 100644 index 00000000000..ef6d3d8e5e2 --- /dev/null +++ b/src/plugins/qmldesigner/utils/uniquename.cpp @@ -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 + +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 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 diff --git a/src/plugins/qmldesigner/utils/uniquename.h b/src/plugins/qmldesigner/utils/uniquename.h new file mode 100644 index 00000000000..51e21bf17ad --- /dev/null +++ b/src/plugins/qmldesigner/utils/uniquename.h @@ -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 + +namespace QmlDesigner { + +class UniqueName +{ +public: + static QString get(const QString &oldName, std::function predicate); + +private: + static QString nextName(const QString &oldName); +}; + +} // namespace QmlDesigner