diff --git a/src/plugins/effectmakernew/effectmakermodel.cpp b/src/plugins/effectmakernew/effectmakermodel.cpp index d459a02845f..45efcb8c3ff 100644 --- a/src/plugins/effectmakernew/effectmakermodel.cpp +++ b/src/plugins/effectmakernew/effectmakermodel.cpp @@ -720,6 +720,8 @@ void EffectMakerModel::exportResources(const QString &name) if (!source.copyFile(target)) qWarning() << __FUNCTION__ << " Failed to copy file: " << source; } + + emit resourcesExported(QString("Effects.%1.%1").arg(name).toUtf8(), effectPath); } void EffectMakerModel::resetEffectError(int type) diff --git a/src/plugins/effectmakernew/effectmakermodel.h b/src/plugins/effectmakernew/effectmakermodel.h index 1f4284b0813..02e46ce2cd7 100644 --- a/src/plugins/effectmakernew/effectmakermodel.h +++ b/src/plugins/effectmakernew/effectmakermodel.h @@ -100,6 +100,7 @@ signals: void currentCompositionChanged(); void nodesChanged(); + void resourcesExported(const QByteArray &type, const Utils::FilePath &path); private: enum Roles { diff --git a/src/plugins/effectmakernew/effectmakerwidget.cpp b/src/plugins/effectmakernew/effectmakerwidget.cpp index e11b4015a10..ceb8017ce43 100644 --- a/src/plugins/effectmakernew/effectmakerwidget.cpp +++ b/src/plugins/effectmakernew/effectmakerwidget.cpp @@ -17,16 +17,21 @@ #include +#include #include #include #include +#include + #include +#include #include #include #include #include +#include namespace EffectMaker { @@ -77,9 +82,27 @@ EffectMakerWidget::EffectMakerWidget(EffectMakerView *view) QmlDesigner::QmlDesignerPlugin::trackWidgetFocusTime( this, QmlDesigner::Constants::EVENT_NEWEFFECTMAKER_TIME); - connect(m_effectMakerModel.data(), &EffectMakerModel::nodesChanged, [this]() { + connect(m_effectMakerModel.data(), &EffectMakerModel::nodesChanged, this, [this]() { m_effectMakerNodesModel->updateCanBeAdded(m_effectMakerModel->uniformNames()); }); + + connect(m_effectMakerModel.data(), &EffectMakerModel::resourcesExported, + this, [this](const QmlDesigner::TypeName &type, const Utils::FilePath &path) { + if (!m_importScan.timer) { + m_importScan.timer = new QTimer(this); + connect(m_importScan.timer, &QTimer::timeout, + this, &EffectMakerWidget::handleImportScanTimer); + } + + if (m_importScan.timer->isActive() && !m_importScan.future.isFinished()) + m_importScan.future.cancel(); + + m_importScan.counter = 0; + m_importScan.type = type; + m_importScan.path = path; + + m_importScan.timer->start(100); + }); } @@ -177,5 +200,65 @@ void EffectMakerWidget::reloadQmlSource() m_quickWidget->setSource(QUrl::fromLocalFile(effectMakerQmlPath)); } +void EffectMakerWidget::handleImportScanTimer() +{ + ++m_importScan.counter; + + if (m_importScan.counter == 1) { + // Rescan the effect import to update code model + auto modelManager = QmlJS::ModelManagerInterface::instance(); + if (modelManager) { + QmlJS::PathsAndLanguages pathToScan; + pathToScan.maybeInsert(m_importScan.path); + m_importScan.future = ::Utils::asyncRun(&QmlJS::ModelManagerInterface::importScan, + modelManager->workingCopy(), + pathToScan, modelManager, true, true, true); + } + } else if (m_importScan.counter < 100) { + // We have to wait a while to ensure qmljs detects new files and updates its + // internal model. Then we force amend on rewriter to trigger qmljs snapshot update. + if (m_importScan.future.isCanceled() || m_importScan.future.isFinished()) + m_importScan.counter = 100; // skip the timeout step + } else if (m_importScan.counter == 100) { + // Scanning is taking too long, abort + m_importScan.future.cancel(); + m_importScan.timer->stop(); + m_importScan.counter = 0; + } else if (m_importScan.counter == 101) { + if (m_effectMakerView->model() && m_effectMakerView->model()->rewriterView()) { + QmlDesigner::QmlDesignerPlugin::instance()->documentManager().resetPossibleImports(); + m_effectMakerView->model()->rewriterView()->forceAmend(); + } + } else if (m_importScan.counter == 102) { + if (m_effectMakerView->model()) { + // If type is in use, we have to reset puppet to update 2D view + if (!m_effectMakerView->allModelNodesOfType( + m_effectMakerView->model()->metaInfo(m_importScan.type)).isEmpty()) { + m_effectMakerView->resetPuppet(); + } + } + } else if (m_importScan.counter >= 103) { + // Refresh property view by resetting selection if any selected node is of updated type + if (m_effectMakerView->model() && m_effectMakerView->hasSelectedModelNodes()) { + const auto nodes = m_effectMakerView->selectedModelNodes(); + QmlDesigner::MetaInfoType metaType + = m_effectMakerView->model()->metaInfo(m_importScan.type).type(); + bool match = false; + for (const QmlDesigner::ModelNode &node : nodes) { + if (node.metaInfo().type() == metaType) { + match = true; + break; + } + } + if (match) { + m_effectMakerView->clearSelectedModelNodes(); + m_effectMakerView->setSelectedModelNodes(nodes); + } + } + m_importScan.timer->stop(); + m_importScan.counter = 0; + } +} + } // namespace EffectMaker diff --git a/src/plugins/effectmakernew/effectmakerwidget.h b/src/plugins/effectmakernew/effectmakerwidget.h index 3c43d732e40..9204026a9c9 100644 --- a/src/plugins/effectmakernew/effectmakerwidget.h +++ b/src/plugins/effectmakernew/effectmakerwidget.h @@ -9,9 +9,14 @@ #include #include +#include class StudioQuickWidget; +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + namespace EffectMaker { class EffectMakerView; @@ -51,6 +56,7 @@ protected: private: void reloadQmlSource(); + void handleImportScanTimer(); QPointer m_effectMakerModel; QPointer m_effectMakerNodesModel; @@ -58,6 +64,16 @@ private: QPointer m_quickWidget; QmlDesigner::QmlModelNodeProxy m_backendModelNode; QmlDesigner::QmlAnchorBindingProxy m_backendAnchorBinding; + + struct ImportScanData { + QFuture future; + int counter = 0; + QTimer *timer = nullptr; + QmlDesigner::TypeName type; + Utils::FilePath path; + }; + + ImportScanData m_importScan; }; } // namespace EffectMaker