diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2024-02-05 14:59:46 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2024-02-05 13:41:21 +0000 |
commit | ca9e72fe6cf9f8e0fe00d794bf7111abac372c54 (patch) | |
tree | 2aee2cb41e75dd6d1c8b12e3513def294e371554 | |
parent | 9201491292b616f62387c1b4dc319a84e602e9ff (diff) |
EffectComposer: Delete obsolete resource files at effect save
If a new version of same effect is saved, remove files that are
no longer part of the effect from the effect import dir after the save.
Fixes: QDS-11737
Change-Id: Iae4da39f9f4713c2e26f1b90263881c8c9e13d78
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
13 files changed, 109 insertions, 15 deletions
diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml index bfe0d3e3b7..c353f8260a 100644 --- a/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml +++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/EffectCompositionNodeUniform.qml @@ -50,7 +50,7 @@ Item { anchors.fill: parent Text { - text: uniformName + text: uniformDisplayName color: StudioTheme.Values.themeTextColor font.pixelSize: StudioTheme.Values.baseFontSize horizontalAlignment: Text.AlignRight diff --git a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueImage.qml b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueImage.qml index b172eb302e..3bdab3a0a0 100644 --- a/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueImage.qml +++ b/share/qtcreator/qmldesigner/effectComposerQmlSources/ValueImage.qml @@ -19,8 +19,10 @@ Row { onAbsoluteFilePathChanged: uniformValue = absoluteFilePath - function defaultAsString() { - let urlStr = uniformDefaultValue.toString() + function defaultAsString(defaultPath) { + if (!defaultPath) + return undefined + let urlStr = defaultPath.toString() urlStr = urlStr.replace(/^(file:\/{3})/, "") // Prepend slash if there is no drive letter @@ -30,7 +32,24 @@ Row { return urlStr } - defaultItems: uniformDefaultValue ? [uniformDefaultValue.split('/').pop()] : undefined - defaultPaths: uniformDefaultValue ? [defaultAsString(uniformDefaultValue)] : undefined + Component.onCompleted: { + let originalPath = defaultAsString( + EffectComposerBackend.rootView.uniformDefaultImage(nodeName, uniformName)) + let originalName = originalPath ? originalPath.split('/').pop() : undefined + if (originalName) { + defaultItems = [originalName] + defaultPaths = [originalPath] + } else { + let currentPath = uniformDefaultValue ? defaultAsString(uniformDefaultValue) : undefined + let currentName = currentPath ? currentPath.split('/').pop() : undefined + if (currentName) { + defaultItems = [currentName] + defaultPaths = [currentPath] + } else { + defaultItems = [] + defaultPaths = [] + } + } + } } } diff --git a/src/plugins/effectcomposer/effectcomposermodel.cpp b/src/plugins/effectcomposer/effectcomposermodel.cpp index 9a3b8ca0af..9919fc7a30 100644 --- a/src/plugins/effectcomposer/effectcomposermodel.cpp +++ b/src/plugins/effectcomposer/effectcomposermodel.cpp @@ -678,6 +678,12 @@ R"( void EffectComposerModel::saveComposition(const QString &name) { + if (name.isEmpty() || name.size() < 3 || name[0].isLower()) { + QString error = QString("Error: Couldn't save composition '%1', name is invalid").arg(name); + qWarning() << error; + return; + } + const QString effectsAssetsDir = QmlDesigner::ModelNodeOperations::getEffectsDefaultDirectory(); const QString path = effectsAssetsDir + QDir::separator() + name + ".qep"; auto saveFile = QFile(path); @@ -708,9 +714,9 @@ void EffectComposerModel::saveComposition(const QString &name) saveFile.write(jsonDoc.toJson()); saveFile.close(); setCurrentComposition(name); - setHasUnsavedChanges(false); saveResources(name); + setHasUnsavedChanges(false); } void EffectComposerModel::openComposition(const QString &path) @@ -808,24 +814,31 @@ void EffectComposerModel::saveResources(const QString &name) // Get effects dir const Utils::FilePath effectsResDir = QmlDesigner::ModelNodeOperations::getEffectsImportDirectory(); const QString effectsResPath = effectsResDir.pathAppended(name).toString() + QDir::separator(); + Utils::FilePath effectPath = Utils::FilePath::fromString(effectsResPath); // Create the qmldir for effects - Utils::FilePath qmldirPath = effectsResDir.resolvePath(QStringLiteral("qmldir")); + QString qmldirFileName("qmldir"); + Utils::FilePath qmldirPath = effectsResDir.resolvePath(qmldirFileName); QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray())); if (qmldirContent.isEmpty()) { qmldirContent.append("module Effects\n"); qmldirPath.writeFileContents(qmldirContent.toUtf8()); } + Utils::FilePaths oldFiles; + QStringList newFileNames; + // Create effect folder if not created - Utils::FilePath effectPath = Utils::FilePath::fromString(effectsResPath); if (!effectPath.exists()) { QDir effectDir(effectsResDir.toString()); effectDir.mkdir(name); + } else { + oldFiles = effectPath.dirEntries(QDir::Files); } // Create effect qmldir - qmldirPath = effectPath.resolvePath(QStringLiteral("qmldir")); + newFileNames.append(qmldirFileName); + qmldirPath = effectPath.resolvePath(qmldirFileName); qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray())); if (qmldirContent.isEmpty()) { qmldirContent.append("module Effects."); @@ -857,13 +870,16 @@ void EffectComposerModel::saveResources(const QString &name) const QString qmlString = qmlStringList.join('\n'); QString qmlFilePath = effectsResPath + qmlFilename; writeToFile(qmlString.toUtf8(), qmlFilePath, FileType::Text); + newFileNames.append(qmlFilename); // Save shaders and images QStringList sources = {m_vertexShaderFilename, m_fragmentShaderFilename}; QStringList dests = {vsFilename, fsFilename}; + QHash<QString, Uniform *> fileNameToUniformHash; const QList<Uniform *> uniforms = allUniforms(); - for (const Uniform *uniform : uniforms) { + bool hasSampler = false; + for (Uniform *uniform : uniforms) { if (uniform->type() == Uniform::Type::Sampler && !uniform->value().toString().isEmpty()) { QString imagePath = uniform->value().toString(); QFileInfo fi(imagePath); @@ -874,6 +890,8 @@ void EffectComposerModel::saveResources(const QString &name) } sources.append(imagePath); dests.append(imageFilename); + fileNameToUniformHash.insert(imageFilename, uniform); + hasSampler = true; } } @@ -893,11 +911,30 @@ void EffectComposerModel::saveResources(const QString &name) for (int i = 0; i < sources.count(); ++i) { Utils::FilePath source = Utils::FilePath::fromString(sources[i]); Utils::FilePath target = Utils::FilePath::fromString(effectsResPath + dests[i]); + newFileNames.append(target.fileName()); if (target.exists() && source.fileName() != target.fileName()) target.removeFile(); // Remove existing file for update - if (!source.copyFile(target)) qWarning() << __FUNCTION__ << " Failed to copy file: " << source; + + if (fileNameToUniformHash.contains(dests[i])) { + Uniform *uniform = fileNameToUniformHash[dests[i]]; + const QVariant newValue = target.toString(); + uniform->setDefaultValue(newValue); + uniform->setValue(newValue); + } + } + + // Delete old content that was not overwritten + for (const Utils::FilePath &oldFile : oldFiles) { + if (!newFileNames.contains(oldFile.fileName())) + oldFile.removeFile(); + } + + // Refresh UI to update sampler UrlChoosers + if (hasSampler) { + beginResetModel(); + endResetModel(); } emit resourcesSaved(QString("Effects.%1.%1").arg(name).toUtf8(), effectPath); diff --git a/src/plugins/effectcomposer/effectcomposernodesmodel.cpp b/src/plugins/effectcomposer/effectcomposernodesmodel.cpp index 28fc943446..1d1d405e81 100644 --- a/src/plugins/effectcomposer/effectcomposernodesmodel.cpp +++ b/src/plugins/effectcomposer/effectcomposernodesmodel.cpp @@ -68,7 +68,10 @@ void EffectComposerNodesModel::loadModel() QDirIterator itEffects(categoryPath.toString(), {"*.qen"}, QDir::Files); while (itEffects.hasNext()) { itEffects.next(); - effects.push_back(new EffectNode(itEffects.filePath())); + auto node = new EffectNode(itEffects.filePath()); + if (!node->defaultImagesHash().isEmpty()) + m_defaultImagesHash.insert(node->name(), node->defaultImagesHash()); + effects.push_back(node); } catName[0] = catName[0].toUpper(); // capitalize first letter @@ -108,4 +111,9 @@ void EffectComposerNodesModel::updateCanBeAdded(const QStringList &uniforms) } } +QHash<QString, QString> EffectComposerNodesModel::defaultImagesForNode(const QString &name) const +{ + return m_defaultImagesHash.value(name); +} + } // namespace EffectComposer diff --git a/src/plugins/effectcomposer/effectcomposernodesmodel.h b/src/plugins/effectcomposer/effectcomposernodesmodel.h index 7edabcd9f9..ce914a5e6d 100644 --- a/src/plugins/effectcomposer/effectcomposernodesmodel.h +++ b/src/plugins/effectcomposer/effectcomposernodesmodel.h @@ -32,12 +32,15 @@ public: void updateCanBeAdded(const QStringList &uniforms); + QHash<QString, QString> defaultImagesForNode(const QString &name) const; + private: QString nodesSourcesPath() const; QList<EffectNodesCategory *> m_categories; bool m_probeNodesDir = false; bool m_modelLoaded = false; + QHash<QString, QHash<QString, QString>> m_defaultImagesHash; }; } // namespace EffectComposer diff --git a/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp b/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp index 9d8c1a31a7..492d5a9e80 100644 --- a/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp +++ b/src/plugins/effectcomposer/effectcomposeruniformsmodel.cpp @@ -19,6 +19,7 @@ QHash<int, QByteArray> EffectComposerUniformsModel::roleNames() const { QHash<int, QByteArray> roles; roles[NameRole] = "uniformName"; + roles[DisplayNameRole] = "uniformDisplayName"; roles[DescriptionRole] = "uniformDescription"; roles[ValueRole] = "uniformValue"; roles[BackendValueRole] = "uniformBackendValue"; diff --git a/src/plugins/effectcomposer/effectcomposeruniformsmodel.h b/src/plugins/effectcomposer/effectcomposeruniformsmodel.h index f60c016ed0..65b2d7b2f0 100644 --- a/src/plugins/effectcomposer/effectcomposeruniformsmodel.h +++ b/src/plugins/effectcomposer/effectcomposeruniformsmodel.h @@ -30,6 +30,7 @@ public: private: enum Roles { NameRole = Qt::UserRole + 1, + DisplayNameRole, DescriptionRole, ValueRole, BackendValueRole, diff --git a/src/plugins/effectcomposer/effectcomposerwidget.cpp b/src/plugins/effectcomposer/effectcomposerwidget.cpp index 9303fe0ac4..b57120cb15 100644 --- a/src/plugins/effectcomposer/effectcomposerwidget.cpp +++ b/src/plugins/effectcomposer/effectcomposerwidget.cpp @@ -188,6 +188,11 @@ QPoint EffectComposerWidget::globalPos(const QPoint &point) const return point; } +QString EffectComposerWidget::uniformDefaultImage(const QString &nodeName, const QString &uniformName) const +{ + return m_effectComposerNodesModel->defaultImagesForNode(nodeName).value(uniformName); +} + QSize EffectComposerWidget::sizeHint() const { return {420, 420}; diff --git a/src/plugins/effectcomposer/effectcomposerwidget.h b/src/plugins/effectcomposer/effectcomposerwidget.h index c7349f3033..fb4c818f4f 100644 --- a/src/plugins/effectcomposer/effectcomposerwidget.h +++ b/src/plugins/effectcomposer/effectcomposerwidget.h @@ -50,6 +50,8 @@ public: Q_INVOKABLE void doOpenComposition(); Q_INVOKABLE QRect screenRect() const; Q_INVOKABLE QPoint globalPos(const QPoint &point) const; + Q_INVOKABLE QString uniformDefaultImage(const QString &nodeName, + const QString &uniformName) const; QSize sizeHint() const override; diff --git a/src/plugins/effectcomposer/effectnode.cpp b/src/plugins/effectcomposer/effectnode.cpp index 73b0068154..6128e3a196 100644 --- a/src/plugins/effectcomposer/effectnode.cpp +++ b/src/plugins/effectcomposer/effectnode.cpp @@ -31,8 +31,13 @@ EffectNode::EffectNode(const QString &qenPath) m_description = node.description(); const QList<Uniform *> uniforms = node.uniforms(); - for (const Uniform *uniform : uniforms) + for (const Uniform *uniform : uniforms) { m_uniformNames.insert(uniform->name()); + if (uniform->type() == Uniform::Type::Sampler) { + m_defaultImagesHash.insert( + uniform->name(), uniform->defaultValue().toString()); + } + } } QString EffectNode::name() const diff --git a/src/plugins/effectcomposer/effectnode.h b/src/plugins/effectcomposer/effectnode.h index 6322ff29f8..dff553a2de 100644 --- a/src/plugins/effectcomposer/effectnode.h +++ b/src/plugins/effectcomposer/effectnode.h @@ -25,6 +25,7 @@ public: QString name() const; QString description() const; QString qenPath() const; + QHash<QString, QString> defaultImagesHash() const { return m_defaultImagesHash; } void setCanBeAdded(bool enabled); @@ -40,6 +41,7 @@ private: QUrl m_iconPath; bool m_canBeAdded = true; QSet<QString> m_uniformNames; + QHash<QString, QString> m_defaultImagesHash; }; } // namespace EffectComposer diff --git a/src/plugins/effectcomposer/uniform.cpp b/src/plugins/effectcomposer/uniform.cpp index 4c8b994388..348c7b3a2b 100644 --- a/src/plugins/effectcomposer/uniform.cpp +++ b/src/plugins/effectcomposer/uniform.cpp @@ -102,6 +102,14 @@ void Uniform::setValue(const QVariant &newValue) } } +void Uniform::setDefaultValue(const QVariant &newValue) +{ + if (m_defaultValue != newValue) { + m_defaultValue = newValue; + emit uniformDefaultValueChanged(); + } +} + QVariant Uniform::defaultValue() const { return m_defaultValue; diff --git a/src/plugins/effectcomposer/uniform.h b/src/plugins/effectcomposer/uniform.h index 09081248c5..92e02bc467 100644 --- a/src/plugins/effectcomposer/uniform.h +++ b/src/plugins/effectcomposer/uniform.h @@ -18,7 +18,8 @@ class Uniform : public QObject { Q_OBJECT - Q_PROPERTY(QString uniformName MEMBER m_displayName CONSTANT) + Q_PROPERTY(QString uniformName MEMBER m_name CONSTANT) + Q_PROPERTY(QString uniformDisplayName MEMBER m_displayName CONSTANT) Q_PROPERTY(QString uniformType READ typeName CONSTANT) Q_PROPERTY(QString uniformControlType READ controlTypeName CONSTANT) Q_PROPERTY(QString uniformDescription READ description CONSTANT) @@ -26,7 +27,7 @@ class Uniform : public QObject Q_PROPERTY(QVariant uniformBackendValue READ backendValue NOTIFY uniformBackendValueChanged) Q_PROPERTY(QVariant uniformMinValue MEMBER m_minValue CONSTANT) Q_PROPERTY(QVariant uniformMaxValue MEMBER m_maxValue CONSTANT) - Q_PROPERTY(QVariant uniformDefaultValue MEMBER m_defaultValue CONSTANT) + Q_PROPERTY(QVariant uniformDefaultValue MEMBER m_defaultValue NOTIFY uniformDefaultValueChanged) Q_PROPERTY(QVariant uniformUseCustomValue MEMBER m_useCustomValue CONSTANT) public: @@ -52,6 +53,7 @@ public: QVariant value() const; void setValue(const QVariant &newValue); + void setDefaultValue(const QVariant &newValue); QVariant backendValue() const; @@ -80,6 +82,7 @@ public: signals: void uniformValueChanged(); void uniformBackendValueChanged(); + void uniformDefaultValueChanged(); private: QString mipmapPropertyName(const QString &name) const; |