diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2024-01-23 17:50:34 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2024-01-25 12:29:04 +0000 |
commit | 6fb7f464acfb00bf8da5599b89535883f6b51641 (patch) | |
tree | a7ca86d52f15d9c6ee7dc0b95780a8562fef7eec | |
parent | 5db5ade17d74a3c0bdcf6c7c659add1a07b3cea8 (diff) |
QmlDesigner: Remove deleted effect usages from current document
If there are any imports or nodes of the deleted effects in use in the
current document, also remove those when deleting effects.
Fixes: QDS-11723
Change-Id: I87972b5fc38b35acb0fb71fd085d2a3fcf691318
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
6 files changed, 91 insertions, 16 deletions
diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index 1033341d34..4134884eb9 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -114,6 +114,8 @@ void AssetsLibraryModel::deleteFiles(const QStringList &filePaths, bool dontAskA if (dontAskAgain) QmlDesignerPlugin::settings().insert(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, false); + QStringList deletedEffects; + for (const QString &filePath : filePaths) { QFileInfo fi(filePath); if (fi.exists()) { @@ -121,22 +123,8 @@ void AssetsLibraryModel::deleteFiles(const QStringList &filePaths, bool dontAskA if (Asset(filePath).isEffect()) { // If effect maker effect was removed, also remove effect module from project QString effectName = fi.baseName(); - if (!effectName.isEmpty()) { - Utils::FilePath eDir = ModelNodeOperations::getEffectsImportDirectory(); - eDir = eDir.pathAppended(effectName); - // The size check is to weed out cases where project path somehow resolves - // to just slash. Shortest legal currentProjectDirPath() would be "/a/". - if (currentProjectDirPath().size() > 2 && eDir.exists() - && eDir.toString().startsWith(currentProjectDirPath())) { - QString error; - eDir.removeRecursively(&error); - if (!error.isEmpty()) { - QMessageBox::warning(Core::ICore::dialogParent(), - tr("Failed to Delete Effect Resources"), - tr("Could not delete \"%1\".").arg(eDir.toString())); - } - } - } + if (!effectName.isEmpty()) + deletedEffects.append(effectName); } } else { QMessageBox::warning(Core::ICore::dialogParent(), @@ -145,6 +133,9 @@ void AssetsLibraryModel::deleteFiles(const QStringList &filePaths, bool dontAskA } } } + + if (!deletedEffects.isEmpty()) + emit effectsDeleted(deletedEffects); } bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &newName) diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h index e37bf8a109..9334e86e9b 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h @@ -64,6 +64,7 @@ signals: void rootPathChanged(); void haveFilesChanged(); void fileChanged(const QString &path); + void effectsDeleted(const QStringList &effectNames); private: void setHaveFiles(bool value); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index 13178c6dd2..56fb1d0ba3 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -8,6 +8,8 @@ #include "assetslibrarymodel.h" #include "assetslibraryview.h" #include "designeractionmanager.h" +#include "import.h" +#include "nodemetainfo.h" #include "modelnodeoperations.h" #include "qmldesignerconstants.h" #include "qmldesignerplugin.h" @@ -27,6 +29,7 @@ #include <QFileDialog> #include <QFileInfo> #include <QImageReader> +#include <QMessageBox> #include <QMimeData> #include <QMouseEvent> #include <QPointF> @@ -118,6 +121,9 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon connect(m_assetsModel, &AssetsLibraryModel::fileChanged, QmlDesignerPlugin::instance(), &QmlDesignerPlugin::assetChanged); + connect(m_assetsModel, &AssetsLibraryModel::effectsDeleted, + this, &AssetsLibraryWidget::handleDeleteEffects); + auto layout = new QVBoxLayout(this); layout->setContentsMargins({}); layout->setSpacing(0); @@ -263,6 +269,73 @@ void AssetsLibraryWidget::setHasSceneEnv(bool b) emit hasSceneEnvChanged(); } +void AssetsLibraryWidget::handleDeleteEffects(const QStringList &effectNames) +{ + DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); + if (!document) + return; + + bool clearStacks = false; + + // Remove usages of deleted effects from the current document + m_assetsView->executeInTransaction(__FUNCTION__, [&]() { + QList<ModelNode> allNodes = m_assetsView->allModelNodes(); + const QString typeTemplate = "Effects.%1.%1"; + const QString importUrlTemplate = "Effects.%1"; + const Imports imports = m_assetsView->model()->imports(); + Imports removedImports; + for (const QString &effectName : effectNames) { + if (effectName.isEmpty()) + continue; + const TypeName type = typeTemplate.arg(effectName).toUtf8(); + for (ModelNode &node : allNodes) { + if (node.metaInfo().typeName() == type) { + clearStacks = true; + node.destroy(); + } + } + + const QString importPath = importUrlTemplate.arg(effectName); + Import removedImport = Utils::findOrDefault(imports, [&importPath](const Import &import) { + return import.url() == importPath; + }); + if (!removedImport.isEmpty()) + removedImports.append(removedImport); + } + + if (!removedImports.isEmpty()) { + m_assetsView->model()->changeImports({}, removedImports); + clearStacks = true; + } + }); + + // The size check here is to weed out cases where project path somehow resolves + // to just slash. Shortest legal currentProjectDirPath() would be "/a/". + if (m_assetsModel->currentProjectDirPath().size() < 3) + return; + + Utils::FilePath effectsDir = ModelNodeOperations::getEffectsImportDirectory(); + + // Delete the effect modules + for (const QString &effectName : effectNames) { + Utils::FilePath eDir = effectsDir.pathAppended(effectName); + if (eDir.exists() && eDir.toString().startsWith(m_assetsModel->currentProjectDirPath())) { + QString error; + eDir.removeRecursively(&error); + if (!error.isEmpty()) { + QMessageBox::warning(Core::ICore::dialogParent(), + tr("Failed to Delete Effect Resources"), + tr("Could not delete \"%1\".").arg(eDir.toString())); + } + } + } + + // Reset undo stack as removing effect components cannot be undone, and thus the stack will + // contain only unworkable states. + if (clearStacks) + document->clearUndoRedoStacks(); +} + void AssetsLibraryWidget::invalidateThumbnail(const QString &id) { m_assetsIconProvider->invalidateThumbnail(id); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h index 4b3976ebae..1cf8f527d3 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h @@ -124,6 +124,8 @@ private: void setHasMaterialLibrary(bool enable); void setHasSceneEnv(bool b); + void handleDeleteEffects(const QStringList &effectNames); + QSize m_itemIconSize; SynchronousImageCache &m_fontImageCache; diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 7d6c93e44a..3ad09a8693 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -514,6 +514,13 @@ bool DesignDocument::isRedoAvailable() const return false; } +void DesignDocument::clearUndoRedoStacks() const +{ + const QPlainTextEdit *edit = plainTextEdit(); + if (edit) + edit->document()->clearUndoRedoStacks(); +} + void DesignDocument::close() { m_documentLoaded = false; diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index c5c1bab27f..aa7ced784f 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -57,6 +57,7 @@ public: #endif bool isUndoAvailable() const; bool isRedoAvailable() const; + void clearUndoRedoStacks() const; Model *currentModel() const; Model *documentModel() const; |