From 5dd4fcd1f4273f55864c9d24340f6184500a75e5 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 13 Mar 2025 14:26:06 +0200 Subject: [PATCH] QmlDesigner: Remove QmlJS usage from 3D related content Removed unnecessary QmlJS usage from 3D importer, lights baking, and bundle importer. Also simplified bundle importer significantly and added usage of new addQuick3DImportAndView3D() function to 3D importer instead of just adding QtQuick3D import. Fixes: QDS-14922 Change-Id: I5c8a4073a146ebe3fbbc89705acffa16cb466ea6 Reviewed-by: Mahmoud Badri --- .../componentcore/bundleimporter.cpp | 68 ++++++++++++++-- .../components/componentcore/bundleimporter.h | 13 ++- .../components/componentcore/utils3d.cpp | 13 +-- .../components/componentcore/utils3d.h | 2 +- .../components/edit3d/bakelights.cpp | 5 +- .../components/import3d/import3dimporter.cpp | 80 ++++++++----------- .../components/import3d/import3dimporter.h | 1 - 7 files changed, 120 insertions(+), 62 deletions(-) diff --git a/src/plugins/qmldesigner/components/componentcore/bundleimporter.cpp b/src/plugins/qmldesigner/components/componentcore/bundleimporter.cpp index 7bd75751647..e83757a549a 100644 --- a/src/plugins/qmldesigner/components/componentcore/bundleimporter.cpp +++ b/src/plugins/qmldesigner/components/componentcore/bundleimporter.cpp @@ -12,7 +12,9 @@ #include #include +#ifndef QDS_USE_PROJECTSTORAGE #include +#endif #include #include @@ -52,15 +54,19 @@ QString BundleImporter::importComponent(const QString &bundleDir, if (!bundleImportPath.exists() && !bundleImportPath.createDir()) return QStringLiteral("Failed to create bundle import folder: '%1'").arg(bundleImportPath.toUrlishString()); +#ifndef QDS_USE_PROJECTSTORAGE bool doScan = false; bool doReset = false; +#endif FilePath qmldirPath = bundleImportPath.pathAppended("qmldir"); QString qmldirContent = QString::fromUtf8(qmldirPath.fileContents().value_or(QByteArray())); if (qmldirContent.isEmpty()) { qmldirContent.append("module "); qmldirContent.append(module); qmldirContent.append('\n'); +#ifndef QDS_USE_PROJECTSTORAGE doScan = true; +#endif } FilePath qmlSourceFile = bundleImportPath.pathAppended(qmlFile); @@ -75,7 +81,9 @@ QString BundleImporter::importComponent(const QString &bundleDir, qmldirContent.append(qmlFile); qmldirContent.append('\n'); qmldirPath.writeFileContents(qmldirContent.toUtf8()); +#ifndef QDS_USE_PROJECTSTORAGE doReset = true; +#endif } QStringList allFiles; @@ -118,15 +126,15 @@ QString BundleImporter::importComponent(const QString &bundleDir, ImportData data; data.isImport = true; data.type = type; + Import import = Import::createLibraryImport(module, "1.0"); +#ifdef QDS_USE_PROJECTSTORAGE + model->changeImports({import}, {}); +#else if (doScan) data.pathToScan = bundleImportPath; else data.fullReset = doReset; - Import import = Import::createLibraryImport(module, "1.0"); -#ifdef QDS_USE_PROJECTSTORAGE - model->changeImports({import}, {}); -#else if (!model->hasImport(import)) { if (model->possibleImports().contains(import)) { try { @@ -151,6 +159,51 @@ QString BundleImporter::importComponent(const QString &bundleDir, void BundleImporter::handleImportTimer() { +#ifdef QDS_USE_PROJECTSTORAGE + auto handleFailure = [this] { + m_importTimer.stop(); + m_importTimerCount = 0; + + // Emit dummy finished signals for all pending types + const QList pendingTypes = m_pendingImports.keys(); + for (const TypeName &pendingType : pendingTypes) { + ImportData data = m_pendingImports.take(pendingType); + if (data.isImport) + emit importFinished({}, m_bundleId); + else + emit unimportFinished({}, m_bundleId); + } + m_bundleId.clear(); + }; + + auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); + Model *model = doc ? doc->currentModel() : nullptr; + if (!model || ++m_importTimerCount > 100) { + handleFailure(); + return; + } + + const QList keys = m_pendingImports.keys(); + for (const TypeName &type : keys) { + ImportData &data = m_pendingImports[type]; + // Verify that code model has the new type fully available (or removed for unimport) + NodeMetaInfo metaInfo = model->metaInfo(type); + const bool typeComplete = metaInfo.isValid() && !metaInfo.prototypes().empty(); + if (data.isImport == typeComplete) { + m_pendingImports.remove(type); + if (data.isImport) + emit importFinished(type, m_bundleId); + else + emit unimportFinished(metaInfo, m_bundleId); + } + } + + if (m_pendingImports.isEmpty()) { + m_bundleId.clear(); + m_importTimer.stop(); + m_importTimerCount = 0; + } +#else auto handleFailure = [this] { m_importTimer.stop(); m_importTimerCount = 0; @@ -277,11 +330,7 @@ void BundleImporter::handleImportTimer() if (data.isImport == typeComplete) { m_pendingImports.remove(type); if (data.isImport) -#ifdef QDS_USE_PROJECTSTORAGE - emit importFinished(type, m_bundleId); -#else emit importFinished(metaInfo, m_bundleId); -#endif else emit unimportFinished(metaInfo, m_bundleId); } @@ -296,6 +345,7 @@ void BundleImporter::handleImportTimer() m_importTimerCount = 0; disconnect(m_libInfoConnection); } +#endif } QVariantHash BundleImporter::loadAssetRefMap(const FilePath &bundlePath) @@ -411,7 +461,9 @@ QString BundleImporter::unimportComponent(const TypeName &type, const QString &q ImportData data; data.isImport = false; data.type = type; +#ifndef QDS_USE_PROJECTSTORAGE data.fullReset = true; +#endif m_pendingImports.insert(type, data); m_importTimerCount = 0; diff --git a/src/plugins/qmldesigner/components/componentcore/bundleimporter.h b/src/plugins/qmldesigner/components/componentcore/bundleimporter.h index 7e3463adc38..3c743bfe55b 100644 --- a/src/plugins/qmldesigner/components/componentcore/bundleimporter.h +++ b/src/plugins/qmldesigner/components/componentcore/bundleimporter.h @@ -7,7 +7,9 @@ #include +#ifndef QDS_USE_PROJECTSTORAGE #include +#endif #include #include @@ -48,6 +50,13 @@ private: QTimer m_importTimer; int m_importTimerCount = 0; QString m_bundleId; +#ifdef QDS_USE_PROJECTSTORAGE + struct ImportData + { + bool isImport = true; // false = unimport + TypeName type; + }; +#else struct ImportData { enum State { @@ -66,8 +75,10 @@ private: State state = Starting; }; - QHash m_pendingImports; QMetaObject::Connection m_libInfoConnection; +#endif + + QHash m_pendingImports; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp index e8d79cfa600..34fab1415c7 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.cpp +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.cpp @@ -369,18 +369,20 @@ ModelNode createMaterial(AbstractView *view, const NodeMetaInfo &metaInfo) } #endif -void addQuick3DImportAndView3D(AbstractView *view) +bool addQuick3DImportAndView3D(AbstractView *view, bool suppressWarningDialog) { DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); if (!view || !view->model() || !document || document->inFileComponentModelActive()) { - Core::AsynchronousMessageBox::warning(Tr::tr("Failed to Add Import"), - Tr::tr("Could not add QtQuick3D import to the document.")); - return; + if (!suppressWarningDialog) { + Core::AsynchronousMessageBox::warning(Tr::tr("Failed to Add Import"), + Tr::tr("Could not add QtQuick3D import to the document.")); + } + return false; } QString importName{"QtQuick3D"}; if (view->model()->hasImport(importName)) - return; + return true; view->executeInTransaction(__FUNCTION__, [&] { Import import = Import::createLibraryImport(importName); @@ -417,6 +419,7 @@ void addQuick3DImportAndView3D(AbstractView *view) if (!models.isEmpty()) assignMaterialTo3dModel(view, models.at(0)); }); + return true; } // Assigns given material to a 3D model. diff --git a/src/plugins/qmldesigner/components/componentcore/utils3d.h b/src/plugins/qmldesigner/components/componentcore/utils3d.h index 4531f3ee36b..3f77326e53d 100644 --- a/src/plugins/qmldesigner/components/componentcore/utils3d.h +++ b/src/plugins/qmldesigner/components/componentcore/utils3d.h @@ -60,7 +60,7 @@ ModelNode createMaterial(AbstractView *view); void renameMaterial(const ModelNode &material, const QString &newName); void duplicateMaterial(AbstractView *view, const ModelNode &material); -void addQuick3DImportAndView3D(AbstractView *view); +bool addQuick3DImportAndView3D(AbstractView *view, bool suppressWarningDialog = false); void assignMaterialTo3dModel(AbstractView *view, const ModelNode &modelNode, const ModelNode &materialNode = {}); diff --git a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp index c7a441e21bf..0410bbf3e5e 100644 --- a/src/plugins/qmldesigner/components/edit3d/bakelights.cpp +++ b/src/plugins/qmldesigner/components/edit3d/bakelights.cpp @@ -22,7 +22,9 @@ #include #include +#ifndef QDS_USE_PROJECTSTORAGE #include +#endif #include #include @@ -283,11 +285,12 @@ void BakeLights::exposeModelsAndLights(const QString &nodeId) } } +#ifndef QDS_USE_PROJECTSTORAGE QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); QmlJS::Document::Ptr doc = rewriter.document(); modelManager->updateDocument(doc); - m_view->model()->rewriterView()->forceAmend(); +#endif compModel->setRewriterView({}); diff --git a/src/plugins/qmldesigner/components/import3d/import3dimporter.cpp b/src/plugins/qmldesigner/components/import3d/import3dimporter.cpp index a249250122a..bcec14f7199 100644 --- a/src/plugins/qmldesigner/components/import3d/import3dimporter.cpp +++ b/src/plugins/qmldesigner/components/import3d/import3dimporter.cpp @@ -16,8 +16,11 @@ #include "viewmanager.h" #include +#include +#ifndef QDS_USE_PROJECTSTORAGE #include +#endif #include #include @@ -241,7 +244,6 @@ void Import3dImporter::reset() m_importFiles.clear(); m_puppetProcess.reset(); m_parseData.clear(); - m_requiredImports.clear(); m_currentImportId = 0; m_puppetQueue.clear(); m_importIdToAssetNameMap.clear(); @@ -449,13 +451,7 @@ void Import3dImporter::postParseQuick3DAsset(ParseData &pd) } } } - - // Add quick3D import unless it is already added - if (impVersionMajor > 0 && (m_requiredImports.isEmpty() - || m_requiredImports.first() != "QtQuick3D")) { - m_requiredImports.prepend("QtQuick3D"); - } - } + } } } } @@ -698,6 +694,11 @@ void Import3dImporter::finalizeQuick3DImport() addInfo(progressTitle); notifyProgress(0, progressTitle); + QTimer *timer = new QTimer(parent()); + static int counter; + counter = 0; + +#ifndef QDS_USE_PROJECTSTORAGE auto modelManager = QmlJS::ModelManagerInterface::instance(); QFuture result; if (modelManager) { @@ -711,49 +712,17 @@ void Import3dImporter::finalizeQuick3DImport() true, true); } - // First 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. - QTimer *timer = new QTimer(parent()); - static int counter; - counter = 0; - timer->callOnTimeout([this, timer, progressTitle, model, result]() { if (!isCancelled()) { notifyProgress(++counter * 2, progressTitle); - if (counter < 49) { + if (counter == 1) { + if (!Utils3D::addQuick3DImportAndView3D(model->rewriterView(), true)) + addError(tr("Failed to insert QtQuick3D import to the qml document.")); + } else if (counter < 50) { if (result.isCanceled() || result.isFinished()) - counter = 48; // skip to next step - } else if (counter == 49) { -#ifndef QDS_USE_PROJECTSTORAGE - QmlDesignerPlugin::instance()->documentManager().resetPossibleImports(); - model->rewriterView()->forceAmend(); - try { - RewriterTransaction transaction = model->rewriterView()->beginRewriterTransaction( - QByteArrayLiteral("Import3dImporter::finalizeQuick3DImport")); - bool success = ModelUtils::addImportsWithCheck(m_requiredImports, model); - if (!success) - addError(tr("Failed to insert import statement into qml document.")); - transaction.commit(); -#else - const Imports &imports = model->imports(); - Imports importsToAdd; - for (const QString &importName : std::as_const(m_requiredImports)) { - auto hasName = [&](const auto &import) { - return import.url() == importName || import.file() == importName; - }; - if (!Utils::anyOf(imports, hasName)) { - Import import = Import::createLibraryImport(importName); - importsToAdd.push_back(import); - } - } - - try { - model->changeImports(std::move(importsToAdd), {}); -#endif - } catch (const RewritingException &e) { - addError(tr("Failed to update imports: %1").arg(e.description())); - } + counter = 49; // skip to next step } else if (counter >= 50) { for (const ParseData &pd : std::as_const(m_parseData)) { if (!pd.overwrittenImports.isEmpty()) { @@ -766,6 +735,27 @@ void Import3dImporter::finalizeQuick3DImport() notifyFinished(); model->rewriterView()->emitCustomNotification("asset_import_finished"); } +#else + counter = 0; + timer->callOnTimeout([this, timer, progressTitle, model]() { + if (!isCancelled()) { + notifyProgress(++counter * 50, progressTitle); + if (counter == 1) { + if (!Utils3D::addQuick3DImportAndView3D(model->rewriterView(), true)) + addError(tr("Failed to insert QtQuick3D import to the qml document.")); + } else if (counter > 1) { + for (const ParseData &pd : std::as_const(m_parseData)) { + if (!pd.overwrittenImports.isEmpty()) { + model->rewriterView()->resetPuppet(); + model->rewriterView()->emitCustomNotification("asset_import_update"); + break; + } + } + timer->stop(); + notifyFinished(); + model->rewriterView()->emitCustomNotification("asset_import_finished"); + } +#endif } else { timer->stop(); } diff --git a/src/plugins/qmldesigner/components/import3d/import3dimporter.h b/src/plugins/qmldesigner/components/import3d/import3dimporter.h index 594a1c98603..b08789954da 100644 --- a/src/plugins/qmldesigner/components/import3d/import3dimporter.h +++ b/src/plugins/qmldesigner/components/import3d/import3dimporter.h @@ -126,7 +126,6 @@ private: QHash m_importIdToAssetNameMap; QHash m_parseData; // Key: asset name QString m_progressTitle; - QStringList m_requiredImports; QList m_puppetQueue; }; } // QmlDesigner