From 08199c5dfd61b96de1627ac6cb42ffe4452b39db Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 1 Aug 2024 17:43:43 +0300 Subject: [PATCH] QmlDesigner: Show an override dialog when adding an exisitng user asset Fixes: QDS-13212 Change-Id: If25da684797867be041e6a539b1a518a8f0a8343 Reviewed-by: Ali Kianian Reviewed-by: Mahmoud Badri --- .../contentlibrary/contentlibrarytexture.cpp | 13 +++++-- .../contentlibrary/contentlibrarytexture.h | 1 + .../contentlibraryusermodel.cpp | 25 ++++++++++-- .../contentlibrary/contentlibraryusermodel.h | 3 +- .../contentlibrary/contentlibraryview.cpp | 39 ++++++++++++++----- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp index d2c2df2baaf..90ab7698a77 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp @@ -78,17 +78,17 @@ QString ContentLibraryTexture::resolveToolTipText() if (m_suffix.isEmpty()) return m_baseName; // empty suffix means we have just the icon and no other data - QString fileName = m_baseName + m_suffix; + QString texFileName = fileName(); QString imageInfo; if (!m_isDownloaded && m_sizeInBytes > 0 && !m_dimensions.isNull()) { imageInfo = ImageUtils::imageInfoString(m_dimensions, m_sizeInBytes); } else { - QString fullDownloadPath = m_dirPath + '/' + fileName; + QString fullDownloadPath = m_dirPath + '/' + texFileName; imageInfo = ImageUtils::imageInfoString(fullDownloadPath); } - return QString("%1\n%2").arg(fileName, imageInfo); + return QString("%1\n%2").arg(texFileName, imageInfo); } bool ContentLibraryTexture::isDownloaded() const @@ -98,7 +98,7 @@ bool ContentLibraryTexture::isDownloaded() const QString ContentLibraryTexture::texturePath() const { - return m_dirPath + '/' + m_baseName + m_suffix; + return m_dirPath + '/' + fileName(); } void ContentLibraryTexture::setDownloaded() @@ -135,6 +135,11 @@ QString ContentLibraryTexture::textureKey() const return m_textureKey; } +QString ContentLibraryTexture::fileName() const +{ + return m_baseName + m_suffix; +} + void ContentLibraryTexture::setHasUpdate(bool value) { if (m_hasUpdate != value) { diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h index aa05667a1cd..bc7c667dd40 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h @@ -42,6 +42,7 @@ public: QString texturePath() const; QString parentDirPath() const; QString textureKey() const; + QString fileName() const; void setHasUpdate(bool value); bool hasUpdate() const; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp index f35815a2e81..89fb4a0a7d1 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.cpp @@ -111,7 +111,24 @@ void ContentLibraryUserModel::addTextures(const Utils::FilePaths &paths) updateIsEmpty(); } -void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex) +void ContentLibraryUserModel::removeTextures(const QStringList &fileNames) +{ + // note: this method doesn't refresh the model after textures removal + + auto texCat = qobject_cast(m_userCategories[TexturesSectionIdx]); + QTC_ASSERT(texCat, return); + + const QObjectList items = texCat->items(); + for (QObject *item : items) { + ContentLibraryTexture *castedItem = qobject_cast(item); + QTC_ASSERT(castedItem, continue); + + if (fileNames.contains(castedItem->fileName())) + removeTexture(castedItem, false); + } +} + +void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex, bool refresh) { // remove resources Utils::FilePath::fromString(tex->texturePath()).removeFile(); @@ -121,8 +138,10 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex) m_userCategories[TexturesSectionIdx]->removeItem(tex); // update model - emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx)); - updateIsEmpty(); + if (refresh) { + emit dataChanged(index(TexturesSectionIdx), index(TexturesSectionIdx)); + updateIsEmpty(); + } } void ContentLibraryUserModel::removeFromContentLib(QObject *item) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h index ca42f8233b6..172bad093a3 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryusermodel.h @@ -51,6 +51,7 @@ public: const QStringList &files); void refreshSection(const QString &bundleId); void addTextures(const Utils::FilePaths &paths); + void removeTextures(const QStringList &fileNames); void removeItemByName(const QString &qmlFileName, const QString &bundleId); @@ -62,7 +63,7 @@ public: Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryItem *mat, bool add = false); Q_INVOKABLE void addToProject(ContentLibraryItem *item); Q_INVOKABLE void removeFromProject(QObject *item); - Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex); + Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex, bool refresh = true); Q_INVOKABLE void removeFromContentLib(QObject *item); signals: diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index 6810199e50b..1cf2aaedf70 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -619,22 +619,43 @@ QPair> ContentLibraryView::modelNodeToQmlString(const M void ContentLibraryView::addLibAssets(const QStringList &paths) { auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/textures"); - Utils::FilePaths pathsInBundle; + Utils::FilePaths sourcePathsToAdd; + Utils::FilePaths targetPathsToAdd; + QStringList fileNamesToRemove; - const QStringList existingTextures = Utils::transform(bundlePath.dirEntries(QDir::Files), + const QStringList existingAssetsFileNames = Utils::transform(bundlePath.dirEntries(QDir::Files), [](const Utils::FilePath &path) { return path.fileName(); }); for (const QString &path : paths) { auto assetFilePath = Utils::FilePath::fromString(path); - if (existingTextures.contains(assetFilePath.fileName())) - continue; + QString assetFileName = assetFilePath.fileName(); - Asset asset(path); + // confirm overwrite if an item with same name exists + if (existingAssetsFileNames.contains(assetFileName)) { + QMessageBox::StandardButton reply = QMessageBox::question(m_widget, tr("Texture Exists"), + tr("A texture with the same name '%1' already exists in the Content Library, are you sure you want to overwrite it?") + .arg(assetFileName), QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::No) + continue; + + fileNamesToRemove.append(assetFileName); + } + + sourcePathsToAdd.append(assetFilePath); + } + + // remove the to-be-overwritten resources from target bundle path + m_widget->userModel()->removeTextures(fileNamesToRemove); + + // copy resources to target bundle path + for (const Utils::FilePath &sourcePath : sourcePathsToAdd) { + Utils::FilePath targetPath = bundlePath.pathAppended(sourcePath.fileName()); + Asset asset{sourcePath.toFSPathString()}; // save icon - QString iconSavePath = bundlePath.pathAppended("icons/" + assetFilePath.baseName() + ".png") + QString iconSavePath = bundlePath.pathAppended("icons/" + sourcePath.baseName() + ".png") .toFSPathString(); QPixmap icon = asset.pixmap({120, 120}); bool iconSaved = icon.save(iconSavePath); @@ -642,13 +663,13 @@ void ContentLibraryView::addLibAssets(const QStringList &paths) qWarning() << __FUNCTION__ << "icon save failed"; // save asset - auto result = assetFilePath.copyFile(bundlePath.pathAppended(asset.fileName())); + auto result = sourcePath.copyFile(targetPath); QTC_ASSERT_EXPECTED(result,); - pathsInBundle.append(bundlePath.pathAppended(asset.fileName())); + targetPathsToAdd.append(targetPath); } - m_widget->userModel()->addTextures(pathsInBundle); + m_widget->userModel()->addTextures(targetPathsToAdd); } void ContentLibraryView::addLib3DComponent(const ModelNode &node)