aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2024-01-23 17:50:34 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2024-01-25 12:29:04 +0000
commit6fb7f464acfb00bf8da5599b89535883f6b51641 (patch)
treea7ca86d52f15d9c6ee7dc0b95780a8562fef7eec
parent5db5ade17d74a3c0bdcf6c7c659add1a07b3cea8 (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>
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp23
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h1
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp73
-rw-r--r--src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h2
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.cpp7
-rw-r--r--src/plugins/qmldesigner/components/integration/designdocument.h1
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;