From 21f00445be1ff13e52d8cf2b8418aed9aeca11b9 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Mon, 13 May 2024 14:13:03 +0300 Subject: [PATCH] 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 --- src/plugins/qmldesigner/CMakeLists.txt | 2 +- .../contentlibraryusermodel.cpp | 11 ++-- src/plugins/qmldesigner/utils/uniquename.cpp | 58 +++++++++++++++++++ src/plugins/qmldesigner/utils/uniquename.h | 19 ++++++ 4 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 src/plugins/qmldesigner/utils/uniquename.cpp create mode 100644 src/plugins/qmldesigner/utils/uniquename.h 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