From 211f53cebae66608f080e856c3bb8ec1b3136e7c Mon Sep 17 00:00:00 2001 From: Knud Dollereder Date: Wed, 26 Oct 2022 16:30:59 +0200 Subject: [PATCH 01/71] Prevent a crash on close The Destructor of the class Model::Private indirecly called modelAboutToBeDetached which did lead the FormEditor to try to access the already deleted ModelPrivate. This patch is a quick-crash-fix that prevents this by moving the detachAllViews call from the destructor of ModelPrivate to the destructor of Model. Note that a clean fix would probably make the access of ModelPrivate outside of Model impossible but this is outside the scope of this fix and left for a later exercise. Fixes: QDS-7587 Change-Id: I0d03423ae6eaf4d86eddba26ec5edb643ea5a51e Reviewed-by: Marco Bubke --- src/plugins/qmldesigner/designercore/model/model.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 32cf4173b22..5946b6cb238 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -88,10 +88,7 @@ ModelPrivate::ModelPrivate( m_currentTimelineNode = m_rootInternalNode; } -ModelPrivate::~ModelPrivate() -{ - detachAllViews(); -} +ModelPrivate::~ModelPrivate() = default; void ModelPrivate::detachAllViews() { @@ -1397,7 +1394,11 @@ Model::Model(const TypeName &typeName, int major, int minor, Model *metaInfoProx : d(std::make_unique(this, typeName, major, minor, metaInfoProxyModel)) {} -Model::~Model() = default; +Model::~Model() +{ + d->detachAllViews(); + d.reset(nullptr); +} const QList &Model::imports() const { From 2bbae7d499d16566f295a56682fef7d68f064a63 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 27 Oct 2022 12:17:22 +0200 Subject: [PATCH 02/71] QmlDesigner: Detach views outside of model destructor modelAboutToBeDetached can still calling the model. So calling the function from inside the model destructor is a little bit undefined. To get around it we add a custom delete which call the detachAllViews() before it deletes the model. Change-Id: I38ff8283f4e1ac48b256aeb9fd5bb9f3fb6bfed1 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Tim Jenssen --- .../assetexporterplugin/assetexporter.cpp | 2 +- .../qmldesigner/components/eventlist/eventlist.h | 2 +- .../components/integration/designdocument.cpp | 2 +- .../components/integration/designdocument.h | 6 +++--- .../components/integration/designdocumentview.cpp | 2 +- .../components/integration/designdocumentview.h | 2 +- .../imagecache/imagecachecollector.cpp | 2 +- .../qmldesigner/designercore/include/model.h | 14 +++++++++----- .../include/qmldesignercorelib_global.h | 2 ++ .../qmldesigner/designercore/model/model.cpp | 11 ++++++----- .../qml/qmldesigner/coretests/tst_testcore.cpp | 8 ++++---- tests/unit/unittest/listmodeleditor-test.cpp | 4 ++-- 12 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp index 66f9bb1f0df..fed78b682e2 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp @@ -257,7 +257,7 @@ void AssetExporter::preprocessQmlFile(const Utils::FilePath &path) { // Load the QML file and assign UUIDs to items having none. // Meanwhile cache the Component UUIDs as well - std::unique_ptr model(Model::create("Item", 2, 7)); + ModelPointer model(Model::create("Item", 2, 7)); Utils::FileReader reader; if (!reader.fetch(path)) { ExportNotification::addError(tr("Cannot preprocess file: %1. Error %2") diff --git a/src/plugins/qmldesigner/components/eventlist/eventlist.h b/src/plugins/qmldesigner/components/eventlist/eventlist.h index 5ee68256623..1fd2588e9ef 100644 --- a/src/plugins/qmldesigner/components/eventlist/eventlist.h +++ b/src/plugins/qmldesigner/components/eventlist/eventlist.h @@ -49,7 +49,7 @@ public: void write(const QString &text); private: - std::unique_ptr m_model; + ModelPointer m_model; std::unique_ptr m_eventView; Utils::FilePath m_path; }; diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index e24f09f4972..1921f458935 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -147,7 +147,7 @@ const AbstractView *DesignDocument::view() const return viewManager().view(); } -std::unique_ptr DesignDocument::createInFileComponentModel() +ModelPointer DesignDocument::createInFileComponentModel() { auto model = Model::create("QtQuick.Item", 1, 0); model->setFileUrl(m_documentModel->fileUrl()); diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 502cf672c29..25cd03c164e 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -125,13 +125,13 @@ private: // functions const AbstractView *view() const; - std::unique_ptr createInFileComponentModel(); + ModelPointer createInFileComponentModel(); bool pasteSVG(); private: // variables - std::unique_ptr m_documentModel; - std::unique_ptr m_inFileComponentModel; + ModelPointer m_documentModel; + ModelPointer m_inFileComponentModel; QPointer m_textEditor; QScopedPointer m_documentTextModifier; QScopedPointer m_inFileComponentTextModifier; diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp index 56b1ea769e9..d2f63010f6d 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentview.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp @@ -152,7 +152,7 @@ static Model *currentModel() return nullptr; } -std::unique_ptr DesignDocumentView::pasteToModel(ExternalDependenciesInterface &externalDependencies) +ModelPointer DesignDocumentView::pasteToModel(ExternalDependenciesInterface &externalDependencies) { Model *parentModel = currentModel(); diff --git a/src/plugins/qmldesigner/components/integration/designdocumentview.h b/src/plugins/qmldesigner/components/integration/designdocumentview.h index 6294f2be30f..1d6c7c0050d 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentview.h +++ b/src/plugins/qmldesigner/components/integration/designdocumentview.h @@ -28,7 +28,7 @@ public: QString toText() const; void fromText(const QString &text); - static std::unique_ptr pasteToModel(ExternalDependenciesInterface &externalDependencies); + static ModelPointer pasteToModel(ExternalDependenciesInterface &externalDependencies); static void copyModelNodes(const QList &nodesToCopy, ExternalDependenciesInterface &externalDependencies); diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp index b99914322a1..be176760491 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp @@ -64,7 +64,7 @@ void ImageCacheCollector::start(Utils::SmallStringView name, captureImageMaximumSize); const QString filePath{name}; - std::unique_ptr model{QmlDesigner::Model::create("QtQuick/Item", 2, 1)}; + auto model = QmlDesigner::Model::create("QtQuick/Item", 2, 1); model->setFileUrl(QUrl::fromLocalFile(filePath)); auto textDocument = std::make_unique(fileToString(filePath)); diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 7906fa28090..433f703777b 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -65,12 +65,15 @@ public: ~Model(); - static std::unique_ptr create(const TypeName &typeName, - int major = 1, - int minor = 1, - Model *metaInfoProxyModel = nullptr) + static ModelPointer create(const TypeName &typeName, + int major = 1, + int minor = 1, + Model *metaInfoProxyModel = nullptr) { - return std::make_unique(typeName, major, minor, metaInfoProxyModel); + return ModelPointer(new Model(typeName, major, minor, metaInfoProxyModel), [](Model *model) { + model->detachAllViews(); + delete model; + }); } QUrl fileUrl() const; @@ -155,6 +158,7 @@ public: private: template NodeMetaInfo createNodeMetaInfo() const; + void detachAllViews(); private: std::unique_ptr d; diff --git a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h index 6be86cdc750..2d21c91a9d8 100644 --- a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h +++ b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h @@ -45,6 +45,8 @@ enum AnchorLineType { AnchorLineAllMask = AnchorLineVerticalMask | AnchorLineHorizontalMask }; +using ModelPointer = std::unique_ptr>; + constexpr bool useProjectStorage() { #ifdef QDS_USE_PROJECTSTORAGE diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 5946b6cb238..fb782750501 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1394,11 +1394,7 @@ Model::Model(const TypeName &typeName, int major, int minor, Model *metaInfoProx : d(std::make_unique(this, typeName, major, minor, metaInfoProxyModel)) {} -Model::~Model() -{ - d->detachAllViews(); - d.reset(nullptr); -} +Model::~Model() = default; const QList &Model::imports() const { @@ -1609,6 +1605,11 @@ NotNullPointer> Model::projectStorage() c return d->projectStorage; } +void Model::detachAllViews() +{ + d->detachAllViews(); +} + bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowHigherVersion) const { if (imports().contains(import)) diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index cc29b586524..e57c4aac0f2 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -166,10 +166,10 @@ public: Model &model; }; -std::unique_ptr createModel(const QString &typeName, - int major = 2, - int minor = 1, - Model *metaInfoPropxyModel = 0) +ModelPointer createModel(const QString &typeName, + int major = 2, + int minor = 1, + Model *metaInfoPropxyModel = 0) { QApplication::processEvents(); diff --git a/tests/unit/unittest/listmodeleditor-test.cpp b/tests/unit/unittest/listmodeleditor-test.cpp index 9b12adc0030..bde9b747003 100644 --- a/tests/unit/unittest/listmodeleditor-test.cpp +++ b/tests/unit/unittest/listmodeleditor-test.cpp @@ -175,7 +175,7 @@ public: protected: MockFunction mockGoIntoComponent; - std::unique_ptr designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; + QmlDesigner::ModelPointer designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)}; NiceMock mockView; QmlDesigner::ListModelEditorModel model{ [&] { return mockView.createModelNode("QtQml.Models.ListModel", 2, 15); }, @@ -187,7 +187,7 @@ protected: ModelNode element1; ModelNode element2; ModelNode element3; - std::unique_ptr componentModel{ + QmlDesigner::ModelPointer componentModel{ QmlDesigner::Model::create("QtQml.Models.ListModel", 1, 1)}; NiceMock mockComponentView; ModelNode componentElement; From 885268a3af013cb8e5df708b465056e980b08841 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 27 Oct 2022 21:53:41 +0200 Subject: [PATCH 03/71] QmlDesigner: Optimize ModelPointer size https://www.nextptr.com/question/qa1366990479/unique_ptr-with-custom-deleter shows how we can provide an std::unique_ptr without any overhead. Change-Id: I8b32799f421351659a245e2e3775b901afb09b3e Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Aleksei German --- src/plugins/qmldesigner/designercore/include/model.h | 6 ++---- .../designercore/include/qmldesignercorelib_global.h | 7 ++++++- src/plugins/qmldesigner/designercore/model/model.cpp | 6 ++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 433f703777b..6c1f10c6886 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -49,6 +49,7 @@ class QMLDESIGNERCORE_EXPORT Model : public QObject friend AbstractView; friend Internal::ModelPrivate; friend Internal::WriteLocker; + friend ModelDeleter; friend class NodeMetaInfoPrivate; Q_OBJECT @@ -70,10 +71,7 @@ public: int minor = 1, Model *metaInfoProxyModel = nullptr) { - return ModelPointer(new Model(typeName, major, minor, metaInfoProxyModel), [](Model *model) { - model->detachAllViews(); - delete model; - }); + return ModelPointer(new Model(typeName, major, minor, metaInfoProxyModel)); } QUrl fileUrl() const; diff --git a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h index 2d21c91a9d8..81ce269bee5 100644 --- a/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h +++ b/src/plugins/qmldesigner/designercore/include/qmldesignercorelib_global.h @@ -45,7 +45,12 @@ enum AnchorLineType { AnchorLineAllMask = AnchorLineVerticalMask | AnchorLineHorizontalMask }; -using ModelPointer = std::unique_ptr>; +struct ModelDeleter +{ + QMLDESIGNERCORE_EXPORT void operator()(class Model *model); +}; + +using ModelPointer = std::unique_ptr; constexpr bool useProjectStorage() { diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index fb782750501..57005fb2c6e 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1605,6 +1605,12 @@ NotNullPointer> Model::projectStorage() c return d->projectStorage; } +void ModelDeleter::operator()(class Model *model) +{ + model->detachAllViews(); + delete model; +} + void Model::detachAllViews() { d->detachAllViews(); From c55ac53f3c8ab92be1fe146f6cf2d46c56118939 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 31 Oct 2022 14:52:10 +0200 Subject: [PATCH 04/71] QmlDesigner: Hide bundle materials from components view Fixes: QDS-8121 Change-Id: I1a6d316f5f48b7f57bbe48742728d14a3c90dca9 Reviewed-by: Mahmoud Badri --- .../qmldesigner/components/itemlibrary/itemlibrarymodel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 3ef77f52ca7..b7c47e09db8 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -339,11 +339,16 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName); QString projectName = project ? project->displayName() : ""; + QString materialBundlePrefix = QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER).mid(1); + materialBundlePrefix.append(".MaterialBundle"); + // create import sections const QList usedImports = model->usedImports(); QHash importHash; for (const Import &import : model->imports()) { if (import.url() != projectName) { + if (import.url() == materialBundlePrefix) + continue; bool addNew = true; bool isQuick3DAsset = import.url().startsWith("Quick3DAssets."); QString importUrl = import.url(); From af9ec8d20a3c70c233e3554a5f8eb6d7a1c70053 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Fri, 28 Oct 2022 18:13:05 +0300 Subject: [PATCH 05/71] QmlDesigner: Add Copy to 3d Context Menu Copy action is added to the context menu of the Edit3DWidget. Task-number: QDS-8063 Change-Id: I8d5c9eeadfeac827012b175fa12c05ef7f31c9f4 Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen --- .../qmldesigner/components/edit3d/edit3dwidget.cpp | 14 +++++++++++++- .../qmldesigner/components/edit3d/edit3dwidget.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 7f62b107ef0..a29dc51565d 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -174,12 +174,21 @@ void Edit3DWidget::createContextMenu() ModelNodeOperations::editMaterial(selCtx); }); + m_contextMenu->addSeparator(); + + m_copyAction = m_contextMenu->addAction(tr("Copy"), [&] { + QmlDesignerPlugin::instance()->currentDesignDocument()->copySelected(); + }); + m_deleteAction = m_contextMenu->addAction(tr("Delete"), [&] { view()->executeInTransaction("Edit3DWidget::createContextMenu", [&] { for (ModelNode &node : m_view->selectedModelNodes()) node.destroy(); }); }); + + + m_contextMenu->addSeparator(); } // Called by the view to update the "create" sub-menu when the Quick3D entries are ready. @@ -303,8 +312,11 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode const bool isValid = modelNode.isValid(); const bool isModel = modelNode.metaInfo().isQtQuick3DModel(); + const bool isValidNotRoot = isValid && !modelNode.isRootNode(); + m_editMaterialAction->setEnabled(isModel); - m_deleteAction->setEnabled(isValid && !modelNode.isRootNode()); + m_deleteAction->setEnabled(isValidNotRoot); + m_copyAction->setEnabled(isValidNotRoot); m_contextMenu->popup(mapToGlobal(pos)); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 24c702617d0..59493281c1e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -62,6 +62,7 @@ private: QPointer m_contextMenu; QPointer m_editMaterialAction; QPointer m_deleteAction; + QPointer m_copyAction; QPointer m_createSubMenu; ModelNode m_contextMenuTarget; QVector3D m_contextMenuPos3d; From b6e8fd3e91b46689703959cf2a0a75b50437632d Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 31 Oct 2022 16:42:44 +0200 Subject: [PATCH 06/71] QmlDesigner: Remove bundle import after last component is unimported Fixes: QDS-8120 Change-Id: Ia544b041347108dbdbe609333c51cc318ba8852c Reviewed-by: Reviewed-by: Mahmoud Badri --- .../components/materialbrowser/bundleimporter.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp index 22c9df2b918..fc86428b8c7 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp @@ -340,6 +340,17 @@ QString BundleImporter::unimportComponent(const QString &qmlFile) if (writeAssetRefs) writeAssetRefMap(bundleImportPath, assetRefMap); + // If the bundle module contains no .qml files after unimport, remove the import statement + if (bundleImportPath.dirEntries({{"*.qml"}, QDir::Files}).isEmpty()) { + auto doc = QmlDesignerPlugin::instance()->currentDesignDocument(); + Model *model = doc ? doc->currentModel() : nullptr; + if (model) { + Import import = Import::createLibraryImport(m_moduleName, "1.0"); + if (model->imports().contains(import)) + model->changeImports({}, {import}); + } + } + m_fullReset = true; m_importTimerCount = 0; m_importTimer.start(); From 9c3df49ca8c580b28f5b8910ac1170ca8bd733db Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 1 Nov 2022 16:41:03 +0200 Subject: [PATCH 07/71] QmlDesigner: Fix memory leak in 3D view context menu handling Change-Id: Id0521945a8c29019000d41ffee7724336029c96e Reviewed-by: Mahmoud Badri --- src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index a29dc51565d..52518a28499 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -200,7 +200,7 @@ void Edit3DWidget::updateCreateSubMenu(const QStringList &keys, if (m_createSubMenu) { m_contextMenu->removeAction(m_createSubMenu->menuAction()); - m_createSubMenu.clear(); + m_createSubMenu->deleteLater(); } m_nameToEntry.clear(); From 0dfd2a2b0984d41160d3aba686388b0e6a548e54 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 1 Nov 2022 14:53:07 +0100 Subject: [PATCH 08/71] QmlDesigner: Reactivate nodeinstance cache Reactivates the node instance cache and fixes update issue. The formeditor relied on instanceInformationsChanged being emitted after attach. The cache is setting the values already before the attach, so instanceInformationsChanged was never called in this case. Task-number: QDS-7642 Change-Id: Ibeb687c7483905e7df97e4342a6c8542b66b7ab0 Reviewed-by: Qt CI Bot Reviewed-by: Marco Bubke --- .../components/formeditor/formeditorview.cpp | 72 +++++++++++-------- .../components/formeditor/formeditorview.h | 1 + .../instances/nodeinstanceview.cpp | 13 ++-- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index dc524d4682a..f25c3b0af11 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -65,6 +65,8 @@ void FormEditorView::modelAttached(Model *model) temporaryBlockView(); setupFormEditorWidget(); + + setupRootItemSize(); } @@ -687,41 +689,18 @@ constexpr AuxiliaryDataKeyView autoSizeProperty{AuxiliaryDataType::Temporary, "a void FormEditorView::instanceInformationsChanged(const QMultiHash &informationChangedHash) { - QList changedItems; - const int rootElementInitWidth = QmlDesignerPlugin::settings().value(DesignerSettingsKey::ROOT_ELEMENT_INIT_WIDTH).toInt(); - const int rootElementInitHeight = QmlDesignerPlugin::settings().value(DesignerSettingsKey::ROOT_ELEMENT_INIT_HEIGHT).toInt(); + QList changedItems; - QList informationChangedNodes = Utils::filtered(informationChangedHash.keys(), [](const ModelNode &node) { - return QmlItemNode::isValidQmlItemNode(node); - }); + QList informationChangedNodes = Utils::filtered( + informationChangedHash.keys(), + [](const ModelNode &node) { return QmlItemNode::isValidQmlItemNode(node); }); for (const ModelNode &node : informationChangedNodes) { const QmlItemNode qmlItemNode(node); if (FormEditorItem *item = scene()->itemForQmlItemNode(qmlItemNode)) { scene()->synchronizeTransformation(item); - if (qmlItemNode.isRootModelNode() && informationChangedHash.values(node).contains(Size)) { - if (qmlItemNode.instanceBoundingRect().isEmpty() && - !(qmlItemNode.propertyAffectedByCurrentState("width") - && qmlItemNode.propertyAffectedByCurrentState("height"))) { - if (!rootModelNode().hasAuxiliaryData(widthProperty)) - rootModelNode().setAuxiliaryData(widthProperty, rootElementInitWidth); - if (!rootModelNode().hasAuxiliaryData(heightProperty)) - rootModelNode().setAuxiliaryData(heightProperty, rootElementInitHeight); - rootModelNode().setAuxiliaryData(autoSizeProperty, true); - formEditorWidget()->updateActions(); - } else { - if (rootModelNode().hasAuxiliaryData(autoSizeProperty) - && (qmlItemNode.propertyAffectedByCurrentState("width") - || qmlItemNode.propertyAffectedByCurrentState("height"))) { - rootModelNode().removeAuxiliaryData(widthProperty); - rootModelNode().removeAuxiliaryData(heightProperty); - rootModelNode().removeAuxiliaryData(autoSizeProperty); - formEditorWidget()->updateActions(); - } - } - formEditorWidget()->setRootItemRect(qmlItemNode.instanceBoundingRect()); - formEditorWidget()->centerScene(); - } + if (qmlItemNode.isRootModelNode() && informationChangedHash.values(node).contains(Size)) + setupRootItemSize(); changedItems.append(item); } @@ -940,6 +919,41 @@ void FormEditorView::setupFormEditor3DView() item->updateGeometry(); } +void FormEditorView::setupRootItemSize() +{ + if (const QmlItemNode rootQmlNode = rootModelNode()) { + const int rootElementInitWidth = QmlDesignerPlugin::settings() + .value(DesignerSettingsKey::ROOT_ELEMENT_INIT_WIDTH) + .toInt(); + const int rootElementInitHeight = QmlDesignerPlugin::settings() + .value(DesignerSettingsKey::ROOT_ELEMENT_INIT_HEIGHT) + .toInt(); + + if (rootQmlNode.instanceBoundingRect().isEmpty() + && !(rootQmlNode.propertyAffectedByCurrentState("width") + && rootQmlNode.propertyAffectedByCurrentState("height"))) { + if (!rootModelNode().hasAuxiliaryData(widthProperty)) + rootModelNode().setAuxiliaryData(widthProperty, rootElementInitWidth); + if (!rootModelNode().hasAuxiliaryData(heightProperty)) + rootModelNode().setAuxiliaryData(heightProperty, rootElementInitHeight); + rootModelNode().setAuxiliaryData(autoSizeProperty, true); + formEditorWidget()->updateActions(); + } else { + if (rootModelNode().hasAuxiliaryData(autoSizeProperty) + && (rootQmlNode.propertyAffectedByCurrentState("width") + || rootQmlNode.propertyAffectedByCurrentState("height"))) { + rootModelNode().removeAuxiliaryData(widthProperty); + rootModelNode().removeAuxiliaryData(heightProperty); + rootModelNode().removeAuxiliaryData(autoSizeProperty); + formEditorWidget()->updateActions(); + } + } + + formEditorWidget()->setRootItemRect(rootQmlNode.instanceBoundingRect()); + formEditorWidget()->centerScene(); + } +} + void FormEditorView::reset() { QTimer::singleShot(200, this, &FormEditorView::delayedReset); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index eefbb6cfd6e..b07da408106 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -136,6 +136,7 @@ private: void addOrRemoveFormEditorItem(const ModelNode &node); void checkRootModelNode(); void setupFormEditor3DView(); + void setupRootItemSize(); QPointer m_formEditorWidget; QPointer m_scene; diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 020fa315d57..5e3d10dd2c0 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1028,10 +1028,15 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() QList nodeList = allModelNodes(); QList instanceList; - for (const ModelNode &node : std::as_const(nodeList)) { - NodeInstance instance = loadNode(node); - if (!isSkippedNode(node)) - instanceList.append(instance); + std::optional oldNodeInstanceHash = m_nodeInstanceCache.take(model()); + if (oldNodeInstanceHash && oldNodeInstanceHash->instances.value(rootModelNode()).isValid()) { + instanceList = loadInstancesFromCache(nodeList, oldNodeInstanceHash.value()); + } else { + for (const ModelNode &node : std::as_const(nodeList)) { + NodeInstance instance = loadNode(node); + if (!isSkippedNode(node)) + instanceList.append(instance); + } } clearErrors(); From 3897d917e21a45490bfdf2fddc322507811576a0 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Tue, 1 Nov 2022 11:51:25 +0200 Subject: [PATCH 09/71] QmlDesigner: Add camera-view align actions to 3d context menu The following items are added to the context menu of the 3d editor: 1. Align Camera to View 2. Align View to Camera Task-number: QDS-8063 Change-Id: I7b5b966aba2b5e96b7cd4d8a88cf4e7db8cdc0ac Reviewed-by: Mahmoud Badri Reviewed-by: Reviewed-by: Samuel Ghinet Reviewed-by: Miikka Heikkinen --- .../components/edit3d/edit3dwidget.cpp | 19 ++++++++++++++++--- .../components/edit3d/edit3dwidget.h | 2 ++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 52518a28499..25d91fab4fc 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -188,6 +188,16 @@ void Edit3DWidget::createContextMenu() }); + m_contextMenu->addSeparator(); + + m_alignCameraAction = m_contextMenu->addAction(tr("Align Camera to View"), [&] { + view()->emitView3DAction(View3DActionType::AlignCamerasToView, true); + }); + + m_alignViewAction = m_contextMenu->addAction(tr("Align View to Camera"), [&] { + view()->emitView3DAction(View3DActionType::AlignViewToCamera, true); + }); + m_contextMenu->addSeparator(); } @@ -312,11 +322,14 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode const bool isValid = modelNode.isValid(); const bool isModel = modelNode.metaInfo().isQtQuick3DModel(); - const bool isValidNotRoot = isValid && !modelNode.isRootNode(); + const bool isNotRoot = isValid && !modelNode.isRootNode(); + const bool isCamera = isValid && modelNode.metaInfo().isQtQuick3DCamera(); m_editMaterialAction->setEnabled(isModel); - m_deleteAction->setEnabled(isValidNotRoot); - m_copyAction->setEnabled(isValidNotRoot); + m_deleteAction->setEnabled(isNotRoot); + m_copyAction->setEnabled(isNotRoot); + m_alignCameraAction->setEnabled(isCamera); + m_alignViewAction->setEnabled(isCamera); m_contextMenu->popup(mapToGlobal(pos)); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 59493281c1e..3ce3e1a9f37 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -63,6 +63,8 @@ private: QPointer m_editMaterialAction; QPointer m_deleteAction; QPointer m_copyAction; + QPointer m_alignCameraAction; + QPointer m_alignViewAction; QPointer m_createSubMenu; ModelNode m_contextMenuTarget; QVector3D m_contextMenuPos3d; From e979579af56916340427c9faa548781c7101fd12 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Tue, 1 Nov 2022 17:31:52 +0200 Subject: [PATCH 10/71] QmlDesigner: Add Edit Component Action to 3d context menu Edit Component action is added to the context menu of the Edit3DWidget Task-number: QDS-8063 Change-Id: I99983004c3816b1230169300ccdf2c3c92f07cd0 Reviewed-by: Reviewed-by: Mahmoud Badri --- src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp | 7 +++++++ src/plugins/qmldesigner/components/edit3d/edit3dwidget.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 25d91fab4fc..a41ef1c81ce 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -168,6 +168,11 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) void Edit3DWidget::createContextMenu() { m_contextMenu = new QMenu(this); + + m_editComponentAction = m_contextMenu->addAction(tr("Edit Component"), [&] { + DocumentManager::goIntoComponent(m_view->singleSelectedModelNode()); + }); + m_editMaterialAction = m_contextMenu->addAction(tr("Edit Material"), [&] { SelectionContext selCtx(m_view); selCtx.setTargetNode(m_contextMenuTarget); @@ -324,7 +329,9 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode const bool isModel = modelNode.metaInfo().isQtQuick3DModel(); const bool isNotRoot = isValid && !modelNode.isRootNode(); const bool isCamera = isValid && modelNode.metaInfo().isQtQuick3DCamera(); + const bool isSingleComponent = view()->hasSingleSelectedModelNode() && modelNode.isComponent(); + m_editComponentAction->setEnabled(isSingleComponent); m_editMaterialAction->setEnabled(isModel); m_deleteAction->setEnabled(isNotRoot); m_copyAction->setEnabled(isNotRoot); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 3ce3e1a9f37..5a49d8bc1cd 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -60,6 +60,7 @@ private: QPointer m_visibilityTogglesMenu; QPointer m_backgroundColorMenu; QPointer m_contextMenu; + QPointer m_editComponentAction; QPointer m_editMaterialAction; QPointer m_deleteAction; QPointer m_copyAction; From 118d9d43d2a053e2641c14a8f404ff202977c154 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 1 Nov 2022 16:28:18 +0100 Subject: [PATCH 11/71] QmlDesigner: Rename default state group Rename default state group from "Root" to "Default". Change-Id: I69527218f38fcfaf0ceb56ce211ffddeca7fae3f Reviewed-by: Pranta Ghosh Dastider Reviewed-by: Reviewed-by: Thomas Hartmann --- .../components/stateseditornew/stateseditormodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp index 158ca4af0fa..398bdfb6f60 100644 --- a/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp +++ b/src/plugins/qmldesigner/components/stateseditornew/stateseditormodel.cpp @@ -293,7 +293,7 @@ QStringList StatesEditorModel::stateGroups() const auto stateGroups = Utils::transform(m_statesEditorView->allModelNodesOfType(groupMetaInfo), [](const ModelNode &node) { return node.displayName(); }); - stateGroups.prepend(tr("Root")); + stateGroups.prepend(tr("Default")); return stateGroups; } From f51162a3fe40a64adc3b606f22e1873268f31669 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 13 Apr 2022 11:47:32 +0200 Subject: [PATCH 12/71] QmlDesigner: Improve ownership of QmlProjectItem Change-Id: Ibfe4b0b5314dada85a601a8f27003af135df78f1 Reviewed-by: Tim Jenssen --- .../fileformat/filefilteritems.cpp | 9 ++--- .../fileformat/filefilteritems.h | 10 +++--- .../fileformat/qmlprojectfileformat.cpp | 8 ++--- .../fileformat/qmlprojectfileformat.h | 4 +-- src/plugins/qmlprojectmanager/qmlproject.cpp | 3 +- .../fileformat/tst_fileformat.cpp | 35 +++++++------------ 6 files changed, 26 insertions(+), 43 deletions(-) diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp index 2647e342822..4b2eb27d2bd 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp @@ -15,8 +15,7 @@ namespace QmlProjectManager { -FileFilterBaseItem::FileFilterBaseItem(QObject *parent) : - QmlProjectContentItem(parent) +FileFilterBaseItem::FileFilterBaseItem() { m_updateFileListTimer.setSingleShot(true); m_updateFileListTimer.setInterval(50); @@ -271,8 +270,7 @@ QSet FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir return fileSet; } -ImageFileFilterItem::ImageFileFilterItem(QObject *parent) - : FileFilterBaseItem(parent) +ImageFileFilterItem::ImageFileFilterItem() { QString filter; // supported image formats according to @@ -284,8 +282,7 @@ ImageFileFilterItem::ImageFileFilterItem(QObject *parent) setFilter(filter); } -FileFilterItem::FileFilterItem(const QString &fileFilter, QObject *parent) - : FileFilterBaseItem(parent) +FileFilterItem::FileFilterItem(const QString &fileFilter) { setFilter(fileFilter); } diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h index 77a2490d735..d7fab82465a 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h @@ -20,9 +20,7 @@ class QmlProjectContentItem : public QObject Q_OBJECT public: - QmlProjectContentItem(QObject *parent = nullptr) - : QObject(parent) - {} + QmlProjectContentItem() {} }; class FileFilterBaseItem : public QmlProjectContentItem { @@ -35,7 +33,7 @@ class FileFilterBaseItem : public QmlProjectContentItem { Q_PROPERTY(QStringList files READ files NOTIFY filesChanged DESIGNABLE false) public: - FileFilterBaseItem(QObject *parent = nullptr); + FileFilterBaseItem(); QString directory() const; void setDirectory(const QString &directoryPath); @@ -99,12 +97,12 @@ private: class FileFilterItem : public FileFilterBaseItem { public: - FileFilterItem(const QString &fileFilter, QObject *parent = nullptr); + FileFilterItem(const QString &fileFilter); }; class ImageFileFilterItem : public FileFilterBaseItem { public: - ImageFileFilterItem(QObject *parent = nullptr); + ImageFileFilterItem(); }; } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp index 71a0c47af3e..5b850e91741 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp @@ -52,7 +52,8 @@ std::unique_ptr setupFileFilterItem( namespace QmlProjectManager { -QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fileName, QString *errorMessage) +std::unique_ptr QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fileName, + QString *errorMessage) { QmlJS::SimpleReader simpleQmlJSReader; @@ -67,7 +68,7 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi } if (rootNode->name() == QLatin1String("Project")) { - auto projectItem = new QmlProjectItem; + auto projectItem = std::make_unique(); const auto mainFileProperty = rootNode->property(QLatin1String("mainFile")); if (mainFileProperty.isValid()) @@ -137,8 +138,7 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi setupFileFilterItem(std::make_unique("*.js"), childNode)); } else if (childNode->name() == QLatin1String("ImageFiles")) { projectItem->appendContent( - setupFileFilterItem(std::make_unique(projectItem), - childNode)); + setupFileFilterItem(std::make_unique(), childNode)); } else if (childNode->name() == QLatin1String("CssFiles")) { projectItem->appendContent( setupFileFilterItem(std::make_unique("*.css"), childNode)); diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h index b92a8024053..6b60122491f 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.h @@ -17,8 +17,8 @@ class QmlProjectFileFormat Q_DECLARE_TR_FUNCTIONS(QmlProjectManager::QmlProjectFileFormat) public: - static QmlProjectItem *parseProjectFile(const Utils::FilePath &fileName, - QString *errorMessage = nullptr); + static std::unique_ptr parseProjectFile(const Utils::FilePath &fileName, + QString *errorMessage = nullptr); }; } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 116859cd7b3..170308c1d6c 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -191,8 +191,7 @@ void QmlBuildSystem::parseProject(RefreshOptions options) m_projectItem.reset(); if (!m_projectItem) { QString errorMessage; - m_projectItem.reset( - QmlProjectFileFormat::parseProjectFile(projectFilePath(), &errorMessage)); + m_projectItem = QmlProjectFileFormat::parseProjectFile(projectFilePath(), &errorMessage); if (m_projectItem) { connect(m_projectItem.get(), &QmlProjectItem::qmlFilesChanged, diff --git a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp index f3329d97c8e..028a29b01a7 100644 --- a/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp +++ b/tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp @@ -41,7 +41,7 @@ tst_FileFormat::tst_FileFormat() static QString testDataDir = QLatin1String(SRCDIR "/data"); -static QmlProjectItem *loadQmlProject(QString name, QString *error) +static std::unique_ptr loadQmlProject(QString name, QString *error) { return QmlProjectFileFormat::parseProjectFile( Utils::FilePath::fromString(testDataDir).pathAppended(name + ".qmlproject"), error); @@ -54,7 +54,7 @@ void tst_FileFormat::testFileFilter() // Search for qml files in directory + subdirectories // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter1"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter1"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -64,14 +64,13 @@ void tst_FileFormat::testFileFilter() << testDataDir + "/file2.qml" << testDataDir + "/subdir/file3.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // search for all qml files in directory // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter2"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter2"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -80,14 +79,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/file1.qml" << testDataDir + "/file2.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // search for all qml files in subdirectory // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter3"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter3"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -95,14 +93,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/subdir/file3.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // multiple entries // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter4"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter4"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -113,14 +110,13 @@ void tst_FileFormat::testFileFilter() << testDataDir + "/subdir/file3.qml"); QCOMPARE(project->files().size(), 3); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // include specific list // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter5"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter5"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -129,14 +125,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/file1.qml" << testDataDir + "/file2.qml"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // include specific list // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter6"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter6"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -144,14 +139,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // use wildcards // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter7"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter7"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -159,14 +153,13 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } // // use Files element (1.1) // { - QmlProjectItem *project = loadQmlProject(QLatin1String("testFileFilter8"), &error); + auto project = loadQmlProject(QLatin1String("testFileFilter8"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -174,7 +167,6 @@ void tst_FileFormat::testFileFilter() QStringList expectedFiles(QStringList() << testDataDir + "/image.gif"); COMPARE_AS_SETS(project->files(), expectedFiles); - delete project; } } @@ -184,7 +176,7 @@ void tst_FileFormat::testMatchesFile() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testMatchesFile"), &error); + auto project = loadQmlProject(QLatin1String("testMatchesFile"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -195,7 +187,6 @@ void tst_FileFormat::testMatchesFile() QVERIFY(project->matchesFile(testDataDir + "/subdir/notyetexistingfile.qml")); QVERIFY(project->matchesFile(testDataDir + "/script.js")); QVERIFY(!project->matchesFile(testDataDir + "/script.css")); - delete project; } void tst_FileFormat::testLibraryPaths() @@ -204,7 +195,7 @@ void tst_FileFormat::testLibraryPaths() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testLibraryPaths"), &error); + auto project = loadQmlProject(QLatin1String("testLibraryPaths"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); @@ -214,7 +205,6 @@ void tst_FileFormat::testLibraryPaths() const QStringList expectedPaths({base.relativeFilePath(SRCDIR "/otherLibrary"), base.relativeFilePath(SRCDIR "/data/library")}); COMPARE_AS_SETS(project->importPaths(), expectedPaths); - delete project; } void tst_FileFormat::testMainFile() @@ -223,12 +213,11 @@ void tst_FileFormat::testMainFile() // // search for qml files in local directory // - QmlProjectItem *project = loadQmlProject(QLatin1String("testMainFile"), &error); + auto project = loadQmlProject(QLatin1String("testMainFile"), &error); QVERIFY(project); QVERIFY(error.isEmpty()); QCOMPARE(project->mainFile(), QString("file1.qml")); - delete project; } QTEST_GUILESS_MAIN(tst_FileFormat); From a8c5cbaf94514f08a04baf18c5212444e6a6f3eb Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Nov 2022 15:56:45 +0200 Subject: [PATCH 13/71] QmlDesigner: Remove duplicate include Change-Id: Idac5b8882a050ecb2c03cdfad644a16f5ce240dc Reviewed-by: Mahmoud Badri --- src/plugins/qmldesigner/designercore/model/texttomodelmerger.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h index cd3b7affbe2..4b2f7ae990a 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h @@ -8,7 +8,6 @@ #include "nodelistproperty.h" #include "modelnode.h" -#include #include #include From e3bf1725852cbefd11b458ec7f3e816b8dedb5dc Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 6 Sep 2022 15:13:29 +0200 Subject: [PATCH 14/71] QmlDesigner: Handles directories in Project storage updater All directories are searched for qml files and they are added to the meta data. If the directory is changed the qmldir is always parsed even if it was not changed. We can optimize that later but I think there is no big advantage fot this optimization. Task-number: QDS-5297 Change-Id: Ibe3102520bc18ac474380aad306486d8e25bc5db Reviewed-by: Reviewed-by: Thomas Hartmann Reviewed-by: Qt CI Bot --- .../projectstorage/filesystem.cpp | 5 + .../designercore/projectstorage/filesystem.h | 1 + .../projectstorage/filesysteminterface.h | 1 + .../projectstorage/projectstorageupdater.cpp | 242 +++--- .../projectstorage/projectstorageupdater.h | 65 +- tests/unit/unittest/filesystemmock.h | 1 + .../unit/unittest/gtest-creator-printing.cpp | 9 +- .../unittest/projectstorageupdater-test.cpp | 720 +++++++++++------- 8 files changed, 627 insertions(+), 417 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp index a34e107bacc..5dfbdd665da 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.cpp @@ -30,6 +30,11 @@ SourceIds FileSystem::directoryEntries(const QString &directoryPath) const return sourceIds; } +QStringList FileSystem::qmlFileNames(const QString &directoryPath) const +{ + return QDir{directoryPath}.entryList({".qml"}); +} + long long FileSystem::lastModified(SourceId sourceId) const { QFileInfo fileInfo(QString(m_sourcePathCache.sourcePath(sourceId))); diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h index 75fef86f020..7c1d5d76cb6 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/filesystem.h @@ -29,6 +29,7 @@ public: {} SourceIds directoryEntries(const QString &directoryPath) const override; + QStringList qmlFileNames(const QString &directoryPath) const override; long long lastModified(SourceId sourceId) const override; FileStatus fileStatus(SourceId sourceId) const override; QString contentAsQString(const QString &filePath) const override; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h b/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h index 20aa6d5ae8d..26ace06f38d 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/filesysteminterface.h @@ -15,6 +15,7 @@ class FileSystemInterface { public: virtual SourceIds directoryEntries(const QString &directoryPath) const = 0; + virtual QStringList qmlFileNames(const QString &directoryPath) const = 0; virtual long long lastModified(SourceId sourceId) const = 0; virtual FileStatus fileStatus(SourceId sourceId) const = 0; virtual void remove(const SourceIds &sourceIds) = 0; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp index e6fcb119414..48b29793866 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.cpp @@ -54,15 +54,35 @@ QList joinImports(const QList &first return imports; } -ComponentReferences createComponentReferences(const QMultiHash &components) +ProjectStorageUpdater::Components createComponents( + const QMultiHash &qmlDirParserComponents, + ModuleId moduleId, + ModuleId pathModuleId, + FileSystemInterface &fileSystem, + const QString &directory) { - ComponentReferences componentReferences; - componentReferences.reserve(static_cast(components.size())); + ProjectStorageUpdater::Components components; - for (const QmlDirParser::Component &component : components) - componentReferences.push_back(std::cref(component)); + auto qmlFileNames = fileSystem.qmlFileNames(directory); - return componentReferences; + components.reserve(static_cast(qmlDirParserComponents.size() + qmlFileNames.size())); + + for (const QString &qmlFileName : qmlFileNames) { + Utils::PathString fileName{qmlFileName}; + Utils::PathString typeName{fileName.begin(), std::find(fileName.begin(), fileName.end(), '.')}; + components.push_back( + ProjectStorageUpdater::Component{fileName, typeName, pathModuleId, -1, -1}); + } + + for (const QmlDirParser::Component &qmlDirParserComponent : qmlDirParserComponents) { + components.push_back(ProjectStorageUpdater::Component{qmlDirParserComponent.fileName, + qmlDirParserComponent.typeName, + moduleId, + qmlDirParserComponent.majorVersion, + qmlDirParserComponent.minorVersion}); + } + + return components; } SourceIds filterNotUpdatedSourceIds(SourceIds updatedSourceIds, SourceIds notUpdatedSourceIds) @@ -140,14 +160,14 @@ void addModuleExportedImports(Storage::Synchronization::ModuleExportedImports &i } // namespace -void ProjectStorageUpdater::update(QStringList qmlDirs, QStringList qmlTypesPaths) +void ProjectStorageUpdater::update(QStringList directories, QStringList qmlTypesPaths) { Storage::Synchronization::SynchronizationPackage package; SourceIds notUpdatedFileStatusSourceIds; SourceIds notUpdatedSourceIds; - updateQmldirs(qmlDirs, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds); + updateDirectories(directories, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds); updateQmlTypes(qmlTypesPaths, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds); package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds), @@ -187,29 +207,50 @@ void ProjectStorageUpdater::updateQmlTypes(const QStringList &qmlTypesPaths, } } -void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - SourceIds ¬UpdatedSourceIds) +namespace { +template +ProjectStorageUpdater::FileState combineState(FileStates... fileStates) { - for (const QString &qmldirPath : qmlDirs) { - SourcePath qmldirSourcePath{qmldirPath}; - SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath); - SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId); - Utils::PathString directoryPath = m_pathCache.sourceContextPath(directoryId); + if (((fileStates == ProjectStorageUpdater::FileState::Changed) || ...)) + return ProjectStorageUpdater::FileState::Changed; - auto state = fileState(qmlDirSourceId, - package.fileStatuses, - package.updatedFileStatusSourceIds, - notUpdatedFileStatusSourceIds); - switch (state) { + if (((fileStates == ProjectStorageUpdater::FileState::NotChanged) || ...)) + return ProjectStorageUpdater::FileState::NotChanged; + + return ProjectStorageUpdater::FileState::NotExists; +} +} // namespace + +void ProjectStorageUpdater::updateDirectories(const QStringList &directories, + Storage::Synchronization::SynchronizationPackage &package, + SourceIds ¬UpdatedFileStatusSourceIds, + SourceIds ¬UpdatedSourceIds) +{ + for (const QString &directory : directories) { + Utils::PathString directoryPath = directory; + SourcePath qmldirSourcePath{directory + "/qmldir"}; + auto [directoryId, qmlDirSourceId] = m_pathCache.sourceContextAndSourceId(qmldirSourcePath); + + SourcePath directorySourcePath{directory + "/."}; + auto directorySourceId = m_pathCache.sourceId(directorySourcePath); + + auto directoryState = fileState(directorySourceId, + package.fileStatuses, + package.updatedFileStatusSourceIds, + notUpdatedFileStatusSourceIds); + + auto qmldirState = fileState(qmlDirSourceId, + package.fileStatuses, + package.updatedFileStatusSourceIds, + notUpdatedFileStatusSourceIds); + + switch (combineState(directoryState, qmldirState)) { case FileState::Changed: { QmlDirParser parser; - parser.parse(m_fileSystem.contentAsQString(qmldirPath)); + parser.parse(m_fileSystem.contentAsQString(QString{qmldirSourcePath})); package.updatedSourceIds.push_back(qmlDirSourceId); - Utils::PathString moduleName{parser.typeNamespace()}; ModuleId moduleId = m_projectStorage.moduleId(moduleName); ModuleId cppModuleId = m_projectStorage.moduleId(moduleName + "-cppnative"); @@ -241,20 +282,21 @@ void ProjectStorageUpdater::updateQmldirs(const QStringList &qmlDirs, notUpdatedFileStatusSourceIds, notUpdatedSourceIds); } - parseQmlComponents(createComponentReferences(parser.components()), - qmlDirSourceId, - directoryId, - moduleId, - pathModuleId, - package, - notUpdatedFileStatusSourceIds); + parseQmlComponents( + createComponents(parser.components(), moduleId, pathModuleId, m_fileSystem, directory), + qmlDirSourceId, + directoryId, + package, + notUpdatedFileStatusSourceIds); package.updatedProjectSourceIds.push_back(qmlDirSourceId); break; } case FileState::NotChanged: { - const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId); - parseTypeInfos(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds); - parseQmlComponents(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, directoryPath); + parseProjectDatas(m_projectStorage.fetchProjectDatas(qmlDirSourceId), + package, + notUpdatedFileStatusSourceIds, + notUpdatedSourceIds, + directoryPath); break; } case FileState::NotExists: { @@ -283,7 +325,6 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds) { - for (const QString &typeInfo : typeInfos) { Utils::PathString qmltypesPath = Utils::PathString::join( {directoryPath, "/", Utils::SmallString{typeInfo}}); @@ -306,22 +347,35 @@ void ProjectStorageUpdater::parseTypeInfos(const QStringList &typeInfos, } } -void ProjectStorageUpdater::parseTypeInfos(const Storage::Synchronization::ProjectDatas &projectDatas, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - SourceIds ¬UpdatedSourceIds) +void ProjectStorageUpdater::parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas, + Storage::Synchronization::SynchronizationPackage &package, + SourceIds ¬UpdatedFileStatusSourceIds, + SourceIds ¬UpdatedSourceIds, + Utils::SmallStringView directoryPath) { for (const Storage::Synchronization::ProjectData &projectData : projectDatas) { - if (projectData.fileType != Storage::Synchronization::FileType::QmlTypes) - continue; + switch (projectData.fileType) { + case Storage::Synchronization::FileType::QmlTypes: { + auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId); - auto qmltypesPath = m_pathCache.sourcePath(projectData.sourceId); + parseTypeInfo(projectData, + qmltypesPath, + package, + notUpdatedFileStatusSourceIds, + notUpdatedSourceIds); + break; + } + case Storage::Synchronization::FileType::QmlDocument: { + SourcePath qmlDocumentPath = m_pathCache.sourcePath(projectData.sourceId); - parseTypeInfo(projectData, - qmltypesPath, - package, - notUpdatedFileStatusSourceIds, - notUpdatedSourceIds); + parseQmlComponent(qmlDocumentPath.name(), + qmlDocumentPath, + directoryPath, + projectData.sourceId, + package, + notUpdatedFileStatusSourceIds); + } + }; } } @@ -357,7 +411,6 @@ auto ProjectStorageUpdater::parseTypeInfo(const Storage::Synchronization::Projec void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFilePath, Utils::SmallStringView directoryPath, Storage::Synchronization::ExportedTypes exportedTypes, - ModuleId moduleId, SourceId qmldirSourceId, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds) @@ -388,7 +441,7 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView relativeFil package.projectDatas.emplace_back(qmldirSourceId, sourceId, - moduleId, + ModuleId{}, Storage::Synchronization::FileType::QmlDocument); package.updatedSourceIds.push_back(sourceId); @@ -432,123 +485,64 @@ void ProjectStorageUpdater::parseQmlComponent(Utils::SmallStringView fileName, namespace { -class ComponentReferencesRange -{ -public: - using const_iterator = ComponentReferences::const_iterator; - - ComponentReferencesRange(const_iterator begin, const_iterator end) - : m_begin{begin} - , m_end{end} - {} - - std::size_t size() const { return static_cast(std::distance(m_begin, m_end)); } - - const_iterator begin() const { return m_begin; } - const_iterator end() const { return m_end; } - -private: - const_iterator m_begin; - const_iterator m_end; -}; - template -void partitionForTheSameFileName(const ComponentReferences &components, Callback callback) +void rangeForTheSameFileName(const ProjectStorageUpdater::Components &components, Callback callback) { auto current = components.begin(); const auto end = components.end(); while (current != end) { - auto nextType = std::partition_point(current, end, [&](const auto &component) { - return component.get().fileName == current->get().fileName; + auto nextType = std::find_if(current, end, [&](const auto &component) { + return component.fileName != current->fileName; }); - callback(ComponentReferencesRange{current, nextType}); + callback(ProjectStorageUpdater::ComponentRange{current, nextType}); current = nextType; } } -Storage::Synchronization::ExportedTypes createExportedTypes(ComponentReferencesRange components, - ModuleId moduleId, - Utils::SmallStringView fileName, - ModuleId pathModuleId) +Storage::Synchronization::ExportedTypes createExportedTypes(ProjectStorageUpdater::ComponentRange components) { Storage::Synchronization::ExportedTypes exportedTypes; exportedTypes.reserve(components.size() + 1); - for (ComponentReference component : components) { - exportedTypes.emplace_back(moduleId, - Utils::SmallString{component.get().typeName}, - Storage::Synchronization::Version{component.get().majorVersion, - component.get().minorVersion}); + for (const ProjectStorageUpdater::Component &component : components) { + exportedTypes.emplace_back(component.moduleId, + Utils::SmallString{component.typeName}, + Storage::Synchronization::Version{component.majorVersion, + component.minorVersion}); } - auto foundDot = std::find(fileName.begin(), fileName.end(), '.'); - - exportedTypes.emplace_back(pathModuleId, - Utils::SmallStringView{fileName.begin(), foundDot}, - Storage::Synchronization::Version{}); - return exportedTypes; } } // namespace -void ProjectStorageUpdater::parseQmlComponents(ComponentReferences components, +void ProjectStorageUpdater::parseQmlComponents(Components components, SourceId qmldirSourceId, SourceContextId directoryId, - ModuleId moduleId, - ModuleId pathModuleId, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds) { std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) { - return std::tie(first.get().fileName, - first.get().typeName, - first.get().majorVersion, - first.get().minorVersion) - > std::tie(first.get().fileName, - second.get().typeName, - second.get().majorVersion, - second.get().minorVersion); + return first.fileName < second.fileName; }); auto directoryPath = m_pathCache.sourceContextPath(directoryId); - auto callback = [&](ComponentReferencesRange componentsWithSameFileName) { + auto callback = [&](ComponentRange componentsWithSameFileName) { const auto &firstComponent = *componentsWithSameFileName.begin(); - const Utils::SmallString fileName{firstComponent.get().fileName}; + const Utils::SmallString fileName{firstComponent.fileName}; parseQmlComponent(fileName, directoryPath, - createExportedTypes(componentsWithSameFileName, moduleId, fileName, pathModuleId), - moduleId, + createExportedTypes(componentsWithSameFileName), qmldirSourceId, package, notUpdatedFileStatusSourceIds); }; - partitionForTheSameFileName(components, callback); -} - -void ProjectStorageUpdater::parseQmlComponents(const Storage::Synchronization::ProjectDatas &projectDatas, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - Utils::SmallStringView directoryPath) -{ - for (const Storage::Synchronization::ProjectData &projectData : projectDatas) { - if (projectData.fileType != Storage::Synchronization::FileType::QmlDocument) - continue; - - SourcePath qmlDocumentPath = m_pathCache.sourcePath(projectData.sourceId); - - parseQmlComponent(qmlDocumentPath.name(), - qmlDocumentPath, - directoryPath, - projectData.sourceId, - package, - notUpdatedFileStatusSourceIds); - } + rangeForTheSameFileName(components, callback); } ProjectStorageUpdater::FileState ProjectStorageUpdater::fileState(SourceId sourceId, diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h index efb8c19a465..80100c636ed 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorageupdater.h @@ -30,9 +30,6 @@ class ProjectStorage; class QmlDocumentParserInterface; class QmlTypesParserInterface; -using ComponentReference = std::reference_wrapper; -using ComponentReferences = std::vector; - class ProjectStorageUpdater { public: @@ -52,24 +49,56 @@ public: , m_qmlTypesParser{qmlTypesParser} {} - void update(QStringList qmlDirs, QStringList qmlTypesPaths); + void update(QStringList directories, QStringList qmlTypesPaths); void pathsWithIdsChanged(const std::vector &idPaths); -private: + struct Component + { + Utils::SmallString fileName; + Utils::SmallString typeName; + ModuleId moduleId; + int majorVersion = -1; + int minorVersion = -1; + }; + + using Components = std::vector; + + class ComponentRange + { + public: + using const_iterator = Components::const_iterator; + + ComponentRange(const_iterator begin, const_iterator end) + : m_begin{begin} + , m_end{end} + {} + + std::size_t size() const { return static_cast(std::distance(m_begin, m_end)); } + + const_iterator begin() const { return m_begin; } + const_iterator end() const { return m_end; } + + private: + const_iterator m_begin; + const_iterator m_end; + }; + enum class FileState { NotChanged, Changed, NotExists, }; +private: + void updateQmlTypes(const QStringList &qmlTypesPaths, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds); - void updateQmldirs(const QStringList &qmlDirs, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - SourceIds ¬UpdatedSourceIds); + void updateDirectories(const QStringList &directories, + Storage::Synchronization::SynchronizationPackage &package, + SourceIds ¬UpdatedFileStatusSourceIds, + SourceIds ¬UpdatedSourceIds); void parseTypeInfos(const QStringList &typeInfos, const QList &qmldirDependencies, @@ -80,30 +109,24 @@ private: Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds); - void parseTypeInfos(const Storage::Synchronization::ProjectDatas &projectDatas, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - SourceIds ¬UpdatedSourceIds); + void parseProjectDatas(const Storage::Synchronization::ProjectDatas &projectDatas, + Storage::Synchronization::SynchronizationPackage &package, + SourceIds ¬UpdatedFileStatusSourceIds, + SourceIds ¬UpdatedSourceIds, + Utils::SmallStringView directoryPath); FileState parseTypeInfo(const Storage::Synchronization::ProjectData &projectData, Utils::SmallStringView qmltypesPath, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds, SourceIds ¬UpdatedSourceIds); - void parseQmlComponents(ComponentReferences components, + void parseQmlComponents(Components components, SourceId qmldirSourceId, SourceContextId directoryId, - ModuleId moduleId, - ModuleId pathModuleId, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds); - void parseQmlComponents(const Storage::Synchronization::ProjectDatas &projectDatas, - Storage::Synchronization::SynchronizationPackage &package, - SourceIds ¬UpdatedFileStatusSourceIds, - Utils::SmallStringView directoryPath); void parseQmlComponent(Utils::SmallStringView fileName, Utils::SmallStringView directory, Storage::Synchronization::ExportedTypes exportedTypes, - ModuleId moduleId, SourceId qmldirSourceId, Storage::Synchronization::SynchronizationPackage &package, SourceIds ¬UpdatedFileStatusSourceIds); diff --git a/tests/unit/unittest/filesystemmock.h b/tests/unit/unittest/filesystemmock.h index 0c325d1bbbb..0af7eef8649 100644 --- a/tests/unit/unittest/filesystemmock.h +++ b/tests/unit/unittest/filesystemmock.h @@ -15,6 +15,7 @@ public: directoryEntries, (const QString &directoryPath), (const, override)); + MOCK_METHOD(QStringList, qmlFileNames, (const QString &directoryPath), (const, override)); MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override)); MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override)); diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index c703b802ade..3eadd98e8fb 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -676,9 +676,12 @@ std::ostream &operator<<(std::ostream &out, ChangeLevel changeLevel) std::ostream &operator<<(std::ostream &out, const SynchronizationPackage &package) { - return out << "(" << package.imports << ", " << package.types << ", " - << package.updatedSourceIds << ", " << package.fileStatuses << ", " - << package.updatedFileStatusSourceIds << ", " << package.projectDatas << ")"; + return out << "(imports: " << package.imports << ", types: " << package.types + << ", updatedSourceIds: " << package.updatedSourceIds + << ", fileStatuses: " << package.fileStatuses + << ", updatedFileStatusSourceIds: " << package.updatedFileStatusSourceIds + << ", updatedProjectSourceIds: " << package.updatedProjectSourceIds + << ", projectDatas: " << package.projectDatas << ")"; } std::ostream &operator<<(std::ostream &out, const ProjectData &data) diff --git a/tests/unit/unittest/projectstorageupdater-test.cpp b/tests/unit/unittest/projectstorageupdater-test.cpp index 30f46081ffc..6d55565c1e2 100644 --- a/tests/unit/unittest/projectstorageupdater-test.cpp +++ b/tests/unit/unittest/projectstorageupdater-test.cpp @@ -103,7 +103,8 @@ MATCHER_P4(IsProjectData, const Storage::Synchronization::ProjectData &projectData = arg; return compareInvalidAreTrue(projectData.projectSourceId, projectSourceId) - && projectData.sourceId == sourceId && projectData.moduleId == moduleId + && projectData.sourceId == sourceId + && compareInvalidAreTrue(projectData.moduleId, moduleId) && projectData.fileType == fileType; } @@ -138,9 +139,17 @@ public: ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId))) .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421})); + ON_CALL(fileSystemMock, fileStatus(Eq(directoryPathSourceId))) + .WillByDefault(Return(FileStatus{directoryPathSourceId, 2, 421})); + ON_CALL(projectStorageMock, fetchFileStatus(Eq(directoryPathSourceId))) + .WillByDefault(Return(FileStatus{directoryPathSourceId, 2, 421})); + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillByDefault(Return(qmldirContent)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml", "Second.qml"})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 12})); ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId1))) @@ -218,6 +227,7 @@ protected: SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes"); SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/types/example2.qmltypes"); SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir"); + SourceId directoryPathSourceId = sourcePathCache.sourceId("/path/."); SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml"); SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First2.qml"); SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); @@ -270,13 +280,13 @@ protected: QString qmldirContent{"module Example\ntypeinfo example.qmltypes\n"}; QString qmltypes1{"Module {\ndependencies: [module1]}"}; QString qmltypes2{"Module {\ndependencies: [module2]}"}; - QStringList qmlDirs = {"/path/qmldir"}; + QStringList directories = {"/path"}; }; TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent) { SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir"); - QStringList qmlDirs = {"/path/one/qmldir", "/path/two/qmldir", "/path/three/qmldir"}; + QStringList directories = {"/path/one", "/path/two", "/path/three"}; ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](auto sourceId) { return FileStatus{sourceId, 21, 421}; }); @@ -291,7 +301,7 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem) @@ -300,25 +310,27 @@ TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem) EXPECT_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlTypes) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsInvalid) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId))) @@ -326,20 +338,21 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsI EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, DontGetContentForQmlTypesIfFileSystemFileStatusIsInvalid) { QString qmldir{R"(module Example typeinfo example.qmltypes)"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))) .WillRepeatedly(Return(qmldir)); ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId))).WillByDefault(Return(FileStatus{})); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))).Times(0); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlTypes) @@ -360,7 +373,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlTypes) EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, Field(&ProjectData::moduleId, exampleCppNativeModuleId))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange) @@ -374,7 +387,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange) EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) @@ -383,6 +396,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) Storage::Synchronization::Version{2, 3}, qmltypesPathSourceId}; QString qmltypes{"Module {\ndependencies: []}"}; + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))).WillByDefault(Return(QStringList{})); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))) .WillByDefault(Return(qmltypes)); ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) @@ -411,7 +425,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes) Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged) @@ -430,12 +444,14 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged) EXPECT_CALL(projectStorageMock, synchronize(PackageIsEmpty())); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments) { SourceId oldSecondSourceId3 = sourcePathCache.sourceId("/path/OldSecond.qml"); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml", "OldSecond.qml", "Second.qml"})); ON_CALL(fileSystemMock, fileStatus(Eq(oldSecondSourceId3))) .WillByDefault(Return(FileStatus{oldSecondSourceId3, 22, 14})); ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))) @@ -453,7 +469,7 @@ TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments) EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/OldSecond.qml")))); EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml")))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlDocuments) @@ -477,7 +493,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocuments) EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _, _, _)); EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _, _, _)); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, ParseQmlDocumentsWithNonExistingQmlDocumentThrows) @@ -486,7 +502,7 @@ TEST_F(ProjectStorageUpdater, ParseQmlDocumentsWithNonExistingQmlDocumentThrows) NonexitingType 1.0 NonexitingType.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - ASSERT_THROW(updater.update(qmlDirs, {}), QmlDesigner::CannotParseQmlDocumentFile); + ASSERT_THROW(updater.update(directories, {}), QmlDesigner::CannotParseQmlDocumentFile); } TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) @@ -501,32 +517,33 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) projectStorageMock, synchronize(AllOf( Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre( - AllOf(IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))), - AllOf(IsStorageType("First2.qml", - Storage::Synchronization::ImportedType{"Object2"}, - TypeTraits::Reference, - qmlDocumentSourceId2, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))), - AllOf(IsStorageType("Second.qml", - Storage::Synchronization::ImportedType{"Object3"}, - TypeTraits::Reference, - qmlDocumentSourceId3, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), - IsExportedType(pathModuleId, "Second", -1, -1)))))), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{"Object2"}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))), + AllOf(IsStorageType("Second.qml", + Storage::Synchronization::ImportedType{"Object3"}, + TypeTraits::Reference, + qmlDocumentSourceId3, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), + IsExportedType(pathModuleId, "Second", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, @@ -545,102 +562,323 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId2, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId3, - exampleModuleId, - FileType::QmlDocument)))))); + UnorderedElementsAre( + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId3, + ModuleId{}, + FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } -TEST_F(ProjectStorageUpdater, SynchronizeRemoved) +TEST_F(ProjectStorageUpdater, SynchronizeAddOnlyQmlDocumentInDirectory) { QString qmldir{R"(module Example - FirstType 1.0 First.qml - FirstType 2.2 First2.qml - typeinfo example.qmltypes - typeinfo types/example2.qmltypes - )"}; + FirstType 1.0 First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId2))) - .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 13})); - ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypes2PathSourceId))) - .WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 21, 421})); - ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) - .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ - {qmlDirPathSourceId, qmltypesPathSourceId, exampleModuleId, FileType::QmlTypes}, - {qmlDirPathSourceId, qmltypes2PathSourceId, exampleModuleId, FileType::QmlTypes}, - {qmlDirPathSourceId, qmlDocumentSourceId1, exampleModuleId, FileType::QmlDocument}, - {qmlDirPathSourceId, qmlDocumentSourceId2, exampleModuleId, FileType::QmlDocument}, - {qmlDirPathSourceId, qmlDocumentSourceId3, exampleModuleId, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); EXPECT_CALL( projectStorageMock, synchronize(AllOf( - Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import4)), + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2, import3)), Field(&SynchronizationPackage::types, UnorderedElementsAre( - Eq(objectType), AllOf(IsStorageType("First.qml", Storage::Synchronization::ImportedType{"Object"}, TypeTraits::Reference, qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{"Object2"}, + TypeTraits::Reference, + qmlDocumentSourceId2, Storage::Synchronization::ChangeLevel::Full), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDocumentSourceId1, qmlDocumentSourceId2)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDocumentSourceId2)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDocumentSourceId2, 22, 13))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, + FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeRemovesQmlDocument) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + FirstType 2.2 First2.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId3))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, -1, -1})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId3, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL(projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field(&SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre( + IsExportedType(exampleModuleId, "FirstType", 1, 0), IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre( + IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, + qmlDocumentSourceId1, + qmlDocumentSourceId2, + qmlDocumentSourceId3)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId3)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, + FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeRemovesQmlDocumentInQmldirOnly) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field(&SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), AllOf(IsStorageType("First2.qml", Storage::Synchronization::ImportedType{}, TypeTraits::Reference, qmlDocumentSourceId2, Storage::Synchronization::ChangeLevel::Minimal), Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))))), + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmltypesPathSourceId, - qmlDocumentSourceId1, - qmlDocumentSourceId2, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, - qmlDocumentSourceId1, - qmltypesPathSourceId, - qmlDocumentSourceId3)), + UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12), - IsFileStatus(qmltypesPathSourceId, 21, 421))), + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, - exampleModuleId, + ModuleId{}, FileType::QmlDocument), IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, - exampleModuleId, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeAddQmlDocumentToQmldir) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + FirstType 2.2 First2.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, FileType::QmlDocument), IsProjectData(qmlDirPathSourceId, - qmltypesPathSourceId, - exampleCppNativeModuleId, - FileType::QmlTypes), - IsProjectData(qmlDirPathSourceId, - qmltypes2PathSourceId, - exampleCppNativeModuleId, - FileType::QmlTypes)))))); + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); +} + +TEST_F(ProjectStorageUpdater, SynchronizeAddQmlDocumentToDirectory) +{ + QString qmldir{R"(module Example + FirstType 1.0 First.qml + )"}; + ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 422})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); + ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) + .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); + ON_CALL(projectStorageMock, fetchProjectDatas(Eq(qmlDirPathSourceId))) + .WillByDefault(Return(QmlDesigner::Storage::Synchronization::ProjectDatas{ + {qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument}, + {qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument}})); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml", "First2.qml"})); + + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, IsEmpty()), + Field(&SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(pathModuleId, "First2", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 422))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId1, + ModuleId{}, + FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId2, + ModuleId{}, + FileType::QmlDocument)))))); + + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) @@ -657,32 +895,33 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) projectStorageMock, synchronize(AllOf( Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1, import2)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre( - AllOf(IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))), - AllOf(IsStorageType("First2.qml", - Storage::Synchronization::ImportedType{"Object2"}, - TypeTraits::Reference, - qmlDocumentSourceId2, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), - IsExportedType(pathModuleId, "First2", -1, -1)))), - AllOf(IsStorageType("Second.qml", - Storage::Synchronization::ImportedType{}, - TypeTraits::Reference, - qmlDocumentSourceId3, - Storage::Synchronization::ChangeLevel::Minimal), - Field(&Storage::Synchronization::Type::exportedTypes, - ElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), - IsExportedType(pathModuleId, "Second", -1, -1)))))), + Field( + &SynchronizationPackage::types, + UnorderedElementsAre( + AllOf(IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))), + AllOf(IsStorageType("First2.qml", + Storage::Synchronization::ImportedType{"Object2"}, + TypeTraits::Reference, + qmlDocumentSourceId2, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 2, 2), + IsExportedType(pathModuleId, "First2", -1, -1)))), + AllOf(IsStorageType("Second.qml", + Storage::Synchronization::ImportedType{}, + TypeTraits::Reference, + qmlDocumentSourceId3, + Storage::Synchronization::ChangeLevel::Minimal), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "SecondType", 2, 2), + IsExportedType(pathModuleId, "Second", -1, -1)))))), Field(&SynchronizationPackage::updatedSourceIds, UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, @@ -697,20 +936,15 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) Field(&SynchronizationPackage::updatedProjectSourceIds, UnorderedElementsAre(qmlDirPathSourceId)), Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId2, - exampleModuleId, - FileType::QmlDocument), - IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId3, - exampleModuleId, - FileType::QmlDocument)))))); + UnorderedElementsAre( + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, qmlDocumentSourceId2, ModuleId{}, FileType::QmlDocument), + IsProjectData(qmlDirPathSourceId, + qmlDocumentSourceId3, + ModuleId{}, + FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, UpdateQmldirDocuments) @@ -744,7 +978,7 @@ TEST_F(ProjectStorageUpdater, AddSourceIdForForInvalidQmldirFileStatus) Field(&SynchronizationPackage::fileStatuses, IsEmpty()), Field(&SynchronizationPackage::updatedFileStatusSourceIds, IsEmpty()), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChanged) @@ -796,7 +1030,7 @@ TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChanged) qmlDocumentSourceId2)), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChangedAndSomeUpdatedFiles) @@ -836,7 +1070,7 @@ TEST_F(ProjectStorageUpdater, SynchronizIfQmldirFileHasNotChangedAndSomeUpdatedF UnorderedElementsAre(qmltypesPathSourceId, qmlDocumentSourceId1)), Field(&SynchronizationPackage::projectDatas, IsEmpty())))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, UpdateQmlTypesFilesIsEmpty) @@ -913,39 +1147,39 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentVersionButSame FirstType 1.1 First.qml FirstType 6.0 First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType", 1, 1), - IsExportedType(exampleModuleId, "FirstType", 6, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument)))))); + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), + Field(&SynchronizationPackage::types, + UnorderedElementsAre(AllOf( + IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(exampleModuleId, "FirstType", 1, 1), + IsExportedType(exampleModuleId, "FirstType", 6, 0), + IsExportedType(pathModuleId, "First", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), + IsFileStatus(qmlDocumentSourceId1, 22, 12))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData( + qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSameVersionAndFileName) @@ -954,38 +1188,38 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithDifferentTypeNameButSam FirstType 1.0 First.qml FirstType2 1.0 First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId1, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType2", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId1, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId1, - exampleModuleId, - FileType::QmlDocument)))))); + EXPECT_CALL( + projectStorageMock, + synchronize(AllOf( + Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), + Field(&SynchronizationPackage::types, + UnorderedElementsAre(AllOf( + IsStorageType("First.qml", + Storage::Synchronization::ImportedType{"Object"}, + TypeTraits::Reference, + qmlDocumentSourceId1, + Storage::Synchronization::ChangeLevel::Full), + Field(&Storage::Synchronization::Type::exportedTypes, + UnorderedElementsAre(IsExportedType(exampleModuleId, "FirstType", 1, 0), + IsExportedType(exampleModuleId, "FirstType2", 1, 0), + IsExportedType(pathModuleId, "First", -1, -1)))))), + Field(&SynchronizationPackage::updatedSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::updatedFileStatusSourceIds, + UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1)), + Field(&SynchronizationPackage::fileStatuses, + UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), + IsFileStatus(qmlDocumentSourceId1, 22, 12))), + Field(&SynchronizationPackage::updatedProjectSourceIds, + UnorderedElementsAre(qmlDirPathSourceId)), + Field(&SynchronizationPackage::projectDatas, + UnorderedElementsAre(IsProjectData( + qmlDirPathSourceId, qmlDocumentSourceId1, ModuleId{}, FileType::QmlDocument)))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, DontSynchronizeSelectors) @@ -995,70 +1229,18 @@ TEST_F(ProjectStorageUpdater, DontSynchronizeSelectors) ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qml/+First.qml")))) .WillByDefault(Return(qmlDocument1)); QString qmldir{R"(module Example - FirstType 1.0 +First.qml - FirstType2 1.0 qml/+First.qml)"}; + FirstType 1.0 +First.qml)"}; ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); + ON_CALL(fileSystemMock, qmlFileNames(Eq(QString("/path")))) + .WillByDefault(Return(QStringList{"First.qml"})); EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, IsEmpty()), - Field(&SynchronizationPackage::types, IsEmpty()), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421))), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, IsEmpty()), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId))))); + synchronize(Not(Field( + &SynchronizationPackage::types, + Contains(Field(&Storage::Synchronization::Type::exportedTypes, + Contains(IsExportedType(exampleModuleId, "FirstType", 1, 0)))))))); - updater.update(qmlDirs, {}); -} - -TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsWithRelativeFilePath) -{ - SourceId qmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml"); - ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId))) - .WillByDefault(Return(FileStatus{qmlDocumentSourceId, 22, 12})); - ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml")))) - .WillByDefault(Return(qmlDocument1)); - QString qmldir{R"(module Example - FirstType 1.0 First.qml - FirstType2 1.0 First.qml)"}; - ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); - - EXPECT_CALL(projectStorageMock, - synchronize( - AllOf(Field(&SynchronizationPackage::imports, UnorderedElementsAre(import1)), - Field(&SynchronizationPackage::types, - UnorderedElementsAre(AllOf( - IsStorageType("First.qml", - Storage::Synchronization::ImportedType{"Object"}, - TypeTraits::Reference, - qmlDocumentSourceId, - Storage::Synchronization::ChangeLevel::Full), - Field(&Storage::Synchronization::Type::exportedTypes, - UnorderedElementsAre( - IsExportedType(exampleModuleId, "FirstType", 1, 0), - IsExportedType(exampleModuleId, "FirstType2", 1, 0), - IsExportedType(pathModuleId, "First", -1, -1)))))), - Field(&SynchronizationPackage::updatedSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)), - Field(&SynchronizationPackage::updatedFileStatusSourceIds, - UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId)), - Field(&SynchronizationPackage::fileStatuses, - UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), - IsFileStatus(qmlDocumentSourceId, 22, 12))), - Field(&SynchronizationPackage::updatedProjectSourceIds, - UnorderedElementsAre(qmlDirPathSourceId)), - Field(&SynchronizationPackage::projectDatas, - UnorderedElementsAre(IsProjectData(qmlDirPathSourceId, - qmlDocumentSourceId, - exampleModuleId, - FileType::QmlDocument)))))); - - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependencies) @@ -1089,7 +1271,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependencies) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithDoubleEntries) @@ -1121,7 +1303,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithDoubleEntries) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithCollidingImports) @@ -1153,7 +1335,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirDependenciesWithCollidingImports) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies) @@ -1170,7 +1352,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoDependencies) Field(&SynchronizationPackage::updatedModuleDependencySourceIds, UnorderedElementsAre(qmltypesPathSourceId, qmltypes2PathSourceId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports) @@ -1212,7 +1394,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirImports) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports) @@ -1226,7 +1408,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirWithNoImports) Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirImportsWithDoubleEntries) @@ -1269,7 +1451,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirImportsWithDoubleEntries) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } TEST_F(ProjectStorageUpdater, SynchronizeQmldirOptionalImports) @@ -1311,7 +1493,7 @@ TEST_F(ProjectStorageUpdater, SynchronizeQmldirOptionalImports) IsAutoVersion::No})), Field(&SynchronizationPackage::updatedModuleIds, ElementsAre(exampleModuleId))))); - updater.update(qmlDirs, {}); + updater.update(directories, {}); } } // namespace From f113b05530fcd236309729ed760691fef32c9881 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Nov 2022 15:59:11 +0200 Subject: [PATCH 15/71] QmlDesigner: Reset possible imports on all open documents DocumentManager keeps track of other documents besides the currently open one. All of those documents can have RewriterView instances. Possible imports need to be reset on all of them instead of just the current one. Fixes: QDS-8109 Change-Id: I18b5c2690d1a33f2605db94d39fda7b7a9b200e2 Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri Reviewed-by: Qt CI Bot --- .../components/itemlibrary/itemlibraryassetimporter.cpp | 4 ++-- .../components/materialbrowser/bundleimporter.cpp | 4 ++-- src/plugins/qmldesigner/documentmanager.cpp | 8 ++++++++ src/plugins/qmldesigner/documentmanager.h | 2 ++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp index 4f3ff160296..3f5ffee4fcf 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp @@ -5,6 +5,7 @@ #include "qmldesignerplugin.h" #include "qmldesignerconstants.h" +#include "documentmanager.h" #include "externaldependenciesinterface.h" #include "model.h" #include "puppetstarter.h" @@ -704,8 +705,7 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport() if (result.isCanceled() || result.isFinished()) counter = 49; // skip to next step } else if (counter == 50) { - if (model && model->rewriterView()) - model->rewriterView()->resetPossibleImports(); + QmlDesignerPlugin::instance()->documentManager().resetPossibleImports(); model->rewriterView()->textModifier()->replace(0, 0, {}); } else if (counter < 100) { try { diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp index fc86428b8c7..24e3d3e1108 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp @@ -25,6 +25,7 @@ #include "bundleimporter.h" +#include "documentmanager.h" #include "import.h" #include "model.h" #include "qmldesignerconstants.h" @@ -205,8 +206,7 @@ void BundleImporter::handleImportTimer() return; } - if (model && model->rewriterView()) - model->rewriterView()->resetPossibleImports(); + QmlDesignerPlugin::instance()->documentManager().resetPossibleImports(); if (m_importAddPending) { try { diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index 14c68b42b71..81afec05788 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -253,6 +253,14 @@ void DocumentManager::removeEditors(const QList &editors) m_designDocuments.erase(editor); } +void DocumentManager::resetPossibleImports() +{ + for (const auto &[key, value] : m_designDocuments) { + if (RewriterView *view = value->rewriterView()) + view->resetPossibleImports(); + } +} + bool DocumentManager::goIntoComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNode.isComponent() && designDocument()) { diff --git a/src/plugins/qmldesigner/documentmanager.h b/src/plugins/qmldesigner/documentmanager.h index 5123a763f7d..d47b05dea59 100644 --- a/src/plugins/qmldesigner/documentmanager.h +++ b/src/plugins/qmldesigner/documentmanager.h @@ -39,6 +39,8 @@ public: void removeEditors(const QList &editors); + void resetPossibleImports(); + static bool goIntoComponent(const ModelNode &modelNode); static void goIntoComponent(const QString &fileName); From 08f5a92bacfada366a7711ec9bd58031df1b257b Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Mon, 31 Oct 2022 18:47:24 +0200 Subject: [PATCH 16/71] QmlDesigner: Add Paste to 3d Context Menu Paste action is added to the context menu of the Edit3DWidget. Task-number: QDS-8063 Change-Id: Ic4e4a58b51ca297536c72f15400f3c6ecd87d84a Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- .../components/edit3d/edit3dwidget.cpp | 42 ++++++++++++++++++- .../components/edit3d/edit3dwidget.h | 5 ++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index a41ef1c81ce..19538382ca3 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include "edit3dwidget.h" +#include "designdocumentview.h" #include "edit3dactions.h" #include "edit3dcanvas.h" #include "edit3dview.h" @@ -11,6 +12,7 @@ #include "qmldesignerconstants.h" #include "qmldesignerplugin.h" #include "qmlvisualnode.h" +#include "timelineactions.h" #include "viewmanager.h" #include @@ -185,6 +187,10 @@ void Edit3DWidget::createContextMenu() QmlDesignerPlugin::instance()->currentDesignDocument()->copySelected(); }); + m_pasteAction = m_contextMenu->addAction(tr("Paste"), [&] { + QmlDesignerPlugin::instance()->currentDesignDocument()->paste(); + }); + m_deleteAction = m_contextMenu->addAction(tr("Delete"), [&] { view()->executeInTransaction("Edit3DWidget::createContextMenu", [&] { for (ModelNode &node : m_view->selectedModelNodes()) @@ -192,7 +198,6 @@ void Edit3DWidget::createContextMenu() }); }); - m_contextMenu->addSeparator(); m_alignCameraAction = m_contextMenu->addAction(tr("Align Camera to View"), [&] { @@ -206,6 +211,38 @@ void Edit3DWidget::createContextMenu() m_contextMenu->addSeparator(); } +bool Edit3DWidget::isPasteAvailable() const +{ + if (TimelineActions::clipboardContainsKeyframes()) + return false; + + auto pasteModel(DesignDocumentView::pasteToModel(view()->externalDependencies())); + if (!pasteModel) + return false; + + DesignDocumentView docView{view()->externalDependencies()}; + pasteModel->attachView(&docView); + auto rootNode = docView.rootModelNode(); + + if (rootNode.type() == "empty") + return false; + + QList allNodes; + if (rootNode.id() == "__multi__selection__") + allNodes << rootNode.directSubModelNodes(); + else + allNodes << rootNode; + + bool hasNon3DNode = std::any_of(allNodes.begin(), allNodes.end(), [](const ModelNode &node) { + return !node.metaInfo().isQtQuick3DNode(); + }); + + if (hasNon3DNode) + return false; + + return true; +} + // Called by the view to update the "create" sub-menu when the Quick3D entries are ready. void Edit3DWidget::updateCreateSubMenu(const QStringList &keys, const QHash> &entriesMap) @@ -333,8 +370,9 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_editComponentAction->setEnabled(isSingleComponent); m_editMaterialAction->setEnabled(isModel); - m_deleteAction->setEnabled(isNotRoot); m_copyAction->setEnabled(isNotRoot); + m_pasteAction->setEnabled(isPasteAvailable()); + m_deleteAction->setEnabled(isNotRoot); m_alignCameraAction->setEnabled(isCamera); m_alignViewAction->setEnabled(isCamera); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 5a49d8bc1cd..e7d45956f56 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -51,6 +51,8 @@ private: void linkActivated(const QString &link); void createContextMenu(); + bool isPasteAvailable() const; + QPointer m_edit3DView; QPointer m_view; QPointer m_canvas; @@ -62,8 +64,9 @@ private: QPointer m_contextMenu; QPointer m_editComponentAction; QPointer m_editMaterialAction; - QPointer m_deleteAction; QPointer m_copyAction; + QPointer m_pasteAction; + QPointer m_deleteAction; QPointer m_alignCameraAction; QPointer m_alignViewAction; QPointer m_createSubMenu; From e8899baa2115f75cd26a9fdb8e8fd3c49e69fe1f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Nov 2022 17:38:38 +0200 Subject: [PATCH 17/71] QmlDesigner: Add support for CubeMapTexture to NodeMetaInfo Task-number: QDS-8169 Change-Id: I326708ef17325acf1731a285f4e4f387ba4f95fb Reviewed-by: Marco Bubke --- .../qmldesigner/designercore/include/nodemetainfo.h | 1 + .../designercore/metainfo/nodemetainfo.cpp | 11 +++++++++++ .../designercore/projectstorage/commontypecache.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h index 5e5984bbc4b..36469d6f309 100644 --- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h @@ -140,6 +140,7 @@ public: bool isQtQuick3DShader() const; bool isQtQuick3DTexture() const; bool isQtQuick3DTextureInput() const; + bool isQtQuick3DCubeMapTexture() const; bool isQtQuick3DView3D() const; bool isQtQuickBorderImage() const; bool isQtQuickControlsSwipeView() const; diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index f68d5d07b43..1996ed79202 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -2768,6 +2768,17 @@ bool NodeMetaInfo::isQtQuick3DTextureInput() const } } +bool NodeMetaInfo::isQtQuick3DCubeMapTexture() const +{ + if constexpr (useProjectStorage()) { + using namespace Storage::Info; + return isBasedOnCommonType(m_projectStorage, m_typeId); + } else { + return isValid() + && (isSubclassOf("QtQuick3D.CubeMapTexture") || isSubclassOf(".QQuick3DCubeMapTexture")); + } +} + bool NodeMetaInfo::isQtQuick3DSceneEnvironment() const { if constexpr (useProjectStorage()) { diff --git a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h index eacb0578c02..2d041df9cf7 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/commontypecache.h @@ -30,6 +30,7 @@ inline constexpr char Camera[] = "Camera"; inline constexpr char Command[] = "Command"; inline constexpr char Component[] = "Component"; inline constexpr char Connections[] = "Connections"; +inline constexpr char CubeMapTexture[] = "CubeMapTexture"; inline constexpr char DefaultMaterial[] = "DefaultMaterial"; inline constexpr char Dialog[] = "Dialog"; inline constexpr char DoubleType[] = "double"; @@ -185,6 +186,7 @@ class CommonTypeCache CacheType, CacheType, CacheType, + CacheType, CacheType, CacheType, CacheType, From 9febccb2d7764ed2dd133ce4992b0ff7311d8e86 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 4 Nov 2022 17:59:39 +0200 Subject: [PATCH 18/71] QmlDesigner: Update material browser materials on state change More generally, materials previews are now updated whenever the instance values on them change. Fixes: QDS-8096 Change-Id: I07dab4c9cefa241ca5f22e32e6a53e85c31aa252 Reviewed-by: Mahmoud Badri --- .../materialbrowser/materialbrowserview.cpp | 36 +++++++++++++++++-- .../materialbrowser/materialbrowserview.h | 7 ++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 7a320fb7b37..2a7b6833b3e 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -38,7 +38,10 @@ namespace QmlDesigner { MaterialBrowserView::MaterialBrowserView(ExternalDependenciesInterface &externalDependencies) : AbstractView{externalDependencies} -{} +{ + m_previewTimer.setSingleShot(true); + connect(&m_previewTimer, &QTimer::timeout, this, &MaterialBrowserView::requestPreviews); +} MaterialBrowserView::~MaterialBrowserView() {} @@ -309,7 +312,9 @@ void MaterialBrowserView::refreshModel(bool updateImages) if (updateImages) { for (const ModelNode &node : std::as_const(materials)) - model()->nodeInstanceView()->previewImageDataForGenericNode(node, {}); + m_previewRequests.insert(node); + if (!m_previewRequests.isEmpty()) + m_previewTimer.start(0); } } @@ -516,6 +521,15 @@ ModelNode MaterialBrowserView::getBundleMaterialDefaultInstance(const TypeName & return {}; } +void MaterialBrowserView::requestPreviews() +{ + if (model() && model()->nodeInstanceView()) { + for (const auto &node : std::as_const(m_previewRequests)) + model()->nodeInstanceView()->previewImageDataForGenericNode(node, {}); + } + m_previewRequests.clear(); +} + void MaterialBrowserView::importsChanged([[maybe_unused]] const QList &addedImports, [[maybe_unused]] const QList &removedImports) { @@ -576,11 +590,27 @@ void MaterialBrowserView::instancesCompleted(const QVector &completed return; const QList materials = m_widget->materialBrowserModel()->materials(); for (const ModelNode &node : materials) - model()->nodeInstanceView()->previewImageDataForGenericNode(node, {}); + m_previewRequests.insert(node); + if (!m_previewRequests.isEmpty()) + m_previewTimer.start(0); }); break; } } } +void MaterialBrowserView::instancePropertyChanged(const QList > &propertyList) +{ + for (const auto &nodeProp : propertyList) { + ModelNode node = nodeProp.first; + if (node.metaInfo().isQtQuick3DMaterial()) + m_previewRequests.insert(node); + } + if (!m_previewRequests.isEmpty() && !m_previewTimer.isActive()) { + // Updating material browser isn't urgent in e.g. timeline scrubbing case, so have a bit + // of delay to reduce unnecessary rendering + m_previewTimer.start(500); + } +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h index ad50bfa463a..a8bcf5f2f1f 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h @@ -7,6 +7,8 @@ #include "nodemetainfo.h" #include +#include +#include namespace QmlDesigner { @@ -41,6 +43,7 @@ public: void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data) override; void instancesCompleted(const QVector &completedNodeList) override; + void instancePropertyChanged(const QList > &propertyList) override; private: void refreshModel(bool updateImages); @@ -50,6 +53,7 @@ private: void updateBundleMaterialsQuick3DVersion(); void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {}); ModelNode getBundleMaterialDefaultInstance(const TypeName &type); + void requestPreviews(); QPointer m_widget; QList m_bundleMaterialTargets; @@ -61,6 +65,9 @@ private: bool m_autoSelectModelMaterial = false; // TODO: wire this to some action bool m_puppetResetPending = false; bool m_propertyGroupsLoaded = false; + + QTimer m_previewTimer; + QSet m_previewRequests; }; } // namespace QmlDesigner From 1c58642ae2c6a548c03c40ba93ec855861070e2d Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Tue, 8 Nov 2022 10:54:45 +0200 Subject: [PATCH 19/71] QmlDesigner: Add Fit Selected to 3d Context Menu "Fit Selected Items to View" action is added to the context menu of the Edit3DWidget. Task-number: QDS-8198 Change-Id: Ib6882bd173ca874ffbf3fe0ade29a6f5008d6cf2 Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen --- src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp | 5 +++++ src/plugins/qmldesigner/components/edit3d/edit3dwidget.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 19538382ca3..8238b649de0 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -200,6 +200,10 @@ void Edit3DWidget::createContextMenu() m_contextMenu->addSeparator(); + m_fitSelectedAction = m_contextMenu->addAction(tr("Fit Selected Items to View"), [&] { + view()->emitView3DAction(View3DActionType::FitToView, true); + }); + m_alignCameraAction = m_contextMenu->addAction(tr("Align Camera to View"), [&] { view()->emitView3DAction(View3DActionType::AlignCamerasToView, true); }); @@ -373,6 +377,7 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_copyAction->setEnabled(isNotRoot); m_pasteAction->setEnabled(isPasteAvailable()); m_deleteAction->setEnabled(isNotRoot); + m_fitSelectedAction->setEnabled(isNotRoot); m_alignCameraAction->setEnabled(isCamera); m_alignViewAction->setEnabled(isCamera); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index e7d45956f56..63aba37484b 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -67,6 +67,7 @@ private: QPointer m_copyAction; QPointer m_pasteAction; QPointer m_deleteAction; + QPointer m_fitSelectedAction; QPointer m_alignCameraAction; QPointer m_alignViewAction; QPointer m_createSubMenu; From d5a7f25e608acdd1efd6c76554d7144f70454f02 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Wed, 26 Oct 2022 19:57:41 +0300 Subject: [PATCH 20/71] QmlDesigner: Implement content library view Fixes: QDS-8058 Fixes: QDS-8059 Change-Id: I1adfdc7ac15141e010467813ec6e673060269241 Reviewed-by: Miikka Heikkinen --- .../ContentLibrary.qml | 121 ++++++ .../ContentLibraryMaterial.qml} | 34 +- .../ContentLibraryMaterialContextMenu.qml | 52 +++ .../ContentLibraryMaterialsView.qml | 91 +++++ .../ContentLibraryTabBar.qml | 33 ++ .../ContentLibraryTabButton.qml | 58 +++ .../ContentLibraryTexture.qml | 34 ++ .../ContentLibraryTextureContextMenu.qml | 39 ++ .../ContentLibraryTexturesView.qml | 92 +++++ .../UnimportBundleMaterialDialog.qml | 28 +- .../MaterialBrowser.qml | 139 +++---- .../MaterialBrowserContextMenu.qml | 26 +- .../MaterialBundleContextMenu.qml | 74 ---- .../materialBrowserQmlSource/TextureItem.qml | 34 ++ .../imports/StudioTheme/Values.qml | 2 + src/plugins/qmldesigner/CMakeLists.txt | 19 +- .../assetslibrary/assetslibrarywidget.cpp | 2 +- .../componentcore/designeractionmanager.cpp | 2 +- .../componentcore/designeractionmanager.h | 18 +- .../componentcore/modelnodeoperations.cpp | 24 +- .../componentcore/modelnodeoperations.h | 12 +- .../components/componentcore/viewmanager.cpp | 6 + .../contentlibrarybundleimporter.cpp} | 54 +-- .../contentlibrarybundleimporter.h | 57 +++ .../contentlibrary/contentlibrarymaterial.cpp | 67 ++++ .../contentlibrary/contentlibrarymaterial.h | 57 +++ .../contentlibrarymaterialscategory.cpp | 63 ++++ .../contentlibrarymaterialscategory.h | 47 +++ .../contentlibrarymaterialsmodel.cpp} | 116 +++--- .../contentlibrarymaterialsmodel.h} | 66 ++-- .../contentlibrary/contentlibrarytexture.cpp | 33 ++ .../contentlibrary/contentlibrarytexture.h | 37 ++ .../contentlibrarytexturescategory.cpp | 56 +++ .../contentlibrarytexturescategory.h | 50 +++ .../contentlibrarytexturesmodel.cpp | 185 +++++++++ .../contentlibrarytexturesmodel.h | 74 ++++ .../contentlibrary/contentlibraryview.cpp | 354 ++++++++++++++++++ .../contentlibrary/contentlibraryview.h | 53 +++ .../contentlibrary/contentlibrarywidget.cpp | 238 ++++++++++++ .../contentlibrary/contentlibrarywidget.h | 76 ++++ .../components/edit3d/edit3dview.cpp | 2 +- .../itemlibrary/itemlibraryview.cpp | 3 +- .../materialbrowser/bundleimporter.h | 79 ---- .../materialbrowser/bundlematerial.cpp | 89 ----- .../materialbrowser/bundlematerial.h | 79 ---- .../bundlematerialcategory.cpp | 85 ----- .../materialbrowser/bundlematerialcategory.h | 69 ---- .../materialbrowsertexturesmodel.cpp | 219 +++++++++++ .../materialbrowsertexturesmodel.h | 63 ++++ .../materialbrowser/materialbrowserview.cpp | 236 +----------- .../materialbrowser/materialbrowserview.h | 10 +- .../materialbrowser/materialbrowserwidget.cpp | 45 +-- .../materialbrowser/materialbrowserwidget.h | 25 +- .../navigator/navigatortreemodel.cpp | 2 +- .../qmldesigner/qmldesignerconstants.h | 1 + 55 files changed, 2540 insertions(+), 1090 deletions(-) create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml rename share/qtcreator/qmldesigner/{materialBrowserQmlSource/BundleMaterialItem.qml => contentLibraryQmlSource/ContentLibraryMaterial.qml} (66%) create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml create mode 100644 share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml rename share/qtcreator/qmldesigner/{materialBrowserQmlSource => contentLibraryQmlSource}/UnimportBundleMaterialDialog.qml (53%) delete mode 100644 share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBundleContextMenu.qml create mode 100644 share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml rename src/plugins/qmldesigner/components/{materialbrowser/bundleimporter.cpp => contentlibrary/contentlibrarybundleimporter.cpp} (86%) create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.h rename src/plugins/qmldesigner/components/{materialbrowser/materialbrowserbundlemodel.cpp => contentlibrary/contentlibrarymaterialsmodel.cpp} (64%) rename src/plugins/qmldesigner/components/{materialbrowser/materialbrowserbundlemodel.h => contentlibrary/contentlibrarymaterialsmodel.h} (50%) create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp create mode 100644 src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h delete mode 100644 src/plugins/qmldesigner/components/materialbrowser/bundleimporter.h delete mode 100644 src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp delete mode 100644 src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h delete mode 100644 src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.cpp delete mode 100644 src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.h create mode 100644 src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp create mode 100644 src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml new file mode 100644 index 00000000000..bbe9641419e --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibrary.qml @@ -0,0 +1,121 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuickDesignerTheme +import HelperWidgets as HelperWidgets +import StudioControls as StudioControls +import StudioTheme as StudioTheme + +Item { + id: root + + // Called also from C++ to close context menu on focus out + function closeContextMenu() + { + materialsView.closeContextMenu() + texturesView.closeContextMenu() + environmentsView.closeContextMenu() + } + + // Called from C++ + function clearSearchFilter() + { + searchBox.clear(); + } + + Column { + id: col + y: 5 + spacing: 5 + + StudioControls.SearchBox { + id: searchBox + + width: root.width + enabled: !materialsModel.hasMaterialRoot && materialsModel.hasQuick3DImport + + onSearchChanged: (searchText) => { + rootView.handleSearchFilterChanged(searchText) + + // make sure categories with matches are expanded + materialsView.expandVisibleSections() + } + } + + Text { + // TODO: only disable the materials section, textures should be available + text: { + if (materialsModel.hasMaterialRoot) + qsTr("Content Library is disabled inside a material component.") + else if (!materialsModel.hasQuick3DImport) + qsTr("To use Content Library, first add the QtQuick3D module in the Components view.") + else + "" + } + + textFormat: Text.RichText + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.mediumFontSize + topPadding: 30 + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + width: root.width + visible: text !== "" + } + + UnimportBundleMaterialDialog { + id: confirmUnimportDialog + } + + ContentLibraryTabBar { + id: tabBar + + visible: materialsModel.hasQuick3DImport + // TODO: update icons + tabsModel: [{name: qsTr("Materials"), icon: StudioTheme.Constants.gradient}, + {name: qsTr("Textures"), icon: StudioTheme.Constants.materialPreviewEnvironment}, + {name: qsTr("Environments"), icon: StudioTheme.Constants.translationSelectLanguages}] + } + + StackLayout { + width: root.width + height: root.height - y + currentIndex: tabBar.currIndex + visible: materialsModel.hasQuick3DImport + + ContentLibraryMaterialsView { + id: materialsView + + width: root.width + + searchBox: searchBox + + onUnimport: (bundleMat) => { + unimportBundleMaterialDialog.targetBundleMaterial = bundleMat + unimportBundleMaterialDialog.open() + } + } + + ContentLibraryTexturesView { + id: texturesView + + width: root.width + model: texturesModel + + searchBox: searchBox + } + + ContentLibraryTexturesView { + id: environmentsView + + width: root.width + model: environmentsModel + + searchBox: searchBox + } + } + } +} diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/BundleMaterialItem.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml similarity index 66% rename from share/qtcreator/qmldesigner/materialBrowserQmlSource/BundleMaterialItem.qml rename to share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml index 59541f47d39..4d6377359ce 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/BundleMaterialItem.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterial.qml @@ -1,27 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 import QtQuick 2.15 import QtQuick.Layouts 1.15 @@ -45,8 +23,8 @@ Item { acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: (mouse) => { - if (mouse.button === Qt.LeftButton && !materialBrowserBundleModel.importerRunning) - rootView.startDragBundleMaterial(modelData, mapToGlobal(mouse.x, mouse.y)) + if (mouse.button === Qt.LeftButton && !materialsModel.importerRunning) + rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y)) else if (mouse.button === Qt.RightButton) root.showContextMenu() } @@ -102,10 +80,10 @@ Item { pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4) anchors.right: img.right anchors.bottom: img.bottom - enabled: !materialBrowserBundleModel.importerRunning + enabled: !materialsModel.importerRunning onClicked: { - materialBrowserBundleModel.addToProject(modelData) + materialsModel.addToProject(modelData) } } } diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml new file mode 100644 index 00000000000..a85699e6dc3 --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialContextMenu.qml @@ -0,0 +1,52 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick 2.15 +import HelperWidgets 2.0 +import StudioControls 1.0 as StudioControls +import StudioTheme 1.0 as StudioTheme + +StudioControls.Menu { + id: root + + property var targetMaterial: null + signal unimport(var bundleMat); + + function popupMenu(targetMaterial = null) + { + this.targetMaterial = targetMaterial + popup() + } + + closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside + + StudioControls.MenuItem { + text: qsTr("Apply to selected (replace)") + enabled: root.targetMaterial && materialsModel.hasModelSelection + onTriggered: materialsModel.applyToSelected(root.targetMaterial, false) + } + + StudioControls.MenuItem { + text: qsTr("Apply to selected (add)") + enabled: root.targetMaterial && materialsModel.hasModelSelection + onTriggered: materialsModel.applyToSelected(root.targetMaterial, true) + } + + StudioControls.MenuSeparator {} + + StudioControls.MenuItem { + enabled: !materialsModel.importerRunning + text: qsTr("Add an instance to project") + + onTriggered: { + materialsModel.addToProject(root.targetMaterial) + } + } + + StudioControls.MenuItem { + enabled: !materialsModel.importerRunning && root.targetMaterial && root.targetMaterial.bundleMaterialImported + text: qsTr("Remove from project") + + onTriggered: root.unimport(root.targetMaterial); + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml new file mode 100644 index 00000000000..589e0250b5e --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryMaterialsView.qml @@ -0,0 +1,91 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import HelperWidgets as HelperWidgets +import StudioControls as StudioControls +import StudioTheme as StudioTheme + +HelperWidgets.ScrollView { + id: root + + clip: true + + readonly property int cellWidth: 100 + readonly property int cellHeight: 120 + + property var currMaterialItem: null + property var rootItem: null + + required property var searchBox + + signal unimport(var bundleMat); + + function closeContextMenu() + { + ctxMenu.close() + } + + function expandVisibleSections() + { + for (let i = 0; i < categoryRepeater.count; ++i) { + let cat = categoryRepeater.itemAt(i) + if (cat.visible && !cat.expanded) + cat.expanded = true + } + } + + Column { + ContentLibraryMaterialContextMenu { + id: ctxMenu + + onUnimport: (bundleMat) => root.unimport(bundleMat) + } + + Repeater { + id: categoryRepeater + + model: materialsModel + + delegate: HelperWidgets.Section { + width: root.width + caption: bundleCategoryName + addTopPadding: false + sectionBackgroundColor: "transparent" + visible: bundleCategoryVisible + expanded: bundleCategoryExpanded + expandOnClick: false + onToggleExpand: bundleCategoryExpanded = !bundleCategoryExpanded + + Grid { + width: root.width + leftPadding: 5 + rightPadding: 5 + bottomPadding: 5 + columns: root.width / root.cellWidth + + Repeater { + model: bundleCategoryMaterials + + delegate: ContentLibraryMaterial { + width: root.cellWidth + height: root.cellHeight + + onShowContextMenu: ctxMenu.popupMenu(modelData) + } + } + } + } + } + + Text { + id: noMatchText + text: qsTr("No match found."); + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.baseFontSize + topPadding: 10 + leftPadding: 10 + visible: materialsModel.isEmpty && !searchBox.isEmpty() && !materialsModel.hasMaterialRoot + } + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml new file mode 100644 index 00000000000..024271d1a23 --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabBar.qml @@ -0,0 +1,33 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import StudioTheme as StudioTheme + +Rectangle { + id: root + + width: parent.width + height: 50 + color: StudioTheme.Values.themeSectionHeadBackground + + property int currIndex: 0 + property alias tabsModel: repeater.model + + Row { + spacing: 1 + + Repeater { + id: repeater + + ContentLibraryTabButton { + height: root.height + + name: modelData.name + icon: modelData.icon + selected: root.currIndex === index + onClicked: root.currIndex = index + } + } + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml new file mode 100644 index 00000000000..cd31f2579d2 --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTabButton.qml @@ -0,0 +1,58 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import StudioTheme as StudioTheme + +Rectangle { + id: root + + signal clicked() + + property alias icon: icon.text + property alias name: name.text + property bool selected: false + + width: 100 + height: 100 + color: root.selected ? StudioTheme.Values.themePanelBackground + : mouseArea.containsMouse ? Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.3) + : StudioTheme.Values.themeSectionHeadBackground + + Text { + id: icon + + color: root.selected ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor + + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.mediumIconFontSize + anchors.horizontalCenter: parent.horizontalCenter + y: 8 + } + + Text { + id: name + + font.weight: Font.DemiBold + font.pixelSize: StudioTheme.Values.baseFontSize + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 6 + + color: root.selected ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeTextColor + } + + Rectangle { // strip + width: root.width + height: 4 + color: root.selected ? StudioTheme.Values.themeInteraction : "transparent" + anchors.bottom: parent.bottom + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: root.clicked() + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml new file mode 100644 index 00000000000..d6c24d4b2af --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexture.qml @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuickDesignerTheme 1.0 +import HelperWidgets 2.0 +import QtQuick.Controls + +import StudioTheme 1.0 as StudioTheme + +Image { + id: root + + source: modelData.textureIcon + visible: modelData.textureVisible + cache: false + + signal showContextMenu() + + MouseArea { + id: mouseArea + + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onPressed: (mouse) => { + if (mouse.button === Qt.LeftButton) + rootView.startDragTexture(modelData, mapToGlobal(mouse.x, mouse.y)) + else if (mouse.button === Qt.RightButton) + root.showContextMenu() + } + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml new file mode 100644 index 00000000000..373b2108084 --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml @@ -0,0 +1,39 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick 2.15 +import HelperWidgets 2.0 +import StudioControls 1.0 as StudioControls +import StudioTheme 1.0 as StudioTheme + +StudioControls.Menu { + id: root + + property var targetTexture: null + + function popupMenu(targetTexture = null) + { + this.targetTexture = targetTexture + popup() + } + + closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside + + StudioControls.MenuItem { + text: qsTr("Add image") + enabled: root.targetTexture + onTriggered: rootView.addImage(root.targetTexture) + } + + StudioControls.MenuItem { + text: qsTr("Add texture") + enabled: root.targetTexture + onTriggered: rootView.addTexture(root.targetTexture) + } + + StudioControls.MenuItem { + text: qsTr("Add scene environment") + enabled: root.targetTexture + onTriggered: rootView.addEnv(root.targetTexture) + } +} diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml new file mode 100644 index 00000000000..469a4170e20 --- /dev/null +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml @@ -0,0 +1,92 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import HelperWidgets as HelperWidgets +import StudioControls as StudioControls +import StudioTheme as StudioTheme + +HelperWidgets.ScrollView { + id: root + + clip: true + + readonly property int cellWidth: 100 + readonly property int cellHeight: 100 + + property var currMaterialItem: null + property var rootItem: null + + required property var searchBox + required property var model + + signal unimport(var bundleMat); + + function closeContextMenu() + { + ctxMenu.close() + } + + function expandVisibleSections() + { + for (let i = 0; i < categoryRepeater.count; ++i) { + let cat = categoryRepeater.itemAt(i) + if (cat.visible && !cat.expanded) + cat.expanded = true + } + } + Column { + ContentLibraryTextureContextMenu { + id: ctxMenu + + // TODO + } + + Repeater { + id: categoryRepeater + + model: root.model + + delegate: HelperWidgets.Section { + width: root.width + caption: bundleCategoryName + addTopPadding: false + sectionBackgroundColor: "transparent" + visible: bundleCategoryVisible + expanded: bundleCategoryExpanded + expandOnClick: false + onToggleExpand: bundleCategoryExpanded = !bundleCategoryExpanded + + Grid { + width: root.width + leftPadding: 5 + rightPadding: 5 + bottomPadding: 5 + spacing: 5 + columns: root.width / root.cellWidth + + Repeater { + model: bundleCategoryTextures + + delegate: ContentLibraryTexture { + width: root.cellWidth + height: root.cellHeight + + onShowContextMenu: ctxMenu.popupMenu(modelData) + } + } + } + } + } + + Text { + id: noMatchText + text: qsTr("No match found."); + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.baseFontSize + topPadding: 10 + leftPadding: 10 + visible: root.model.isEmpty && !searchBox.isEmpty() && !root.model.hasMaterialRoot + } + } +} diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/UnimportBundleMaterialDialog.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml similarity index 53% rename from share/qtcreator/qmldesigner/materialBrowserQmlSource/UnimportBundleMaterialDialog.qml rename to share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml index 82708467a8a..1c887ca317f 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/UnimportBundleMaterialDialog.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/UnimportBundleMaterialDialog.qml @@ -1,27 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 import QtQuick import QtQuick.Controls @@ -69,7 +47,7 @@ Dialog { text: qsTr("Remove") onClicked: { - materialBrowserBundleModel.removeFromProject(root.targetBundleMaterial) + materialsModel.removeFromProject(root.targetBundleMaterial) root.accept() } } diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 2b921374ae6..9edc5019769 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -19,13 +19,12 @@ Item { function closeContextMenu() { ctxMenu.close() - ctxMenuBundle.close() } // Called from C++ to refresh a preview material after it changes function refreshPreview(idx) { - var item = gridRepeater.itemAt(idx); + var item = materialRepeater.itemAt(idx); if (item) item.refreshPreview(); } @@ -44,12 +43,14 @@ Item { acceptedButtons: Qt.RightButton onClicked: (mouse) => { - // root context-menu works only for user materials - var userMatsSecBottom = mapFromItem(userMaterialsSection, 0, userMaterialsSection.y).y - + userMaterialsSection.height; + if (materialBrowserModel.hasMaterialRoot || !materialBrowserModel.hasQuick3DImport) + return; + + var matsSecBottom = mapFromItem(materialsSection, 0, materialsSection.y).y + + materialsSection.height; if (!materialBrowserModel.hasMaterialRoot && materialBrowserModel.hasQuick3DImport - && (!materialBrowserBundleModel.matBundleExists || mouse.y < userMatsSecBottom)) { + && mouse.y < matsSecBottom) { ctxMenu.popupMenu() } } @@ -63,7 +64,7 @@ Item { if (root.currMaterialItem) root.currMaterialItem.commitRename(); - root.currMaterialItem = gridRepeater.itemAt(materialBrowserModel.selectedIndex); + root.currMaterialItem = materialRepeater.itemAt(materialBrowserModel.selectedIndex); } } @@ -71,19 +72,6 @@ Item { id: ctxMenu } - MaterialBundleContextMenu { - id: ctxMenuBundle - - onUnimport: (bundleMat) => { - unimportBundleMaterialDialog.targetBundleMaterial = bundleMat - unimportBundleMaterialDialog.open() - } - } - - UnimportBundleMaterialDialog { - id: unimportBundleMaterialDialog - } - Column { id: col y: 5 @@ -100,19 +88,6 @@ Item { onSearchChanged: (searchText) => { rootView.handleSearchFilterChanged(searchText) - - // make sure searched categories that have matches are expanded - if (!materialBrowserModel.isEmpty && !userMaterialsSection.expanded) - userMaterialsSection.expanded = true - - if (!materialBrowserBundleModel.isEmpty && !bundleMaterialsSection.expanded) - bundleMaterialsSection.expanded = true - - for (let i = 0; i < bundleMaterialsSectionRepeater.count; ++i) { - let sec = bundleMaterialsSectionRepeater.itemAt(i) - if (sec.visible && !sec.expanded) - sec.expanded = true - } } } @@ -156,29 +131,28 @@ Item { height: root.height - searchBox.height clip: true visible: materialBrowserModel.hasQuick3DImport && !materialBrowserModel.hasMaterialRoot - interactive: !ctxMenu.opened && !ctxMenuBundle.opened + interactive: !ctxMenu.opened Column { Section { - id: userMaterialsSection + id: materialsSection width: root.width caption: qsTr("Materials") - hideHeader: !materialBrowserBundleModel.matBundleExists dropEnabled: true onDropEnter: (drag) => { - drag.accepted = rootView.draggedBundleMaterial - userMaterialsSection.highlight = rootView.draggedBundleMaterial + drag.accepted = drag.formats[0] === "application/vnd.qtdesignstudio.bundlematerial" + materialsSection.highlight = drag.accepted } onDropExit: { - userMaterialsSection.highlight = false + materialsSection.highlight = false } onDrop: { - userMaterialsSection.highlight = false - materialBrowserBundleModel.addToProject(rootView.draggedBundleMaterial) + materialsSection.highlight = false + rootView.acceptBundleMaterialDrop() } Grid { @@ -191,7 +165,7 @@ Item { columns: root.width / root.cellWidth Repeater { - id: gridRepeater + id: materialRepeater model: materialBrowserModel delegate: MaterialItem { @@ -226,62 +200,51 @@ Item { } Section { - id: bundleMaterialsSection + id: texturesSection width: root.width - caption: qsTr("Material Library") - addTopPadding: noMatchText.visible - visible: materialBrowserBundleModel.matBundleExists + caption: qsTr("Textures") + + Grid { + width: scrollView.width + leftPadding: 5 + rightPadding: 5 + bottomPadding: 5 + spacing: 5 + columns: root.width / root.cellWidth - Column { Repeater { - id: bundleMaterialsSectionRepeater + id: texturesRepeater - model: materialBrowserBundleModel + model: materialBrowserTexturesModel + delegate: TextureItem { + width: root.cellWidth + height: root.cellWidth - delegate: Section { - width: root.width - caption: bundleCategoryName - addTopPadding: false - sectionBackgroundColor: "transparent" - visible: bundleCategoryVisible - expanded: bundleCategoryExpanded - expandOnClick: false - onToggleExpand: bundleCategoryExpanded = !bundleCategoryExpanded - onExpand: bundleCategoryExpanded = true - onCollapse: bundleCategoryExpanded = false - - Grid { - width: scrollView.width - leftPadding: 5 - rightPadding: 5 - bottomPadding: 5 - columns: root.width / root.cellWidth - - Repeater { - model: bundleCategoryMaterials - - delegate: BundleMaterialItem { - width: root.cellWidth - height: root.cellHeight - - onShowContextMenu: { - ctxMenuBundle.popupMenu(modelData) - } - } - } + onShowContextMenu: { +// ctxMenuTexture.popupMenu(this, model) // TODO: implement textures context menu } } } + } - Text { - id: noMatchText - text: qsTr("No match found."); - color: StudioTheme.Values.themeTextColor - font.pixelSize: StudioTheme.Values.baseFontSize - leftPadding: 10 - visible: materialBrowserBundleModel.isEmpty && !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot - } + Text { + text: qsTr("No match found."); + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.baseFontSize + leftPadding: 10 + visible: materialBrowserModel.isEmpty && !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot + } + + Text { + text:qsTr("There are no texture in this project.") + visible: materialBrowserTexturesModel.isEmpty && searchBox.isEmpty() + textFormat: Text.RichText + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.mediumFontSize + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + width: root.width } } } diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml index 796bcab6ebd..25e271c1c4e 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowserContextMenu.qml @@ -1,27 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 import QtQuick import HelperWidgets diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBundleContextMenu.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBundleContextMenu.qml deleted file mode 100644 index eb698d69932..00000000000 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBundleContextMenu.qml +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -import QtQuick 2.15 -import HelperWidgets 2.0 -import StudioControls 1.0 as StudioControls -import StudioTheme 1.0 as StudioTheme - -StudioControls.Menu { - id: root - - property var targetMaterial: null - signal unimport(var bundleMat); - - function popupMenu(targetMaterial = null) - { - this.targetMaterial = targetMaterial - popup() - } - - closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside - - StudioControls.MenuItem { - text: qsTr("Apply to selected (replace)") - enabled: root.targetMaterial && materialBrowserModel.hasModelSelection - onTriggered: materialBrowserBundleModel.applyToSelected(root.targetMaterial, false) - } - - StudioControls.MenuItem { - text: qsTr("Apply to selected (add)") - enabled: root.targetMaterial && materialBrowserModel.hasModelSelection - onTriggered: materialBrowserBundleModel.applyToSelected(root.targetMaterial, true) - } - - StudioControls.MenuSeparator {} - - StudioControls.MenuItem { - enabled: !materialBrowserBundleModel.importerRunning - text: qsTr("Add an instance to project") - - onTriggered: { - materialBrowserBundleModel.addToProject(root.targetMaterial) - } - } - - StudioControls.MenuItem { - enabled: !materialBrowserBundleModel.importerRunning && root.targetMaterial.bundleMaterialImported - text: qsTr("Remove from project") - - onTriggered: root.unimport(root.targetMaterial); - } -} diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml new file mode 100644 index 00000000000..e208ed1ec52 --- /dev/null +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml @@ -0,0 +1,34 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Layouts +import QtQuickDesignerTheme +import HelperWidgets +import StudioTheme as StudioTheme + +Image { + id: root + + source: textureSource + sourceSize.width: root.width + sourceSize.height: root.height + visible: textureVisible + cache: false + + signal showContextMenu() + + MouseArea { + id: mouseArea + + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onPressed: (mouse) => { + if (mouse.button === Qt.LeftButton) + rootView.startDragTexture(modelData, mapToGlobal(mouse.x, mouse.y)) + else if (mouse.button === Qt.RightButton) + root.showContextMenu() + } + } +} diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml index 2355f33281c..536c8adc6a4 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -13,6 +13,7 @@ QtObject { property real mediumFont: 14 property real bigFont: 16 property real baseIconFont: 12 + property real mediumIconFont: 18 property real bigIconFont: 26 property real scaleFactor: 1.0 @@ -24,6 +25,7 @@ QtObject { property real bigFontSize: Math.round(values.bigFont * values.scaleFactor) property real baseIconFontSize: Math.round(values.baseIconFont * values.scaleFactor) property real myIconFontSize: values.baseIconFontSize; // TODO: rename all refs to myIconFontSize -> baseIconFontSize then remove myIconFontSize + property real mediumIconFontSize: Math.round(values.mediumIconFont * values.scaleFactor) property real bigIconFontSize: Math.round(values.bigIconFont * values.scaleFactor) property real squareComponentWidth: values.height diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index fdfde219199..279bcbf4c61 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -912,6 +912,20 @@ extend_qtc_plugin(QmlDesigner quick2propertyeditorview.cpp quick2propertyeditorview.h ) +extend_qtc_plugin(QmlDesigner + SOURCES_PREFIX components/contentlibrary + SOURCES + contentlibrarybundleimporter.cpp contentlibrarybundleimporter.h + contentlibraryview.cpp contentlibraryview.h + contentlibrarywidget.cpp contentlibrarywidget.h + contentlibrarytexturesmodel.cpp contentlibrarytexturesmodel.h + contentlibrarytexturescategory.cpp contentlibrarytexturescategory.h + contentlibrarytexture.cpp contentlibrarytexture.h + contentlibrarymaterialsmodel.cpp contentlibrarymaterialsmodel.h + contentlibrarymaterialscategory.cpp contentlibrarymaterialscategory.h + contentlibrarymaterial.cpp contentlibrarymaterial.h +) + extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/materialeditor SOURCES @@ -929,10 +943,7 @@ extend_qtc_plugin(QmlDesigner materialbrowserview.cpp materialbrowserview.h materialbrowserwidget.cpp materialbrowserwidget.h materialbrowsermodel.cpp materialbrowsermodel.h - bundleimporter.cpp bundleimporter.h - materialbrowserbundlemodel.cpp materialbrowserbundlemodel.h - bundlematerial.cpp bundlematerial.h - bundlematerialcategory.cpp bundlematerialcategory.h + materialbrowsertexturesmodel.cpp materialbrowsertexturesmodel.h ) extend_qtc_plugin(QmlDesigner diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index 44f1c2e747b..c7493a64bb6 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -448,7 +448,7 @@ void AssetsLibraryWidget::addResources(const QStringList &files) QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_RESOURCE_IMPORTED + category); if (operation) { AddFilesResult result = operation(fileNames, - document->fileName().parentDir().toString()); + document->fileName().parentDir().toString(), true); if (result == AddFilesResult::Failed) { Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), tr("Could not add %1 to project.") diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 9216635e260..bb60e2a1c9d 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -276,7 +276,7 @@ QHash DesignerActionManager::handleExternalAssetsDrop(cons for (const QString &category : categories) { AddResourceOperation operation = categoryOperation.value(category); QStringList files = categoryFiles.value(category); - AddFilesResult result = operation(files, {}); + AddFilesResult result = operation(files, {}, true); if (result == AddFilesResult::Succeeded) addedCategoryFiles.insert(category, files); } diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h index 099174865fe..928d136a02e 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.h @@ -24,20 +24,20 @@ namespace QmlDesigner { class DesignerActionManagerView; -using AddResourceOperation = std::function; -using ModelNodePreviewImageOperation = std::function; +using AddResourceOperation = std::function; +using ModelNodePreviewImageOperation = std::function; struct AddResourceHandler { public: - AddResourceHandler( const QString &_category, - const QString &_filter, - AddResourceOperation _operation, - int _priority = 0) + AddResourceHandler(const QString &_category, + const QString &_filter, + AddResourceOperation _operation, + int _priority = 0) : category(_category) - ,filter(_filter) - ,operation(_operation) - ,piority(_priority) + , filter(_filter) + , operation(_operation) + , piority(_priority) { } diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 34b257fe12c..78118e8f8bb 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -1034,9 +1034,9 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext) } -AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory); + QString directory = showDialog ? AddImagesDialog::getDirectory(fileNames, defaultDir) : defaultDir; if (directory.isEmpty()) return AddFilesResult::Cancelled; @@ -1105,29 +1105,29 @@ static QString getAssetDefaultDirectory(const QString &assetDir, const QString & return adjustedDefaultDirectory; } -AddFilesResult addFontToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addFontToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - return addFilesToProject(fileNames, getAssetDefaultDirectory("fonts", defaultDirectory)); + return addFilesToProject(fileNames, getAssetDefaultDirectory("fonts", defaultDir), showDialog); } -AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - return addFilesToProject(fileNames, getAssetDefaultDirectory("sounds", defaultDirectory)); + return addFilesToProject(fileNames, getAssetDefaultDirectory("sounds", defaultDir), showDialog); } -AddFilesResult addShaderToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addShaderToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - return addFilesToProject(fileNames, getAssetDefaultDirectory("shaders", defaultDirectory)); + return addFilesToProject(fileNames, getAssetDefaultDirectory("shaders", defaultDir), showDialog); } -AddFilesResult addImageToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addImageToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - return addFilesToProject(fileNames, getAssetDefaultDirectory("images", defaultDirectory)); + return addFilesToProject(fileNames, getAssetDefaultDirectory("images", defaultDir), showDialog); } -AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &defaultDirectory) +AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog) { - return addFilesToProject(fileNames, getAssetDefaultDirectory("videos", defaultDirectory)); + return addFilesToProject(fileNames, getAssetDefaultDirectory("videos", defaultDir), showDialog); } void createFlowActionArea(const SelectionContext &selectionContext) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h index 8156203a7ca..6ea503bc846 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h @@ -57,12 +57,12 @@ void addItemToStackedContainer(const SelectionContext &selectionContext); void increaseIndexOfStackedContainer(const SelectionContext &selectionContext); void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext); void addTabBarToStackedContainer(const SelectionContext &selectionContext); -QMLDESIGNERCORE_EXPORT AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDirectory); -AddFilesResult addImageToProject(const QStringList &fileNames, const QString &directory); -AddFilesResult addFontToProject(const QStringList &fileNames, const QString &directory); -AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &directory); -AddFilesResult addShaderToProject(const QStringList &fileNames, const QString &directory); -AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &directory); +QMLDESIGNERCORE_EXPORT AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDir, bool showDialog = true); +AddFilesResult addImageToProject(const QStringList &fileNames, const QString &directory, bool showDialog = true); +AddFilesResult addFontToProject(const QStringList &fileNames, const QString &directory, bool showDialog = true); +AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &directory, bool showDialog = true); +AddFilesResult addShaderToProject(const QStringList &fileNames, const QString &directory, bool showDialog = true); +AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &directory, bool showDialog = true); void createFlowActionArea(const SelectionContext &selectionContext); void addTransition(const SelectionContext &selectionState); void addFlowEffect(const SelectionContext &selectionState, const TypeName &typeName); diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp index fc56a37f86f..5a06b2b1e83 100644 --- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -56,6 +58,7 @@ public: ? capturingConnectionManager : connectionManager, externalDependencies) + , contentLibraryView{externalDependencies} , componentView{externalDependencies} , edit3DView{externalDependencies} , formEditorView{externalDependencies} @@ -76,6 +79,7 @@ public: Internal::DebugView debugView; DesignerActionManagerView designerActionManagerView; NodeInstanceView nodeInstanceView; + ContentLibraryView contentLibraryView; ComponentView componentView; Edit3DView edit3DView; FormEditorView formEditorView; @@ -212,6 +216,7 @@ QList ViewManager::standardViews() const &d->itemLibraryView, &d->navigatorView, &d->propertyEditorView, + &d->contentLibraryView, &d->materialEditorView, &d->materialBrowserView, &d->statesEditorView, @@ -392,6 +397,7 @@ QList ViewManager::widgetInfos() const widgetInfoList.append(d->itemLibraryView.widgetInfo()); widgetInfoList.append(d->navigatorView.widgetInfo()); widgetInfoList.append(d->propertyEditorView.widgetInfo()); + widgetInfoList.append(d->contentLibraryView.widgetInfo()); widgetInfoList.append(d->materialEditorView.widgetInfo()); widgetInfoList.append(d->materialBrowserView.widgetInfo()); if (useOldStatesEditor()) diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp similarity index 86% rename from src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp rename to src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp index 24e3d3e1108..086ce32379a 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.cpp @@ -1,29 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 -#include "bundleimporter.h" +#include "contentlibrarybundleimporter.h" #include "documentmanager.h" #include "import.h" @@ -43,17 +21,17 @@ using namespace Utils; namespace QmlDesigner::Internal { -BundleImporter::BundleImporter(const QString &bundleDir, - const QString &bundleId, - const QStringList &sharedFiles, - QObject *parent) +ContentLibraryBundleImporter::ContentLibraryBundleImporter(const QString &bundleDir, + const QString &bundleId, + const QStringList &sharedFiles, + QObject *parent) : QObject(parent) , m_bundleDir(FilePath::fromString(bundleDir)) , m_bundleId(bundleId) , m_sharedFiles(sharedFiles) { m_importTimer.setInterval(200); - connect(&m_importTimer, &QTimer::timeout, this, &BundleImporter::handleImportTimer); + connect(&m_importTimer, &QTimer::timeout, this, &ContentLibraryBundleImporter::handleImportTimer); m_moduleName = QStringLiteral("%1.%2").arg( QLatin1String(Constants::COMPONENT_BUNDLES_FOLDER), m_bundleId).mid(1); // Chop leading slash @@ -63,8 +41,8 @@ BundleImporter::BundleImporter(const QString &bundleDir, // Note that there is also an asynchronous portion to the import, which will only // be done if this method returns success. Once the asynchronous portion of the // import is completed, importFinished signal will be emitted. -QString BundleImporter::importComponent(const QString &qmlFile, - const QStringList &files) +QString ContentLibraryBundleImporter::importComponent(const QString &qmlFile, + const QStringList &files) { FilePath bundleImportPath = resolveBundleImportPath(); if (bundleImportPath.isEmpty()) @@ -171,7 +149,7 @@ QString BundleImporter::importComponent(const QString &qmlFile, return {}; } -void BundleImporter::handleImportTimer() +void ContentLibraryBundleImporter::handleImportTimer() { auto handleFailure = [this]() { m_importTimer.stop(); @@ -243,7 +221,7 @@ void BundleImporter::handleImportTimer() } } -QVariantHash BundleImporter::loadAssetRefMap(const Utils::FilePath &bundlePath) +QVariantHash ContentLibraryBundleImporter::loadAssetRefMap(const Utils::FilePath &bundlePath) { FilePath assetRefPath = bundlePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_ASSET_REF_FILE)); const std::optional content = assetRefPath.fileContents(); @@ -260,8 +238,8 @@ QVariantHash BundleImporter::loadAssetRefMap(const Utils::FilePath &bundlePath) return {}; } -void BundleImporter::writeAssetRefMap(const Utils::FilePath &bundlePath, - const QVariantHash &assetRefMap) +void ContentLibraryBundleImporter::writeAssetRefMap(const Utils::FilePath &bundlePath, + const QVariantHash &assetRefMap) { FilePath assetRefPath = bundlePath.resolvePath(QLatin1String(Constants::COMPONENT_BUNDLES_ASSET_REF_FILE)); QJsonObject jsonObj = QJsonObject::fromVariantHash(assetRefMap); @@ -271,7 +249,7 @@ void BundleImporter::writeAssetRefMap(const Utils::FilePath &bundlePath, } } -QString BundleImporter::unimportComponent(const QString &qmlFile) +QString ContentLibraryBundleImporter::unimportComponent(const QString &qmlFile) { FilePath bundleImportPath = resolveBundleImportPath(); if (bundleImportPath.isEmpty()) @@ -358,7 +336,7 @@ QString BundleImporter::unimportComponent(const QString &qmlFile) return {}; } -FilePath BundleImporter::resolveBundleImportPath() +FilePath ContentLibraryBundleImporter::resolveBundleImportPath() { FilePath bundleImportPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath(); if (bundleImportPath.isEmpty()) diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h new file mode 100644 index 00000000000..4da431319db --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarybundleimporter.h @@ -0,0 +1,57 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +#include "nodemetainfo.h" + +#include +#include + +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE + +namespace QmlDesigner::Internal { + +class ContentLibraryBundleImporter : public QObject +{ + Q_OBJECT + +public: + ContentLibraryBundleImporter(const QString &bundleDir, + const QString &bundleId, + const QStringList &sharedFiles, + QObject *parent = nullptr); + ~ContentLibraryBundleImporter() = default; + + QString importComponent(const QString &qmlFile, + const QStringList &files); + QString unimportComponent(const QString &qmlFile); + Utils::FilePath resolveBundleImportPath(); + +signals: + // The metaInfo parameter will be invalid if an error was encountered during + // asynchronous part of the import. In this case all remaining pending imports have been + // terminated, and will not receive separate importFinished notifications. + void importFinished(const QmlDesigner::NodeMetaInfo &metaInfo); + void unimportFinished(const QmlDesigner::NodeMetaInfo &metaInfo); + +private: + void handleImportTimer(); + QVariantHash loadAssetRefMap(const Utils::FilePath &bundlePath); + void writeAssetRefMap(const Utils::FilePath &bundlePath, const QVariantHash &assetRefMap); + + Utils::FilePath m_bundleDir; + QString m_bundleId; + QString m_moduleName; + QStringList m_sharedFiles; + QTimer m_importTimer; + int m_importTimerCount = 0; + bool m_importAddPending = false; + bool m_fullReset = false; + QHash m_pendingTypes; // +}; + +} // namespace QmlDesigner::Internal diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp new file mode 100644 index 00000000000..8f034d7a08d --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.cpp @@ -0,0 +1,67 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarymaterial.h" + +namespace QmlDesigner { + +ContentLibraryMaterial::ContentLibraryMaterial(QObject *parent, + const QString &name, + const QString &qml, + const TypeName &type, + const QUrl &icon, + const QStringList &files) + : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) {} + +bool ContentLibraryMaterial::filter(const QString &searchText) +{ + if (m_visible != m_name.contains(searchText, Qt::CaseInsensitive)) { + m_visible = !m_visible; + emit materialVisibleChanged(); + } + + return m_visible; +} + +QUrl ContentLibraryMaterial::icon() const +{ + return m_icon; +} + +QString ContentLibraryMaterial::qml() const +{ + return m_qml; +} + +TypeName ContentLibraryMaterial::type() const +{ + return m_type; +} + +QStringList ContentLibraryMaterial::files() const +{ + return m_files; +} + +bool ContentLibraryMaterial::visible() const +{ + return m_visible; +} + +bool ContentLibraryMaterial::setImported(bool imported) +{ + if (m_imported != imported) { + m_imported = imported; + emit materialImportedChanged(); + return true; + } + + return false; +} + +bool ContentLibraryMaterial::imported() const +{ + return m_imported; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h new file mode 100644 index 00000000000..5d156809583 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterial.h @@ -0,0 +1,57 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "qmldesignercorelib_global.h" + +#include +#include +#include + +namespace QmlDesigner { + +class ContentLibraryMaterial : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString bundleMaterialName MEMBER m_name CONSTANT) + Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT) + Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged) + Q_PROPERTY(bool bundleMaterialImported READ imported WRITE setImported NOTIFY materialImportedChanged) + +public: + ContentLibraryMaterial(QObject *parent, + const QString &name, + const QString &qml, + const TypeName &type, + const QUrl &icon, + const QStringList &files); + + bool filter(const QString &searchText); + + QUrl icon() const; + QString qml() const; + TypeName type() const; + QStringList files() const; + bool visible() const; + + bool setImported(bool imported); + bool imported() const; + +signals: + void materialVisibleChanged(); + void materialImportedChanged(); + +private: + QString m_name; + QString m_qml; + TypeName m_type; + QUrl m_icon; + QStringList m_files; + + bool m_visible = true; + bool m_imported = false; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.cpp new file mode 100644 index 00000000000..17465f6b31b --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.cpp @@ -0,0 +1,63 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarymaterialscategory.h" + +#include "contentlibrarymaterial.h" + +namespace QmlDesigner { + +ContentLibraryMaterialsCategory::ContentLibraryMaterialsCategory(QObject *parent, const QString &name) + : QObject(parent), m_name(name) {} + +void ContentLibraryMaterialsCategory::addBundleMaterial(ContentLibraryMaterial *bundleMat) +{ + m_categoryMaterials.append(bundleMat); +} + +bool ContentLibraryMaterialsCategory::updateImportedState(const QStringList &importedMats) +{ + bool changed = false; + + for (ContentLibraryMaterial *mat : std::as_const(m_categoryMaterials)) + changed |= mat->setImported(importedMats.contains(mat->qml().chopped(4))); + + return changed; +} + +bool ContentLibraryMaterialsCategory::filter(const QString &searchText) +{ + bool visible = false; + for (ContentLibraryMaterial *mat : std::as_const(m_categoryMaterials)) + visible |= mat->filter(searchText); + + if (visible != m_visible) { + m_visible = visible; + emit categoryVisibleChanged(); + return true; + } + + return false; +} + +QString ContentLibraryMaterialsCategory::name() const +{ + return m_name; +} + +bool ContentLibraryMaterialsCategory::visible() const +{ + return m_visible; +} + +bool ContentLibraryMaterialsCategory::expanded() const +{ + return m_expanded; +} + +QList ContentLibraryMaterialsCategory::categoryMaterials() const +{ + return m_categoryMaterials; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.h new file mode 100644 index 00000000000..8010270b25a --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialscategory.h @@ -0,0 +1,47 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace QmlDesigner { + +class ContentLibraryMaterial; + +class ContentLibraryMaterialsCategory : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString bundleCategoryName MEMBER m_name CONSTANT) + Q_PROPERTY(bool bundleCategoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged) + Q_PROPERTY(bool bundleCategoryExpanded MEMBER m_expanded NOTIFY categoryExpandChanged) + Q_PROPERTY(QList bundleCategoryMaterials MEMBER m_categoryMaterials + NOTIFY bundleMaterialsModelChanged) + +public: + ContentLibraryMaterialsCategory(QObject *parent, const QString &name); + + void addBundleMaterial(ContentLibraryMaterial *bundleMat); + bool updateImportedState(const QStringList &importedMats); + bool filter(const QString &searchText); + + QString name() const; + bool visible() const; + bool expanded() const; + QList categoryMaterials() const; + +signals: + void categoryVisibleChanged(); + void categoryExpandChanged(); + void bundleMaterialsModelChanged(); + +private: + QString m_name; + bool m_visible = true; + bool m_expanded = true; + + QList m_categoryMaterials; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp similarity index 64% rename from src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp rename to src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp index 7cb2a39c0d1..92be78f016b 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.cpp @@ -1,33 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 -#include "materialbrowserbundlemodel.h" +#include "contentlibrarymaterialsmodel.h" -#include "bundleimporter.h" -#include "bundlematerial.h" -#include "bundlematerialcategory.h" +#include "contentlibrarybundleimporter.h" +#include "contentlibrarymaterial.h" +#include "contentlibrarymaterialscategory.h" #include "qmldesignerconstants.h" #include "utils/qtcassert.h" @@ -38,18 +16,18 @@ namespace QmlDesigner { -MaterialBrowserBundleModel::MaterialBrowserBundleModel(QObject *parent) +ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(QObject *parent) : QAbstractListModel(parent) { loadMaterialBundle(); } -int MaterialBrowserBundleModel::rowCount(const QModelIndex &) const +int ContentLibraryMaterialsModel::rowCount(const QModelIndex &) const { return m_bundleCategories.size(); } -QVariant MaterialBrowserBundleModel::data(const QModelIndex &index, int role) const +QVariant ContentLibraryMaterialsModel::data(const QModelIndex &index, int role) const { QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {}); QTC_ASSERT(roleNames().contains(role), return {}); @@ -57,13 +35,13 @@ QVariant MaterialBrowserBundleModel::data(const QModelIndex &index, int role) co return m_bundleCategories.at(index.row())->property(roleNames().value(role)); } -bool MaterialBrowserBundleModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool ContentLibraryMaterialsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || !roleNames().contains(role)) return false; QByteArray roleName = roleNames().value(role); - BundleMaterialCategory *bundleCategory = m_bundleCategories.at(index.row()); + ContentLibraryMaterialsCategory *bundleCategory = m_bundleCategories.at(index.row()); QVariant currValue = bundleCategory->property(roleName); if (currValue != value) { @@ -76,12 +54,12 @@ bool MaterialBrowserBundleModel::setData(const QModelIndex &index, const QVarian return false; } -bool MaterialBrowserBundleModel::isValidIndex(int idx) const +bool ContentLibraryMaterialsModel::isValidIndex(int idx) const { return idx > -1 && idx < rowCount(); } -QHash MaterialBrowserBundleModel::roleNames() const +QHash ContentLibraryMaterialsModel::roleNames() const { static const QHash roles { {Qt::UserRole + 1, "bundleCategoryName"}, @@ -92,7 +70,7 @@ QHash MaterialBrowserBundleModel::roleNames() const return roles; } -void MaterialBrowserBundleModel::loadMaterialBundle() +void ContentLibraryMaterialsModel::loadMaterialBundle() { if (m_matBundleLoaded || m_probeMatBundleDir) return; @@ -137,7 +115,7 @@ void MaterialBrowserBundleModel::loadMaterialBundle() const QJsonObject catsObj = m_matBundleObj.value("categories").toObject(); const QStringList categories = catsObj.keys(); for (const QString &cat : categories) { - auto category = new BundleMaterialCategory(this, cat); + auto category = new ContentLibraryMaterialsCategory(this, cat); const QJsonObject matsObj = catsObj.value(cat).toObject(); const QStringList mats = matsObj.keys(); @@ -156,7 +134,7 @@ void MaterialBrowserBundleModel::loadMaterialBundle() bundleId, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml - auto bundleMat = new BundleMaterial(category, mat, qml, type, icon, files); + auto bundleMat = new ContentLibraryMaterial(category, mat, qml, type, icon, files); category->addBundleMaterial(bundleMat); } @@ -168,15 +146,17 @@ void MaterialBrowserBundleModel::loadMaterialBundle() for (const auto /*QJson{Const,}ValueRef*/ &file : sharedFilesArr) sharedFiles.append(file.toString()); - m_importer = new Internal::BundleImporter(matBundleDir.path(), bundleId, sharedFiles); - connect(m_importer, &Internal::BundleImporter::importFinished, this, [&](const QmlDesigner::NodeMetaInfo &metaInfo) { + m_importer = new Internal::ContentLibraryBundleImporter(matBundleDir.path(), bundleId, sharedFiles); + connect(m_importer, &Internal::ContentLibraryBundleImporter::importFinished, this, + [&](const QmlDesigner::NodeMetaInfo &metaInfo) { m_importerRunning = false; emit importerRunningChanged(); if (metaInfo.isValid()) emit bundleMaterialImported(metaInfo); }); - connect(m_importer, &Internal::BundleImporter::unimportFinished, this, [&](const QmlDesigner::NodeMetaInfo &metaInfo) { + connect(m_importer, &Internal::ContentLibraryBundleImporter::unimportFinished, this, + [&](const QmlDesigner::NodeMetaInfo &metaInfo) { Q_UNUSED(metaInfo) m_importerRunning = false; emit importerRunningChanged(); @@ -184,12 +164,26 @@ void MaterialBrowserBundleModel::loadMaterialBundle() }); } -bool MaterialBrowserBundleModel::hasMaterialRoot() const +bool ContentLibraryMaterialsModel::hasQuick3DImport() const +{ + return m_hasQuick3DImport; +} + +void ContentLibraryMaterialsModel::setHasQuick3DImport(bool b) +{ + if (b == m_hasQuick3DImport) + return; + + m_hasQuick3DImport = b; + emit hasQuick3DImportChanged(); +} + +bool ContentLibraryMaterialsModel::hasMaterialRoot() const { return m_hasMaterialRoot; } -void MaterialBrowserBundleModel::setHasMaterialRoot(bool b) +void ContentLibraryMaterialsModel::setHasMaterialRoot(bool b) { if (m_hasMaterialRoot == b) return; @@ -198,17 +192,17 @@ void MaterialBrowserBundleModel::setHasMaterialRoot(bool b) emit hasMaterialRootChanged(); } -bool MaterialBrowserBundleModel::matBundleExists() const +bool ContentLibraryMaterialsModel::matBundleExists() const { return m_matBundleLoaded && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3; } -Internal::BundleImporter *MaterialBrowserBundleModel::bundleImporter() const +Internal::ContentLibraryBundleImporter *ContentLibraryMaterialsModel::bundleImporter() const { return m_importer; } -void MaterialBrowserBundleModel::setSearchText(const QString &searchText) +void ContentLibraryMaterialsModel::setSearchText(const QString &searchText) { QString lowerSearchText = searchText.toLower(); @@ -220,7 +214,7 @@ void MaterialBrowserBundleModel::setSearchText(const QString &searchText) bool anyCatVisible = false; bool catVisibilityChanged = false; - for (BundleMaterialCategory *cat : std::as_const(m_bundleCategories)) { + for (ContentLibraryMaterialsCategory *cat : std::as_const(m_bundleCategories)) { catVisibilityChanged |= cat->filter(m_searchText); anyCatVisible |= cat->visible(); } @@ -234,17 +228,17 @@ void MaterialBrowserBundleModel::setSearchText(const QString &searchText) resetModel(); } -void MaterialBrowserBundleModel::updateImportedState(const QStringList &importedMats) +void ContentLibraryMaterialsModel::updateImportedState(const QStringList &importedMats) { bool changed = false; - for (BundleMaterialCategory *cat : std::as_const(m_bundleCategories)) + for (ContentLibraryMaterialsCategory *cat : std::as_const(m_bundleCategories)) changed |= cat->updateImportedState(importedMats); if (changed) resetModel(); } -void MaterialBrowserBundleModel::setQuick3DImportVersion(int major, int minor) +void ContentLibraryMaterialsModel::setQuick3DImportVersion(int major, int minor) { bool bundleExisted = matBundleExists(); @@ -255,18 +249,18 @@ void MaterialBrowserBundleModel::setQuick3DImportVersion(int major, int minor) emit matBundleExistsChanged(); } -void MaterialBrowserBundleModel::resetModel() +void ContentLibraryMaterialsModel::resetModel() { beginResetModel(); endResetModel(); } -void MaterialBrowserBundleModel::applyToSelected(BundleMaterial *mat, bool add) +void ContentLibraryMaterialsModel::applyToSelected(ContentLibraryMaterial *mat, bool add) { emit applyToSelectedTriggered(mat, add); } -void MaterialBrowserBundleModel::addToProject(BundleMaterial *mat) +void ContentLibraryMaterialsModel::addToProject(ContentLibraryMaterial *mat) { QString err = m_importer->importComponent(mat->qml(), mat->files()); @@ -278,7 +272,7 @@ void MaterialBrowserBundleModel::addToProject(BundleMaterial *mat) } } -void MaterialBrowserBundleModel::removeFromProject(BundleMaterial *mat) +void ContentLibraryMaterialsModel::removeFromProject(ContentLibraryMaterial *mat) { emit bundleMaterialAboutToUnimport(mat->type()); @@ -292,4 +286,18 @@ void MaterialBrowserBundleModel::removeFromProject(BundleMaterial *mat) } } +bool ContentLibraryMaterialsModel::hasModelSelection() const +{ + return m_hasModelSelection; +} + +void ContentLibraryMaterialsModel::setHasModelSelection(bool b) +{ + if (b == m_hasModelSelection) + return; + + m_hasModelSelection = b; + emit hasModelSelectionChanged(); +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h similarity index 50% rename from src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.h rename to src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h index beb445422e7..9fe76cd25df 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserbundlemodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarymaterialsmodel.h @@ -1,58 +1,35 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #pragma once -#include -#include +#include "nodemetainfo.h" #include #include -#include -#include namespace QmlDesigner { -class BundleMaterial; -class BundleMaterialCategory; +class ContentLibraryMaterial; +class ContentLibraryMaterialsCategory; namespace Internal { -class BundleImporter; +class ContentLibraryBundleImporter; } -class MaterialBrowserBundleModel : public QAbstractListModel +class ContentLibraryMaterialsModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) + Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) + Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged) Q_PROPERTY(bool importerRunning MEMBER m_importerRunning NOTIFY importerRunningChanged) public: - MaterialBrowserBundleModel(QObject *parent = nullptr); + ContentLibraryMaterialsModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; @@ -64,25 +41,32 @@ public: void setQuick3DImportVersion(int major, int minor); + bool hasQuick3DImport() const; + void setHasQuick3DImport(bool b); + bool hasMaterialRoot() const; void setHasMaterialRoot(bool b); bool matBundleExists() const; - Internal::BundleImporter *bundleImporter() const; + bool hasModelSelection() const; + void setHasModelSelection(bool b); void resetModel(); - Q_INVOKABLE void applyToSelected(QmlDesigner::BundleMaterial *mat, bool add = false); - Q_INVOKABLE void addToProject(QmlDesigner::BundleMaterial *mat); - Q_INVOKABLE void removeFromProject(QmlDesigner::BundleMaterial *mat); + Internal::ContentLibraryBundleImporter *bundleImporter() const; + + Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); + Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat); + Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat); signals: void isEmptyChanged(); void hasQuick3DImportChanged(); + void hasModelSelectionChanged(); void hasMaterialRootChanged(); void materialVisibleChanged(); - void applyToSelectedTriggered(QmlDesigner::BundleMaterial *mat, bool add = false); + void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); void bundleMaterialImported(const QmlDesigner::NodeMetaInfo &metaInfo); void bundleMaterialAboutToUnimport(const QmlDesigner::TypeName &type); void bundleMaterialUnimported(const QmlDesigner::NodeMetaInfo &metaInfo); @@ -94,13 +78,15 @@ private: bool isValidIndex(int idx) const; QString m_searchText; - QList m_bundleCategories; + QList m_bundleCategories; QJsonObject m_matBundleObj; - Internal::BundleImporter *m_importer = nullptr; + Internal::ContentLibraryBundleImporter *m_importer = nullptr; bool m_isEmpty = true; bool m_hasMaterialRoot = false; + bool m_hasQuick3DImport = false; bool m_matBundleLoaded = false; + bool m_hasModelSelection = false; bool m_probeMatBundleDir = false; bool m_importerRunning = false; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp new file mode 100644 index 00000000000..288e04aaff6 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarytexture.h" + +namespace QmlDesigner { + +ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QString &path, const QUrl &icon) + : QObject(parent) + , m_path(path) + , m_icon(icon) {} + +bool ContentLibraryTexture::filter(const QString &searchText) +{ + if (m_visible != m_path.contains(searchText, Qt::CaseInsensitive)) { + m_visible = !m_visible; + emit textureVisibleChanged(); + } + + return m_visible; +} + +QUrl ContentLibraryTexture::icon() const +{ + return m_icon; +} + +QString ContentLibraryTexture::path() const +{ + return m_path; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h new file mode 100644 index 00000000000..88d50158325 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexture.h @@ -0,0 +1,37 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include +#include + +namespace QmlDesigner { + +class ContentLibraryTexture : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString texturePath MEMBER m_path CONSTANT) + Q_PROPERTY(QUrl textureIcon MEMBER m_icon CONSTANT) + Q_PROPERTY(bool textureVisible MEMBER m_visible NOTIFY textureVisibleChanged) + +public: + ContentLibraryTexture(QObject *parent, const QString &path, const QUrl &icon); + + bool filter(const QString &searchText); + + QUrl icon() const; + QString path() const; + +signals: + void textureVisibleChanged(); + +private: + QString m_path; + QUrl m_icon; + + bool m_visible = true; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp new file mode 100644 index 00000000000..56468364e67 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarytexturescategory.h" + +#include "contentlibrarytexture.h" + +#include + +namespace QmlDesigner { + +ContentLibraryTexturesCategory::ContentLibraryTexturesCategory(QObject *parent, const QString &name) + : QObject(parent), m_name(name) {} + +void ContentLibraryTexturesCategory::addTexture(const QFileInfo &tex) +{ + QUrl icon = QUrl::fromLocalFile(tex.path() + "/icon/" + tex.baseName() + ".png"); + m_categoryTextures.append(new ContentLibraryTexture(this, tex.filePath(), icon)); +} + +bool ContentLibraryTexturesCategory::filter(const QString &searchText) +{ + bool visible = false; + for (ContentLibraryTexture *tex : std::as_const(m_categoryTextures)) + visible |= tex->filter(searchText); + + if (visible != m_visible) { + m_visible = visible; + emit categoryVisibleChanged(); + return true; + } + + return false; +} + +QString ContentLibraryTexturesCategory::name() const +{ + return m_name; +} + +bool ContentLibraryTexturesCategory::visible() const +{ + return m_visible; +} + +bool ContentLibraryTexturesCategory::expanded() const +{ + return m_expanded; +} + +QList ContentLibraryTexturesCategory::categoryTextures() const +{ + return m_categoryTextures; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h new file mode 100644 index 00000000000..1e0055d28cd --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturescategory.h @@ -0,0 +1,50 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +class QFileInfo; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class ContentLibraryTexture; + +class ContentLibraryTexturesCategory : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString bundleCategoryName MEMBER m_name CONSTANT) + Q_PROPERTY(bool bundleCategoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged) + Q_PROPERTY(bool bundleCategoryExpanded MEMBER m_expanded NOTIFY categoryExpandChanged) + Q_PROPERTY(QList bundleCategoryTextures MEMBER m_categoryTextures + NOTIFY bundleTexturesModelChanged) + +public: + ContentLibraryTexturesCategory(QObject *parent, const QString &name); + + void addTexture(const QFileInfo &tex); + bool filter(const QString &searchText); + + QString name() const; + bool visible() const; + bool expanded() const; + QList categoryTextures() const; + +signals: + void categoryVisibleChanged(); + void categoryExpandChanged(); + void bundleTexturesModelChanged(); + +private: + QString m_name; + bool m_visible = true; + bool m_expanded = true; + + QList m_categoryTextures; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp new file mode 100644 index 00000000000..38c9522879b --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp @@ -0,0 +1,185 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarytexturesmodel.h" + +#include "contentlibrarytexturescategory.h" +#include "utils/qtcassert.h" + +#include +#include +#include +#include + +namespace QmlDesigner { + +ContentLibraryTexturesModel::ContentLibraryTexturesModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int ContentLibraryTexturesModel::rowCount(const QModelIndex &) const +{ + return m_bundleCategories.size(); +} + +QVariant ContentLibraryTexturesModel::data(const QModelIndex &index, int role) const +{ + QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {}); + QTC_ASSERT(roleNames().contains(role), return {}); + + return m_bundleCategories.at(index.row())->property(roleNames().value(role)); +} + +bool ContentLibraryTexturesModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || !roleNames().contains(role)) + return false; + + QByteArray roleName = roleNames().value(role); + ContentLibraryTexturesCategory *bundleCategory = m_bundleCategories.at(index.row()); + QVariant currValue = bundleCategory->property(roleName); + + if (currValue != value) { + bundleCategory->setProperty(roleName, value); + + emit dataChanged(index, index, {role}); + return true; + } + + return false; +} + +bool ContentLibraryTexturesModel::isValidIndex(int idx) const +{ + return idx > -1 && idx < rowCount(); +} + +QHash ContentLibraryTexturesModel::roleNames() const +{ + static const QHash roles { + {Qt::UserRole + 1, "bundleCategoryName"}, + {Qt::UserRole + 2, "bundleCategoryVisible"}, + {Qt::UserRole + 3, "bundleCategoryExpanded"}, + {Qt::UserRole + 4, "bundleCategoryTextures"} + }; + return roles; +} + +void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath) +{ + QDir bundleDir = QDir(bundlePath); + if (!bundleDir.exists()) { + qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundlePath; + return; + } + + if (m_texBundleLoaded) + return; + + const QFileInfoList dirs = bundleDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QFileInfo &dir : dirs) { + auto category = new ContentLibraryTexturesCategory(this, dir.fileName()); + const QFileInfoList texFiles = QDir(dir.filePath()).entryInfoList(QDir::Files); + for (const QFileInfo &tex : texFiles) + category->addTexture(tex); + m_bundleCategories.append(category); + } +} + +bool ContentLibraryTexturesModel::hasQuick3DImport() const +{ + return m_hasQuick3DImport; +} + +void ContentLibraryTexturesModel::setHasQuick3DImport(bool b) +{ + if (b == m_hasQuick3DImport) + return; + + m_hasQuick3DImport = b; + emit hasQuick3DImportChanged(); +} + +bool ContentLibraryTexturesModel::hasMaterialRoot() const +{ + return m_hasMaterialRoot; +} + +void ContentLibraryTexturesModel::setHasMaterialRoot(bool b) +{ + if (m_hasMaterialRoot == b) + return; + + m_hasMaterialRoot = b; + emit hasMaterialRootChanged(); +} + +bool ContentLibraryTexturesModel::matBundleExists() const +{ + return m_texBundleLoaded && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3; +} + +void ContentLibraryTexturesModel::setSearchText(const QString &searchText) +{ + QString lowerSearchText = searchText.toLower(); + + if (m_searchText == lowerSearchText) + return; + + m_searchText = lowerSearchText; + + bool anyCatVisible = false; + bool catVisibilityChanged = false; + + for (ContentLibraryTexturesCategory *cat : std::as_const(m_bundleCategories)) { + catVisibilityChanged |= cat->filter(m_searchText); + anyCatVisible |= cat->visible(); + } + + if (anyCatVisible == m_isEmpty) { + m_isEmpty = !anyCatVisible; + emit isEmptyChanged(); + } + + if (catVisibilityChanged) + resetModel(); +} + +void ContentLibraryTexturesModel::setQuick3DImportVersion(int major, int minor) +{ + bool bundleExisted = matBundleExists(); + + m_quick3dMajorVersion = major; + m_quick3dMinorVersion = minor; + + if (bundleExisted != matBundleExists()) + emit matBundleExistsChanged(); +} + +void ContentLibraryTexturesModel::resetModel() +{ + beginResetModel(); + endResetModel(); +} + +void ContentLibraryTexturesModel::addToProject(const QString &mat) +{ + // TODO: import asset +} + +bool ContentLibraryTexturesModel::hasModelSelection() const +{ + return m_hasModelSelection; +} + +void ContentLibraryTexturesModel::setHasModelSelection(bool b) +{ + if (b == m_hasModelSelection) + return; + + m_hasModelSelection = b; + emit hasModelSelectionChanged(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h new file mode 100644 index 00000000000..8009dd3ff80 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h @@ -0,0 +1,74 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace QmlDesigner { + +class ContentLibraryTexturesCategory; + +class ContentLibraryTexturesModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) + Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) + Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) + Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) + Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged) + +public: + ContentLibraryTexturesModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + QHash roleNames() const override; + + void setSearchText(const QString &searchText); + + void setQuick3DImportVersion(int major, int minor); + + bool hasQuick3DImport() const; + void setHasQuick3DImport(bool b); + + bool hasMaterialRoot() const; + void setHasMaterialRoot(bool b); + + bool matBundleExists() const; + + bool hasModelSelection() const; + void setHasModelSelection(bool b); + + void resetModel(); + void loadTextureBundle(const QString &bundlePath); + + Q_INVOKABLE void addToProject(const QString &mat); + +signals: + void isEmptyChanged(); + void hasQuick3DImportChanged(); + void hasModelSelectionChanged(); + void hasMaterialRootChanged(); + void materialVisibleChanged(); + void matBundleExistsChanged(); + +private: + bool isValidIndex(int idx) const; + + QString m_searchText; + QList m_bundleCategories; + + bool m_isEmpty = true; + bool m_hasMaterialRoot = false; + bool m_hasQuick3DImport = false; + bool m_texBundleLoaded = false; + bool m_hasModelSelection = false; + + int m_quick3dMajorVersion = -1; + int m_quick3dMinorVersion = -1; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp new file mode 100644 index 00000000000..fe035cee345 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -0,0 +1,354 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibraryview.h" + +#include "contentlibrarybundleimporter.h" +#include "contentlibrarywidget.h" +#include "contentlibrarymaterial.h" +#include "contentlibrarymaterialsmodel.h" +#include "modelnodeoperations.h" +#include "nodelistproperty.h" +#include "qmlobjectnode.h" +#include "variantproperty.h" + +#include +#include + +#ifndef QMLDESIGNER_TEST +#include +#include +#include +#include +#include +#endif + +namespace QmlDesigner { + +ContentLibraryView::ContentLibraryView(ExternalDependenciesInterface &externalDependencies) + : AbstractView(externalDependencies) +{} + +ContentLibraryView::~ContentLibraryView() +{} + +bool ContentLibraryView::hasWidget() const +{ + return true; +} + +WidgetInfo ContentLibraryView::widgetInfo() +{ + if (m_widget.isNull()) { + m_widget = new ContentLibraryWidget(); + + connect(m_widget, &ContentLibraryWidget::bundleMaterialDragStarted, this, + [&] (QmlDesigner::ContentLibraryMaterial *mat) { + m_draggedBundleMaterial = mat; + }); + connect(m_widget, &ContentLibraryWidget::addTextureRequested, this, + [&] (const QString texPath, ContentLibraryWidget::AddTextureMode mode) { + AddFilesResult result = ModelNodeOperations::addImageToProject({texPath}, "images", false); + + if (result == AddFilesResult::Failed) { + Core::AsynchronousMessageBox::warning(tr("Failed to Add Texture"), + tr("Could not add %1 to project.").arg(texPath)); + return; + } + + if (mode == ContentLibraryWidget::AddTextureMode::Texture) { + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return; + + NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.Texture"); + ModelNode newTexNode = createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), + metaInfo.minorVersion()); + newTexNode.validId(); + VariantProperty sourceProp = newTexNode.variantProperty("source"); + sourceProp.setValue(QLatin1String("images/%1").arg(texPath.split('/').last())); + matLib.defaultNodeListProperty().reparentHere(newTexNode); + } else if (mode == ContentLibraryWidget::AddTextureMode::Environment) { + // TODO: assign as env + } + }); + + ContentLibraryMaterialsModel *materialsModel = m_widget->materialsModel().data(); + + connect(materialsModel, &ContentLibraryMaterialsModel::applyToSelectedTriggered, this, + [&] (ContentLibraryMaterial *bundleMat, bool add) { + if (m_selectedModels.isEmpty()) + return; + + m_bundleMaterialTargets = m_selectedModels; + m_bundleMaterialAddToSelected = add; + + ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); + if (defaultMat.isValid()) + applyBundleMaterialToDropTarget(defaultMat); + else + m_widget->materialsModel()->addToProject(bundleMat); + }); + + connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialImported, this, + [&] (const QmlDesigner::NodeMetaInfo &metaInfo) { + applyBundleMaterialToDropTarget({}, metaInfo); + updateBundleMaterialsImportedState(); + }); + + connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialAboutToUnimport, this, + [&] (const QmlDesigner::TypeName &type) { + // delete instances of the bundle material that is about to be unimported + executeInTransaction("MaterialBrowserView::widgetInfo", [&] { + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return; + + Utils::reverseForeach(matLib.directSubModelNodes(), [&](const ModelNode &mat) { + if (mat.isValid() && mat.type() == type) + QmlObjectNode(mat).destroy(); + }); + }); + }); + + connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialUnimported, this, + &ContentLibraryView::updateBundleMaterialsImportedState); + } + + return createWidgetInfo(m_widget.data(), + "ContentLibrary", + WidgetInfo::LeftPane, + 0, + tr("Content Library")); +} + +void ContentLibraryView::modelAttached(Model *model) +{ + AbstractView::modelAttached(model); + + m_hasQuick3DImport = model->hasImport("QtQuick3D"); + + m_widget->materialsModel()->setHasMaterialRoot(rootModelNode().metaInfo().isQtQuick3DMaterial()); + m_widget->materialsModel()->setHasQuick3DImport(m_hasQuick3DImport); + + updateBundleMaterialsQuick3DVersion(); + updateBundleMaterialsImportedState(); +} + +void ContentLibraryView::modelAboutToBeDetached(Model *model) +{ + + AbstractView::modelAboutToBeDetached(model); +} + +void ContentLibraryView::importsChanged(const QList &addedImports, const QList &removedImports) +{ + Q_UNUSED(addedImports) + Q_UNUSED(removedImports) + + updateBundleMaterialsQuick3DVersion(); + + bool hasQuick3DImport = model()->hasImport("QtQuick3D"); + + if (hasQuick3DImport == m_hasQuick3DImport) + return; + + m_hasQuick3DImport = hasQuick3DImport; + m_widget->materialsModel()->setHasQuick3DImport(m_hasQuick3DImport); +} + +void ContentLibraryView::selectedNodesChanged(const QList &selectedNodeList, + const QList &lastSelectedNodeList) +{ + Q_UNUSED(lastSelectedNodeList) + + m_selectedModels = Utils::filtered(selectedNodeList, [](const ModelNode &node) { + return node.metaInfo().isQtQuick3DModel(); + }); + + m_widget->materialsModel()->setHasModelSelection(!m_selectedModels.isEmpty()); +} + +void ContentLibraryView::customNotification(const AbstractView *view, const QString &identifier, + const QList &nodeList, const QList &data) +{ + Q_UNUSED(data) + + if (view == this) + return; + + if (identifier == "drop_bundle_material") { + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return; + + m_bundleMaterialTargets = nodeList; + + ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type()); + if (defaultMat.isValid()) { + if (m_bundleMaterialTargets.isEmpty()) // if no drop target, create a duplicate material + createMaterial(defaultMat.metaInfo()); + else + applyBundleMaterialToDropTarget(defaultMat); + } else { + m_widget->materialsModel()->addToProject(m_draggedBundleMaterial); + } + + m_draggedBundleMaterial = nullptr; + } +} + +void ContentLibraryView::applyBundleMaterialToDropTarget(const ModelNode &bundleMat, + const NodeMetaInfo &metaInfo) +{ + if (!bundleMat.isValid() && !metaInfo.isValid()) + return; + + executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] { + ModelNode newMatNode = metaInfo.isValid() ? createMaterial(metaInfo) : bundleMat; + + // TODO: unify this logic as it exist elsewhere also + auto expToList = [](const QString &exp) { + QString copy = exp; + copy = copy.remove("[").remove("]"); + + QStringList tmp = copy.split(',', Qt::SkipEmptyParts); + for (QString &str : tmp) + str = str.trimmed(); + + return tmp; + }; + + auto listToExp = [](QStringList &stringList) { + if (stringList.size() > 1) + return QString("[" + stringList.join(",") + "]"); + + if (stringList.size() == 1) + return stringList.first(); + + return QString(); + }; + + for (const ModelNode &target : std::as_const(m_bundleMaterialTargets)) { + if (target.isValid() && target.metaInfo().isQtQuick3DModel()) { + QmlObjectNode qmlObjNode(target); + if (m_bundleMaterialAddToSelected) { + QStringList matList = expToList(qmlObjNode.expression("materials")); + matList.append(newMatNode.id()); + QString updatedExp = listToExp(matList); + qmlObjNode.setBindingProperty("materials", updatedExp); + } else { + qmlObjNode.setBindingProperty("materials", newMatNode.id()); + } + } + + m_bundleMaterialTargets = {}; + m_bundleMaterialAddToSelected = false; + } + }); +} + +ModelNode ContentLibraryView::getBundleMaterialDefaultInstance(const TypeName &type) +{ + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return {}; + + const QList matLibNodes = matLib.directSubModelNodes(); + for (const ModelNode &mat : matLibNodes) { + if (mat.isValid() && mat.type() == type) { + bool isDefault = true; + const QList props = mat.properties(); + for (const AbstractProperty &prop : props) { + if (prop.name() != "objectName") { + isDefault = false; + break; + } + } + + if (isDefault) + return mat; + } + } + + return {}; +} + +ModelNode ContentLibraryView::createMaterial(const NodeMetaInfo &metaInfo) +{ + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid() || !metaInfo.isValid()) + return {}; + + ModelNode newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(), + metaInfo.minorVersion()); + matLib.defaultNodeListProperty().reparentHere(newMatNode); + + static QRegularExpression rgx("([A-Z])([a-z]*)"); + QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed(); + if (newName.endsWith(" Material")) + newName.chop(9); // remove trailing " Material" + QString newId = model()->generateIdFromName(newName, "material"); + newMatNode.setIdWithRefactoring(newId); + + VariantProperty objNameProp = newMatNode.variantProperty("objectName"); + objNameProp.setValue(newName); + + return newMatNode; +} + +void ContentLibraryView::updateBundleMaterialsImportedState() +{ + using namespace Utils; + + if (!m_widget->materialsModel()->bundleImporter()) + return; + + QStringList importedBundleMats; + + FilePath materialBundlePath = m_widget->materialsModel()->bundleImporter()->resolveBundleImportPath(); + + if (materialBundlePath.exists()) { + importedBundleMats = transform(materialBundlePath.dirEntries({{"*.qml"}, QDir::Files}), + [](const FilePath &f) { return f.fileName().chopped(4); }); + } + + m_widget->materialsModel()->updateImportedState(importedBundleMats); +} + +void ContentLibraryView::updateBundleMaterialsQuick3DVersion() +{ + bool hasImport = false; + int major = -1; + int minor = -1; + const QString url {"QtQuick3D"}; + const auto imports = model()->imports(); + for (const auto &import : imports) { + if (import.url() == url) { + hasImport = true; + const int importMajor = import.majorVersion(); + if (major < importMajor) { + minor = -1; + major = importMajor; + } + if (major == importMajor) + minor = qMax(minor, import.minorVersion()); + } + } +#ifndef QMLDESIGNER_TEST + if (hasImport && major == -1) { + // Import without specifying version, so we take the kit version + auto target = ProjectExplorer::SessionManager::startupTarget(); + if (target) { + QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target->kit()); + if (qtVersion) { + major = qtVersion->qtVersion().majorVersion(); + minor = qtVersion->qtVersion().minorVersion(); + } + } + } +#endif + m_widget->materialsModel()->setQuick3DImportVersion(major, minor); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h new file mode 100644 index 00000000000..8ece6a76d05 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h @@ -0,0 +1,53 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "abstractview.h" +#include "nodemetainfo.h" + +#include +#include + +namespace QmlDesigner { + +class ContentLibraryMaterial; +class ContentLibraryWidget; +class Model; + +class ContentLibraryView : public AbstractView +{ + Q_OBJECT + +public: + ContentLibraryView(ExternalDependenciesInterface &externalDependencies); + ~ContentLibraryView() override; + + bool hasWidget() const override; + WidgetInfo widgetInfo() override; + + // AbstractView + void modelAttached(Model *model) override; + void modelAboutToBeDetached(Model *model) override; + void importsChanged(const QList &addedImports, const QList &removedImports) override; + void selectedNodesChanged(const QList &selectedNodeList, + const QList &lastSelectedNodeList) override; + void customNotification(const AbstractView *view, const QString &identifier, + const QList &nodeList, const QList &data) override; + +private: + void updateBundleMaterialsImportedState(); + void updateBundleMaterialsQuick3DVersion(); + void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {}); + ModelNode getBundleMaterialDefaultInstance(const TypeName &type); + ModelNode createMaterial(const NodeMetaInfo &metaInfo); + + QPointer m_widget; + QList m_bundleMaterialTargets; + QList m_selectedModels; // selected 3D model nodes + ContentLibraryMaterial *m_draggedBundleMaterial = nullptr; + bool m_bundleMaterialAddToSelected = false; + bool m_hasQuick3DImport = false; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp new file mode 100644 index 00000000000..02d116811eb --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -0,0 +1,238 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "contentlibrarywidget.h" + +#include "contentlibrarymaterial.h" +#include "contentlibrarymaterialsmodel.h" +#include "contentlibrarytexture.h" +#include "contentlibrarytexturesmodel.h" + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +static QString propertyEditorResourcesPath() +{ +#ifdef SHARE_QML_PATH + if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) + return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources"; +#endif + return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString(); +} + +bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::FocusOut) { + if (obj == m_quickWidget.data()) + QMetaObject::invokeMethod(m_quickWidget->rootObject(), "closeContextMenu"); + } else if (event->type() == QMouseEvent::MouseMove) { + DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); + QTC_ASSERT(document, return false); + Model *model = document->currentModel(); + QTC_ASSERT(model, return false); + + if (m_materialToDrag) { + QMouseEvent *me = static_cast(event); + if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { + QByteArray data; + QMimeData *mimeData = new QMimeData; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << m_materialToDrag->type(); + mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, data); + mimeData->removeFormat("text/plain"); + + if (!m_draggedMaterial) { + m_draggedMaterial = m_materialToDrag; + emit draggedMaterialChanged(); + } + + emit bundleMaterialDragStarted(m_materialToDrag); + model->startDrag(mimeData, m_materialToDrag->icon().toLocalFile()); + m_materialToDrag = nullptr; + } + } else if (m_textureToDrag) { + QMouseEvent *me = static_cast(event); + if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { + QByteArray data; + QMimeData *mimeData = new QMimeData; + QDataStream stream(&data, QIODevice::WriteOnly); + stream << m_textureToDrag->path(); + mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE, data); + mimeData->removeFormat("text/plain"); + + model->startDrag(mimeData, m_textureToDrag->icon().toLocalFile()); + m_textureToDrag = nullptr; + } + } + } else if (event->type() == QMouseEvent::MouseButtonRelease) { + m_materialToDrag = nullptr; + m_textureToDrag = nullptr; + + if (m_draggedMaterial) { + m_draggedMaterial = nullptr; + emit draggedMaterialChanged(); + } + } + + return QObject::eventFilter(obj, event); +} + +ContentLibraryWidget::ContentLibraryWidget() + : m_quickWidget(new QQuickWidget(this)) + , m_materialsModel(new ContentLibraryMaterialsModel(this)) + , m_texturesModel(new ContentLibraryTexturesModel(this)) + , m_environmentsModel(new ContentLibraryTexturesModel(this)) +{ + setWindowTitle(tr("Content Library", "Title of content library widget")); + setMinimumWidth(120); + + m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); + m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); + m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); + + QString textureBundlePath = findTextureBundlePath(); + m_texturesModel->loadTextureBundle(textureBundlePath + "/Textures"); + m_environmentsModel->loadTextureBundle(textureBundlePath + "/Environments"); + + m_quickWidget->rootContext()->setContextProperties({ + {"rootView", QVariant::fromValue(this)}, + {"materialsModel", QVariant::fromValue(m_materialsModel.data())}, + {"texturesModel", QVariant::fromValue(m_texturesModel.data())}, + {"environmentsModel", QVariant::fromValue(m_environmentsModel.data())}, + }); + + Theme::setupTheme(m_quickWidget->engine()); + m_quickWidget->installEventFilter(this); + + auto layout = new QVBoxLayout(this); + layout->setContentsMargins({}); + layout->setSpacing(0); + layout->addWidget(m_quickWidget.data()); + + updateSearch(); + + setStyleSheet(Theme::replaceCssColors( + QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css")))); + + m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F11), this); + connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ContentLibraryWidget::reloadQmlSource); + +// QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_MATERIALBROWSER_TIME); // TODO + + reloadQmlSource(); +} + +QList ContentLibraryWidget::createToolBarWidgets() +{ + return {}; +} + +void ContentLibraryWidget::handleSearchFilterChanged(const QString &filterText) +{ + if (filterText != m_filterText) { + m_filterText = filterText; + updateSearch(); + } +} + +QString ContentLibraryWidget::qmlSourcesPath() +{ +#ifdef SHARE_QML_PATH + if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE")) + return QLatin1String(SHARE_QML_PATH) + "/contentLibraryQmlSource"; +#endif + return Core::ICore::resourcePath("qmldesigner/contentLibraryQmlSource").toString(); +} + +void ContentLibraryWidget::clearSearchFilter() +{ + QMetaObject::invokeMethod(m_quickWidget->rootObject(), "clearSearchFilter"); +} + +void ContentLibraryWidget::reloadQmlSource() +{ + const QString materialBrowserQmlPath = qmlSourcesPath() + "/ContentLibrary.qml"; + + QTC_ASSERT(QFileInfo::exists(materialBrowserQmlPath), return); + + m_quickWidget->engine()->clearComponentCache(); + m_quickWidget->setSource(QUrl::fromLocalFile(materialBrowserQmlPath)); +} + +void ContentLibraryWidget::updateSearch() +{ + m_materialsModel->setSearchText(m_filterText); + m_texturesModel->setSearchText(m_filterText); + m_environmentsModel->setSearchText(m_filterText); + m_quickWidget->update(); +} + +QString ContentLibraryWidget::findTextureBundlePath() +{ + QDir texBundleDir(qEnvironmentVariable("TEXTURE_BUNDLE_PATH")); + + // search for matBundleDir from exec dir and up + if (texBundleDir.dirName() == ".") { + texBundleDir.setPath(QCoreApplication::applicationDirPath()); + while (!texBundleDir.cd("texture_bundle") && texBundleDir.cdUp()) + ; // do nothing + + if (texBundleDir.dirName() != "texture_bundle") // bundlePathDir not found + return {}; + } + + return texBundleDir.path(); +} + +void ContentLibraryWidget::startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, + const QPointF &mousePos) +{ + m_materialToDrag = mat; + m_dragStartPoint = mousePos.toPoint(); +} + +void ContentLibraryWidget::startDragTexture(QmlDesigner::ContentLibraryTexture *tex, + const QPointF &mousePos) +{ + m_textureToDrag = tex; + m_dragStartPoint = mousePos.toPoint(); +} + +void ContentLibraryWidget::addImage(ContentLibraryTexture *tex) +{ + emit addTextureRequested(tex->path(), AddTextureMode::Image); +} + +void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex) +{ + emit addTextureRequested(tex->path(), AddTextureMode::Texture); +} + +void ContentLibraryWidget::addEnv(ContentLibraryTexture *tex) +{ + emit addTextureRequested(tex->path(), AddTextureMode::Environment); +} + +QPointer ContentLibraryWidget::materialsModel() const +{ + return m_materialsModel; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h new file mode 100644 index 00000000000..3eb470b7ae3 --- /dev/null +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h @@ -0,0 +1,76 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include +#include + +QT_BEGIN_NAMESPACE +class QShortcut; +class QToolButton; +class QQuickWidget; +QT_END_NAMESPACE + +namespace QmlDesigner { + +class ContentLibraryTexture; +class ContentLibraryMaterial; +class ContentLibraryTexturesModel; +class ContentLibraryMaterialsModel; + +class ContentLibraryWidget : public QFrame +{ + Q_OBJECT + +public: + ContentLibraryWidget(); + + QList createToolBarWidgets(); + + static QString qmlSourcesPath(); + void clearSearchFilter(); + + Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText); + + void setMaterialsModel(QPointer newMaterialsModel); + + QPointer materialsModel() const; + + Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos); + Q_INVOKABLE void startDragTexture(QmlDesigner::ContentLibraryTexture *tex, const QPointF &mousePos); + Q_INVOKABLE void addImage(QmlDesigner::ContentLibraryTexture *tex); + Q_INVOKABLE void addTexture(QmlDesigner::ContentLibraryTexture *tex); + Q_INVOKABLE void addEnv(QmlDesigner::ContentLibraryTexture *tex); + + enum class AddTextureMode { Image, Texture, Environment }; + +signals: + void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat); + void draggedMaterialChanged(); + void addTextureRequested(const QString texPath, QmlDesigner::ContentLibraryWidget::AddTextureMode mode); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +private: + void reloadQmlSource(); + void updateSearch(); + QString findTextureBundlePath(); + + QScopedPointer m_quickWidget; + QPointer m_materialsModel; + QPointer m_texturesModel; + QPointer m_environmentsModel; + + QShortcut *m_qmlSourceUpdateShortcut = nullptr; + + QString m_filterText; + + ContentLibraryMaterial *m_materialToDrag = nullptr; + ContentLibraryMaterial *m_draggedMaterial = nullptr; + ContentLibraryTexture *m_textureToDrag = nullptr; + QPoint m_dragStartPoint; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 80fd6aa2b16..c734b0e362c 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -286,7 +286,7 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos }); } } else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleMaterialDrop) { - emitCustomNotification("drop_bundle_material", {modelNode}); // To MaterialBrowserView + emitCustomNotification("drop_bundle_material", {modelNode}); // To ContentLibraryView } m_nodeAtPosReqType = NodeAtPosReqType::None; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index 7d90020d961..813b021b85d 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -146,7 +146,8 @@ void ItemLibraryView::updateImport3DSupport(const QVariantMap &supportMap) m_importableExtensions3DMap = extMap; AddResourceOperation import3DModelOperation = [this](const QStringList &fileNames, - const QString &defaultDir) -> AddFilesResult { + const QString &defaultDir, + bool showDialog) -> AddFilesResult { auto importDlg = new ItemLibraryAssetImportDialog(fileNames, defaultDir, m_importableExtensions3DMap, m_importOptions3DMap, {}, {}, diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.h b/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.h deleted file mode 100644 index 64344915ce1..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/bundleimporter.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -#include "nodemetainfo.h" - -#include -#include - -QT_BEGIN_NAMESPACE -QT_END_NAMESPACE - -namespace QmlDesigner::Internal { - -class BundleImporter : public QObject -{ - Q_OBJECT - -public: - BundleImporter(const QString &bundleDir, - const QString &bundleId, - const QStringList &sharedFiles, - QObject *parent = nullptr); - ~BundleImporter() = default; - - QString importComponent(const QString &qmlFile, - const QStringList &files); - QString unimportComponent(const QString &qmlFile); - Utils::FilePath resolveBundleImportPath(); - -signals: - // The metaInfo parameter will be invalid if an error was encountered during - // asynchronous part of the import. In this case all remaining pending imports have been - // terminated, and will not receive separate importFinished notifications. - void importFinished(const QmlDesigner::NodeMetaInfo &metaInfo); - void unimportFinished(const QmlDesigner::NodeMetaInfo &metaInfo); - -private: - void handleImportTimer(); - QVariantHash loadAssetRefMap(const Utils::FilePath &bundlePath); - void writeAssetRefMap(const Utils::FilePath &bundlePath, const QVariantHash &assetRefMap); - - Utils::FilePath m_bundleDir; - QString m_bundleId; - QString m_moduleName; - QStringList m_sharedFiles; - QTimer m_importTimer; - int m_importTimerCount = 0; - bool m_importAddPending = false; - bool m_fullReset = false; - QHash m_pendingTypes; // -}; - -} // namespace QmlDesigner::Internal diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp deleted file mode 100644 index 6cee76475ac..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "bundlematerial.h" - -namespace QmlDesigner { - -BundleMaterial::BundleMaterial(QObject *parent, - const QString &name, - const QString &qml, - const TypeName &type, - const QUrl &icon, - const QStringList &files) - : QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files) {} - -bool BundleMaterial::filter(const QString &searchText) -{ - if (m_visible != m_name.contains(searchText, Qt::CaseInsensitive)) { - m_visible = !m_visible; - emit materialVisibleChanged(); - } - - return m_visible; -} - -QUrl BundleMaterial::icon() const -{ - return m_icon; -} - -QString BundleMaterial::qml() const -{ - return m_qml; -} - -TypeName BundleMaterial::type() const -{ - return m_type; -} - -QStringList BundleMaterial::files() const -{ - return m_files; -} - -bool BundleMaterial::visible() const -{ - return m_visible; -} - -bool BundleMaterial::setImported(bool imported) -{ - if (m_imported != imported) { - m_imported = imported; - emit materialImportedChanged(); - return true; - } - - return false; -} - -bool BundleMaterial::imported() const -{ - return m_imported; -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h b/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h deleted file mode 100644 index 64d79aa65ee..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerial.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "qmldesignercorelib_global.h" - -#include -#include -#include - -namespace QmlDesigner { - -class BundleMaterial : public QObject -{ - Q_OBJECT - - Q_PROPERTY(QString bundleMaterialName MEMBER m_name CONSTANT) - Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT) - Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged) - Q_PROPERTY(bool bundleMaterialImported READ imported WRITE setImported NOTIFY materialImportedChanged) - -public: - BundleMaterial(QObject *parent, - const QString &name, - const QString &qml, - const TypeName &type, - const QUrl &icon, - const QStringList &files); - - bool filter(const QString &searchText); - - QUrl icon() const; - QString qml() const; - TypeName type() const; - QStringList files() const; - bool visible() const; - - bool setImported(bool imported); - bool imported() const; - -signals: - void materialVisibleChanged(); - void materialImportedChanged(); - -private: - QString m_name; - QString m_qml; - TypeName m_type; - QUrl m_icon; - QStringList m_files; - - bool m_visible = true; - bool m_imported = false; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.cpp b/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.cpp deleted file mode 100644 index 60910abb046..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "bundlematerialcategory.h" - -#include "bundlematerial.h" - -namespace QmlDesigner { - -BundleMaterialCategory::BundleMaterialCategory(QObject *parent, const QString &name) - : QObject(parent), m_name(name) {} - -void BundleMaterialCategory::addBundleMaterial(BundleMaterial *bundleMat) -{ - m_categoryMaterials.append(bundleMat); -} - -bool BundleMaterialCategory::updateImportedState(const QStringList &importedMats) -{ - bool changed = false; - - for (BundleMaterial *mat : std::as_const(m_categoryMaterials)) - changed |= mat->setImported(importedMats.contains(mat->qml().chopped(4))); - - return changed; -} - -bool BundleMaterialCategory::filter(const QString &searchText) -{ - bool visible = false; - for (BundleMaterial *mat : std::as_const(m_categoryMaterials)) - visible |= mat->filter(searchText); - - if (visible != m_visible) { - m_visible = visible; - emit categoryVisibleChanged(); - return true; - } - - return false; -} - -QString BundleMaterialCategory::name() const -{ - return m_name; -} - -bool BundleMaterialCategory::visible() const -{ - return m_visible; -} - -bool BundleMaterialCategory::expanded() const -{ - return m_expanded; -} - -QList BundleMaterialCategory::categoryMaterials() const -{ - return m_categoryMaterials; -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.h b/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.h deleted file mode 100644 index 14f7ddf654e..00000000000 --- a/src/plugins/qmldesigner/components/materialbrowser/bundlematerialcategory.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace QmlDesigner { - -class BundleMaterial; - -class BundleMaterialCategory : public QObject -{ - Q_OBJECT - - Q_PROPERTY(QString bundleCategoryName MEMBER m_name CONSTANT) - Q_PROPERTY(bool bundleCategoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged) - Q_PROPERTY(bool bundleCategoryExpanded MEMBER m_expanded NOTIFY categoryExpandChanged) - Q_PROPERTY(QList bundleCategoryMaterials MEMBER m_categoryMaterials - NOTIFY bundleMaterialsModelChanged) - -public: - BundleMaterialCategory(QObject *parent, const QString &name); - - void addBundleMaterial(BundleMaterial *bundleMat); - bool updateImportedState(const QStringList &importedMats); - bool filter(const QString &searchText); - - QString name() const; - bool visible() const; - bool expanded() const; - QList categoryMaterials() const; - -signals: - void categoryVisibleChanged(); - void categoryExpandChanged(); - void bundleMaterialsModelChanged(); - -private: - QString m_name; - bool m_visible = true; - bool m_expanded = true; - - QList m_categoryMaterials; -}; - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp new file mode 100644 index 00000000000..b39bdbb1f94 --- /dev/null +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.cpp @@ -0,0 +1,219 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#include "materialbrowsertexturesmodel.h" + +#include +#include +#include +#include +#include +#include +#include "utils/qtcassert.h" + +namespace QmlDesigner { + +MaterialBrowserTexturesModel::MaterialBrowserTexturesModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +MaterialBrowserTexturesModel::~MaterialBrowserTexturesModel() +{ +} + +int MaterialBrowserTexturesModel::rowCount(const QModelIndex &) const +{ + return m_textureList.count(); +} + +QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role) const +{ + QTC_ASSERT(index.isValid() && index.row() < m_textureList.count(), return {}); + QTC_ASSERT(roleNames().contains(role), return {}); + + QByteArray roleName = roleNames().value(role); + if (roleName == "textureSource") { + QString source = m_textureList.at(index.row()).variantProperty("source").value().toString(); + return QUrl::fromLocalFile(DocumentManager::currentResourcePath().path() + '/' + source); + } + + if (roleName == "textureVisible") + return isTextureVisible(index.row()); + + if (roleName == "hasDynamicProperties") + return !m_textureList.at(index.row()).dynamicProperties().isEmpty(); + + return {}; +} + +bool MaterialBrowserTexturesModel::isTextureVisible(int idx) const +{ + if (!isValidIndex(idx)) + return false; + + return m_searchText.isEmpty() || m_textureList.at(idx).variantProperty("objectName") + .value().toString().contains(m_searchText, Qt::CaseInsensitive); +} + +bool MaterialBrowserTexturesModel::isValidIndex(int idx) const +{ + return idx > -1 && idx < rowCount(); +} + + +QHash MaterialBrowserTexturesModel::roleNames() const +{ + static const QHash roles { + {Qt::UserRole + 1, "textureSource"}, + {Qt::UserRole + 2, "textureVisible"}, + {Qt::UserRole + 3, "hasDynamicProperties"} + }; + return roles; +} + +QList MaterialBrowserTexturesModel::textures() const +{ + return m_textureList; +} + +void MaterialBrowserTexturesModel::setSearchText(const QString &searchText) +{ + QString lowerSearchText = searchText.toLower(); + + if (m_searchText == lowerSearchText) + return; + + m_searchText = lowerSearchText; + + bool isEmpty = false; + + // if selected texture goes invisible, select nearest one + if (!isTextureVisible(m_selectedIndex)) { + int inc = 1; + int incCap = m_textureList.count(); + while (!isEmpty && inc < incCap) { + if (isTextureVisible(m_selectedIndex - inc)) { + selectTexture(m_selectedIndex - inc); + break; + } else if (isTextureVisible(m_selectedIndex + inc)) { + selectTexture(m_selectedIndex + inc); + break; + } + ++inc; + isEmpty = !isValidIndex(m_selectedIndex + inc) + && !isValidIndex(m_selectedIndex - inc); + } + if (!isTextureVisible(m_selectedIndex)) // handles the case of a single item + isEmpty = true; + } + + if (isEmpty != m_isEmpty) { + m_isEmpty = isEmpty; + emit isEmptyChanged(); + } + + resetModel(); +} + +void MaterialBrowserTexturesModel::setTextures(const QList &textures) +{ + m_textureList = textures; + m_textureIndexHash.clear(); + for (int i = 0; i < textures.size(); ++i) + m_textureIndexHash.insert(textures.at(i).internalId(), i); + + bool isEmpty = textures.size() == 0; + if (isEmpty != m_isEmpty) { + m_isEmpty = isEmpty; + emit isEmptyChanged(); + } + + updateSelectedTexture(); + resetModel(); +} + +void MaterialBrowserTexturesModel::removeTexture(const ModelNode &texture) +{ + if (!m_textureIndexHash.contains(texture.internalId())) + return; + + m_textureList.removeOne(texture); + int idx = m_textureIndexHash.value(texture.internalId()); + m_textureIndexHash.remove(texture.internalId()); + + // update index hash + for (int i = idx; i < rowCount(); ++i) + m_textureIndexHash.insert(m_textureList.at(i).internalId(), i); + + resetModel(); + + if (m_textureList.isEmpty()) { + m_isEmpty = true; + emit isEmptyChanged(); + } +} + +void MaterialBrowserTexturesModel::deleteSelectedTexture() +{ + deleteTexture(m_selectedIndex); +} + +void MaterialBrowserTexturesModel::updateSelectedTexture() +{ + selectTexture(m_selectedIndex, true); +} + +int MaterialBrowserTexturesModel::textureIndex(const ModelNode &texture) const +{ + if (m_textureIndexHash.contains(texture.internalId())) + return m_textureIndexHash.value(texture.internalId()); + + return -1; +} + +ModelNode MaterialBrowserTexturesModel::textureAt(int idx) const +{ + if (isValidIndex(idx)) + return m_textureList.at(idx); + + return {}; +} + +void MaterialBrowserTexturesModel::resetModel() +{ + beginResetModel(); + endResetModel(); +} + +void MaterialBrowserTexturesModel::selectTexture(int idx, bool force) +{ + if (m_textureList.size() == 0) { + m_selectedIndex = -1; + emit selectedIndexChanged(m_selectedIndex); + return; + } + + idx = std::max(0, std::min(idx, rowCount() - 1)); + + if (idx != m_selectedIndex || force) { + m_selectedIndex = idx; + emit selectedIndexChanged(idx); + } +} + +void MaterialBrowserTexturesModel::duplicateTexture(int idx) +{ + emit duplicateTextureTriggered(m_textureList.at(idx)); +} + +void MaterialBrowserTexturesModel::deleteTexture(int idx) +{ + if (isValidIndex(idx)) { + ModelNode node = m_textureList[idx]; + if (node.isValid()) + QmlObjectNode(node).destroy(); + } +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h new file mode 100644 index 00000000000..4b5d1bd55bf --- /dev/null +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowsertexturesmodel.h @@ -0,0 +1,63 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +#include +#include + +namespace QmlDesigner { + +class MaterialBrowserTexturesModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) + Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged) + +public: + MaterialBrowserTexturesModel(QObject *parent = nullptr); + ~MaterialBrowserTexturesModel() override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + void setSearchText(const QString &searchText); + + QList textures() const; + void setTextures(const QList &textures); + void removeTexture(const ModelNode &texture); + void deleteSelectedTexture(); + void updateSelectedTexture(); + int textureIndex(const ModelNode &material) const; + ModelNode textureAt(int idx) const; + + void resetModel(); + + Q_INVOKABLE void selectTexture(int idx, bool force = false); + Q_INVOKABLE void duplicateTexture(int idx); + Q_INVOKABLE void deleteTexture(int idx); + +signals: + void isEmptyChanged(); + void materialSectionsChanged(); + void selectedIndexChanged(int idx); + void duplicateTextureTriggered(const QmlDesigner::ModelNode &material); + +private: + bool isTextureVisible(int idx) const; + bool isValidIndex(int idx) const; + + QString m_searchText; + QList m_textureList; + ModelNode m_copiedMaterial; + QHash m_textureIndexHash; // internalId -> index + + int m_selectedIndex = 0; + bool m_isEmpty = true; +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 2a7b6833b3e..86d6c69b59f 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -4,11 +4,9 @@ #include "materialbrowserview.h" #include "bindingproperty.h" -#include "bundlematerial.h" -#include "bundleimporter.h" -#include "materialbrowsermodel.h" #include "materialbrowserwidget.h" -#include "materialbrowserbundlemodel.h" +#include "materialbrowsermodel.h" +#include "materialbrowsertexturesmodel.h" #include "nodeabstractproperty.h" #include "nodemetainfo.h" #include "qmlobjectnode.h" @@ -22,14 +20,6 @@ #include #include -#ifndef QMLDESIGNER_TEST -#include -#include -#include -#include -#include -#endif - #include #include #include @@ -149,48 +139,6 @@ WidgetInfo MaterialBrowserView::widgetInfo() } }); }); - - connect(m_widget, &MaterialBrowserWidget::bundleMaterialDragStarted, this, - [&] (QmlDesigner::BundleMaterial *bundleMat) { - m_draggedBundleMaterial = bundleMat; - }); - - MaterialBrowserBundleModel *matBrowserBundleModel = m_widget->materialBrowserBundleModel().data(); - - connect(matBrowserBundleModel, &MaterialBrowserBundleModel::applyToSelectedTriggered, this, - [&] (BundleMaterial *bundleMat, bool add) { - if (m_selectedModels.isEmpty()) - return; - - m_bundleMaterialTargets = m_selectedModels; - m_bundleMaterialAddToSelected = add; - - ModelNode defaultMat = getBundleMaterialDefaultInstance(bundleMat->type()); - if (defaultMat.isValid()) - applyBundleMaterialToDropTarget(defaultMat); - else - m_widget->materialBrowserBundleModel()->addToProject(bundleMat); - }); - - connect(matBrowserBundleModel, &MaterialBrowserBundleModel::bundleMaterialImported, this, - [&] (const QmlDesigner::NodeMetaInfo &metaInfo) { - applyBundleMaterialToDropTarget({}, metaInfo); - updateBundleMaterialsImportedState(); - }); - - connect(matBrowserBundleModel, &MaterialBrowserBundleModel::bundleMaterialAboutToUnimport, this, - [&] (const QmlDesigner::TypeName &type) { - // delete instances of the bundle material that is about to be unimported - executeInTransaction("MaterialBrowserView::widgetInfo", [&] { - Utils::reverseForeach(m_widget->materialBrowserModel()->materials(), [&](const ModelNode &mat) { - if (mat.isValid() && mat.type() == type) - QmlObjectNode(mat).destroy(); - }); - }); - }); - - connect(matBrowserBundleModel, &MaterialBrowserBundleModel::bundleMaterialUnimported, this, - &MaterialBrowserView::updateBundleMaterialsImportedState); } return createWidgetInfo(m_widget.data(), @@ -200,77 +148,6 @@ WidgetInfo MaterialBrowserView::widgetInfo() tr("Material Browser")); } -void MaterialBrowserView::applyBundleMaterialToDropTarget(const ModelNode &bundleMat, - const NodeMetaInfo &metaInfo) -{ - if (!bundleMat.isValid() && !metaInfo.isValid()) - return; - - ModelNode matLib = materialLibraryNode(); - if (!matLib.isValid()) - return; - - executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] { - ModelNode newMatNode; - if (metaInfo.isValid()) { - newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(), - metaInfo.minorVersion()); - matLib.defaultNodeListProperty().reparentHere(newMatNode); - - static QRegularExpression rgx("([A-Z])([a-z]*)"); - QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed(); - if (newName.endsWith(" Material")) - newName.chop(9); // remove trailing " Material" - QString newId = model()->generateIdFromName(newName, "material"); - newMatNode.setIdWithRefactoring(newId); - - VariantProperty objNameProp = newMatNode.variantProperty("objectName"); - objNameProp.setValue(newName); - } else { - newMatNode = bundleMat; - } - - // TODO: unify this logic as it exist elsewhere also - auto expToList = [](const QString &exp) { - QString copy = exp; - copy = copy.remove("[").remove("]"); - - QStringList tmp = copy.split(',', Qt::SkipEmptyParts); - for (QString &str : tmp) - str = str.trimmed(); - - return tmp; - }; - - auto listToExp = [](QStringList &stringList) { - if (stringList.size() > 1) - return QString("[" + stringList.join(",") + "]"); - - if (stringList.size() == 1) - return stringList.first(); - - return QString(); - }; - - for (const ModelNode &target : std::as_const(m_bundleMaterialTargets)) { - if (target.isValid() && target.metaInfo().isQtQuick3DModel()) { - QmlObjectNode qmlObjNode(target); - if (m_bundleMaterialAddToSelected) { - QStringList matList = expToList(qmlObjNode.expression("materials")); - matList.append(newMatNode.id()); - QString updatedExp = listToExp(matList); - qmlObjNode.setBindingProperty("materials", updatedExp); - } else { - qmlObjNode.setBindingProperty("materials", newMatNode.id()); - } - } - - m_bundleMaterialTargets = {}; - m_bundleMaterialAddToSelected = false; - } - }); -} - void MaterialBrowserView::modelAttached(Model *model) { AbstractView::modelAttached(model); @@ -280,9 +157,6 @@ void MaterialBrowserView::modelAttached(Model *model) rootModelNode().metaInfo().isQtQuick3DMaterial()); m_hasQuick3DImport = model->hasImport("QtQuick3D"); - updateBundleMaterialsQuick3DVersion(); - updateBundleMaterialsImportedState(); - // Project load is already very busy and may even trigger puppet reset, so let's wait a moment // before refreshing the model QTimer::singleShot(1000, model, [this]() { @@ -297,18 +171,22 @@ void MaterialBrowserView::refreshModel(bool updateImages) return; ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID); - QList materials; + QList materials; + QList textures; if (m_hasQuick3DImport && matLib.isValid()) { const QList matLibNodes = matLib.directSubModelNodes(); for (const ModelNode &node : matLibNodes) { if (isMaterial(node)) materials.append(node); + else if (isTexture(node)) + textures.append(node); } } m_widget->clearSearchFilter(); m_widget->materialBrowserModel()->setMaterials(materials, m_hasQuick3DImport); + m_widget->materialBrowserTexturesModel()->setTextures(textures); if (updateImages) { for (const ModelNode &node : std::as_const(materials)) @@ -323,6 +201,14 @@ bool MaterialBrowserView::isMaterial(const ModelNode &node) const return node.metaInfo().isQtQuick3DMaterial(); } +bool MaterialBrowserView::isTexture(const ModelNode &node) const +{ + if (!node.isValid()) + return false; + + return node.metaInfo().isQtQuick3DTexture(); +} + void MaterialBrowserView::modelAboutToBeDetached(Model *model) { m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport); @@ -388,7 +274,9 @@ void MaterialBrowserView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &oldPropertyParent, [[maybe_unused]] PropertyChangeFlags propertyChange) { - if (!isMaterial(node)) + Q_UNUSED(propertyChange) + + if (!isMaterial(node) && !isTexture(node)) return; ModelNode newParentNode = newPropertyParent.parentModelNode(); @@ -445,82 +333,6 @@ void QmlDesigner::MaterialBrowserView::loadPropertyGroups() m_propertyGroupsLoaded = m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath); } -void MaterialBrowserView::updateBundleMaterialsImportedState() -{ - using namespace Utils; - - if (!m_widget->materialBrowserBundleModel()->bundleImporter()) - return; - - QStringList importedBundleMats; - - FilePath materialBundlePath = m_widget->materialBrowserBundleModel()->bundleImporter()->resolveBundleImportPath(); - - if (materialBundlePath.exists()) { - importedBundleMats = transform(materialBundlePath.dirEntries({{"*.qml"}, QDir::Files}), - [](const FilePath &f) { return f.fileName().chopped(4); }); - } - - m_widget->materialBrowserBundleModel()->updateImportedState(importedBundleMats); -} - -void MaterialBrowserView::updateBundleMaterialsQuick3DVersion() -{ - bool hasImport = false; - int major = -1; - int minor = -1; - const QString url {"QtQuick3D"}; - const auto imports = model()->imports(); - for (const auto &import : imports) { - if (import.url() == url) { - hasImport = true; - const int importMajor = import.majorVersion(); - if (major < importMajor) { - minor = -1; - major = importMajor; - } - if (major == importMajor) - minor = qMax(minor, import.minorVersion()); - } - } -#ifndef QMLDESIGNER_TEST - if (hasImport && major == -1) { - // Import without specifying version, so we take the kit version - auto target = ProjectExplorer::SessionManager::startupTarget(); - if (target) { - QtSupport::QtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(target->kit()); - if (qtVersion) { - major = qtVersion->qtVersion().majorVersion(); - minor = qtVersion->qtVersion().minorVersion(); - } - } - } -#endif - m_widget->materialBrowserBundleModel()->setQuick3DImportVersion(major, minor); -} - -ModelNode MaterialBrowserView::getBundleMaterialDefaultInstance(const TypeName &type) -{ - const QList materials = m_widget->materialBrowserModel()->materials(); - for (const ModelNode &mat : materials) { - if (mat.type() == type) { - bool isDefault = true; - const QList props = mat.properties(); - for (const AbstractProperty &prop : props) { - if (prop.name() != "objectName") { - isDefault = false; - break; - } - } - - if (isDefault) - return mat; - } - } - - return {}; -} - void MaterialBrowserView::requestPreviews() { if (model() && model()->nodeInstanceView()) { @@ -535,8 +347,6 @@ void MaterialBrowserView::importsChanged([[maybe_unused]] const QList &a { bool hasQuick3DImport = model()->hasImport("QtQuick3D"); - updateBundleMaterialsQuick3DVersion(); - if (hasQuick3DImport == m_hasQuick3DImport) return; @@ -566,16 +376,6 @@ void MaterialBrowserView::customNotification(const AbstractView *view, }); } else if (identifier == "delete_selected_material") { m_widget->materialBrowserModel()->deleteSelectedMaterial(); - } else if (identifier == "drop_bundle_material") { - m_bundleMaterialTargets = nodeList; - - ModelNode defaultMat = getBundleMaterialDefaultInstance(m_draggedBundleMaterial->type()); - if (defaultMat.isValid()) - applyBundleMaterialToDropTarget(defaultMat); - else - m_widget->materialBrowserBundleModel()->addToProject(m_draggedBundleMaterial); - - m_draggedBundleMaterial = nullptr; } } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h index a8bcf5f2f1f..f59cb2dbbcd 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h @@ -4,7 +4,6 @@ #pragma once #include "abstractview.h" -#include "nodemetainfo.h" #include #include @@ -12,7 +11,6 @@ namespace QmlDesigner { -class BundleMaterial; class MaterialBrowserWidget; class MaterialBrowserView : public AbstractView @@ -48,19 +46,13 @@ public: private: void refreshModel(bool updateImages); bool isMaterial(const ModelNode &node) const; + bool isTexture(const ModelNode &node) const; void loadPropertyGroups(); - void updateBundleMaterialsImportedState(); - void updateBundleMaterialsQuick3DVersion(); - void applyBundleMaterialToDropTarget(const ModelNode &bundleMat, const NodeMetaInfo &metaInfo = {}); - ModelNode getBundleMaterialDefaultInstance(const TypeName &type); void requestPreviews(); QPointer m_widget; - QList m_bundleMaterialTargets; QList m_selectedModels; // selected 3D model nodes - BundleMaterial *m_draggedBundleMaterial = nullptr; - bool m_bundleMaterialAddToSelected = false; bool m_hasQuick3DImport = false; bool m_autoSelectModelMaterial = false; // TODO: wire this to some action bool m_puppetResetPending = false; diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index 4a513d380f3..f51dd57b804 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -3,9 +3,8 @@ #include "materialbrowserwidget.h" -#include "bundlematerial.h" -#include "materialbrowserbundlemodel.h" #include "materialbrowsermodel.h" +#include "materialbrowsertexturesmodel.h" #include "materialbrowserview.h" #include @@ -30,10 +29,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -108,34 +107,9 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) QString::number(m_materialToDrag.internalId()), nullptr, {128, 128})); m_materialToDrag = {}; } - } else if (m_bundleMaterialToDrag != nullptr) { - QMouseEvent *me = static_cast(event); - if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { - QByteArray data; - QMimeData *mimeData = new QMimeData; - QDataStream stream(&data, QIODevice::WriteOnly); - stream << m_bundleMaterialToDrag->type(); - mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, data); - mimeData->removeFormat("text/plain"); - - if (!m_draggedBundleMaterial) { - m_draggedBundleMaterial = m_bundleMaterialToDrag; - emit draggedBundleMaterialChanged(); - } - - emit bundleMaterialDragStarted(m_bundleMaterialToDrag); - model->startDrag(mimeData, m_bundleMaterialToDrag->icon().toLocalFile()); - m_bundleMaterialToDrag = nullptr; - } } } else if (event->type() == QMouseEvent::MouseButtonRelease) { m_materialToDrag = {}; - m_bundleMaterialToDrag = nullptr; - - if (m_draggedBundleMaterial) { - m_draggedBundleMaterial = nullptr; - emit draggedBundleMaterialChanged(); - } } return QObject::eventFilter(obj, event); @@ -144,7 +118,7 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view) : m_materialBrowserView(view) , m_materialBrowserModel(new MaterialBrowserModel(this)) - , m_materialBrowserBundleModel(new MaterialBrowserBundleModel(this)) + , m_materialBrowserTexturesModel(new MaterialBrowserTexturesModel(this)) , m_quickWidget(new QQuickWidget(this)) , m_previewImageProvider(new PreviewImageProvider()) { @@ -163,7 +137,7 @@ MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view) m_quickWidget->rootContext()->setContextProperties({ {"rootView", QVariant::fromValue(this)}, {"materialBrowserModel", QVariant::fromValue(m_materialBrowserModel.data())}, - {"materialBrowserBundleModel", QVariant::fromValue(m_materialBrowserBundleModel.data())}, + {"materialBrowserTexturesModel", QVariant::fromValue(m_materialBrowserTexturesModel.data())}, }); m_quickWidget->engine()->addImageProvider("materialBrowser", m_previewImageProvider); @@ -223,10 +197,9 @@ void MaterialBrowserWidget::startDragMaterial(int index, const QPointF &mousePos m_dragStartPoint = mousePos.toPoint(); } -void MaterialBrowserWidget::startDragBundleMaterial(QmlDesigner::BundleMaterial *bundleMat, const QPointF &mousePos) +void MaterialBrowserWidget::acceptBundleMaterialDrop() { - m_bundleMaterialToDrag = bundleMat; - m_dragStartPoint = mousePos.toPoint(); + m_materialBrowserView->emitCustomNotification("drop_bundle_material", {}, {}); // To ContentLibraryView } QString MaterialBrowserWidget::qmlSourcesPath() @@ -256,7 +229,6 @@ void MaterialBrowserWidget::reloadQmlSource() void MaterialBrowserWidget::updateSearch() { m_materialBrowserModel->setSearchText(m_filterText); - m_materialBrowserBundleModel->setSearchText(m_filterText); m_quickWidget->update(); } @@ -270,10 +242,9 @@ QPointer MaterialBrowserWidget::materialBrowserModel() con return m_materialBrowserModel; } -QPointer MaterialBrowserWidget::materialBrowserBundleModel() const +QPointer MaterialBrowserWidget::materialBrowserTexturesModel() const { - return m_materialBrowserBundleModel; + return m_materialBrowserTexturesModel; } - } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h index 42739d83c42..af5909b546b 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h @@ -11,32 +11,27 @@ #include #include -#include -#include #include -#include -#include -#include #include QT_BEGIN_NAMESPACE -class QStackedWidget; +class QQuickWidget; +class QPointF; class QShortcut; +class QToolButton; QT_END_NAMESPACE namespace QmlDesigner { -class BundleMaterial; class MaterialBrowserView; class MaterialBrowserModel; -class MaterialBrowserBundleModel; +class MaterialBrowserTexturesModel; class PreviewImageProvider; class MaterialBrowserWidget : public QFrame { Q_OBJECT - Q_PROPERTY(BundleMaterial *draggedBundleMaterial MEMBER m_draggedBundleMaterial NOTIFY draggedBundleMaterialChanged) public: MaterialBrowserWidget(MaterialBrowserView *view); @@ -49,19 +44,15 @@ public: void clearSearchFilter(); QPointer materialBrowserModel() const; - QPointer materialBrowserBundleModel() const; + QPointer materialBrowserTexturesModel() const; void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap); Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText); Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos); - Q_INVOKABLE void startDragBundleMaterial(QmlDesigner::BundleMaterial *bundleMat, const QPointF &mousePos); + Q_INVOKABLE void acceptBundleMaterialDrop(); QQuickWidget *quickWidget() const; -signals: - void bundleMaterialDragStarted(QmlDesigner::BundleMaterial *bundleMat); - void draggedBundleMaterialChanged(); - protected: bool eventFilter(QObject *obj, QEvent *event) override; @@ -71,7 +62,7 @@ private: QPointer m_materialBrowserView; QPointer m_materialBrowserModel; - QPointer m_materialBrowserBundleModel; + QPointer m_materialBrowserTexturesModel; QScopedPointer m_quickWidget; QShortcut *m_qmlSourceUpdateShortcut = nullptr; @@ -81,8 +72,6 @@ private: QString m_filterText; ModelNode m_materialToDrag; - BundleMaterial *m_bundleMaterialToDrag = nullptr; - BundleMaterial *m_draggedBundleMaterial = nullptr; QPoint m_dragStartPoint; }; diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 12d496b2522..a407cf129b3 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -544,7 +544,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData, } else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) { ModelNode targetNode(modelNodeForIndex(dropModelIndex)); if (targetNode.isValid()) - m_view->emitCustomNotification("drop_bundle_material", {targetNode}); // To MaterialBrowserView + m_view->emitCustomNotification("drop_bundle_material", {targetNode}); // To ContentLibraryView } else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) { const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(','); NodeAbstractProperty targetProperty; diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 9b5dac8aa9f..6a3a4e0de48 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -76,6 +76,7 @@ const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.iteml const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets"; const char MIME_TYPE_MATERIAL[] = "application/vnd.qtdesignstudio.material"; const char MIME_TYPE_BUNDLE_MATERIAL[] = "application/vnd.qtdesignstudio.bundlematerial"; +const char MIME_TYPE_BUNDLE_TEXTURE[] = "application/vnd.qtdesignstudio.bundletexture"; const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image"; const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font"; const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader"; From 15dd073e0c43c7c257684997fef033fad9089fd6 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Mon, 7 Nov 2022 16:49:17 +0200 Subject: [PATCH 21/71] QmlDesigner: Add basic drag-n-drop support to textures Dropping textures to different views to be handled separately. Change-Id: I1e0ac5681e5e1b3dca8bdaf6819a6b699f629e79 Reviewed-by: Miikka Heikkinen --- .../materialBrowserQmlSource/TextureItem.qml | 2 +- .../materialbrowser/materialbrowserwidget.cpp | 28 ++++++++++++++++--- .../materialbrowser/materialbrowserwidget.h | 2 ++ .../qmldesigner/qmldesignerconstants.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml index e208ed1ec52..68f832f65f6 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml @@ -26,7 +26,7 @@ Image { onPressed: (mouse) => { if (mouse.button === Qt.LeftButton) - rootView.startDragTexture(modelData, mapToGlobal(mouse.x, mouse.y)) + rootView.startDragTexture(index, mapToGlobal(mouse.x, mouse.y)) else if (mouse.button === Qt.RightButton) root.showContextMenu() } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index f51dd57b804..ccbd972daa4 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -93,23 +94,36 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) Model *model = document->currentModel(); QTC_ASSERT(model, return false); - if (m_materialToDrag.isValid()) { + if (m_materialToDrag.isValid() || m_textureToDrag.isValid()) { QMouseEvent *me = static_cast(event); if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) { + bool isMaterial = m_materialToDrag.isValid(); QByteArray data; QMimeData *mimeData = new QMimeData; QDataStream stream(&data, QIODevice::WriteOnly); stream << m_materialToDrag.internalId(); - mimeData->setData(Constants::MIME_TYPE_MATERIAL, data); + mimeData->setData(isMaterial ? QString::fromLatin1(Constants::MIME_TYPE_MATERIAL) + : QString::fromLatin1(Constants::MIME_TYPE_TEXTURE), + data); mimeData->removeFormat("text/plain"); - model->startDrag(mimeData, m_previewImageProvider->requestPixmap( - QString::number(m_materialToDrag.internalId()), nullptr, {128, 128})); + if (isMaterial) { + model->startDrag(mimeData, m_previewImageProvider->requestPixmap( + QString::number(m_materialToDrag.internalId()), nullptr, {128, 128})); + } else { + QString iconPath = QLatin1String("%1/%2") + .arg(DocumentManager::currentResourcePath().path(), + m_textureToDrag.variantProperty("source").value().toString()); + + model->startDrag(mimeData, QPixmap(iconPath).scaled({128, 128})); + } m_materialToDrag = {}; + m_textureToDrag = {}; } } } else if (event->type() == QMouseEvent::MouseButtonRelease) { m_materialToDrag = {}; + m_textureToDrag = {}; } return QObject::eventFilter(obj, event); @@ -197,6 +211,12 @@ void MaterialBrowserWidget::startDragMaterial(int index, const QPointF &mousePos m_dragStartPoint = mousePos.toPoint(); } +void MaterialBrowserWidget::startDragTexture(int index, const QPointF &mousePos) +{ + m_textureToDrag = m_materialBrowserTexturesModel->textureAt(index); + m_dragStartPoint = mousePos.toPoint(); +} + void MaterialBrowserWidget::acceptBundleMaterialDrop() { m_materialBrowserView->emitCustomNotification("drop_bundle_material", {}, {}); // To ContentLibraryView diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h index af5909b546b..902883aa778 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h @@ -49,6 +49,7 @@ public: Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText); Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos); + Q_INVOKABLE void startDragTexture(int index, const QPointF &mousePos); Q_INVOKABLE void acceptBundleMaterialDrop(); QQuickWidget *quickWidget() const; @@ -72,6 +73,7 @@ private: QString m_filterText; ModelNode m_materialToDrag; + ModelNode m_textureToDrag; QPoint m_dragStartPoint; }; diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 6a3a4e0de48..92565d36308 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -75,6 +75,7 @@ const char MATERIAL_LIB_ID[] = "__materialLibrary__"; const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.itemlibraryinfo"; const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets"; const char MIME_TYPE_MATERIAL[] = "application/vnd.qtdesignstudio.material"; +const char MIME_TYPE_TEXTURE[] = "application/vnd.qtdesignstudio.texture"; const char MIME_TYPE_BUNDLE_MATERIAL[] = "application/vnd.qtdesignstudio.bundlematerial"; const char MIME_TYPE_BUNDLE_TEXTURE[] = "application/vnd.qtdesignstudio.bundletexture"; const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image"; From 442a916026941cc47e4e8859992a0e2c972dfe1d Mon Sep 17 00:00:00 2001 From: Pranta Dastider Date: Tue, 8 Nov 2022 11:17:11 +0100 Subject: [PATCH 22/71] QmlDesigner: Update Adobe XD Information Update the missing infomration about Adobe XD supported version for Qt Bridge in the document. Fixes: QDS-8190 Change-Id: Ic171749eb1f3138d9e1638e9f22be88d9c708373 Reviewed-by: Leena Miettinen --- doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc index 6133642c531..4827453aba7 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc @@ -37,6 +37,7 @@ \list \li Adobe Photoshop version 22.3.1 + \li Adobe XD version 55.0.12 \li Figma version 97.x \li Sketch version 72.2 \endlist From 3f2c3324fd2dd011b72ff59a25a1fa6ec2cfae1d Mon Sep 17 00:00:00 2001 From: Pranta Dastider Date: Tue, 8 Nov 2022 12:01:32 +0100 Subject: [PATCH 23/71] QmlDesigner: Update the typo in Adobe illustrator export Update and change the typo found in Adobe illustrator design export doc. Fixes: QDS-8187 Change-Id: I219078aab77799ec5b0eb2287fb0b299fa46351c Reviewed-by: Mats Honkamaa Reviewed-by: Leena Miettinen --- doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc index 685eeadc57d..e94d8700bc6 100644 --- a/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc +++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-ai.qdoc @@ -9,7 +9,7 @@ \title Exporting Designs from Adobe Illustrator Even though \QDS does not provide a specific export bridge for Adobe - Illustrator, you can desing UIs in it and export your designs to \QDS in + Illustrator, you can design UIs in it and export your designs to \QDS in the following ways: \list From d9d4d1829af35e8d01ca812825b0d413904abca1 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 8 Nov 2022 13:02:06 +0200 Subject: [PATCH 24/71] QmlDesigner: Fix material name editing issues Material name field in material browser now ensures that the start of the string is visible when editing is not focused. Any click outside the name field will take the focus away from the field, and name field state is properly updated when focus goes away for any reason. Trying to set same name as before is ignored instead of changing the name to 1. Fixes: QDS-8185 Change-Id: I723e3ae312e3e2c4ce8a95a3b05effcee2bae328 Reviewed-by: Mahmoud Badri --- .../materialBrowserQmlSource/MaterialBrowser.qml | 11 +++++++++++ .../materialBrowserQmlSource/MaterialItem.qml | 15 ++++++++++++--- .../materialeditor/materialeditorview.cpp | 4 ++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 9edc5019769..9a9cb26f791 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -35,6 +35,17 @@ Item { searchBox.clear(); } + MouseArea { + id: focusGrabber + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onPressed: (mouse) => { + forceActiveFocus() // Steal focus from name edit + mouse.accepted = false + } + z: 1 + } + MouseArea { id: rootMouseArea diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml index 71ac8911235..6eaf0351d2f 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialItem.qml @@ -23,6 +23,7 @@ Rectangle { matName.readOnly = false matName.selectAll() matName.forceActiveFocus() + matName.ensureVisible(matName.text.length) nameMouseArea.enabled = false } @@ -31,10 +32,8 @@ Rectangle { if (matName.readOnly) return; - matName.readOnly = true - nameMouseArea.enabled = true - materialBrowserModel.renameMaterial(index, matName.text); + mouseArea.forceActiveFocus() } border.width: materialBrowserModel.selectedIndex === index ? 1 : 0 @@ -102,6 +101,16 @@ Rectangle { onEditingFinished: root.commitRename() + onActiveFocusChanged: { + if (!activeFocus) { + matName.readOnly = true + nameMouseArea.enabled = true + ensureVisible(0) + } + } + + Component.onCompleted: ensureVisible(0) + MouseArea { id: nameMouseArea diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index 39d036f6772..58bb81434fb 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -998,6 +998,10 @@ void MaterialEditorView::renameMaterial(ModelNode &material, const QString &newN { QTC_ASSERT(material.isValid(), return); + QVariant objName = material.variantProperty("objectName").value(); + if (objName.isValid() && objName.toString() == newName) + return; + executeInTransaction("MaterialEditorView:renameMaterial", [&] { material.setIdWithRefactoring(model()->generateIdFromName(newName, "material")); From 77e49a954ea85cb9fa2e1ccbde5ffc3992ea1be1 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 18 Oct 2022 22:28:04 +0200 Subject: [PATCH 25/71] QmlDesigner: Workaround strange superClasses behavior superClasses() return not only the super classes but the type itself. We should later fix that and introduce something like prototypes(). Change-Id: Ied9c1edad40754cb995bfb26b8d65b0aa3d17753 Reviewed-by: Thomas Hartmann --- tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index e57c4aac0f2..365748c1fb2 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -4821,7 +4821,7 @@ void tst_TestCore::testMetaInfoSimpleType() QCOMPARE(itemMetaInfo.minorVersion(), 1); // super classes - NodeMetaInfo qobject = itemMetaInfo.superClasses().front(); + NodeMetaInfo qobject = itemMetaInfo.superClasses()[1]; QVERIFY(qobject.isValid()); QVERIFY(qobject.isQtObject()); @@ -4849,7 +4849,7 @@ void tst_TestCore::testMetaInfoUncreatableType() QCOMPARE(animationTypeInfo.majorVersion(), 2); QCOMPARE(animationTypeInfo.minorVersion(), 1); - NodeMetaInfo qObjectTypeInfo = animationTypeInfo.superClasses().front(); + NodeMetaInfo qObjectTypeInfo = animationTypeInfo.superClasses()[1]; QVERIFY(qObjectTypeInfo.isValid()); QCOMPARE(qObjectTypeInfo.simplifiedTypeName(), QmlDesigner::TypeName("QtObject")); @@ -4867,7 +4867,7 @@ void tst_TestCore::testMetaInfoExtendedType() QVERIFY(typeInfo.hasProperty("font")); // from QGraphicsWidget QVERIFY(typeInfo.hasProperty("enabled")); // from QGraphicsItem - NodeMetaInfo graphicsObjectTypeInfo = typeInfo.superClasses().front(); + NodeMetaInfo graphicsObjectTypeInfo = typeInfo.superClasses()[1]; QVERIFY(graphicsObjectTypeInfo.isValid()); } @@ -4889,7 +4889,7 @@ void tst_TestCore::testMetaInfoCustomType() QVERIFY(propertyChangesInfo.hasProperty("restoreEntryValues")); QVERIFY(propertyChangesInfo.hasProperty("explicit")); - NodeMetaInfo stateOperationInfo = propertyChangesInfo.superClasses().front(); + NodeMetaInfo stateOperationInfo = propertyChangesInfo.superClasses()[1]; QVERIFY(stateOperationInfo.isValid()); QCOMPARE(stateOperationInfo.typeName(), QmlDesigner::TypeName("QtQuick.QQuickStateOperation")); QCOMPARE(stateOperationInfo.majorVersion(), -1); From 0228cfef1c4d12b3c21a0b3b9bf1726af241512f Mon Sep 17 00:00:00 2001 From: Pranta Dastider Date: Thu, 3 Nov 2022 16:11:19 +0100 Subject: [PATCH 26/71] QmlDesigner: Update the state group name Update the state group name from "root" to "default". Update the photos for that particular sections. Fixes: QDS-8144 Change-Id: I044172d1555c0402e42d37d6d5bb17a0238ce6ac Reviewed-by: Mats Honkamaa Reviewed-by: Thomas Hartmann --- doc/qtdesignstudio/images/extended-state.webp | Bin 10666 -> 10518 bytes .../images/no-extended-state.webp | Bin 12630 -> 12590 bytes .../images/qmldesigner-screen-design.png | Bin 25413 -> 24718 bytes .../images/qmldesigner-states.png | Bin 23625 -> 23873 bytes .../images/qmldesigner-transitions.png | Bin 10532 -> 10272 bytes .../src/views/qtquick-states.qdoc | 2 +- 6 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtdesignstudio/images/extended-state.webp b/doc/qtdesignstudio/images/extended-state.webp index 58eae1febfcc6395d4a4861b88b820ac7f2663be..1feb878d76ac98f849e1cc1348eb294b6ad3ddc0 100644 GIT binary patch literal 10518 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 literal 10666 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 diff --git a/doc/qtdesignstudio/images/no-extended-state.webp b/doc/qtdesignstudio/images/no-extended-state.webp index 41fe322f0db4328284d2c4c50dc0b07fc9bc7e90..db0281aefff7dd9558016add6b02f7408f48f702 100644 GIT binary patch literal 12590 zcmWIYbaPWPWMBw)bqWXzuuzaPWMByJW1P#VWzTYe(QdBK0`Dct%1Ww5yBIbIcc$mP ztB$%MP`B~z-qY7!KfdHG)ngMAkbimS|M>m-%gZ`zc^Tth)TX@M@!9j)+n1lu|G#+u zTKBJ3m;dwkANaNA!|qS>bL|%X==*y7UHqh|F2+wo#~S{Hjn9( z!typPov8nL&IPYo=@Sp%oqnqz@$ycGz1triiF>G!C&We+k-P75&#tQisnyRv#ym7T z(0E{#WX1MhGncNoxIvihK#t3+8PV`Z3FZ+7oCCglmT6Sp03DPrDac7vnOq0H?zqu>d?6SvjEnsYWp z`@3%Wf*_&_exFycR?cncc*35NyFuXHy?IAIg-SN(mCfX3TLsToR4N*vLer$ zCC%@RmL=m&=^Pe!1*@40wTn((+{xj&zUuMMU*Dcq3Eo@pWPSAo@296%b|2-4eG+(J z22aLG)fAR#dolCU9Dj|!LFteq;>VhgrAQe8I^79`cNQxdkd#m z?U`GFYU$55&o7!J@twJ5`oXj80`+NGM`T{C2o_s6BQG&r@NTW+m*WlmWu|jK8~!Nj zSon1JhRWdDOaE+`B?ULRu3js7>gQIQf=QcJ*z7*@NmGBuV%0DI71vF9pnTC;ds6eM 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 N22WQ%mvv4FO#rzy$}j)` literal 25413 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Ð#6QxBeI&fF0&;b7X4sp~jY?9T0p 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�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 HDWM4fPbM~1 literal 23625 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 diff --git a/doc/qtdesignstudio/images/qmldesigner-transitions.png b/doc/qtdesignstudio/images/qmldesigner-transitions.png index 4142cacee632fe9e53dc7ef371f76875450b7d14..012863d614557d14303426d2f69e4bd570f17e81 100644 GIT binary patch delta 10165 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 delta 10383 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 diff --git a/doc/qtdesignstudio/src/views/qtquick-states.qdoc b/doc/qtdesignstudio/src/views/qtquick-states.qdoc index aee10e2c5ba..6b55e5e59f0 100644 --- a/doc/qtdesignstudio/src/views/qtquick-states.qdoc +++ b/doc/qtdesignstudio/src/views/qtquick-states.qdoc @@ -180,7 +180,7 @@ Each state group has its own property changes and transitions. - By default, there is one root state group. + By default, there is one default state group. \section1 Extending States From c1f3dc4f5473cb3fa8cb59bf2c6d607a059c75c6 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Mon, 7 Nov 2022 16:50:23 +0200 Subject: [PATCH 27/71] QmlDesigner: Add positioning methods to QmlVisualNode QmlVisualNode would be able to: 1. Set a position for the visual node 2. Translate the position of the visual node 3. The visual node could be scattered 4. Get the related position of visual node All these methods will work for either 2D or 3D nodes. Also, a potential bug has been fixed for the Position. It was assumed that if a position equals to 0, it's not a valid position, but now it's handled by this change. Change-Id: I9dd59dbe0d14084087ff39bd14d2a783d24a5efd Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- .../designercore/include/qmlvisualnode.h | 16 +-- .../designercore/model/qmlvisualnode.cpp | 97 +++++++++++++++---- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h index ee0817d3737..8506de0edf7 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h @@ -26,23 +26,24 @@ class QMLDESIGNERCORE_EXPORT QmlVisualNode : public QmlObjectNode friend class QmlAnchors; public: - class Position + class Position : public QVector3D { friend class QmlVisualNode; public: Position() {} Position(const QPointF &position) : - m_2dPos(position) + QVector3D(position) {} Position(const QVector3D &position) : - m_3dPos(position) + QVector3D(position), + m_is3D(true) {} + bool is3D() const; QList> propertyPairList() const; private: - QPointF m_2dPos; - QVector3D m_3dPos; + bool m_is3D = false; }; QmlVisualNode() = default; @@ -65,7 +66,10 @@ public: void setVisibilityOverride(bool visible); bool visibilityOverride() const; - void initializePosition(const Position &position); + void scatter(const ModelNode &targetNode, const std::optional &offset); + void translate(const QVector3D &vector); + void setPosition(const Position &position); + Position position() const; static bool isItemOr3DNode(const ModelNode &modelNode); diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index 0fb9209b3f1..36edea4e9ea 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace QmlDesigner { @@ -156,21 +157,81 @@ bool QmlVisualNode::visibilityOverride() const return false; } +void QmlVisualNode::scatter(const ModelNode &targetNode, const std::optional &offset) +{ + if (!isValid()) + return; + + if (targetNode.metaInfo().isValid() && targetNode.metaInfo().isLayoutable()) + return; + + bool scatter = false; + const QList targetDirectNodes = targetNode.directSubModelNodes(); + for (const ModelNode &childNode : targetDirectNodes) { + if (childNode == modelNode()) + continue; + + if (isValidQmlVisualNode(childNode)) { + Position childPos = QmlVisualNode(childNode).position(); + if (qFuzzyCompare(position().distanceToPoint(childPos), 0.f)) { + scatter = true; + break; + } + } + } + + if (!scatter) + return; + + if (offset.has_value()) { // offset + double offsetValue = offset.value(); + this->translate(QVector3D(offsetValue, offsetValue, offsetValue)); + } else { // scatter in range + const double scatterRange = 20.; + double x = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; + double y = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; + double z = (modelNode().metaInfo().isQtQuick3DNode()) + ? QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2 + : 0.; + this->translate(QVector3D(x, y, z)); + } +} + +void QmlVisualNode::translate(const QVector3D &vector) +{ + setPosition(position() + vector); +} + void QmlVisualNode::setDoubleProperty(const PropertyName &name, double value) { modelNode().variantProperty(name).setValue(value); } -void QmlVisualNode::initializePosition(const QmlVisualNode::Position &position) +void QmlVisualNode::setPosition(const QmlVisualNode::Position &position) { - if (!position.m_2dPos.isNull()) { - setDoubleProperty("x", qRound(position.m_2dPos.x())); - setDoubleProperty("y", qRound(position.m_2dPos.y())); - } else if (!position.m_3dPos.isNull()) { - setDoubleProperty("x", position.m_3dPos.x()); - setDoubleProperty("y", position.m_3dPos.y()); - setDoubleProperty("z", position.m_3dPos.z()); + if (!isValid()) + return; + + setDoubleProperty("x", position.x()); + setDoubleProperty("y", position.y()); + + if (position.is3D() && modelNode().metaInfo().isQtQuick3DNode()) + setDoubleProperty("z", position.z()); +} + +QmlVisualNode::Position QmlVisualNode::position() const +{ + if (!isValid()) + return {}; + + double x = modelNode().variantProperty("x").value().toDouble(); + double y = modelNode().variantProperty("y").value().toDouble(); + + if (modelNode().metaInfo().isQtQuick3DModel()) { + double z = modelNode().variantProperty("z").value().toDouble(); + return Position(QVector3D(x,y,z)); } + return Position(QPointF(x,y)); } QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, @@ -230,7 +291,7 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view, if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) { ModelNode rootModelNode = rewriterView->rootModelNode(); inputModel->detachView(rewriterView.data()); - QmlVisualNode(rootModelNode).initializePosition(position); + QmlVisualNode(rootModelNode).setPosition(position); ModelMerger merger(view); return merger.insertModel(rootModelNode); } @@ -496,18 +557,20 @@ QmlModelState QmlModelStateGroup::state(const QString &name) const return QmlModelState(); } +bool QmlVisualNode::Position::is3D() const +{ + return m_is3D; +} + QList > QmlVisualNode::Position::propertyPairList() const { QList > propertyPairList; - if (!m_2dPos.isNull()) { - propertyPairList.append({"x", QVariant(qRound(m_2dPos.x()))}); - propertyPairList.append({"y", QVariant(qRound(m_2dPos.y()))}); - } else if (!m_3dPos.isNull()) { - propertyPairList.append({"x", QVariant(m_3dPos.x())}); - propertyPairList.append({"y", QVariant(m_3dPos.y())}); - propertyPairList.append({"z", QVariant(m_3dPos.z())}); - } + propertyPairList.append({"x", QVariant(qRound(x()))}); + propertyPairList.append({"y", QVariant(qRound(y()))}); + + if (m_is3D) + propertyPairList.append({"z", QVariant(z())}); return propertyPairList; } From 4d1041169eceb630604eab8d25f257ae9d15a988 Mon Sep 17 00:00:00 2001 From: Pranta Dastider Date: Tue, 8 Nov 2022 15:59:55 +0100 Subject: [PATCH 28/71] QmlDesigner: Update Version Number Update version numbers of software in the Qt Bridge "Supported Platforms" document. Change-Id: I143a3c8b207db74c6f6e91dcf7e523d03062e6ea Reviewed-by: Thomas Hartmann --- doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc index 4827453aba7..5a50eb2bf40 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc @@ -36,9 +36,9 @@ \QB is available for the following design tools: \list - \li Adobe Photoshop version 22.3.1 + \li Adobe Photoshop version 24.0 \li Adobe XD version 55.0.12 - \li Figma version 97.x - \li Sketch version 72.2 + \li Figma version 116.4 + \li Sketch version 90.0 \endlist */ From ac526d326cab6f19955cec4e19c73bc309bd96c8 Mon Sep 17 00:00:00 2001 From: Pranta Dastider Date: Tue, 8 Nov 2022 15:11:01 +0100 Subject: [PATCH 29/71] QmlDesigner: Update qtbridge typo In the documentation of "Using Qt Bridge for Sketch" there was a typo regarding qtbridge. This is for fixing that particular text. Fixes: QDS-8188 Change-Id: If87f6561656f61a43888e1ddc517020cc576cbf6 Reviewed-by: Mats Honkamaa Reviewed-by: Leena Miettinen --- doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc index 88729477842..50bfff87060 100644 --- a/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc +++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-sketch-using.qdoc @@ -231,7 +231,7 @@ you specified. This might take a little while depending on the complexity of your project. - You can now create a project in \QDS and import the .atbrige archive to it, as + You can now create a project in \QDS and import the .qtbridge archive to it, as described in \l {Creating Projects} and \l{Importing Designs}. \section1 Specifying Export Path and Asset Format From 63022d08ea8f9f04a75d301602e639b83b1b7396 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 2 Nov 2022 13:58:34 +0100 Subject: [PATCH 30/71] QmlDesigner: QmlPuppet as standalone tool The qmlpuppet is now a standalone tool. There is new a library too with the communication code. That is shared between the designer and the puppet. It's in a .cmake file so it can be included by the standalone tool if it is not part of a designer build. Task-number: QDS-5879 Change-Id: I2bc2a0b463fbb3e0c8c23d182abfd368cf87e968 Reviewed-by: Thomas Hartmann Reviewed-by: Reviewed-by: Qt CI Bot --- share/qtcreator/CMakeLists.txt | 1 - .../qml/qmlpuppet/commands/commands.pri | 75 -------- .../qml/qmlpuppet/container/container.pri | 26 --- .../qml/qmlpuppet/interfaces/interfaces.pri | 8 - .../qml/qmlpuppet/qml2puppet/qml2puppet.pri | 46 ----- .../qml/qmlpuppet/qml2puppet/qml2puppet.pro | 11 -- .../qml/qmlpuppet/qmlpuppet_utilities.pri | 31 ---- share/qtcreator/qml/qmlpuppet/types/types.pri | 3 - src/libs/CMakeLists.txt | 1 + .../qmlpuppetcommunication/CMakeLists.txt | 1 + .../QmlPuppetCommunication.cmake | 87 +++++++++ .../commands/captureddatacommand.h | 0 .../commands/changeauxiliarycommand.cpp | 0 .../commands/changeauxiliarycommand.h | 0 .../commands/changebindingscommand.cpp | 0 .../commands/changebindingscommand.h | 0 .../commands/changefileurlcommand.cpp | 0 .../commands/changefileurlcommand.h | 0 .../commands/changeidscommand.cpp | 0 .../commands/changeidscommand.h | 0 .../commands/changelanguagecommand.cpp | 0 .../commands/changelanguagecommand.h | 0 .../commands/changenodesourcecommand.cpp | 0 .../commands/changenodesourcecommand.h | 0 .../changepreviewimagesizecommand.cpp | 0 .../commands/changepreviewimagesizecommand.h | 0 .../commands/changeselectioncommand.cpp | 0 .../commands/changeselectioncommand.h | 0 .../commands/changestatecommand.cpp | 0 .../commands/changestatecommand.h | 0 .../commands/changevaluescommand.cpp | 0 .../commands/changevaluescommand.h | 0 .../commands/childrenchangedcommand.cpp | 0 .../commands/childrenchangedcommand.h | 0 .../commands/clearscenecommand.cpp | 0 .../commands/clearscenecommand.h | 0 .../commands/completecomponentcommand.cpp | 0 .../commands/completecomponentcommand.h | 0 .../commands/componentcompletedcommand.cpp | 0 .../commands/componentcompletedcommand.h | 0 .../commands/createinstancescommand.cpp | 0 .../commands/createinstancescommand.h | 0 .../commands/createscenecommand.cpp | 0 .../commands/createscenecommand.h | 0 .../commands/debugoutputcommand.cpp | 0 .../commands/debugoutputcommand.h | 0 .../commands/endpuppetcommand.cpp | 0 .../commands/endpuppetcommand.h | 0 .../commands/informationchangedcommand.cpp | 0 .../commands/informationchangedcommand.h | 0 .../commands/inputeventcommand.cpp | 0 .../commands/inputeventcommand.h | 0 .../commands/nanotracecommand.cpp | 0 .../commands/nanotracecommand.h | 0 .../commands/pixmapchangedcommand.cpp | 0 .../commands/pixmapchangedcommand.h | 0 .../commands/puppetalivecommand.cpp | 0 .../commands/puppetalivecommand.h | 0 .../commands/puppettocreatorcommand.cpp | 0 .../commands/puppettocreatorcommand.h | 0 .../commands/removeinstancescommand.cpp | 0 .../commands/removeinstancescommand.h | 0 .../commands/removepropertiescommand.cpp | 0 .../commands/removepropertiescommand.h | 0 .../commands/removesharedmemorycommand.cpp | 0 .../commands/removesharedmemorycommand.h | 0 .../commands/reparentinstancescommand.cpp | 0 .../commands/reparentinstancescommand.h | 0 .../requestmodelnodepreviewimagecommand.cpp | 0 .../requestmodelnodepreviewimagecommand.h | 0 .../commands/scenecreatedcommand.h | 0 .../statepreviewimagechangedcommand.cpp | 0 .../statepreviewimagechangedcommand.h | 0 .../commands/synchronizecommand.h | 0 .../commands/tokencommand.cpp | 0 .../commands/tokencommand.h | 0 .../commands/update3dviewstatecommand.cpp | 0 .../commands/update3dviewstatecommand.h | 0 .../commands/valueschangedcommand.cpp | 0 .../commands/valueschangedcommand.h | 0 .../commands/view3dactioncommand.cpp | 0 .../commands/view3dactioncommand.h | 0 .../container/addimportcontainer.cpp | 0 .../container/addimportcontainer.h | 0 .../container/idcontainer.cpp | 0 .../container/idcontainer.h | 0 .../container/imagecontainer.cpp | 0 .../container/imagecontainer.h | 0 .../container/informationcontainer.cpp | 0 .../container/informationcontainer.h | 0 .../container/instancecontainer.cpp | 0 .../container/instancecontainer.h | 0 .../container/mockuptypecontainer.cpp | 0 .../container/mockuptypecontainer.h | 0 .../container/propertyabstractcontainer.cpp | 0 .../container/propertyabstractcontainer.h | 0 .../container/propertybindingcontainer.cpp | 0 .../container/propertybindingcontainer.h | 0 .../container/propertyvaluecontainer.cpp | 0 .../container/propertyvaluecontainer.h | 0 .../container/reparentcontainer.cpp | 0 .../container/reparentcontainer.h | 0 .../container/sharedmemory.h | 0 .../container/sharedmemory_qt.cpp | 0 .../container/sharedmemory_unix.cpp | 0 .../interfaces/commondefines.h | 0 .../interfaces/nodeinstanceclientinterface.h | 0 .../interfaces/nodeinstanceglobal.h | 0 .../nodeinstanceserverinterface.cpp | 0 .../interfaces/nodeinstanceserverinterface.h | 0 .../types/enumeration.h | 0 src/plugins/qmldesigner/CMakeLists.txt | 125 +------------ src/tools/qml2puppet/CMakeLists.txt | 169 +++++------------- .../tools/qml2puppet}/editor3d_qt5.qrc | 0 .../tools/qml2puppet}/editor3d_qt6.qrc | 0 .../tools/qml2puppet}/html/welcome.html | 0 .../images/non-visual-component.png | Bin .../images/non-visual-component@2x.png | Bin .../qml2puppet}/images/template_image.png | Bin .../tools/qml2puppet}/images/webkit.png | Bin .../tools/qml2puppet}/instances/instances.pri | 0 .../instances/nodeinstanceclientproxy.cpp | 0 .../instances/nodeinstanceclientproxy.h | 0 .../tools/qml2puppet}/mockfiles/Dialog.qml | 0 .../qml2puppet}/mockfiles/GenericBackend.qml | 0 .../tools/qml2puppet}/mockfiles/SwipeView.qml | 0 .../qml2puppet}/mockfiles/ToggleButton.qml | 0 .../qml2puppet}/mockfiles/ToolBarButton.qml | 0 .../tools/qml2puppet}/mockfiles/Window.qml | 0 .../qml2puppet}/mockfiles/images/area.png | Bin .../qml2puppet}/mockfiles/images/area@2x.png | Bin .../mockfiles/images/directional.png | Bin .../mockfiles/images/directional@2x.png | Bin .../mockfiles/images/editor_camera.png | Bin .../mockfiles/images/editor_camera@2x.png | Bin .../images/editor_particlesystem.png | Bin .../images/editor_particlesystem@2x.png | Bin .../mockfiles/images/floor_tex.png | Bin .../qml2puppet}/mockfiles/images/point.png | Bin .../qml2puppet}/mockfiles/images/point@2x.png | Bin .../mockfiles/images/preview_landscape.hdr | Bin .../mockfiles/images/preview_studio.hdr | Bin .../qml2puppet}/mockfiles/images/spot.png | Bin .../qml2puppet}/mockfiles/images/spot@2x.png | Bin .../mockfiles/images/static_floor.png | Bin .../qml2puppet}/mockfiles/meshes/arrow.mesh | Bin .../mockfiles/meshes/axishelper.mesh | Bin .../qml2puppet}/mockfiles/meshes/ring.mesh | Bin .../mockfiles/meshes/ringselect.mesh | Bin .../mockfiles/meshes/scalerod.mesh | Bin .../mockfiles/qt5/AdjustableArrow.qml | 0 .../mockfiles/qt5/AreaLightHandle.qml | 0 .../tools/qml2puppet}/mockfiles/qt5/Arrow.qml | 0 .../mockfiles/qt5/AutoScaleHelper.qml | 0 .../qml2puppet}/mockfiles/qt5/AxisHelper.qml | 0 .../mockfiles/qt5/AxisHelperArm.qml | 0 .../mockfiles/qt5/CameraFrustum.qml | 0 .../qml2puppet}/mockfiles/qt5/CameraGizmo.qml | 0 .../mockfiles/qt5/DirectionalDraggable.qml | 0 .../mockfiles/qt5/EditCameraController.qml | 0 .../qml2puppet}/mockfiles/qt5/EditView3D.qml | 0 .../qml2puppet}/mockfiles/qt5/FadeHandle.qml | 0 .../qml2puppet}/mockfiles/qt5/HelperGrid.qml | 0 .../qml2puppet}/mockfiles/qt5/IconGizmo.qml | 0 .../mockfiles/qt5/IconRenderer3D.qml | 0 .../qml2puppet}/mockfiles/qt5/LightGizmo.qml | 0 .../mockfiles/qt5/LightIconGizmo.qml | 0 .../qml2puppet}/mockfiles/qt5/LightModel.qml | 0 .../qml2puppet}/mockfiles/qt5/Line3D.qml | 0 .../mockfiles/qt5/MaterialNodeView.qml | 0 .../mockfiles/qt5/ModelNode2DImageView.qml | 0 .../mockfiles/qt5/ModelNode3DImageView.qml | 0 .../mockfiles/qt5/ModelNodeView.qml | 0 .../qml2puppet}/mockfiles/qt5/MoveGizmo.qml | 0 .../mockfiles/qt5/NodeNodeView.qml | 0 .../qml2puppet}/mockfiles/qt5/Overlay2D.qml | 0 .../mockfiles/qt5/PlanarDraggable.qml | 0 .../mockfiles/qt5/PlanarMoveHandle.qml | 0 .../mockfiles/qt5/PlanarScaleHandle.qml | 0 .../qml2puppet}/mockfiles/qt5/RotateGizmo.qml | 0 .../qml2puppet}/mockfiles/qt5/RotateRing.qml | 0 .../qml2puppet}/mockfiles/qt5/ScaleGizmo.qml | 0 .../qml2puppet}/mockfiles/qt5/ScaleRod.qml | 0 .../qml2puppet}/mockfiles/qt5/SceneView3D.qml | 0 .../mockfiles/qt5/SelectionBox.qml | 0 .../mockfiles/qt5/SpotLightHandle.qml | 0 .../mockfiles/qt6/AdjustableArrow.qml | 0 .../mockfiles/qt6/AreaLightHandle.qml | 0 .../tools/qml2puppet}/mockfiles/qt6/Arrow.qml | 0 .../mockfiles/qt6/AutoScaleHelper.qml | 0 .../qml2puppet}/mockfiles/qt6/AxisHelper.qml | 0 .../mockfiles/qt6/AxisHelperArm.qml | 0 .../mockfiles/qt6/CameraFrustum.qml | 0 .../qml2puppet}/mockfiles/qt6/CameraGizmo.qml | 0 .../mockfiles/qt6/DirectionalDraggable.qml | 0 .../mockfiles/qt6/EditCameraController.qml | 0 .../qml2puppet}/mockfiles/qt6/EditView3D.qml | 0 .../qml2puppet}/mockfiles/qt6/FadeHandle.qml | 0 .../qml2puppet}/mockfiles/qt6/HelperGrid.qml | 0 .../qml2puppet}/mockfiles/qt6/IconGizmo.qml | 0 .../qml2puppet}/mockfiles/qt6/LightGizmo.qml | 0 .../mockfiles/qt6/LightIconGizmo.qml | 0 .../qml2puppet}/mockfiles/qt6/LightModel.qml | 0 .../qml2puppet}/mockfiles/qt6/Line3D.qml | 0 .../mockfiles/qt6/MaterialNodeView.qml | 0 .../mockfiles/qt6/ModelNode2DImageView.qml | 0 .../mockfiles/qt6/ModelNode3DImageView.qml | 0 .../mockfiles/qt6/ModelNodeView.qml | 0 .../qml2puppet}/mockfiles/qt6/MoveGizmo.qml | 0 .../mockfiles/qt6/NodeNodeView.qml | 0 .../qml2puppet}/mockfiles/qt6/Overlay2D.qml | 0 .../mockfiles/qt6/ParticleEmitterGizmo.qml | 0 .../mockfiles/qt6/ParticleSystemGizmo.qml | 0 .../mockfiles/qt6/PlanarDraggable.qml | 0 .../mockfiles/qt6/PlanarMoveHandle.qml | 0 .../mockfiles/qt6/PlanarScaleHandle.qml | 0 .../qml2puppet}/mockfiles/qt6/RotateGizmo.qml | 0 .../qml2puppet}/mockfiles/qt6/RotateRing.qml | 0 .../qml2puppet}/mockfiles/qt6/ScaleGizmo.qml | 0 .../qml2puppet}/mockfiles/qt6/ScaleRod.qml | 0 .../qml2puppet}/mockfiles/qt6/SceneView3D.qml | 0 .../mockfiles/qt6/SelectionBox.qml | 0 .../mockfiles/qt6/SpotLightHandle.qml | 0 .../tools/qml2puppet}/qml2puppet/Info.plist | 0 .../qml2puppet/editor3d/camerageometry.cpp | 0 .../qml2puppet/editor3d/camerageometry.h | 0 .../qml2puppet/editor3d/editor3d.pri | 0 .../qml2puppet/editor3d/generalhelper.cpp | 0 .../qml2puppet/editor3d/generalhelper.h | 0 .../qml2puppet/editor3d/geometrybase.cpp | 0 .../qml2puppet/editor3d/geometrybase.h | 0 .../qml2puppet/editor3d/gridgeometry.cpp | 0 .../qml2puppet/editor3d/gridgeometry.h | 0 .../editor3d/icongizmoimageprovider.cpp | 0 .../editor3d/icongizmoimageprovider.h | 0 .../qml2puppet/editor3d/lightgeometry.cpp | 0 .../qml2puppet/editor3d/lightgeometry.h | 0 .../qml2puppet/editor3d/linegeometry.cpp | 0 .../qml2puppet/editor3d/linegeometry.h | 0 .../qml2puppet/editor3d/mousearea3d.cpp | 0 .../qml2puppet/editor3d/mousearea3d.h | 0 .../editor3d/qt5compat/qquick3darealight.cpp | 0 .../editor3d/qt5compat/qquick3darealight_p.h | 0 .../editor3d/selectionboxgeometry.cpp | 0 .../editor3d/selectionboxgeometry.h | 0 .../qml2puppet/iconrenderer/iconrenderer.cpp | 0 .../qml2puppet/iconrenderer/iconrenderer.h | 0 .../qml2puppet/iconrenderer/iconrenderer.pri | 0 .../qml2puppet/import3d/import3d.cpp | 0 .../qml2puppet/import3d/import3d.h | 0 .../qml2puppet/import3d/import3d.pri | 0 .../instances/anchorchangesnodeinstance.cpp | 0 .../instances/anchorchangesnodeinstance.h | 0 .../qml2puppet/instances/animationdriver.cpp | 0 .../qml2puppet/instances/animationdriver.h | 0 .../instances/behaviornodeinstance.cpp | 0 .../instances/behaviornodeinstance.h | 0 .../capturenodeinstanceserverdispatcher.cpp | 0 .../capturenodeinstanceserverdispatcher.h | 0 .../instances/childrenchangeeventfilter.cpp | 0 .../instances/childrenchangeeventfilter.h | 0 .../instances/componentnodeinstance.cpp | 0 .../instances/componentnodeinstance.h | 0 .../instances/dummycontextobject.cpp | 0 .../qml2puppet/instances/dummycontextobject.h | 0 .../instances/dummynodeinstance.cpp | 0 .../qml2puppet/instances/dummynodeinstance.h | 0 .../qml2puppet/instances/instances.pri | 0 .../instances/layoutnodeinstance.cpp | 0 .../qml2puppet/instances/layoutnodeinstance.h | 0 .../instances/nodeinstanceserver.cpp | 0 .../qml2puppet/instances/nodeinstanceserver.h | 0 .../nodeinstanceserverdispatcher.cpp | 0 .../instances/nodeinstanceserverdispatcher.h | 0 .../instances/nodeinstancesignalspy.cpp | 0 .../instances/nodeinstancesignalspy.h | 0 .../instances/objectnodeinstance.cpp | 0 .../qml2puppet/instances/objectnodeinstance.h | 0 .../instances/positionernodeinstance.cpp | 0 .../instances/positionernodeinstance.h | 0 .../qmlpropertychangesnodeinstance.cpp | 0 .../qmlpropertychangesnodeinstance.h | 0 .../instances/qmlstatenodeinstance.cpp | 0 .../instances/qmlstatenodeinstance.h | 0 .../instances/qmltransitionnodeinstance.cpp | 0 .../instances/qmltransitionnodeinstance.h | 0 .../qt3dpresentationnodeinstance.cpp | 0 .../instances/qt3dpresentationnodeinstance.h | 0 .../qt5captureimagenodeinstanceserver.cpp | 0 .../qt5captureimagenodeinstanceserver.h | 0 .../qt5capturepreviewnodeinstanceserver.cpp | 0 .../qt5capturepreviewnodeinstanceserver.h | 0 .../qt5informationnodeinstanceserver.cpp | 0 .../qt5informationnodeinstanceserver.h | 0 .../instances/qt5nodeinstanceclientproxy.cpp | 0 .../instances/qt5nodeinstanceclientproxy.h | 0 .../instances/qt5nodeinstanceserver.cpp | 0 .../instances/qt5nodeinstanceserver.h | 0 .../qt5previewnodeinstanceserver.cpp | 0 .../instances/qt5previewnodeinstanceserver.h | 0 .../instances/qt5rendernodeinstanceserver.cpp | 0 .../instances/qt5rendernodeinstanceserver.h | 0 .../instances/qt5testnodeinstanceserver.cpp | 0 .../instances/qt5testnodeinstanceserver.h | 0 .../instances/quick3dmaterialnodeinstance.cpp | 0 .../instances/quick3dmaterialnodeinstance.h | 0 .../instances/quick3dnodeinstance.cpp | 0 .../instances/quick3dnodeinstance.h | 0 .../quick3drenderablenodeinstance.cpp | 0 .../instances/quick3drenderablenodeinstance.h | 0 .../instances/quick3dtexturenodeinstance.cpp | 0 .../instances/quick3dtexturenodeinstance.h | 0 .../instances/quickitemnodeinstance.cpp | 0 .../instances/quickitemnodeinstance.h | 0 .../instances/servernodeinstance.cpp | 0 .../qml2puppet/instances/servernodeinstance.h | 0 .../qml2puppet/instances/viewconfig.cpp | 0 .../qml2puppet/instances/viewconfig.h | 0 .../qml2puppet}/qml2puppet/qml2puppetmain.cpp | 0 .../qmlprivategate/qmlprivategate.cpp | 0 .../qmlprivategate/qmlprivategate.h | 0 .../qmlprivategate/qmlprivategate.pri | 0 .../tools/qml2puppet}/qmlpuppet.qrc | 0 tests/unit/unittest/CMakeLists.txt | 6 +- 324 files changed, 136 insertions(+), 454 deletions(-) delete mode 100644 share/qtcreator/qml/qmlpuppet/commands/commands.pri delete mode 100644 share/qtcreator/qml/qmlpuppet/container/container.pri delete mode 100644 share/qtcreator/qml/qmlpuppet/interfaces/interfaces.pri delete mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri delete mode 100644 share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pro delete mode 100644 share/qtcreator/qml/qmlpuppet/qmlpuppet_utilities.pri delete mode 100644 share/qtcreator/qml/qmlpuppet/types/types.pri create mode 100644 src/libs/qmlpuppetcommunication/CMakeLists.txt create mode 100644 src/libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/captureddatacommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeauxiliarycommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeauxiliarycommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changebindingscommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changebindingscommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changefileurlcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changefileurlcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeidscommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeidscommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changelanguagecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changelanguagecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changenodesourcecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changenodesourcecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changepreviewimagesizecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changepreviewimagesizecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeselectioncommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changeselectioncommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changestatecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changestatecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changevaluescommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/changevaluescommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/childrenchangedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/childrenchangedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/clearscenecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/clearscenecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/completecomponentcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/completecomponentcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/componentcompletedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/componentcompletedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/createinstancescommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/createinstancescommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/createscenecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/createscenecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/debugoutputcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/debugoutputcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/endpuppetcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/endpuppetcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/informationchangedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/informationchangedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/inputeventcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/inputeventcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/nanotracecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/nanotracecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/pixmapchangedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/pixmapchangedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/puppetalivecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/puppetalivecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/puppettocreatorcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/puppettocreatorcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removeinstancescommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removeinstancescommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removepropertiescommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removepropertiescommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removesharedmemorycommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/removesharedmemorycommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/reparentinstancescommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/reparentinstancescommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/requestmodelnodepreviewimagecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/requestmodelnodepreviewimagecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/scenecreatedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/statepreviewimagechangedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/statepreviewimagechangedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/synchronizecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/tokencommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/tokencommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/update3dviewstatecommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/update3dviewstatecommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/valueschangedcommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/valueschangedcommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/view3dactioncommand.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/commands/view3dactioncommand.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/addimportcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/addimportcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/idcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/idcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/imagecontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/imagecontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/informationcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/informationcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/instancecontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/instancecontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/mockuptypecontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/mockuptypecontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertyabstractcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertyabstractcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertybindingcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertybindingcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertyvaluecontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/propertyvaluecontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/reparentcontainer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/reparentcontainer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/sharedmemory.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/sharedmemory_qt.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/container/sharedmemory_unix.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/interfaces/commondefines.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/interfaces/nodeinstanceclientinterface.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/interfaces/nodeinstanceglobal.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/interfaces/nodeinstanceserverinterface.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/interfaces/nodeinstanceserverinterface.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/libs/qmlpuppetcommunication}/types/enumeration.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/editor3d_qt5.qrc (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/editor3d_qt6.qrc (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/html/welcome.html (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/images/non-visual-component.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/images/non-visual-component@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/images/template_image.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/images/webkit.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/instances/instances.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/instances/nodeinstanceclientproxy.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/instances/nodeinstanceclientproxy.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/Dialog.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/GenericBackend.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/SwipeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/ToggleButton.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/ToolBarButton.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/Window.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/area.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/area@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/directional.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/directional@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/editor_camera.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/editor_camera@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/editor_particlesystem.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/editor_particlesystem@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/floor_tex.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/point.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/point@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/preview_landscape.hdr (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/preview_studio.hdr (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/spot.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/spot@2x.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/images/static_floor.png (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/meshes/arrow.mesh (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/meshes/axishelper.mesh (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/meshes/ring.mesh (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/meshes/ringselect.mesh (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/meshes/scalerod.mesh (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/AdjustableArrow.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/AreaLightHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/Arrow.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/AutoScaleHelper.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/AxisHelper.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/AxisHelperArm.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/CameraFrustum.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/CameraGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/DirectionalDraggable.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/EditCameraController.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/EditView3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/FadeHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/HelperGrid.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/IconGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/IconRenderer3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/LightGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/LightIconGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/LightModel.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/Line3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/MaterialNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/ModelNode2DImageView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/ModelNode3DImageView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/ModelNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/MoveGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/NodeNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/Overlay2D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/PlanarDraggable.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/PlanarMoveHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/PlanarScaleHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/RotateGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/RotateRing.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/ScaleGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/ScaleRod.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/SceneView3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/SelectionBox.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt5/SpotLightHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/AdjustableArrow.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/AreaLightHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/Arrow.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/AutoScaleHelper.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/AxisHelper.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/AxisHelperArm.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/CameraFrustum.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/CameraGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/DirectionalDraggable.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/EditCameraController.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/EditView3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/FadeHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/HelperGrid.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/IconGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/LightGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/LightIconGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/LightModel.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/Line3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/MaterialNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ModelNode2DImageView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ModelNode3DImageView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ModelNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/MoveGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/NodeNodeView.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/Overlay2D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ParticleEmitterGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ParticleSystemGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/PlanarDraggable.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/PlanarMoveHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/PlanarScaleHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/RotateGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/RotateRing.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ScaleGizmo.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/ScaleRod.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/SceneView3D.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/SelectionBox.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/mockfiles/qt6/SpotLightHandle.qml (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/Info.plist (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/camerageometry.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/camerageometry.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/editor3d.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/generalhelper.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/generalhelper.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/geometrybase.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/geometrybase.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/gridgeometry.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/gridgeometry.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/icongizmoimageprovider.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/icongizmoimageprovider.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/lightgeometry.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/lightgeometry.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/linegeometry.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/linegeometry.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/mousearea3d.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/mousearea3d.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/qt5compat/qquick3darealight.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/qt5compat/qquick3darealight_p.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/selectionboxgeometry.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/editor3d/selectionboxgeometry.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/iconrenderer/iconrenderer.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/iconrenderer/iconrenderer.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/iconrenderer/iconrenderer.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/import3d/import3d.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/import3d/import3d.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/import3d/import3d.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/anchorchangesnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/anchorchangesnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/animationdriver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/animationdriver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/behaviornodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/behaviornodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/capturenodeinstanceserverdispatcher.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/capturenodeinstanceserverdispatcher.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/childrenchangeeventfilter.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/childrenchangeeventfilter.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/componentnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/componentnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/dummycontextobject.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/dummycontextobject.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/dummynodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/dummynodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/instances.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/layoutnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/layoutnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstanceserverdispatcher.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstanceserverdispatcher.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstancesignalspy.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/nodeinstancesignalspy.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/objectnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/objectnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/positionernodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/positionernodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmlpropertychangesnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmlpropertychangesnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmlstatenodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmlstatenodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmltransitionnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qmltransitionnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt3dpresentationnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt3dpresentationnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5captureimagenodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5informationnodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5informationnodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5nodeinstanceclientproxy.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5nodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5nodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5previewnodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5previewnodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5rendernodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5rendernodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5testnodeinstanceserver.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/qt5testnodeinstanceserver.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dmaterialnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dmaterialnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3drenderablenodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3drenderablenodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dtexturenodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quick3dtexturenodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quickitemnodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/quickitemnodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/servernodeinstance.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/servernodeinstance.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/viewconfig.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/instances/viewconfig.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qml2puppet/qml2puppetmain.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qmlprivategate/qmlprivategate.cpp (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qmlprivategate/qmlprivategate.h (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qmlprivategate/qmlprivategate.pri (100%) rename {share/qtcreator/qml/qmlpuppet => src/tools/qml2puppet}/qmlpuppet.qrc (100%) diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt index 25d976ea9cf..5bd0f05bf22 100644 --- a/share/qtcreator/CMakeLists.txt +++ b/share/qtcreator/CMakeLists.txt @@ -4,7 +4,6 @@ set(resource_directories glsl indexer_preincludes modeleditor - qml qmldesigner qmlicons qml-type-descriptions diff --git a/share/qtcreator/qml/qmlpuppet/commands/commands.pri b/share/qtcreator/qml/qmlpuppet/commands/commands.pri deleted file mode 100644 index 0fb8e0132c7..00000000000 --- a/share/qtcreator/qml/qmlpuppet/commands/commands.pri +++ /dev/null @@ -1,75 +0,0 @@ -INCLUDEPATH += $$PWD $$PWD/../interfaces - -HEADERS += $$PWD/synchronizecommand.h \ \ - $$PWD/captureddatacommand.h \ - $$PWD/changepreviewimagesizecommand.h \ - $$PWD/changelanguagecommand.h \ - $$PWD//debugoutputcommand.h \ - $$PWD/endpuppetcommand.h \ - $$PWD/scenecreatedcommand.h \ - $$PWD/tokencommand.h \ - $$PWD/componentcompletedcommand.h \ - $$PWD/completecomponentcommand.h \ - $$PWD/statepreviewimagechangedcommand.h \ - $$PWD/childrenchangedcommand.h \ - $$PWD/changebindingscommand.h \ - $$PWD/changefileurlcommand.h \ - $$PWD/changeidscommand.h \ - $$PWD/changenodesourcecommand.h \ - $$PWD/changestatecommand.h \ - $$PWD/changevaluescommand.h \ - $$PWD/createscenecommand.h \ - $$PWD/clearscenecommand.h \ - $$PWD/createinstancescommand.h \ - $$PWD/informationchangedcommand.h \ - $$PWD/nanotracecommand.h \ - $$PWD/pixmapchangedcommand.h \ - $$PWD/removeinstancescommand.h \ - $$PWD/removepropertiescommand.h \ - $$PWD/reparentinstancescommand.h \ - $$PWD/valueschangedcommand.h \ - $$PWD/changeauxiliarycommand.h \ - $$PWD/removesharedmemorycommand.h \ - $$PWD/puppetalivecommand.h \ - $$PWD/changeselectioncommand.h \ - $$PWD/update3dviewstatecommand.h \ - $$PWD/puppettocreatorcommand.h \ - $$PWD/inputeventcommand.h \ - $$PWD/view3dactioncommand.h \ - $$PWD/requestmodelnodepreviewimagecommand.h - -SOURCES += \ - $$PWD/changepreviewimagesizecommand.cpp \ - $$PWD/changelanguagecommand.cpp \ - $$PWD/debugoutputcommand.cpp \ - $$PWD/endpuppetcommand.cpp \ - $$PWD/tokencommand.cpp \ - $$PWD/componentcompletedcommand.cpp \ - $$PWD/completecomponentcommand.cpp \ - $$PWD/statepreviewimagechangedcommand.cpp \ - $$PWD/childrenchangedcommand.cpp \ - $$PWD/changebindingscommand.cpp \ - $$PWD/changefileurlcommand.cpp \ - $$PWD/changeidscommand.cpp \ - $$PWD/changenodesourcecommand.cpp \ - $$PWD/changestatecommand.cpp \ - $$PWD/changevaluescommand.cpp \ - $$PWD/informationchangedcommand.cpp \ - $$PWD/nanotracecommand.cpp \ - $$PWD/removeinstancescommand.cpp \ - $$PWD/removepropertiescommand.cpp \ - $$PWD/reparentinstancescommand.cpp \ - $$PWD/valueschangedcommand.cpp \ - $$PWD/clearscenecommand.cpp \ - $$PWD/createinstancescommand.cpp \ - $$PWD/createscenecommand.cpp \ - $$PWD/pixmapchangedcommand.cpp \ - $$PWD/changeauxiliarycommand.cpp \ - $$PWD/removesharedmemorycommand.cpp \ - $$PWD/puppetalivecommand.cpp \ - $$PWD/changeselectioncommand.cpp \ - $$PWD/update3dviewstatecommand.cpp \ - $$PWD/puppettocreatorcommand.cpp \ - $$PWD/inputeventcommand.cpp \ - $$PWD/view3dactioncommand.cpp \ - $$PWD/requestmodelnodepreviewimagecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/container.pri b/share/qtcreator/qml/qmlpuppet/container/container.pri deleted file mode 100644 index 381e5cf117d..00000000000 --- a/share/qtcreator/qml/qmlpuppet/container/container.pri +++ /dev/null @@ -1,26 +0,0 @@ -INCLUDEPATH += $$PWD/ - -HEADERS += $$PWD/addimportcontainer.h -HEADERS += $$PWD/mockuptypecontainer.h -HEADERS += $$PWD/sharedmemory.h -HEADERS += $$PWD/imagecontainer.h -HEADERS += $$PWD/idcontainer.h -HEADERS += $$PWD/informationcontainer.h -HEADERS += $$PWD/instancecontainer.h -HEADERS += $$PWD/reparentcontainer.h -HEADERS += $$PWD/propertyabstractcontainer.h -HEADERS += $$PWD/propertybindingcontainer.h -HEADERS += $$PWD/propertyvaluecontainer.h - -SOURCES += $$PWD/addimportcontainer.cpp -SOURCES += $$PWD/mockuptypecontainer.cpp -unix:SOURCES += $$PWD/sharedmemory_unix.cpp -!unix:SOURCES += $$PWD/sharedmemory_qt.cpp -SOURCES += $$PWD/imagecontainer.cpp -SOURCES += $$PWD/idcontainer.cpp -SOURCES += $$PWD/informationcontainer.cpp -SOURCES += $$PWD/instancecontainer.cpp -SOURCES += $$PWD/reparentcontainer.cpp -SOURCES += $$PWD/propertyabstractcontainer.cpp -SOURCES += $$PWD/propertybindingcontainer.cpp -SOURCES += $$PWD/propertyvaluecontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/interfaces.pri b/share/qtcreator/qml/qmlpuppet/interfaces/interfaces.pri deleted file mode 100644 index aeaf3a765e2..00000000000 --- a/share/qtcreator/qml/qmlpuppet/interfaces/interfaces.pri +++ /dev/null @@ -1,8 +0,0 @@ -INCLUDEPATH += $$PWD/ - -HEADERS += $$PWD/nodeinstanceclientinterface.h -HEADERS += $$PWD/nodeinstanceglobal.h -HEADERS += $$PWD/nodeinstanceserverinterface.h -HEADERS += $$PWD/commondefines.h - -SOURCES += $$PWD/nodeinstanceserverinterface.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri deleted file mode 100644 index 0b364d32b3e..00000000000 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri +++ /dev/null @@ -1,46 +0,0 @@ -QT += core gui widgets qml quick network -QT += core-private qml-private quick-private gui-private - -CONFIG += c++17 -win32:!mingw: QMAKE_CXXFLAGS += /std:c++17 - -DEFINES -= QT_CREATOR - -# This .pri file contains classes to enable a special multilanguage translator -MULTILANGUAGE_SUPPORT_PRI=$$(MULTILANGUAGE_SUPPORT_PRI) -!isEmpty(MULTILANGUAGE_SUPPORT_PRI) { - exists($$(MULTILANGUAGE_SUPPORT_PRI)): message(including \"$$(MULTILANGUAGE_SUPPORT_PRI)\") - else: error("MULTILANGUAGE_SUPPORT_PRI: \"$$(MULTILANGUAGE_SUPPORT_PRI)\" does not exist.") - include($$(MULTILANGUAGE_SUPPORT_PRI)) - DEFINES += MULTILANGUAGE_TRANSLATIONPROVIDER -} - -include (editor3d/editor3d.pri) -include (../instances/instances.pri) -include (instances/instances.pri) -include (../commands/commands.pri) -include (../container/container.pri) -include (../interfaces/interfaces.pri) -include (../types/types.pri) -include (../qmlprivategate/qmlprivategate.pri) -include (iconrenderer/iconrenderer.pri) -include (import3d/import3d.pri) - -SOURCES += $$PWD/qml2puppetmain.cpp -RESOURCES += $$PWD/../qmlpuppet.qrc - -versionAtLeast(QT_VERSION, 6.0.0): RESOURCES += $$PWD/../editor3d_qt6.qrc -else: RESOURCES += $$PWD/../editor3d_qt5.qrc - -DISTFILES += Info.plist - -unix:!openbsd:!osx: LIBS += -lrt # posix shared memory - -osx { - CONFIG -= app_bundle - QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$system_quote($$PWD/Info.plist) -} - -osx: target.path = $$INSTALL_LIBEXEC_PATH/qmldesigner -else: target.path = $$INSTALL_LIBEXEC_PATH -INSTALLS += target diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pro b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pro deleted file mode 100644 index 1457e8d10e8..00000000000 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pro +++ /dev/null @@ -1,11 +0,0 @@ -TARGET = qml2puppet - -TEMPLATE = app -CONFIG += console - -build_all:!build_pass { - CONFIG -= build_all - CONFIG += release -} - -include(qml2puppet.pri) diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet_utilities.pri b/share/qtcreator/qml/qmlpuppet/qmlpuppet_utilities.pri deleted file mode 100644 index 341550502a3..00000000000 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet_utilities.pri +++ /dev/null @@ -1,31 +0,0 @@ -# Try to find location of Qt private headers (see README) -isEmpty(QT_PRIVATE_HEADERS) { - QT_PRIVATE_HEADERS = $$[QT_INSTALL_HEADERS] -} else { - INCLUDEPATH += \ - $${QT_PRIVATE_HEADERS} \ - $${QT_PRIVATE_HEADERS}/QtCore \ - $${QT_PRIVATE_HEADERS}/QtGui \ - $${QT_PRIVATE_HEADERS}/QtScript \ - $${QT_PRIVATE_HEADERS}/QtDeclarative -} - -defineTest(minQtVersion) { - maj = $$1 - min = $$2 - patch = $$3 - isEqual(QT_MAJOR_VERSION, $$maj) { - isEqual(QT_MINOR_VERSION, $$min) { - isEqual(QT_PATCH_VERSION, $$patch) { - return(true) - } - greaterThan(QT_PATCH_VERSION, $$patch) { - return(true) - } - } - greaterThan(QT_MINOR_VERSION, $$min) { - return(true) - } - } - return(false) -} diff --git a/share/qtcreator/qml/qmlpuppet/types/types.pri b/share/qtcreator/qml/qmlpuppet/types/types.pri deleted file mode 100644 index e5f10bcbe46..00000000000 --- a/share/qtcreator/qml/qmlpuppet/types/types.pri +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDEPATH += $$PWD/ - -HEADERS += $$PWD/enumeration.h diff --git a/src/libs/CMakeLists.txt b/src/libs/CMakeLists.txt index 72658107376..0f2b3409398 100644 --- a/src/libs/CMakeLists.txt +++ b/src/libs/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(glsl) add_subdirectory(languageserverprotocol) add_subdirectory(sqlite) add_subdirectory(tracing) +add_subdirectory(qmlpuppetcommunication) add_subdirectory(qtcreatorcdbext) diff --git a/src/libs/qmlpuppetcommunication/CMakeLists.txt b/src/libs/qmlpuppetcommunication/CMakeLists.txt new file mode 100644 index 00000000000..a6b74f58e65 --- /dev/null +++ b/src/libs/qmlpuppetcommunication/CMakeLists.txt @@ -0,0 +1 @@ +include(QmlPuppetCommunication.cmake) diff --git a/src/libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake b/src/libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake new file mode 100644 index 00000000000..43cbc78af2d --- /dev/null +++ b/src/libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake @@ -0,0 +1,87 @@ +add_qtc_library(QmlPuppetCommunication STATIC + PROPERTIES AUTOUIC OFF + DEPENDS Qt5::Core Qt5::CorePrivate Qt5::Gui +) + +extend_qtc_library(QmlPuppetCommunication + CONDITION TARGET Nanotrace + PUBLIC_DEPENDS Nanotrace +) + +extend_qtc_library(QmlPuppetCommunication + PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/types + SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/types + SOURCES + enumeration.h +) + +extend_qtc_library(QmlPuppetCommunication + PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/interfaces + SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/interfaces + SOURCES + commondefines.h + nodeinstanceclientinterface.h + nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h + nodeinstanceglobal.h +) + +extend_qtc_library(QmlPuppetCommunication + PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/container + SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/container + SOURCES + addimportcontainer.cpp addimportcontainer.h + idcontainer.cpp idcontainer.h + imagecontainer.cpp imagecontainer.h + informationcontainer.cpp informationcontainer.h + instancecontainer.cpp instancecontainer.h + mockuptypecontainer.cpp mockuptypecontainer.h + propertyabstractcontainer.cpp propertyabstractcontainer.h + propertybindingcontainer.cpp propertybindingcontainer.h + propertyvaluecontainer.cpp propertyvaluecontainer.h + reparentcontainer.cpp reparentcontainer.h + sharedmemory.h + $,sharedmemory_unix.cpp,sharedmemory_qt.cpp> +) + +extend_qtc_library(QmlPuppetCommunication + PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/commands + SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/commands + SOURCES + captureddatacommand.h + changeauxiliarycommand.cpp changeauxiliarycommand.h + changebindingscommand.cpp changebindingscommand.h + changefileurlcommand.cpp changefileurlcommand.h + changeidscommand.cpp changeidscommand.h + changelanguagecommand.cpp changelanguagecommand.h + changenodesourcecommand.cpp changenodesourcecommand.h + changepreviewimagesizecommand.cpp changepreviewimagesizecommand.h + changeselectioncommand.cpp changeselectioncommand.h + changestatecommand.cpp changestatecommand.h + changevaluescommand.cpp changevaluescommand.h + childrenchangedcommand.cpp childrenchangedcommand.h + clearscenecommand.cpp clearscenecommand.h + completecomponentcommand.cpp completecomponentcommand.h + componentcompletedcommand.cpp componentcompletedcommand.h + createinstancescommand.cpp createinstancescommand.h + createscenecommand.cpp createscenecommand.h + debugoutputcommand.cpp debugoutputcommand.h + endpuppetcommand.cpp endpuppetcommand.h + informationchangedcommand.cpp informationchangedcommand.h + inputeventcommand.cpp inputeventcommand.h + nanotracecommand.cpp nanotracecommand.h + pixmapchangedcommand.cpp pixmapchangedcommand.h + puppetalivecommand.cpp puppetalivecommand.h + puppettocreatorcommand.cpp puppettocreatorcommand.h + removeinstancescommand.cpp removeinstancescommand.h + removepropertiescommand.cpp removepropertiescommand.h + removesharedmemorycommand.cpp removesharedmemorycommand.h + reparentinstancescommand.cpp reparentinstancescommand.h + requestmodelnodepreviewimagecommand.cpp requestmodelnodepreviewimagecommand.h + scenecreatedcommand.h + statepreviewimagechangedcommand.cpp statepreviewimagechangedcommand.h + synchronizecommand.h + tokencommand.cpp tokencommand.h + update3dviewstatecommand.cpp update3dviewstatecommand.h + valueschangedcommand.cpp valueschangedcommand.h + view3dactioncommand.cpp view3dactioncommand.h +) diff --git a/share/qtcreator/qml/qmlpuppet/commands/captureddatacommand.h b/src/libs/qmlpuppetcommunication/commands/captureddatacommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/captureddatacommand.h rename to src/libs/qmlpuppetcommunication/commands/captureddatacommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeauxiliarycommand.cpp b/src/libs/qmlpuppetcommunication/commands/changeauxiliarycommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeauxiliarycommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changeauxiliarycommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeauxiliarycommand.h b/src/libs/qmlpuppetcommunication/commands/changeauxiliarycommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeauxiliarycommand.h rename to src/libs/qmlpuppetcommunication/commands/changeauxiliarycommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changebindingscommand.cpp b/src/libs/qmlpuppetcommunication/commands/changebindingscommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changebindingscommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changebindingscommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changebindingscommand.h b/src/libs/qmlpuppetcommunication/commands/changebindingscommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changebindingscommand.h rename to src/libs/qmlpuppetcommunication/commands/changebindingscommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changefileurlcommand.cpp b/src/libs/qmlpuppetcommunication/commands/changefileurlcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changefileurlcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changefileurlcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changefileurlcommand.h b/src/libs/qmlpuppetcommunication/commands/changefileurlcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changefileurlcommand.h rename to src/libs/qmlpuppetcommunication/commands/changefileurlcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeidscommand.cpp b/src/libs/qmlpuppetcommunication/commands/changeidscommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeidscommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changeidscommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeidscommand.h b/src/libs/qmlpuppetcommunication/commands/changeidscommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeidscommand.h rename to src/libs/qmlpuppetcommunication/commands/changeidscommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changelanguagecommand.cpp b/src/libs/qmlpuppetcommunication/commands/changelanguagecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changelanguagecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changelanguagecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changelanguagecommand.h b/src/libs/qmlpuppetcommunication/commands/changelanguagecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changelanguagecommand.h rename to src/libs/qmlpuppetcommunication/commands/changelanguagecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changenodesourcecommand.cpp b/src/libs/qmlpuppetcommunication/commands/changenodesourcecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changenodesourcecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changenodesourcecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changenodesourcecommand.h b/src/libs/qmlpuppetcommunication/commands/changenodesourcecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changenodesourcecommand.h rename to src/libs/qmlpuppetcommunication/commands/changenodesourcecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changepreviewimagesizecommand.cpp b/src/libs/qmlpuppetcommunication/commands/changepreviewimagesizecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changepreviewimagesizecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changepreviewimagesizecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changepreviewimagesizecommand.h b/src/libs/qmlpuppetcommunication/commands/changepreviewimagesizecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changepreviewimagesizecommand.h rename to src/libs/qmlpuppetcommunication/commands/changepreviewimagesizecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeselectioncommand.cpp b/src/libs/qmlpuppetcommunication/commands/changeselectioncommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeselectioncommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changeselectioncommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changeselectioncommand.h b/src/libs/qmlpuppetcommunication/commands/changeselectioncommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changeselectioncommand.h rename to src/libs/qmlpuppetcommunication/commands/changeselectioncommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changestatecommand.cpp b/src/libs/qmlpuppetcommunication/commands/changestatecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changestatecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changestatecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changestatecommand.h b/src/libs/qmlpuppetcommunication/commands/changestatecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changestatecommand.h rename to src/libs/qmlpuppetcommunication/commands/changestatecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/changevaluescommand.cpp b/src/libs/qmlpuppetcommunication/commands/changevaluescommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changevaluescommand.cpp rename to src/libs/qmlpuppetcommunication/commands/changevaluescommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/changevaluescommand.h b/src/libs/qmlpuppetcommunication/commands/changevaluescommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/changevaluescommand.h rename to src/libs/qmlpuppetcommunication/commands/changevaluescommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/childrenchangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/childrenchangedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/childrenchangedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/childrenchangedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/childrenchangedcommand.h b/src/libs/qmlpuppetcommunication/commands/childrenchangedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/childrenchangedcommand.h rename to src/libs/qmlpuppetcommunication/commands/childrenchangedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/clearscenecommand.cpp b/src/libs/qmlpuppetcommunication/commands/clearscenecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/clearscenecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/clearscenecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/clearscenecommand.h b/src/libs/qmlpuppetcommunication/commands/clearscenecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/clearscenecommand.h rename to src/libs/qmlpuppetcommunication/commands/clearscenecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/completecomponentcommand.cpp b/src/libs/qmlpuppetcommunication/commands/completecomponentcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/completecomponentcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/completecomponentcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/completecomponentcommand.h b/src/libs/qmlpuppetcommunication/commands/completecomponentcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/completecomponentcommand.h rename to src/libs/qmlpuppetcommunication/commands/completecomponentcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/componentcompletedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/componentcompletedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/componentcompletedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/componentcompletedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/componentcompletedcommand.h b/src/libs/qmlpuppetcommunication/commands/componentcompletedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/componentcompletedcommand.h rename to src/libs/qmlpuppetcommunication/commands/componentcompletedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/createinstancescommand.cpp b/src/libs/qmlpuppetcommunication/commands/createinstancescommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/createinstancescommand.cpp rename to src/libs/qmlpuppetcommunication/commands/createinstancescommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/createinstancescommand.h b/src/libs/qmlpuppetcommunication/commands/createinstancescommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/createinstancescommand.h rename to src/libs/qmlpuppetcommunication/commands/createinstancescommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp b/src/libs/qmlpuppetcommunication/commands/createscenecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/createscenecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/createscenecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h b/src/libs/qmlpuppetcommunication/commands/createscenecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/createscenecommand.h rename to src/libs/qmlpuppetcommunication/commands/createscenecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/debugoutputcommand.cpp b/src/libs/qmlpuppetcommunication/commands/debugoutputcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/debugoutputcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/debugoutputcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/debugoutputcommand.h b/src/libs/qmlpuppetcommunication/commands/debugoutputcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/debugoutputcommand.h rename to src/libs/qmlpuppetcommunication/commands/debugoutputcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/endpuppetcommand.cpp b/src/libs/qmlpuppetcommunication/commands/endpuppetcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/endpuppetcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/endpuppetcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/endpuppetcommand.h b/src/libs/qmlpuppetcommunication/commands/endpuppetcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/endpuppetcommand.h rename to src/libs/qmlpuppetcommunication/commands/endpuppetcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/informationchangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/informationchangedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/informationchangedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/informationchangedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/informationchangedcommand.h b/src/libs/qmlpuppetcommunication/commands/informationchangedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/informationchangedcommand.h rename to src/libs/qmlpuppetcommunication/commands/informationchangedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/inputeventcommand.cpp b/src/libs/qmlpuppetcommunication/commands/inputeventcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/inputeventcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/inputeventcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/inputeventcommand.h b/src/libs/qmlpuppetcommunication/commands/inputeventcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/inputeventcommand.h rename to src/libs/qmlpuppetcommunication/commands/inputeventcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/nanotracecommand.cpp b/src/libs/qmlpuppetcommunication/commands/nanotracecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/nanotracecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/nanotracecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/nanotracecommand.h b/src/libs/qmlpuppetcommunication/commands/nanotracecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/nanotracecommand.h rename to src/libs/qmlpuppetcommunication/commands/nanotracecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/pixmapchangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/pixmapchangedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/pixmapchangedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/pixmapchangedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/pixmapchangedcommand.h b/src/libs/qmlpuppetcommunication/commands/pixmapchangedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/pixmapchangedcommand.h rename to src/libs/qmlpuppetcommunication/commands/pixmapchangedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppetalivecommand.cpp b/src/libs/qmlpuppetcommunication/commands/puppetalivecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/puppetalivecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/puppetalivecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppetalivecommand.h b/src/libs/qmlpuppetcommunication/commands/puppetalivecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/puppetalivecommand.h rename to src/libs/qmlpuppetcommunication/commands/puppetalivecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.cpp b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h b/src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h rename to src/libs/qmlpuppetcommunication/commands/puppettocreatorcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/removeinstancescommand.cpp b/src/libs/qmlpuppetcommunication/commands/removeinstancescommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removeinstancescommand.cpp rename to src/libs/qmlpuppetcommunication/commands/removeinstancescommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/removeinstancescommand.h b/src/libs/qmlpuppetcommunication/commands/removeinstancescommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removeinstancescommand.h rename to src/libs/qmlpuppetcommunication/commands/removeinstancescommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/removepropertiescommand.cpp b/src/libs/qmlpuppetcommunication/commands/removepropertiescommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removepropertiescommand.cpp rename to src/libs/qmlpuppetcommunication/commands/removepropertiescommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/removepropertiescommand.h b/src/libs/qmlpuppetcommunication/commands/removepropertiescommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removepropertiescommand.h rename to src/libs/qmlpuppetcommunication/commands/removepropertiescommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/removesharedmemorycommand.cpp b/src/libs/qmlpuppetcommunication/commands/removesharedmemorycommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removesharedmemorycommand.cpp rename to src/libs/qmlpuppetcommunication/commands/removesharedmemorycommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/removesharedmemorycommand.h b/src/libs/qmlpuppetcommunication/commands/removesharedmemorycommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/removesharedmemorycommand.h rename to src/libs/qmlpuppetcommunication/commands/removesharedmemorycommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/reparentinstancescommand.cpp b/src/libs/qmlpuppetcommunication/commands/reparentinstancescommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/reparentinstancescommand.cpp rename to src/libs/qmlpuppetcommunication/commands/reparentinstancescommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/reparentinstancescommand.h b/src/libs/qmlpuppetcommunication/commands/reparentinstancescommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/reparentinstancescommand.h rename to src/libs/qmlpuppetcommunication/commands/reparentinstancescommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp b/src/libs/qmlpuppetcommunication/commands/requestmodelnodepreviewimagecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/requestmodelnodepreviewimagecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h b/src/libs/qmlpuppetcommunication/commands/requestmodelnodepreviewimagecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h rename to src/libs/qmlpuppetcommunication/commands/requestmodelnodepreviewimagecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/scenecreatedcommand.h b/src/libs/qmlpuppetcommunication/commands/scenecreatedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/scenecreatedcommand.h rename to src/libs/qmlpuppetcommunication/commands/scenecreatedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/statepreviewimagechangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/statepreviewimagechangedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/statepreviewimagechangedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/statepreviewimagechangedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/statepreviewimagechangedcommand.h b/src/libs/qmlpuppetcommunication/commands/statepreviewimagechangedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/statepreviewimagechangedcommand.h rename to src/libs/qmlpuppetcommunication/commands/statepreviewimagechangedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/synchronizecommand.h b/src/libs/qmlpuppetcommunication/commands/synchronizecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/synchronizecommand.h rename to src/libs/qmlpuppetcommunication/commands/synchronizecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/tokencommand.cpp b/src/libs/qmlpuppetcommunication/commands/tokencommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/tokencommand.cpp rename to src/libs/qmlpuppetcommunication/commands/tokencommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/tokencommand.h b/src/libs/qmlpuppetcommunication/commands/tokencommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/tokencommand.h rename to src/libs/qmlpuppetcommunication/commands/tokencommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/update3dviewstatecommand.cpp b/src/libs/qmlpuppetcommunication/commands/update3dviewstatecommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/update3dviewstatecommand.cpp rename to src/libs/qmlpuppetcommunication/commands/update3dviewstatecommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/update3dviewstatecommand.h b/src/libs/qmlpuppetcommunication/commands/update3dviewstatecommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/update3dviewstatecommand.h rename to src/libs/qmlpuppetcommunication/commands/update3dviewstatecommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.cpp rename to src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h b/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/valueschangedcommand.h rename to src/libs/qmlpuppetcommunication/commands/valueschangedcommand.h diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.cpp b/src/libs/qmlpuppetcommunication/commands/view3dactioncommand.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.cpp rename to src/libs/qmlpuppetcommunication/commands/view3dactioncommand.cpp diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h b/src/libs/qmlpuppetcommunication/commands/view3dactioncommand.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h rename to src/libs/qmlpuppetcommunication/commands/view3dactioncommand.h diff --git a/share/qtcreator/qml/qmlpuppet/container/addimportcontainer.cpp b/src/libs/qmlpuppetcommunication/container/addimportcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/addimportcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/addimportcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/addimportcontainer.h b/src/libs/qmlpuppetcommunication/container/addimportcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/addimportcontainer.h rename to src/libs/qmlpuppetcommunication/container/addimportcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/idcontainer.cpp b/src/libs/qmlpuppetcommunication/container/idcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/idcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/idcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/idcontainer.h b/src/libs/qmlpuppetcommunication/container/idcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/idcontainer.h rename to src/libs/qmlpuppetcommunication/container/idcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp b/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp rename to src/libs/qmlpuppetcommunication/container/imagecontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.h b/src/libs/qmlpuppetcommunication/container/imagecontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/imagecontainer.h rename to src/libs/qmlpuppetcommunication/container/imagecontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/informationcontainer.cpp b/src/libs/qmlpuppetcommunication/container/informationcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/informationcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/informationcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/informationcontainer.h b/src/libs/qmlpuppetcommunication/container/informationcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/informationcontainer.h rename to src/libs/qmlpuppetcommunication/container/informationcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp b/src/libs/qmlpuppetcommunication/container/instancecontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp rename to src/libs/qmlpuppetcommunication/container/instancecontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h b/src/libs/qmlpuppetcommunication/container/instancecontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/instancecontainer.h rename to src/libs/qmlpuppetcommunication/container/instancecontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/mockuptypecontainer.cpp b/src/libs/qmlpuppetcommunication/container/mockuptypecontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/mockuptypecontainer.cpp rename to src/libs/qmlpuppetcommunication/container/mockuptypecontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/mockuptypecontainer.h b/src/libs/qmlpuppetcommunication/container/mockuptypecontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/mockuptypecontainer.h rename to src/libs/qmlpuppetcommunication/container/mockuptypecontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyabstractcontainer.cpp b/src/libs/qmlpuppetcommunication/container/propertyabstractcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertyabstractcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/propertyabstractcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyabstractcontainer.h b/src/libs/qmlpuppetcommunication/container/propertyabstractcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertyabstractcontainer.h rename to src/libs/qmlpuppetcommunication/container/propertyabstractcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/propertybindingcontainer.cpp b/src/libs/qmlpuppetcommunication/container/propertybindingcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertybindingcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/propertybindingcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/propertybindingcontainer.h b/src/libs/qmlpuppetcommunication/container/propertybindingcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertybindingcontainer.h rename to src/libs/qmlpuppetcommunication/container/propertybindingcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp b/src/libs/qmlpuppetcommunication/container/propertyvaluecontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.cpp rename to src/libs/qmlpuppetcommunication/container/propertyvaluecontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h b/src/libs/qmlpuppetcommunication/container/propertyvaluecontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/propertyvaluecontainer.h rename to src/libs/qmlpuppetcommunication/container/propertyvaluecontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/reparentcontainer.cpp b/src/libs/qmlpuppetcommunication/container/reparentcontainer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/reparentcontainer.cpp rename to src/libs/qmlpuppetcommunication/container/reparentcontainer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/reparentcontainer.h b/src/libs/qmlpuppetcommunication/container/reparentcontainer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/reparentcontainer.h rename to src/libs/qmlpuppetcommunication/container/reparentcontainer.h diff --git a/share/qtcreator/qml/qmlpuppet/container/sharedmemory.h b/src/libs/qmlpuppetcommunication/container/sharedmemory.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/sharedmemory.h rename to src/libs/qmlpuppetcommunication/container/sharedmemory.h diff --git a/share/qtcreator/qml/qmlpuppet/container/sharedmemory_qt.cpp b/src/libs/qmlpuppetcommunication/container/sharedmemory_qt.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/sharedmemory_qt.cpp rename to src/libs/qmlpuppetcommunication/container/sharedmemory_qt.cpp diff --git a/share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp b/src/libs/qmlpuppetcommunication/container/sharedmemory_unix.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/container/sharedmemory_unix.cpp rename to src/libs/qmlpuppetcommunication/container/sharedmemory_unix.cpp diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h b/src/libs/qmlpuppetcommunication/interfaces/commondefines.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h rename to src/libs/qmlpuppetcommunication/interfaces/commondefines.h diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceclientinterface.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceclientinterface.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceclientinterface.h rename to src/libs/qmlpuppetcommunication/interfaces/nodeinstanceclientinterface.h diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceglobal.h rename to src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceserverinterface.cpp b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceserverinterface.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceserverinterface.cpp rename to src/libs/qmlpuppetcommunication/interfaces/nodeinstanceserverinterface.cpp diff --git a/share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceserverinterface.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceserverinterface.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/interfaces/nodeinstanceserverinterface.h rename to src/libs/qmlpuppetcommunication/interfaces/nodeinstanceserverinterface.h diff --git a/share/qtcreator/qml/qmlpuppet/types/enumeration.h b/src/libs/qmlpuppetcommunication/types/enumeration.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/types/enumeration.h rename to src/libs/qmlpuppetcommunication/types/enumeration.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 279bcbf4c61..e106f828088 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -42,6 +42,7 @@ add_qtc_library(QmlDesignerCore STATIC QmlProjectManager QtSupport PUBLIC_DEPENDS + QmlPuppetCommunication QmlDesignerUtils TextEditor Sqlite @@ -349,118 +350,6 @@ extend_qtc_library(QmlDesignerCore widgetpluginpath.h ) -extend_qtc_library(QmlDesignerCore - SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet - INCLUDES - ${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/commands - ${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/container - PUBLIC_INCLUDES - "${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/interfaces" - "${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/types" - SOURCES - commands/captureddatacommand.h - commands/changeauxiliarycommand.cpp - commands/changeauxiliarycommand.h - commands/changebindingscommand.cpp - commands/changebindingscommand.h - commands/changefileurlcommand.cpp - commands/changefileurlcommand.h - commands/changeidscommand.cpp - commands/changeidscommand.h - commands/changelanguagecommand.cpp - commands/changelanguagecommand.h - commands/changenodesourcecommand.cpp - commands/changenodesourcecommand.h - commands/changepreviewimagesizecommand.cpp - commands/changepreviewimagesizecommand.h - commands/changeselectioncommand.cpp - commands/changeselectioncommand.h - commands/changestatecommand.cpp - commands/changestatecommand.h - commands/changevaluescommand.cpp - commands/changevaluescommand.h - commands/childrenchangedcommand.cpp - commands/childrenchangedcommand.h - commands/clearscenecommand.cpp - commands/clearscenecommand.h - commands/completecomponentcommand.cpp - commands/completecomponentcommand.h - commands/componentcompletedcommand.cpp - commands/componentcompletedcommand.h - commands/createinstancescommand.cpp - commands/createinstancescommand.h - commands/createscenecommand.cpp - commands/createscenecommand.h - commands/debugoutputcommand.cpp - commands/debugoutputcommand.h - commands/endpuppetcommand.cpp - commands/endpuppetcommand.h - commands/informationchangedcommand.cpp - commands/informationchangedcommand.h - commands/nanotracecommand.cpp - commands/nanotracecommand.h - commands/inputeventcommand.cpp - commands/inputeventcommand.h - commands/pixmapchangedcommand.cpp - commands/pixmapchangedcommand.h - commands/puppetalivecommand.cpp - commands/puppetalivecommand.h - commands/puppettocreatorcommand.cpp - commands/puppettocreatorcommand.h - commands/removeinstancescommand.cpp - commands/removeinstancescommand.h - commands/removepropertiescommand.cpp - commands/removepropertiescommand.h - commands/removesharedmemorycommand.cpp - commands/removesharedmemorycommand.h - commands/reparentinstancescommand.cpp - commands/reparentinstancescommand.h - commands/requestmodelnodepreviewimagecommand.cpp - commands/requestmodelnodepreviewimagecommand.h - commands/scenecreatedcommand.h - commands/statepreviewimagechangedcommand.cpp - commands/statepreviewimagechangedcommand.h - commands/synchronizecommand.h - commands/tokencommand.cpp - commands/tokencommand.h - commands/update3dviewstatecommand.cpp - commands/update3dviewstatecommand.h - commands/valueschangedcommand.cpp - commands/valueschangedcommand.h - commands/view3dactioncommand.cpp - commands/view3dactioncommand.h - - container/addimportcontainer.cpp - container/addimportcontainer.h - container/idcontainer.cpp - container/idcontainer.h - container/imagecontainer.cpp - container/imagecontainer.h - container/informationcontainer.cpp - container/informationcontainer.h - container/instancecontainer.cpp - container/instancecontainer.h - container/mockuptypecontainer.cpp - container/mockuptypecontainer.h - container/propertyabstractcontainer.cpp - container/propertyabstractcontainer.h - container/propertybindingcontainer.cpp - container/propertybindingcontainer.h - container/propertyvaluecontainer.cpp - container/propertyvaluecontainer.h - container/reparentcontainer.cpp - container/reparentcontainer.h - container/sharedmemory.h - - interfaces/commondefines.h - interfaces/nodeinstanceclientinterface.h - interfaces/nodeinstanceglobal.h - interfaces/nodeinstanceserverinterface.cpp - interfaces/nodeinstanceserverinterface.h - - types/enumeration.h -) - extend_qtc_library(QmlDesignerCore SOURCES_PREFIX designercore/projectstorage PUBLIC_INCLUDES designercore/projectstorage @@ -498,18 +387,6 @@ extend_qtc_library(QmlDesignerCore qmldocumentparser.cpp qmldocumentparser.h ) -extend_qtc_library(QmlDesignerCore - CONDITION UNIX - SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/container - SOURCES sharedmemory_unix.cpp -) - -extend_qtc_library(QmlDesignerCore - CONDITION NOT UNIX - SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator/qml/qmlpuppet/container - SOURCES sharedmemory_qt.cpp -) - file(GLOB PROJECTSTORAGE_EXCLUDED_SOURCES designercore/projectstorage/*.cpp) set_property(SOURCE ${PROJECTSTORAGE_EXCLUDED_SOURCES} PROPERTY SKIP_AUTOMOC ON) diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index f615e7322a4..7ef09420ee2 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -1,136 +1,60 @@ -set(SRCDIR "${PROJECT_SOURCE_DIR}/share/qtcreator/qml/qmlpuppet") +cmake_minimum_required(VERSION 3.16) -set(DESTDIR "${IDE_LIBEXEC_PATH}") -if (APPLE) - string(APPEND DESTDIR "/qmldesigner") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake") + + +project(qml2puppet) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if (NOT QT_CREATOR_API_DEFINED) + # standalone build + set(DESTINATION DESTINATION $ENV{QDS_PUPPET_DESTINATION}) + include(QtCreatorIDEBranding) + include(QtCreatorAPI) endif() -add_qtc_library(qml2puppet_static - STATIC - DEPENDS - Qt5::CorePrivate Qt5::Widgets - PUBLIC_INCLUDES "${SRCDIR}/interfaces" - SOURCES_PREFIX "${SRCDIR}/interfaces" - SOURCES - commondefines.h - nodeinstanceclientinterface.h - nodeinstanceglobal.h - nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h +find_package(Qt5 + COMPONENTS Concurrent Core Gui Network PrintSupport Qml Quick Sql Widgets Xml Core5Compat + REQUIRED ) -extend_qtc_library(qml2puppet_static - PUBLIC_INCLUDES "${SRCDIR}/types" - SOURCES "${SRCDIR}/types/enumeration.h" -) - -extend_qtc_library(qml2puppet_static - PUBLIC_INCLUDES "${SRCDIR}/container" - SOURCES_PREFIX "${SRCDIR}/container" - SOURCES - addimportcontainer.cpp addimportcontainer.h - idcontainer.cpp idcontainer.h - imagecontainer.cpp imagecontainer.h - informationcontainer.cpp informationcontainer.h - instancecontainer.cpp instancecontainer.h - mockuptypecontainer.cpp mockuptypecontainer.h - propertyabstractcontainer.cpp propertyabstractcontainer.h - propertybindingcontainer.cpp propertybindingcontainer.h - propertyvaluecontainer.cpp propertyvaluecontainer.h - reparentcontainer.cpp reparentcontainer.h - sharedmemory.h -) - -extend_qtc_library(qml2puppet_static - CONDITION UNIX - SOURCES_PREFIX "${SRCDIR}/container" - SOURCES - sharedmemory_unix.cpp -) - -extend_qtc_library(qml2puppet_static - CONDITION NOT UNIX - SOURCES_PREFIX "${SRCDIR}/container" - SOURCES - sharedmemory_qt.cpp -) - -extend_qtc_library(qml2puppet_static - PUBLIC_INCLUDES "${SRCDIR}/commands" - SOURCES_PREFIX "${SRCDIR}/commands" - SOURCES - changeauxiliarycommand.cpp changeauxiliarycommand.h - changebindingscommand.cpp changebindingscommand.h - changefileurlcommand.cpp changefileurlcommand.h - changeidscommand.cpp changeidscommand.h - changenodesourcecommand.cpp changenodesourcecommand.h - changestatecommand.cpp changestatecommand.h - changevaluescommand.cpp changevaluescommand.h - childrenchangedcommand.cpp childrenchangedcommand.h - clearscenecommand.cpp clearscenecommand.h - completecomponentcommand.cpp completecomponentcommand.h - componentcompletedcommand.cpp componentcompletedcommand.h - createinstancescommand.cpp createinstancescommand.h - createscenecommand.cpp createscenecommand.h - changepreviewimagesizecommand.cpp changepreviewimagesizecommand.h - changelanguagecommand.cpp changelanguagecommand.h - debugoutputcommand.cpp debugoutputcommand.h - endpuppetcommand.cpp endpuppetcommand.h - informationchangedcommand.cpp informationchangedcommand.h - nanotracecommand.cpp nanotracecommand.h - pixmapchangedcommand.cpp pixmapchangedcommand.h - puppetalivecommand.cpp puppetalivecommand.h - removeinstancescommand.cpp removeinstancescommand.h - removepropertiescommand.cpp removepropertiescommand.h - removesharedmemorycommand.cpp removesharedmemorycommand.h - reparentinstancescommand.cpp reparentinstancescommand.h - statepreviewimagechangedcommand.cpp statepreviewimagechangedcommand.h - synchronizecommand.h - tokencommand.cpp tokencommand.h - changeselectioncommand.cpp changeselectioncommand.h - update3dviewstatecommand.cpp update3dviewstatecommand.h - puppettocreatorcommand.cpp puppettocreatorcommand.h - inputeventcommand.cpp inputeventcommand.h - view3dactioncommand.cpp view3dactioncommand.h - requestmodelnodepreviewimagecommand.cpp requestmodelnodepreviewimagecommand.h - valueschangedcommand.cpp - captureddatacommand.h - scenecreatedcommand.h -) - -extend_qtc_library(qml2puppet_static - PUBLIC_INCLUDES "${PROJECT_SOURCE_DIR}/src/libs" -) -extend_qtc_library(qml2puppet_static - CONDITION TARGET Nanotrace - DEPENDS Nanotrace -) +if (NOT TARGET QmlPuppetCommunication) +include(../../libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake) +endif() add_qtc_executable(qml2puppet - CONDITION TARGET Qt5::QuickPrivate + ${DESTINATION} DEPENDS Qt5::CorePrivate Qt5::Widgets Qt5::QmlPrivate Qt5::QuickPrivate Qt5::Network Qt5::GuiPrivate - qml2puppet_static + QmlPuppetCommunication SOURCES - "${SRCDIR}/qml2puppet/qml2puppetmain.cpp" - "${SRCDIR}/qmlpuppet.qrc" - DESTINATION ${DESTDIR} + qml2puppet/qml2puppetmain.cpp + qmlpuppet.qrc ) -set_target_properties(qml2puppet PROPERTIES OUTPUT_NAME qml2puppet-${IDE_VERSION}) +if (NOT "$ENV{QDS_PUPPET_VERSION}" STREQUAL "") + set_target_properties(qml2puppet PROPERTIES OUTPUT_NAME qml2puppet-$ENV{QDS_PUPPET_VERSION}) +else() + set_target_properties(qml2puppet PROPERTIES OUTPUT_NAME qml2puppet-${IDE_VERSION}) +endif() extend_qtc_executable(qml2puppet CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0 - SOURCES_PREFIX "${SRCDIR}/" SOURCES - "editor3d_qt6.qrc" + editor3d_qt6.qrc ) extend_qtc_executable(qml2puppet CONDITION Qt5_VERSION VERSION_LESS 6.0.0 - SOURCES_PREFIX "${SRCDIR}/" SOURCES - "editor3d_qt5.qrc" + editor3d_qt5.qrc ) extend_qtc_executable(qml2puppet @@ -139,7 +63,7 @@ extend_qtc_executable(qml2puppet ) extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/instances" + SOURCES_PREFIX instances SOURCES nodeinstanceclientproxy.cpp nodeinstanceclientproxy.h ) @@ -151,7 +75,7 @@ extend_qtc_executable(qml2puppet DEPENDS Qt5::Quick3D Qt5::Quick3DPrivate DEFINES QUICK3D_MODULE - SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d" + SOURCES_PREFIX qml2puppet/editor3d SOURCES generalhelper.cpp generalhelper.h mousearea3d.cpp mousearea3d.h @@ -191,26 +115,25 @@ extend_qtc_executable(qml2puppet extend_qtc_executable(qml2puppet CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0 - - SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d/qt5compat" + SOURCES_PREFIX qml2puppet/editor3d/qt5compat SOURCES qquick3darealight.cpp qquick3darealight_p.h ) extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/qml2puppet/iconrenderer" + SOURCES_PREFIX qml2puppet/iconrenderer SOURCES iconrenderer.cpp iconrenderer.h ) extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/qml2puppet/import3d" + SOURCES_PREFIX qml2puppet/import3d SOURCES import3d.cpp import3d.h ) extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/qml2puppet/instances" + SOURCES_PREFIX qml2puppet/instances SOURCES anchorchangesnodeinstance.cpp anchorchangesnodeinstance.h behaviornodeinstance.cpp behaviornodeinstance.h @@ -248,13 +171,7 @@ extend_qtc_executable(qml2puppet ) extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/types" - SOURCES - enumeration.h -) - -extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/qmlprivategate" + SOURCES_PREFIX qmlprivategate SOURCES qmlprivategate.cpp qmlprivategate.h ) @@ -270,7 +187,7 @@ extend_qtc_executable(qml2puppet ) extend_qtc_executable(qml2puppet - PUBLIC_INCLUDES "${PROJECT_SOURCE_DIR}/src/libs" + PUBLIC_INCLUDES src/libs ) extend_qtc_executable(qml2puppet diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc b/src/tools/qml2puppet/editor3d_qt5.qrc similarity index 100% rename from share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc rename to src/tools/qml2puppet/editor3d_qt5.qrc diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc b/src/tools/qml2puppet/editor3d_qt6.qrc similarity index 100% rename from share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc rename to src/tools/qml2puppet/editor3d_qt6.qrc diff --git a/share/qtcreator/qml/qmlpuppet/html/welcome.html b/src/tools/qml2puppet/html/welcome.html similarity index 100% rename from share/qtcreator/qml/qmlpuppet/html/welcome.html rename to src/tools/qml2puppet/html/welcome.html diff --git a/share/qtcreator/qml/qmlpuppet/images/non-visual-component.png b/src/tools/qml2puppet/images/non-visual-component.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/images/non-visual-component.png rename to src/tools/qml2puppet/images/non-visual-component.png diff --git a/share/qtcreator/qml/qmlpuppet/images/non-visual-component@2x.png b/src/tools/qml2puppet/images/non-visual-component@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/images/non-visual-component@2x.png rename to src/tools/qml2puppet/images/non-visual-component@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/images/template_image.png b/src/tools/qml2puppet/images/template_image.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/images/template_image.png rename to src/tools/qml2puppet/images/template_image.png diff --git a/share/qtcreator/qml/qmlpuppet/images/webkit.png b/src/tools/qml2puppet/images/webkit.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/images/webkit.png rename to src/tools/qml2puppet/images/webkit.png diff --git a/share/qtcreator/qml/qmlpuppet/instances/instances.pri b/src/tools/qml2puppet/instances/instances.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/instances/instances.pri rename to src/tools/qml2puppet/instances/instances.pri diff --git a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp rename to src/tools/qml2puppet/instances/nodeinstanceclientproxy.cpp diff --git a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.h b/src/tools/qml2puppet/instances/nodeinstanceclientproxy.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.h rename to src/tools/qml2puppet/instances/nodeinstanceclientproxy.h diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Dialog.qml b/src/tools/qml2puppet/mockfiles/Dialog.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/Dialog.qml rename to src/tools/qml2puppet/mockfiles/Dialog.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/GenericBackend.qml b/src/tools/qml2puppet/mockfiles/GenericBackend.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/GenericBackend.qml rename to src/tools/qml2puppet/mockfiles/GenericBackend.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SwipeView.qml b/src/tools/qml2puppet/mockfiles/SwipeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/SwipeView.qml rename to src/tools/qml2puppet/mockfiles/SwipeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml b/src/tools/qml2puppet/mockfiles/ToggleButton.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml rename to src/tools/qml2puppet/mockfiles/ToggleButton.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml b/src/tools/qml2puppet/mockfiles/ToolBarButton.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/ToolBarButton.qml rename to src/tools/qml2puppet/mockfiles/ToolBarButton.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Window.qml b/src/tools/qml2puppet/mockfiles/Window.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/Window.qml rename to src/tools/qml2puppet/mockfiles/Window.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area.png b/src/tools/qml2puppet/mockfiles/images/area.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/area.png rename to src/tools/qml2puppet/mockfiles/images/area.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/area@2x.png b/src/tools/qml2puppet/mockfiles/images/area@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/area@2x.png rename to src/tools/qml2puppet/mockfiles/images/area@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional.png b/src/tools/qml2puppet/mockfiles/images/directional.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/directional.png rename to src/tools/qml2puppet/mockfiles/images/directional.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/directional@2x.png b/src/tools/qml2puppet/mockfiles/images/directional@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/directional@2x.png rename to src/tools/qml2puppet/mockfiles/images/directional@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_camera.png b/src/tools/qml2puppet/mockfiles/images/editor_camera.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_camera.png rename to src/tools/qml2puppet/mockfiles/images/editor_camera.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_camera@2x.png b/src/tools/qml2puppet/mockfiles/images/editor_camera@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_camera@2x.png rename to src/tools/qml2puppet/mockfiles/images/editor_camera@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem.png b/src/tools/qml2puppet/mockfiles/images/editor_particlesystem.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem.png rename to src/tools/qml2puppet/mockfiles/images/editor_particlesystem.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem@2x.png b/src/tools/qml2puppet/mockfiles/images/editor_particlesystem@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem@2x.png rename to src/tools/qml2puppet/mockfiles/images/editor_particlesystem@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/floor_tex.png b/src/tools/qml2puppet/mockfiles/images/floor_tex.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/floor_tex.png rename to src/tools/qml2puppet/mockfiles/images/floor_tex.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point.png b/src/tools/qml2puppet/mockfiles/images/point.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/point.png rename to src/tools/qml2puppet/mockfiles/images/point.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/point@2x.png b/src/tools/qml2puppet/mockfiles/images/point@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/point@2x.png rename to src/tools/qml2puppet/mockfiles/images/point@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdr b/src/tools/qml2puppet/mockfiles/images/preview_landscape.hdr similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_landscape.hdr rename to src/tools/qml2puppet/mockfiles/images/preview_landscape.hdr diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdr b/src/tools/qml2puppet/mockfiles/images/preview_studio.hdr similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/preview_studio.hdr rename to src/tools/qml2puppet/mockfiles/images/preview_studio.hdr diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/spot.png b/src/tools/qml2puppet/mockfiles/images/spot.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/spot.png rename to src/tools/qml2puppet/mockfiles/images/spot.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/spot@2x.png b/src/tools/qml2puppet/mockfiles/images/spot@2x.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/spot@2x.png rename to src/tools/qml2puppet/mockfiles/images/spot@2x.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/static_floor.png b/src/tools/qml2puppet/mockfiles/images/static_floor.png similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/images/static_floor.png rename to src/tools/qml2puppet/mockfiles/images/static_floor.png diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/arrow.mesh b/src/tools/qml2puppet/mockfiles/meshes/arrow.mesh similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/meshes/arrow.mesh rename to src/tools/qml2puppet/mockfiles/meshes/arrow.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh b/src/tools/qml2puppet/mockfiles/meshes/axishelper.mesh similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh rename to src/tools/qml2puppet/mockfiles/meshes/axishelper.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/ring.mesh b/src/tools/qml2puppet/mockfiles/meshes/ring.mesh similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/meshes/ring.mesh rename to src/tools/qml2puppet/mockfiles/meshes/ring.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/ringselect.mesh b/src/tools/qml2puppet/mockfiles/meshes/ringselect.mesh similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/meshes/ringselect.mesh rename to src/tools/qml2puppet/mockfiles/meshes/ringselect.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.mesh b/src/tools/qml2puppet/mockfiles/meshes/scalerod.mesh similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/meshes/scalerod.mesh rename to src/tools/qml2puppet/mockfiles/meshes/scalerod.mesh diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AdjustableArrow.qml b/src/tools/qml2puppet/mockfiles/qt5/AdjustableArrow.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AdjustableArrow.qml rename to src/tools/qml2puppet/mockfiles/qt5/AdjustableArrow.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AreaLightHandle.qml b/src/tools/qml2puppet/mockfiles/qt5/AreaLightHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AreaLightHandle.qml rename to src/tools/qml2puppet/mockfiles/qt5/AreaLightHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Arrow.qml b/src/tools/qml2puppet/mockfiles/qt5/Arrow.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Arrow.qml rename to src/tools/qml2puppet/mockfiles/qt5/Arrow.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AutoScaleHelper.qml b/src/tools/qml2puppet/mockfiles/qt5/AutoScaleHelper.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AutoScaleHelper.qml rename to src/tools/qml2puppet/mockfiles/qt5/AutoScaleHelper.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelper.qml b/src/tools/qml2puppet/mockfiles/qt5/AxisHelper.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelper.qml rename to src/tools/qml2puppet/mockfiles/qt5/AxisHelper.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelperArm.qml b/src/tools/qml2puppet/mockfiles/qt5/AxisHelperArm.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelperArm.qml rename to src/tools/qml2puppet/mockfiles/qt5/AxisHelperArm.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraFrustum.qml b/src/tools/qml2puppet/mockfiles/qt5/CameraFrustum.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraFrustum.qml rename to src/tools/qml2puppet/mockfiles/qt5/CameraFrustum.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/CameraGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/CameraGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/DirectionalDraggable.qml b/src/tools/qml2puppet/mockfiles/qt5/DirectionalDraggable.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/DirectionalDraggable.qml rename to src/tools/qml2puppet/mockfiles/qt5/DirectionalDraggable.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditCameraController.qml b/src/tools/qml2puppet/mockfiles/qt5/EditCameraController.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditCameraController.qml rename to src/tools/qml2puppet/mockfiles/qt5/EditCameraController.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml rename to src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/FadeHandle.qml b/src/tools/qml2puppet/mockfiles/qt5/FadeHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/FadeHandle.qml rename to src/tools/qml2puppet/mockfiles/qt5/FadeHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/HelperGrid.qml b/src/tools/qml2puppet/mockfiles/qt5/HelperGrid.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/HelperGrid.qml rename to src/tools/qml2puppet/mockfiles/qt5/HelperGrid.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/IconGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/IconGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconRenderer3D.qml b/src/tools/qml2puppet/mockfiles/qt5/IconRenderer3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconRenderer3D.qml rename to src/tools/qml2puppet/mockfiles/qt5/IconRenderer3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/LightGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/LightGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightIconGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/LightIconGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightIconGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/LightIconGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightModel.qml b/src/tools/qml2puppet/mockfiles/qt5/LightModel.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightModel.qml rename to src/tools/qml2puppet/mockfiles/qt5/LightModel.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Line3D.qml b/src/tools/qml2puppet/mockfiles/qt5/Line3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Line3D.qml rename to src/tools/qml2puppet/mockfiles/qt5/Line3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml b/src/tools/qml2puppet/mockfiles/qt5/MaterialNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt5/MaterialNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode2DImageView.qml b/src/tools/qml2puppet/mockfiles/qt5/ModelNode2DImageView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode2DImageView.qml rename to src/tools/qml2puppet/mockfiles/qt5/ModelNode2DImageView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml b/src/tools/qml2puppet/mockfiles/qt5/ModelNode3DImageView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml rename to src/tools/qml2puppet/mockfiles/qt5/ModelNode3DImageView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNodeView.qml b/src/tools/qml2puppet/mockfiles/qt5/ModelNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt5/ModelNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MoveGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/MoveGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MoveGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/MoveGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/NodeNodeView.qml b/src/tools/qml2puppet/mockfiles/qt5/NodeNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/NodeNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt5/NodeNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Overlay2D.qml b/src/tools/qml2puppet/mockfiles/qt5/Overlay2D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Overlay2D.qml rename to src/tools/qml2puppet/mockfiles/qt5/Overlay2D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarDraggable.qml b/src/tools/qml2puppet/mockfiles/qt5/PlanarDraggable.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarDraggable.qml rename to src/tools/qml2puppet/mockfiles/qt5/PlanarDraggable.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarMoveHandle.qml b/src/tools/qml2puppet/mockfiles/qt5/PlanarMoveHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarMoveHandle.qml rename to src/tools/qml2puppet/mockfiles/qt5/PlanarMoveHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarScaleHandle.qml b/src/tools/qml2puppet/mockfiles/qt5/PlanarScaleHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarScaleHandle.qml rename to src/tools/qml2puppet/mockfiles/qt5/PlanarScaleHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/RotateGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/RotateGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateRing.qml b/src/tools/qml2puppet/mockfiles/qt5/RotateRing.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateRing.qml rename to src/tools/qml2puppet/mockfiles/qt5/RotateRing.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleGizmo.qml b/src/tools/qml2puppet/mockfiles/qt5/ScaleGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt5/ScaleGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleRod.qml b/src/tools/qml2puppet/mockfiles/qt5/ScaleRod.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleRod.qml rename to src/tools/qml2puppet/mockfiles/qt5/ScaleRod.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SceneView3D.qml b/src/tools/qml2puppet/mockfiles/qt5/SceneView3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SceneView3D.qml rename to src/tools/qml2puppet/mockfiles/qt5/SceneView3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SelectionBox.qml b/src/tools/qml2puppet/mockfiles/qt5/SelectionBox.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SelectionBox.qml rename to src/tools/qml2puppet/mockfiles/qt5/SelectionBox.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SpotLightHandle.qml b/src/tools/qml2puppet/mockfiles/qt5/SpotLightHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SpotLightHandle.qml rename to src/tools/qml2puppet/mockfiles/qt5/SpotLightHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AdjustableArrow.qml b/src/tools/qml2puppet/mockfiles/qt6/AdjustableArrow.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AdjustableArrow.qml rename to src/tools/qml2puppet/mockfiles/qt6/AdjustableArrow.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AreaLightHandle.qml b/src/tools/qml2puppet/mockfiles/qt6/AreaLightHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AreaLightHandle.qml rename to src/tools/qml2puppet/mockfiles/qt6/AreaLightHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Arrow.qml b/src/tools/qml2puppet/mockfiles/qt6/Arrow.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Arrow.qml rename to src/tools/qml2puppet/mockfiles/qt6/Arrow.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AutoScaleHelper.qml b/src/tools/qml2puppet/mockfiles/qt6/AutoScaleHelper.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AutoScaleHelper.qml rename to src/tools/qml2puppet/mockfiles/qt6/AutoScaleHelper.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelper.qml b/src/tools/qml2puppet/mockfiles/qt6/AxisHelper.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelper.qml rename to src/tools/qml2puppet/mockfiles/qt6/AxisHelper.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelperArm.qml b/src/tools/qml2puppet/mockfiles/qt6/AxisHelperArm.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelperArm.qml rename to src/tools/qml2puppet/mockfiles/qt6/AxisHelperArm.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraFrustum.qml b/src/tools/qml2puppet/mockfiles/qt6/CameraFrustum.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraFrustum.qml rename to src/tools/qml2puppet/mockfiles/qt6/CameraFrustum.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/CameraGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/CameraGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/DirectionalDraggable.qml b/src/tools/qml2puppet/mockfiles/qt6/DirectionalDraggable.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/DirectionalDraggable.qml rename to src/tools/qml2puppet/mockfiles/qt6/DirectionalDraggable.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditCameraController.qml b/src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditCameraController.qml rename to src/tools/qml2puppet/mockfiles/qt6/EditCameraController.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml rename to src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/FadeHandle.qml b/src/tools/qml2puppet/mockfiles/qt6/FadeHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/FadeHandle.qml rename to src/tools/qml2puppet/mockfiles/qt6/FadeHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/HelperGrid.qml b/src/tools/qml2puppet/mockfiles/qt6/HelperGrid.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/HelperGrid.qml rename to src/tools/qml2puppet/mockfiles/qt6/HelperGrid.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/IconGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/IconGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/LightGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/LightGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightIconGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/LightIconGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightIconGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/LightIconGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightModel.qml b/src/tools/qml2puppet/mockfiles/qt6/LightModel.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightModel.qml rename to src/tools/qml2puppet/mockfiles/qt6/LightModel.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Line3D.qml b/src/tools/qml2puppet/mockfiles/qt6/Line3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Line3D.qml rename to src/tools/qml2puppet/mockfiles/qt6/Line3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml b/src/tools/qml2puppet/mockfiles/qt6/MaterialNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt6/MaterialNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode2DImageView.qml b/src/tools/qml2puppet/mockfiles/qt6/ModelNode2DImageView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode2DImageView.qml rename to src/tools/qml2puppet/mockfiles/qt6/ModelNode2DImageView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml b/src/tools/qml2puppet/mockfiles/qt6/ModelNode3DImageView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml rename to src/tools/qml2puppet/mockfiles/qt6/ModelNode3DImageView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml b/src/tools/qml2puppet/mockfiles/qt6/ModelNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt6/ModelNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MoveGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/MoveGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MoveGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/MoveGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/NodeNodeView.qml b/src/tools/qml2puppet/mockfiles/qt6/NodeNodeView.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/NodeNodeView.qml rename to src/tools/qml2puppet/mockfiles/qt6/NodeNodeView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Overlay2D.qml b/src/tools/qml2puppet/mockfiles/qt6/Overlay2D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Overlay2D.qml rename to src/tools/qml2puppet/mockfiles/qt6/Overlay2D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/ParticleEmitterGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/ParticleEmitterGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleSystemGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/ParticleSystemGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleSystemGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/ParticleSystemGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarDraggable.qml b/src/tools/qml2puppet/mockfiles/qt6/PlanarDraggable.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarDraggable.qml rename to src/tools/qml2puppet/mockfiles/qt6/PlanarDraggable.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarMoveHandle.qml b/src/tools/qml2puppet/mockfiles/qt6/PlanarMoveHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarMoveHandle.qml rename to src/tools/qml2puppet/mockfiles/qt6/PlanarMoveHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarScaleHandle.qml b/src/tools/qml2puppet/mockfiles/qt6/PlanarScaleHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarScaleHandle.qml rename to src/tools/qml2puppet/mockfiles/qt6/PlanarScaleHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/RotateGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/RotateGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateRing.qml b/src/tools/qml2puppet/mockfiles/qt6/RotateRing.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateRing.qml rename to src/tools/qml2puppet/mockfiles/qt6/RotateRing.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleGizmo.qml b/src/tools/qml2puppet/mockfiles/qt6/ScaleGizmo.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleGizmo.qml rename to src/tools/qml2puppet/mockfiles/qt6/ScaleGizmo.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleRod.qml b/src/tools/qml2puppet/mockfiles/qt6/ScaleRod.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleRod.qml rename to src/tools/qml2puppet/mockfiles/qt6/ScaleRod.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/SceneView3D.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml rename to src/tools/qml2puppet/mockfiles/qt6/SceneView3D.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SelectionBox.qml b/src/tools/qml2puppet/mockfiles/qt6/SelectionBox.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SelectionBox.qml rename to src/tools/qml2puppet/mockfiles/qt6/SelectionBox.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SpotLightHandle.qml b/src/tools/qml2puppet/mockfiles/qt6/SpotLightHandle.qml similarity index 100% rename from share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SpotLightHandle.qml rename to src/tools/qml2puppet/mockfiles/qt6/SpotLightHandle.qml diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/Info.plist b/src/tools/qml2puppet/qml2puppet/Info.plist similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/Info.plist rename to src/tools/qml2puppet/qml2puppet/Info.plist diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/camerageometry.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/camerageometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h b/src/tools/qml2puppet/qml2puppet/editor3d/camerageometry.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h rename to src/tools/qml2puppet/qml2puppet/editor3d/camerageometry.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/src/tools/qml2puppet/qml2puppet/editor3d/editor3d.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri rename to src/tools/qml2puppet/qml2puppet/editor3d/editor3d.pri diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h rename to src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/geometrybase.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/geometrybase.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.h b/src/tools/qml2puppet/qml2puppet/editor3d/geometrybase.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.h rename to src/tools/qml2puppet/qml2puppet/editor3d/geometrybase.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/gridgeometry.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/gridgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h b/src/tools/qml2puppet/qml2puppet/editor3d/gridgeometry.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h rename to src/tools/qml2puppet/qml2puppet/editor3d/gridgeometry.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/icongizmoimageprovider.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/icongizmoimageprovider.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/icongizmoimageprovider.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/icongizmoimageprovider.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/icongizmoimageprovider.h b/src/tools/qml2puppet/qml2puppet/editor3d/icongizmoimageprovider.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/icongizmoimageprovider.h rename to src/tools/qml2puppet/qml2puppet/editor3d/icongizmoimageprovider.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/lightgeometry.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/lightgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h b/src/tools/qml2puppet/qml2puppet/editor3d/lightgeometry.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h rename to src/tools/qml2puppet/qml2puppet/editor3d/lightgeometry.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/linegeometry.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/linegeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h b/src/tools/qml2puppet/qml2puppet/editor3d/linegeometry.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h rename to src/tools/qml2puppet/qml2puppet/editor3d/linegeometry.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/mousearea3d.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/mousearea3d.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h b/src/tools/qml2puppet/qml2puppet/editor3d/mousearea3d.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h rename to src/tools/qml2puppet/qml2puppet/editor3d/mousearea3d.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/qt5compat/qquick3darealight.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/qt5compat/qquick3darealight.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/qt5compat/qquick3darealight.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/qt5compat/qquick3darealight.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/qt5compat/qquick3darealight_p.h b/src/tools/qml2puppet/qml2puppet/editor3d/qt5compat/qquick3darealight_p.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/qt5compat/qquick3darealight_p.h rename to src/tools/qml2puppet/qml2puppet/editor3d/qt5compat/qquick3darealight_p.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/selectionboxgeometry.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp rename to src/tools/qml2puppet/qml2puppet/editor3d/selectionboxgeometry.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/src/tools/qml2puppet/qml2puppet/editor3d/selectionboxgeometry.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h rename to src/tools/qml2puppet/qml2puppet/editor3d/selectionboxgeometry.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp b/src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp rename to src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h b/src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h rename to src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri b/src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri rename to src/tools/qml2puppet/qml2puppet/iconrenderer/iconrenderer.pri diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.cpp b/src/tools/qml2puppet/qml2puppet/import3d/import3d.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.cpp rename to src/tools/qml2puppet/qml2puppet/import3d/import3d.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.h b/src/tools/qml2puppet/qml2puppet/import3d/import3d.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.h rename to src/tools/qml2puppet/qml2puppet/import3d/import3d.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.pri b/src/tools/qml2puppet/qml2puppet/import3d/import3d.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/import3d/import3d.pri rename to src/tools/qml2puppet/qml2puppet/import3d/import3d.pri diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/anchorchangesnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/anchorchangesnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/anchorchangesnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/anchorchangesnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/anchorchangesnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/anchorchangesnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/anchorchangesnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/anchorchangesnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/animationdriver.cpp b/src/tools/qml2puppet/qml2puppet/instances/animationdriver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/animationdriver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/animationdriver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/animationdriver.h b/src/tools/qml2puppet/qml2puppet/instances/animationdriver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/animationdriver.h rename to src/tools/qml2puppet/qml2puppet/instances/animationdriver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/behaviornodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/behaviornodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/behaviornodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/behaviornodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/behaviornodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/behaviornodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/behaviornodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/behaviornodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.cpp b/src/tools/qml2puppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.cpp rename to src/tools/qml2puppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.h b/src/tools/qml2puppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.h rename to src/tools/qml2puppet/qml2puppet/instances/capturenodeinstanceserverdispatcher.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/childrenchangeeventfilter.cpp b/src/tools/qml2puppet/qml2puppet/instances/childrenchangeeventfilter.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/childrenchangeeventfilter.cpp rename to src/tools/qml2puppet/qml2puppet/instances/childrenchangeeventfilter.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/childrenchangeeventfilter.h b/src/tools/qml2puppet/qml2puppet/instances/childrenchangeeventfilter.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/childrenchangeeventfilter.h rename to src/tools/qml2puppet/qml2puppet/instances/childrenchangeeventfilter.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/componentnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/componentnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/componentnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/componentnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/componentnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummycontextobject.cpp b/src/tools/qml2puppet/qml2puppet/instances/dummycontextobject.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummycontextobject.cpp rename to src/tools/qml2puppet/qml2puppet/instances/dummycontextobject.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummycontextobject.h b/src/tools/qml2puppet/qml2puppet/instances/dummycontextobject.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummycontextobject.h rename to src/tools/qml2puppet/qml2puppet/instances/dummycontextobject.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummynodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/dummynodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummynodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/dummynodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummynodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/dummynodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/dummynodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/dummynodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri b/src/tools/qml2puppet/qml2puppet/instances/instances.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri rename to src/tools/qml2puppet/qml2puppet/instances/instances.pri diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/layoutnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/layoutnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/layoutnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/layoutnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/layoutnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/layoutnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/layoutnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/layoutnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserverdispatcher.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserverdispatcher.h rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserverdispatcher.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstancesignalspy.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstancesignalspy.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstancesignalspy.cpp rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstancesignalspy.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstancesignalspy.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstancesignalspy.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstancesignalspy.h rename to src/tools/qml2puppet/qml2puppet/instances/nodeinstancesignalspy.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/positionernodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/positionernodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/positionernodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/positionernodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/positionernodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/positionernodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/positionernodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/positionernodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlpropertychangesnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/qmlpropertychangesnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlpropertychangesnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qmlpropertychangesnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlpropertychangesnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/qmlpropertychangesnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlpropertychangesnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/qmlpropertychangesnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlstatenodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/qmlstatenodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlstatenodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qmlstatenodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlstatenodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/qmlstatenodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmlstatenodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/qmlstatenodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmltransitionnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/qmltransitionnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmltransitionnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qmltransitionnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmltransitionnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/qmltransitionnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qmltransitionnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/qmltransitionnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt3dpresentationnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt3dpresentationnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt3dpresentationnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt3dpresentationnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt3dpresentationnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/qt3dpresentationnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt3dpresentationnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/qt3dpresentationnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.h b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceclientproxy.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5nodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5previewnodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5rendernodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp rename to src/tools/qml2puppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5testnodeinstanceserver.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.h rename to src/tools/qml2puppet/qml2puppet/instances/qt5testnodeinstanceserver.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/quick3dmaterialnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/quick3dmaterialnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dmaterialnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/quick3dmaterialnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quick3dnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/quick3dnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/quick3dnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/quick3dnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/quick3drenderablenodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/quick3drenderablenodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dtexturenodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quick3dtexturenodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dtexturenodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/quick3dtexturenodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dtexturenodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/quick3dtexturenodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dtexturenodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/quick3dtexturenodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/quickitemnodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp rename to src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h b/src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h rename to src/tools/qml2puppet/qml2puppet/instances/servernodeinstance.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/viewconfig.cpp b/src/tools/qml2puppet/qml2puppet/instances/viewconfig.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/viewconfig.cpp rename to src/tools/qml2puppet/qml2puppet/instances/viewconfig.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/viewconfig.h b/src/tools/qml2puppet/qml2puppet/instances/viewconfig.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/instances/viewconfig.h rename to src/tools/qml2puppet/qml2puppet/instances/viewconfig.h diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/src/tools/qml2puppet/qml2puppet/qml2puppetmain.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp rename to src/tools/qml2puppet/qml2puppet/qml2puppetmain.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.cpp b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.cpp rename to src/tools/qml2puppet/qmlprivategate/qmlprivategate.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.h b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.h similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.h rename to src/tools/qml2puppet/qmlprivategate/qmlprivategate.h diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.pri b/src/tools/qml2puppet/qmlprivategate/qmlprivategate.pri similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qmlprivategate/qmlprivategate.pri rename to src/tools/qml2puppet/qmlprivategate/qmlprivategate.pri diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/src/tools/qml2puppet/qmlpuppet.qrc similarity index 100% rename from share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc rename to src/tools/qml2puppet/qmlpuppet.qrc diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index dc390d92633..4e2deb605d0 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -155,8 +155,8 @@ extend_qtc_test(unittest "${QmlDesignerDir}/designercore" "${QmlDesignerDir}/designercore/include" "${QmlDesignerDir}/designercore/imagecache" - "${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces" - "${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types" + "${QmlDesignerDir}/../../../src/libs/qmlpuppetcommunication/interfaces" + "${QmlDesignerDir}/../../../src/libs/qmlpuppetcommunication/types" DEFINES QMLDESIGNERCORE_STATIC_LIBRARY QMLDESIGNER_STATIC_LIBRARY SOURCES_PREFIX @@ -167,7 +167,7 @@ extend_qtc_test(unittest extend_qtc_test(unittest SOURCES_PREFIX "${QmlDesignerDir}/designercore" SOURCES - ../../../../share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h + ../../../../src/libs/qmlpuppetcommunication/interfaces/commondefines.h ../components/listmodeleditor/listmodeleditormodel.cpp ../components/listmodeleditor/listmodeleditormodel.h exceptions/exception.cpp From 583e53cb085db1dec0dbd648b4511d00f262277d Mon Sep 17 00:00:00 2001 From: Knud Dollereder Date: Wed, 9 Nov 2022 15:21:30 +0100 Subject: [PATCH 31/71] QmlDesigner: Make DS find the qmlpuppet on macOS The puppet is now build into a different directory. This patch updates the qml2puppet search path for DS. Change-Id: Ib522df599f429914275700813fa8d1e526b1ce4a Reviewed-by: Marco Bubke Reviewed-by: Qt CI Bot --- .../qmldesigner/qmldesignerexternaldependencies.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp index 9538f61297d..eb37c71b500 100644 --- a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp +++ b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp @@ -137,13 +137,6 @@ bool ExternalDependencies::hasStartupTarget() const } namespace { -Utils::FilePath defaultPuppetFallbackDirectory() -{ - if (Utils::HostOsInfo::isMacHost()) - return Core::ICore::libexecPath("qmldesigner"); - - return Core::ICore::libexecPath(); -} Utils::FilePath qmlPuppetExecutablePath(const Utils::FilePath &workingDirectory) { @@ -156,7 +149,7 @@ Utils::FilePath qmlPuppetFallbackDirectory(const DesignerSettings &settings) auto puppetFallbackDirectory = Utils::FilePath::fromString( settings.value(DesignerSettingsKey::PUPPET_DEFAULT_DIRECTORY).toString()); if (puppetFallbackDirectory.isEmpty() || !puppetFallbackDirectory.exists()) - return defaultPuppetFallbackDirectory(); + return Core::ICore::libexecPath(); return puppetFallbackDirectory; } From 7cfad178506c7344e29075e334a57cce6cea02ed Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 9 Nov 2022 12:06:09 +0100 Subject: [PATCH 32/71] QmlDesigner: Fix warning for QQmlListReference Change-Id: I18e2462d5d52d9c464de5510f86e8cb4da05cc1d Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- .../qml2puppet/instances/objectnodeinstance.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp index fe51d7ecc77..49720c38d46 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/objectnodeinstance.cpp @@ -273,9 +273,15 @@ static QVariant objectToVariant(QObject *object) return QVariant::fromValue(object); } -static void removeObjectFromList(const QQmlProperty &property, QObject *objectToBeRemoved, QQmlEngine * engine) +static void removeObjectFromList(const QQmlProperty &property, + QObject *objectToBeRemoved, + [[maybe_unused]] QQmlEngine *engine) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + QQmlListReference listReference(property.object(), property.name().toUtf8()); +#else QQmlListReference listReference(property.object(), property.name().toUtf8(), engine); +#endif if (!QmlPrivateGate::hasFullImplementedListInterface(listReference)) { qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!"; From cc690a407f07f24eec4cfd7b0843f8fbff34ff31 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 9 Nov 2022 12:06:09 +0100 Subject: [PATCH 33/71] QmlDesigner: Remove macos specific puppet path We already removed it everywhere else. Change-Id: Id71880474550ca4c5dfc26ef77db74455a44ca16 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp index eb37c71b500..7cff56d272b 100644 --- a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp +++ b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp @@ -28,10 +28,7 @@ double ExternalDependencies::formEditorDevicePixelRatio() const QString ExternalDependencies::defaultPuppetFallbackDirectory() const { - if (Utils::HostOsInfo::isMacHost()) - return Core::ICore::libexecPath("qmldesigner").toString(); - else - return Core::ICore::libexecPath().toString(); + return Core::ICore::libexecPath().toString(); } QString ExternalDependencies::qmlPuppetFallbackDirectory() const From 7fe256ca325923db150f5da2ae87ebda019a2543 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Nov 2022 17:39:38 +0200 Subject: [PATCH 34/71] QmlDesigner: Insert CubeMapTexture to correct prop in SceneEnvironment Fixes: QDS-8169 Change-Id: Ic19430a25ad7e04e0e7c72c2dcc2991d30beac07 Reviewed-by: Mahmoud Badri Reviewed-by: --- .../components/navigator/choosefrompropertylistdialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp index 6a267f2742d..8c1d2b360c3 100644 --- a/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp +++ b/src/plugins/qmldesigner/components/navigator/choosefrompropertylistdialog.cpp @@ -57,7 +57,10 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i } else if (parentInfo.isQtQuick3DTextureInput()) { propertyList.append("texture"); } else if (parentInfo.isQtQuick3DSceneEnvironment()) { - propertyList.append("lightProbe"); + if (insertInfo.isQtQuick3DCubeMapTexture()) + propertyList.append("skyBoxCubeMap"); + else + propertyList.append("lightProbe"); } } else if (insertInfo.isQtQuick3DEffect()) { if (parentInfo.isQtQuick3DSceneEnvironment()) From 08f87321085da426144de11b68ef0f8153718670 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Tue, 8 Nov 2022 17:20:38 +0200 Subject: [PATCH 35/71] QmlDesigner: Move nodes to a specific position A list of nodes could be moved to a new position. This is useful for positioning the visual items within the transactions of the DesignDocument. Paste to position is also available. Paste method is modified by this commit. Task-number: QDS-8063 Change-Id: Id5a295ee6a096952379e2b46d8e740d28562d5e9 Reviewed-by: Mahmoud Badri Reviewed-by: Reviewed-by: Samuel Ghinet Reviewed-by: Miikka Heikkinen --- .../components/integration/designdocument.cpp | 240 ++++++++---------- .../components/integration/designdocument.h | 2 + 2 files changed, 101 insertions(+), 141 deletions(-) diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 1921f458935..e75c791a197 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -191,6 +191,93 @@ bool DesignDocument::pasteSVG() return true; } +void DesignDocument::moveNodesToPosition(const QList &nodes, const std::optional &position) +{ + if (!nodes.size()) + return; + + QList movingNodes = nodes; + DesignDocumentView view{m_externalDependencies}; + currentModel()->attachView(&view); + + ModelNode targetNode; // the node that new nodes should be placed in + if (!view.selectedModelNodes().isEmpty()) + targetNode = view.firstSelectedModelNode(); + + // in case we copy and paste a selection we paste in the parent item + if ((view.selectedModelNodes().count() == movingNodes.count()) + && targetNode.hasParentProperty()) { + targetNode = targetNode.parentProperty().parentModelNode(); + } else if (view.selectedModelNodes().isEmpty()) { + // if selection is empty and copied nodes are all 3D nodes, paste them under the active scene + bool all3DNodes = Utils::allOf(movingNodes, [](const ModelNode &node) { + return node.metaInfo().isQtQuick3DNode(); + }); + + if (all3DNodes) { + auto data = rootModelNode().auxiliaryData(active3dSceneProperty); + if (data) { + if (int activeSceneId = data->toInt(); activeSceneId != -1) { + NodeListProperty sceneNodeProperty = QmlVisualNode::findSceneNodeProperty( + rootModelNode().view(), activeSceneId); + targetNode = sceneNodeProperty.parentModelNode(); + } + } + } + } + + if (!targetNode.isValid()) + targetNode = view.rootModelNode(); + + for (const ModelNode &node : std::as_const(movingNodes)) { + for (const ModelNode &node2 : std::as_const(movingNodes)) { + if (node.isAncestorOf(node2)) + movingNodes.removeAll(node2); + } + } + + bool isSingleNode = movingNodes.size() == 1; + if (isSingleNode) { + ModelNode singleNode = movingNodes.first(); + if (targetNode.hasParentProperty() + && singleNode.simplifiedTypeName() == targetNode.simplifiedTypeName() + && singleNode.variantProperty("width").value() == targetNode.variantProperty("width").value() + && singleNode.variantProperty("height").value() == targetNode.variantProperty("height").value()) { + targetNode = targetNode.parentProperty().parentModelNode(); + } + } + + const PropertyName defaultPropertyName = targetNode.metaInfo().defaultPropertyName(); + if (!targetNode.metaInfo().property(defaultPropertyName).isListProperty()) + qWarning() << Q_FUNC_INFO << "Cannot reparent to" << targetNode; + NodeListProperty parentProperty = targetNode.nodeListProperty(defaultPropertyName); + QList pastedNodeList; + + const double scatterRange = 20.; + int offset = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; + + std::optional firstVisualNode; + QVector3D translationVect; + for (const ModelNode &node : std::as_const(movingNodes)) { + ModelNode pastedNode(view.insertModel(node)); + pastedNodeList.append(pastedNode); + parentProperty.reparentHere(pastedNode); + + QmlVisualNode visualNode(pastedNode); + if (!firstVisualNode.has_value() && visualNode.isValid()){ + firstVisualNode = visualNode; + translationVect = (position.has_value() && firstVisualNode.has_value()) + ? position.value() - firstVisualNode->position() + : QVector3D(); + } + visualNode.translate(translationVect); + visualNode.scatter(targetNode, offset); + } + + view.setSelectedModelNodes(pastedNodeList); + view.model()->clearMetaInfoCache(); +} + bool DesignDocument::inFileComponentModelActive() const { return bool(m_inFileComponentModel); @@ -492,46 +579,12 @@ void DesignDocument::cutSelected() deleteSelected(); } -static void scatterItem(const ModelNode &pastedNode, const ModelNode &targetNode, int offset = -2000) +void DesignDocument::paste() { - if (targetNode.metaInfo().isValid() && targetNode.metaInfo().isLayoutable()) - return; - - if (!(pastedNode.hasVariantProperty("x") && pastedNode.hasVariantProperty("y"))) - return; - - bool scatter = false; - for (const ModelNode &childNode : targetNode.directSubModelNodes()) { - if (childNode.variantProperty("x").value() == pastedNode.variantProperty("x").value() && - childNode.variantProperty("y").value() == pastedNode.variantProperty("y").value()) { - scatter = true; - break; - } - } - if (!scatter) - return; - - if (offset == -2000) { // scatter in range - double x = pastedNode.variantProperty("x").value().toDouble(); - double y = pastedNode.variantProperty("y").value().toDouble(); - - const double scatterRange = 20.; - x += QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; - y += QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; - - pastedNode.variantProperty("x").setValue(int(x)); - pastedNode.variantProperty("y").setValue(int(y)); - } else { // offset - int x = pastedNode.variantProperty("x").value().toInt(); - int y = pastedNode.variantProperty("y").value().toInt(); - x += offset; - y += offset; - pastedNode.variantProperty("x").setValue(x); - pastedNode.variantProperty("y").setValue(y); - } + pasteToPosition({}); } -void DesignDocument::paste() +void DesignDocument::pasteToPosition(const std::optional &position) { if (pasteSVG()) return; @@ -547,116 +600,21 @@ void DesignDocument::paste() DesignDocumentView view{m_externalDependencies}; pasteModel->attachView(&view); ModelNode rootNode(view.rootModelNode()); - QList selectedNodes = rootNode.directSubModelNodes(); - pasteModel->detachView(&view); if (rootNode.type() == "empty") return; - if (rootNode.id() == "__multi__selection__") { // pasting multiple objects - currentModel()->attachView(&view); + QList selectedNodes; + if (rootNode.id() == "__multi__selection__") + selectedNodes << rootNode.directSubModelNodes(); + else + selectedNodes << rootNode; - ModelNode targetNode; + pasteModel->detachView(&view); - if (!view.selectedModelNodes().isEmpty()) - targetNode = view.firstSelectedModelNode(); - - // in case we copy and paste a selection we paste in the parent item - if ((view.selectedModelNodes().count() == selectedNodes.count()) - && targetNode.hasParentProperty()) { - targetNode = targetNode.parentProperty().parentModelNode(); - } else if (view.selectedModelNodes().isEmpty()) { - // if selection is empty and copied nodes are all 3D nodes, paste them under the active scene - bool all3DNodes = std::find_if(selectedNodes.cbegin(), - selectedNodes.cend(), - [](const ModelNode &node) { - return !node.metaInfo().isQtQuick3DNode(); - }) - == selectedNodes.cend(); - if (all3DNodes) { - auto data = rootModelNode().auxiliaryData(active3dSceneProperty); - if (data) { - if (int activeSceneId = data->toInt(); activeSceneId != -1) { - NodeListProperty sceneNodeProperty = QmlVisualNode::findSceneNodeProperty( - rootModelNode().view(), activeSceneId); - targetNode = sceneNodeProperty.parentModelNode(); - } - } - } - } - - if (!targetNode.isValid()) - targetNode = view.rootModelNode(); - - for (const ModelNode &node : std::as_const(selectedNodes)) { - for (const ModelNode &node2 : std::as_const(selectedNodes)) { - if (node.isAncestorOf(node2)) - selectedNodes.removeAll(node2); - } - } - - rewriterView()->executeInTransaction("DesignDocument::paste1", [&view, selectedNodes, targetNode]() { - QList pastedNodeList; - - const double scatterRange = 20.; - int offset = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; - - const auto defaultPropertyName = targetNode.metaInfo().defaultPropertyName(); - auto parentProperty = targetNode.nodeListProperty(defaultPropertyName); - for (const ModelNode &node : std::as_const(selectedNodes)) { - ModelNode pastedNode(view.insertModel(node)); - pastedNodeList.append(pastedNode); - scatterItem(pastedNode, targetNode, offset); - parentProperty.reparentHere(pastedNode); - } - - view.setSelectedModelNodes(pastedNodeList); - }); - - } else { // pasting single object - rewriterView()->executeInTransaction("DesignDocument::paste1", [this, &view, rootNode]() { - currentModel()->attachView(&view); - ModelNode pastedNode(view.insertModel(rootNode)); - ModelNode targetNode; - - if (!view.selectedModelNodes().isEmpty()) { - targetNode = view.firstSelectedModelNode(); - } else { - // if selection is empty and this is a 3D Node, paste it under the active scene - if (pastedNode.metaInfo().isQtQuick3DNode()) { - auto data = rootModelNode().auxiliaryData(active3dSceneProperty); - if (data) { - if (int activeSceneId = data->toInt(); activeSceneId != -1) { - NodeListProperty sceneNodeProperty = QmlVisualNode::findSceneNodeProperty( - rootModelNode().view(), activeSceneId); - targetNode = sceneNodeProperty.parentModelNode(); - } - } - } - } - - if (!targetNode.isValid()) - targetNode = view.rootModelNode(); - - if (targetNode.hasParentProperty() && - pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName() && - pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value() && - pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value()) { - targetNode = targetNode.parentProperty().parentModelNode(); - } - - PropertyName defaultProperty(targetNode.metaInfo().defaultPropertyName()); - - scatterItem(pastedNode, targetNode); - if (targetNode.metaInfo().property(defaultProperty).isListProperty()) - targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); - else - qWarning() << "Cannot reparent to" << targetNode; - - view.setSelectedModelNodes({pastedNode}); - }); - view.model()->clearMetaInfoCache(); - } + rewriterView()->executeInTransaction("DesignDocument::pasteToPosition", [this, selectedNodes, position]() { + moveNodesToPosition(selectedNodes, position); + }); } void DesignDocument::selectAll() diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 25cd03c164e..4750908f64a 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -99,6 +99,7 @@ public: void copySelected(); void cutSelected(); void paste(); + void pasteToPosition(const std::optional &position); void selectAll(); void undo(); void redo(); @@ -128,6 +129,7 @@ private: // functions ModelPointer createInFileComponentModel(); bool pasteSVG(); + void moveNodesToPosition(const QList &nodes, const std::optional &position); private: // variables ModelPointer m_documentModel; From bb64505cab8754e114231e8947cad1444db74014 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 8 Nov 2022 17:29:52 +0200 Subject: [PATCH 36/71] QmlDesigner: Implement adding a bundle texture as light probe Fixes: QDS-8205 Change-Id: Icb57287fa36df5d44d59ffc64e26fa3d778d24d6 Reviewed-by: Miikka Heikkinen --- .../ContentLibraryTextureContextMenu.qml | 7 +- .../ContentLibraryTexturesView.qml | 2 +- .../contentlibrarytexturesmodel.cpp | 14 ++++ .../contentlibrarytexturesmodel.h | 6 ++ .../contentlibrary/contentlibraryview.cpp | 68 +++++++++++++++---- .../contentlibrary/contentlibraryview.h | 2 + .../contentlibrary/contentlibrarywidget.cpp | 14 +++- .../contentlibrary/contentlibrarywidget.h | 6 +- .../components/edit3d/edit3dview.cpp | 3 +- .../designercore/include/abstractview.h | 3 + .../qmldesigner/designercore/include/model.h | 2 + .../designercore/model/abstractview.cpp | 16 +++++ .../qmldesigner/designercore/model/model.cpp | 18 ++++- .../qmldesigner/designercore/model/model_p.h | 2 + 14 files changed, 138 insertions(+), 25 deletions(-) diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml index 373b2108084..61bd0ebfd7e 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTextureContextMenu.qml @@ -10,6 +10,7 @@ StudioControls.Menu { id: root property var targetTexture: null + property bool hasSceneEnv: false function popupMenu(targetTexture = null) { @@ -32,8 +33,8 @@ StudioControls.Menu { } StudioControls.MenuItem { - text: qsTr("Add scene environment") - enabled: root.targetTexture - onTriggered: rootView.addEnv(root.targetTexture) + text: qsTr("Add light probe") + enabled: root.hasSceneEnv && root.targetTexture + onTriggered: rootView.addLightProbe(root.targetTexture) } } diff --git a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml index 469a4170e20..4e2854a48bf 100644 --- a/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml +++ b/share/qtcreator/qmldesigner/contentLibraryQmlSource/ContentLibraryTexturesView.qml @@ -39,7 +39,7 @@ HelperWidgets.ScrollView { ContentLibraryTextureContextMenu { id: ctxMenu - // TODO + hasSceneEnv: root.model.hasSceneEnv } Repeater { diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp index 38c9522879b..4d793e4e2bd 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.cpp @@ -115,6 +115,20 @@ void ContentLibraryTexturesModel::setHasMaterialRoot(bool b) emit hasMaterialRootChanged(); } +bool ContentLibraryTexturesModel::hasSceneEnv() const +{ + return m_hasSceneEnv; +} + +void ContentLibraryTexturesModel::setHasSceneEnv(bool b) +{ + if (b == m_hasSceneEnv) + return; + + m_hasSceneEnv = b; + emit hasSceneEnvChanged(); +} + bool ContentLibraryTexturesModel::matBundleExists() const { return m_texBundleLoaded && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h index 8009dd3ff80..ca5e7a6963b 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarytexturesmodel.h @@ -18,6 +18,7 @@ class ContentLibraryTexturesModel : public QAbstractListModel Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged) + Q_PROPERTY(bool hasSceneEnv READ hasSceneEnv WRITE setHasSceneEnv NOTIFY hasSceneEnvChanged) public: ContentLibraryTexturesModel(QObject *parent = nullptr); @@ -42,6 +43,9 @@ public: bool hasModelSelection() const; void setHasModelSelection(bool b); + bool hasSceneEnv() const; + void setHasSceneEnv(bool b); + void resetModel(); void loadTextureBundle(const QString &bundlePath); @@ -54,6 +58,7 @@ signals: void hasMaterialRootChanged(); void materialVisibleChanged(); void matBundleExistsChanged(); + void hasSceneEnvChanged(); private: bool isValidIndex(int idx) const; @@ -66,6 +71,7 @@ private: bool m_hasQuick3DImport = false; bool m_texBundleLoaded = false; bool m_hasModelSelection = false; + bool m_hasSceneEnv = false; int m_quick3dMajorVersion = -1; int m_quick3dMinorVersion = -1; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index fe035cee345..28aa071a8ec 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -3,16 +3,19 @@ #include "contentlibraryview.h" +#include "bindingproperty.h" #include "contentlibrarybundleimporter.h" #include "contentlibrarywidget.h" #include "contentlibrarymaterial.h" #include "contentlibrarymaterialsmodel.h" +#include "contentlibrarytexturesmodel.h" #include "modelnodeoperations.h" #include "nodelistproperty.h" #include "qmlobjectnode.h" #include "variantproperty.h" #include +#include #include #ifndef QMLDESIGNER_TEST @@ -48,15 +51,20 @@ WidgetInfo ContentLibraryView::widgetInfo() }); connect(m_widget, &ContentLibraryWidget::addTextureRequested, this, [&] (const QString texPath, ContentLibraryWidget::AddTextureMode mode) { - AddFilesResult result = ModelNodeOperations::addImageToProject({texPath}, "images", false); + executeInTransaction("ContentLibraryView::widgetInfo", [&] { + // copy image to project + AddFilesResult result = ModelNodeOperations::addImageToProject({texPath}, "images", false); - if (result == AddFilesResult::Failed) { - Core::AsynchronousMessageBox::warning(tr("Failed to Add Texture"), - tr("Could not add %1 to project.").arg(texPath)); - return; - } + if (result == AddFilesResult::Failed) { + Core::AsynchronousMessageBox::warning(tr("Failed to Add Texture"), + tr("Could not add %1 to project.").arg(texPath)); + return; + } - if (mode == ContentLibraryWidget::AddTextureMode::Texture) { + if (mode == ContentLibraryWidget::AddTextureMode::Image) + return; + + // create a texture from the image ModelNode matLib = materialLibraryNode(); if (!matLib.isValid()) return; @@ -68,9 +76,15 @@ WidgetInfo ContentLibraryView::widgetInfo() VariantProperty sourceProp = newTexNode.variantProperty("source"); sourceProp.setValue(QLatin1String("images/%1").arg(texPath.split('/').last())); matLib.defaultNodeListProperty().reparentHere(newTexNode); - } else if (mode == ContentLibraryWidget::AddTextureMode::Environment) { - // TODO: assign as env - } + + // assign the texture as scene environment's light probe + if (mode == ContentLibraryWidget::AddTextureMode::LightProbe && m_activeSceneEnv.isValid()) { + BindingProperty lightProbeProp = m_activeSceneEnv.bindingProperty("lightProbe"); + lightProbeProp.setExpression(newTexNode.id()); + VariantProperty bgModeProp = m_activeSceneEnv.variantProperty("backgroundMode"); + bgModeProp.setValue(QVariant::fromValue(Enumeration("SceneEnvironment", "SkyBox"))); + } + }); }); ContentLibraryMaterialsModel *materialsModel = m_widget->materialsModel().data(); @@ -99,7 +113,7 @@ WidgetInfo ContentLibraryView::widgetInfo() connect(materialsModel, &ContentLibraryMaterialsModel::bundleMaterialAboutToUnimport, this, [&] (const QmlDesigner::TypeName &type) { // delete instances of the bundle material that is about to be unimported - executeInTransaction("MaterialBrowserView::widgetInfo", [&] { + executeInTransaction("ContentLibraryView::widgetInfo", [&] { ModelNode matLib = materialLibraryNode(); if (!matLib.isValid()) return; @@ -157,8 +171,36 @@ void ContentLibraryView::importsChanged(const QList &addedImports, const m_widget->materialsModel()->setHasQuick3DImport(m_hasQuick3DImport); } +void ContentLibraryView::active3DSceneChanged(qint32 sceneId) +{ + m_activeSceneEnv = {}; + bool sceneEnvExists = false; + if (sceneId != -1) { + ModelNode activeScene = active3DSceneNode(); + if (activeScene.isValid()) { + ModelNode view3D; + if (activeScene.metaInfo().isQtQuick3DView3D()) { + view3D = activeScene; + } else { + ModelNode sceneParent = activeScene.parentProperty().parentModelNode(); + if (sceneParent.metaInfo().isQtQuick3DView3D()) + view3D = sceneParent; + } + + if (view3D.isValid()) { + m_activeSceneEnv = modelNodeForId(view3D.bindingProperty("environment").expression()); + if (m_activeSceneEnv.isValid()) + sceneEnvExists = true; + } + } + } + + m_widget->texturesModel()->setHasSceneEnv(sceneEnvExists); + m_widget->environmentsModel()->setHasSceneEnv(sceneEnvExists); +} + void ContentLibraryView::selectedNodesChanged(const QList &selectedNodeList, - const QList &lastSelectedNodeList) + const QList &lastSelectedNodeList) { Q_UNUSED(lastSelectedNodeList) @@ -204,7 +246,7 @@ void ContentLibraryView::applyBundleMaterialToDropTarget(const ModelNode &bundle if (!bundleMat.isValid() && !metaInfo.isValid()) return; - executeInTransaction("MaterialBrowserView::applyBundleMaterialToDropTarget", [&] { + executeInTransaction("ContentLibraryView::applyBundleMaterialToDropTarget", [&] { ModelNode newMatNode = metaInfo.isValid() ? createMaterial(metaInfo) : bundleMat; // TODO: unify this logic as it exist elsewhere also diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h index 8ece6a76d05..a55d7d772fa 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h @@ -30,6 +30,7 @@ public: void modelAttached(Model *model) override; void modelAboutToBeDetached(Model *model) override; void importsChanged(const QList &addedImports, const QList &removedImports) override; + void active3DSceneChanged(qint32 sceneId) override; void selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList) override; void customNotification(const AbstractView *view, const QString &identifier, @@ -46,6 +47,7 @@ private: QList m_bundleMaterialTargets; QList m_selectedModels; // selected 3D model nodes ContentLibraryMaterial *m_draggedBundleMaterial = nullptr; + ModelNode m_activeSceneEnv; bool m_bundleMaterialAddToSelected = false; bool m_hasQuick3DImport = false; }; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp index 02d116811eb..99a24e70b40 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.cpp @@ -225,9 +225,9 @@ void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex) emit addTextureRequested(tex->path(), AddTextureMode::Texture); } -void ContentLibraryWidget::addEnv(ContentLibraryTexture *tex) +void ContentLibraryWidget::addLightProbe(ContentLibraryTexture *tex) { - emit addTextureRequested(tex->path(), AddTextureMode::Environment); + emit addTextureRequested(tex->path(), AddTextureMode::LightProbe); } QPointer ContentLibraryWidget::materialsModel() const @@ -235,4 +235,14 @@ QPointer ContentLibraryWidget::materialsModel() co return m_materialsModel; } +QPointer ContentLibraryWidget::texturesModel() const +{ + return m_texturesModel; +} + +QPointer ContentLibraryWidget::environmentsModel() const +{ + return m_environmentsModel; +} + } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h index 3eb470b7ae3..1c14794c6c2 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h @@ -36,14 +36,16 @@ public: void setMaterialsModel(QPointer newMaterialsModel); QPointer materialsModel() const; + QPointer texturesModel() const; + QPointer environmentsModel() const; Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos); Q_INVOKABLE void startDragTexture(QmlDesigner::ContentLibraryTexture *tex, const QPointF &mousePos); Q_INVOKABLE void addImage(QmlDesigner::ContentLibraryTexture *tex); Q_INVOKABLE void addTexture(QmlDesigner::ContentLibraryTexture *tex); - Q_INVOKABLE void addEnv(QmlDesigner::ContentLibraryTexture *tex); + Q_INVOKABLE void addLightProbe(QmlDesigner::ContentLibraryTexture *tex); - enum class AddTextureMode { Image, Texture, Environment }; + enum class AddTextureMode { Image, Texture, LightProbe }; signals: void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index c734b0e362c..cbf78003754 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -11,7 +11,6 @@ #include "nodehints.h" #include "seekerslider.h" -#include #include #include #include @@ -110,7 +109,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) if (sceneState.contains(sceneKey)) { qint32 newActiveScene = sceneState[sceneKey].value(); edit3DWidget()->canvas()->updateActiveScene(newActiveScene); - rootModelNode().setAuxiliaryData(active3dSceneProperty, newActiveScene); + model()->setActive3DSceneId(newActiveScene); } if (sceneState.contains(selectKey)) diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index b67533acf91..2afc56e6e0a 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -219,6 +219,8 @@ public: virtual void view3DAction(View3DActionType type, const QVariant &value); + virtual void active3DSceneChanged(qint32 sceneId); + virtual void dragStarted(QMimeData *mimeData); virtual void dragEnded(); @@ -226,6 +228,7 @@ public: void ensureMaterialLibraryNode(); ModelNode materialLibraryNode(); + ModelNode active3DSceneNode(); void assignMaterialTo3dModel(const ModelNode &modelNode, const ModelNode &materialNode = {}); const NodeInstanceView *nodeInstanceView() const; diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 6c1f10c6886..e22dbe70b6e 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -148,6 +148,8 @@ public: QString generateNewId(const QString &prefixName, const QString &fallbackPrefix = "element") const; QString generateIdFromName(const QString &name, const QString &fallbackId = "element") const; + void setActive3DSceneId(qint32 sceneId); + void startDrag(QMimeData *mimeData, const QPixmap &icon); void endDrag(); diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 0dd4695ad76..8f937f97958 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -3,6 +3,7 @@ #include "abstractview.h" +#include "auxiliarydataproperties.h" #include "model.h" #include "model_p.h" #include "internalnode_p.h" @@ -392,6 +393,8 @@ void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, con void AbstractView::view3DAction(View3DActionType, const QVariant &) {} +void AbstractView::active3DSceneChanged(qint32 /*sceneId*/) {} + void AbstractView::dragStarted(QMimeData * /*mimeData*/) {} void AbstractView::dragEnded() {} @@ -843,6 +846,19 @@ ModelNode AbstractView::materialLibraryNode() return modelNodeForId(Constants::MATERIAL_LIB_ID); } +ModelNode AbstractView::active3DSceneNode() +{ + auto activeSceneAux = rootModelNode().auxiliaryData(active3dSceneProperty); + if (activeSceneAux) { + int activeScene = activeSceneAux->toInt(); + + if (hasModelNodeForInternalId(activeScene)) + return modelNodeForInternalId(activeScene); + } + + return {}; +} + // Assigns given material to a 3D model. // The assigned material is also inserted into material library if not already there. // If given material is not valid, first existing material from material library is used, diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 57005fb2c6e..d0f5353d471 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -6,9 +6,8 @@ #include "model_p.h" #include - - #include "abstractview.h" +#include "auxiliarydataproperties.h" #include "internalnodeabstractproperty.h" #include "internalnodelistproperty.h" #include "internalproperty.h" @@ -571,6 +570,11 @@ void ModelPrivate::notifyView3DAction(View3DActionType type, const QVariant &val notifyNormalViewsLast([&](AbstractView *view) { view->view3DAction(type, value); }); } +void ModelPrivate::notifyActive3DSceneIdChanged(qint32 sceneId) +{ + notifyInstanceChanges([&](AbstractView *view) { view->active3DSceneChanged(sceneId); }); +} + void ModelPrivate::notifyDragStarted(QMimeData *mimeData) { notifyInstanceChanges([&](AbstractView *view) { view->dragStarted(mimeData); }); @@ -1582,6 +1586,16 @@ QString Model::generateIdFromName(const QString &name, const QString &fallbackId return newId; } +void Model::setActive3DSceneId(qint32 sceneId) +{ + auto activeSceneAux = d->rootNode()->auxiliaryData(active3dSceneProperty); + if (activeSceneAux && activeSceneAux->toInt() == sceneId) + return; + + d->rootNode()->setAuxiliaryData(active3dSceneProperty, sceneId); + d->notifyActive3DSceneIdChanged(sceneId); +} + void Model::startDrag(QMimeData *mimeData, const QPixmap &icon) { d->notifyDragStarted(mimeData); diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 9901e1bfa10..c2715cbf192 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -177,6 +177,8 @@ public: void notifyNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d); void notifyView3DAction(View3DActionType type, const QVariant &value); + void notifyActive3DSceneIdChanged(qint32 sceneId); + void notifyDragStarted(QMimeData *mimeData); void notifyDragEnded(); From cbea3f15cea19cfc01a8f81874ad6d5a3d06903f Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 10 Nov 2022 15:24:26 +0200 Subject: [PATCH 37/71] QmlDesigner: Allow material browser texture selection For now texture selection is independent from material selection. Change-Id: Iffa8354948f0ce64e4a54458531274e0441e87ea Reviewed-by: Miikka Heikkinen --- .../MaterialBrowser.qml | 1 - .../materialBrowserQmlSource/TextureItem.qml | 22 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml index 9a9cb26f791..7849dfd9269 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/MaterialBrowser.qml @@ -221,7 +221,6 @@ Item { leftPadding: 5 rightPadding: 5 bottomPadding: 5 - spacing: 5 columns: root.width / root.cellWidth Repeater { diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml index 68f832f65f6..b5ef129a6c3 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml @@ -7,14 +7,16 @@ import QtQuickDesignerTheme import HelperWidgets import StudioTheme as StudioTheme -Image { +Rectangle { id: root - source: textureSource - sourceSize.width: root.width - sourceSize.height: root.height visible: textureVisible - cache: false + + color: "transparent" + border.width: materialBrowserTexturesModel.selectedIndex === index ? 1 : 0 + border.color: materialBrowserTexturesModel.selectedIndex === index + ? StudioTheme.Values.themeControlOutlineInteraction + : "transparent" signal showContextMenu() @@ -25,10 +27,20 @@ Image { acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: (mouse) => { + materialBrowserTexturesModel.selectTexture(index) + if (mouse.button === Qt.LeftButton) rootView.startDragTexture(index, mapToGlobal(mouse.x, mouse.y)) else if (mouse.button === Qt.RightButton) root.showContextMenu() } } + + Image { + source: textureSource + sourceSize.width: root.width - 10 + sourceSize.height: root.height - 10 + anchors.centerIn: parent + cache: false + } } From 16dde463ed4a447e11b670106e016fccaf8cebf0 Mon Sep 17 00:00:00 2001 From: Samuel Ghinet Date: Mon, 31 Oct 2022 14:03:08 +0200 Subject: [PATCH 38/71] QmlDesigner: Remove "App" from the Components view Task-number: QDS-8116 Change-Id: I9f578bf3081c9399eaf12c2f3d0aa3c27151a016 Reviewed-by: Mahmoud Badri Reviewed-by: Miikka Heikkinen --- .../designercore/metainfo/subcomponentmanager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index 899a753e637..d99834188c5 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -38,6 +38,7 @@ QT_END_NAMESPACE namespace QmlDesigner { static const QString s_qmlFilePattern = QStringLiteral("*.qml"); +constexpr const char AppFileName[] = "App.qml"; SubComponentManager::SubComponentManager(Model *model, ExternalDependenciesInterface &externalDependencies) @@ -232,11 +233,17 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a QFileInfoList monitoredList = watchedFiles(canonicalDirPath); QFileInfoList newList; const QFileInfoList qmlFileList = dir.entryInfoList(); + const QString appFilePath = m_filePathDir.absoluteFilePath(AppFileName); + for (const QFileInfo &qmlFile : qmlFileList) { if (QFileInfo(m_filePath.toLocalFile()) == qmlFile) { // do not parse main file continue; } + + if (qmlFile.absoluteFilePath() == appFilePath) + continue; + if (!qmlFile.fileName().at(0).isUpper()) { // QML sub components must be upper case continue; From 1f6511dba0d0460bd2121fd098275c79903d8d4b Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 10 Nov 2022 17:39:48 +0100 Subject: [PATCH 39/71] QmlDesigner: Fix findCommonAncestor() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QDS-8247 Change-Id: Ia9d8c0728ebfae6e47acf7ff3a2823c8711549fc Reviewed-by: Henning Gründl --- .../components/propertyeditor/propertyeditorqmlbackend.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 894957ed049..3606f626a54 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -809,9 +809,6 @@ NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node) if (!node.isValid()) return node.metaInfo(); - if (auto metaInfo = node.metaInfo()) - return metaInfo; - AbstractView *view = node.view(); if (view->selectedModelNodes().count() > 1) { From 019e44ce2763dc12b3fecae1c159b48869f15e4d Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 4 Nov 2022 18:20:24 +0100 Subject: [PATCH 40/71] QmlDesigner: Rename Projects to Project Task-number: QDS-8127 Change-Id: I675db923474d1c02105bf9d308637368e00565cb Reviewed-by: Reviewed-by: Pranta Ghosh Dastider Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designmodewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 233c88a4b88..574c7cf3651 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -114,7 +114,7 @@ QWidget *DesignModeWidget::createProjectExplorerWidget(QWidget *parent) navigationView.widget = nullptr; for (Core::INavigationWidgetFactory *factory : factories) { - if (factory->id() == "Projects") { + if (factory->id() == "Project") { navigationView = factory->createWidget(); hideToolButtons(navigationView.dockToolBarWidgets); } From a2b85953cfc8577fc36ca8a7a12c635a0b9dde6f Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Thu, 10 Nov 2022 15:53:54 +0200 Subject: [PATCH 41/71] QmlDesigner: Paste to the clicked position Copied items would be placed in the clicked position by the paste action. Task-number: QDS-8063 Change-Id: Iac4b6faacb0f429b826b144dadad3ec32f53580e Reviewed-by: Mahmoud Badri Reviewed-by: Samuel Ghinet Reviewed-by: Reviewed-by: Miikka Heikkinen --- src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 8238b649de0..10c91ff0a45 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -188,7 +188,7 @@ void Edit3DWidget::createContextMenu() }); m_pasteAction = m_contextMenu->addAction(tr("Paste"), [&] { - QmlDesignerPlugin::instance()->currentDesignDocument()->paste(); + QmlDesignerPlugin::instance()->currentDesignDocument()->pasteToPosition(m_contextMenuPos3d); }); m_deleteAction = m_contextMenu->addAction(tr("Delete"), [&] { From 455c84ccbf544120adad8d67ea0a43fa628f6a25 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Thu, 10 Nov 2022 15:44:45 +0200 Subject: [PATCH 42/71] QmlDesigner: Add Duplicate to 3d Context Menu Duplicate action is added to the context menu of the Edit3DWidget. Task-number: QDS-8063 Change-Id: Id1347d28cd819a81e145bb0319e85d19a734090f Reviewed-by: Samuel Ghinet Reviewed-by: Mahmoud Badri Reviewed-by: Reviewed-by: Miikka Heikkinen --- .../qmldesigner/components/edit3d/edit3dwidget.cpp | 5 +++++ .../qmldesigner/components/edit3d/edit3dwidget.h | 1 + .../components/integration/designdocument.cpp | 12 ++++++++++++ .../components/integration/designdocument.h | 1 + 4 files changed, 19 insertions(+) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 10c91ff0a45..91ee59666d3 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -183,6 +183,10 @@ void Edit3DWidget::createContextMenu() m_contextMenu->addSeparator(); + m_duplicateAction = m_contextMenu->addAction(tr("Duplicate"), [&] { + QmlDesignerPlugin::instance()->currentDesignDocument()->duplicateSelected(); + }); + m_copyAction = m_contextMenu->addAction(tr("Copy"), [&] { QmlDesignerPlugin::instance()->currentDesignDocument()->copySelected(); }); @@ -374,6 +378,7 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_editComponentAction->setEnabled(isSingleComponent); m_editMaterialAction->setEnabled(isModel); + m_duplicateAction->setEnabled(isNotRoot); m_copyAction->setEnabled(isNotRoot); m_pasteAction->setEnabled(isPasteAvailable()); m_deleteAction->setEnabled(isNotRoot); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 63aba37484b..38ff56e67ad 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -64,6 +64,7 @@ private: QPointer m_contextMenu; QPointer m_editComponentAction; QPointer m_editMaterialAction; + QPointer m_duplicateAction; QPointer m_copyAction; QPointer m_pasteAction; QPointer m_deleteAction; diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index e75c791a197..2b185f2bf0b 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -579,6 +579,18 @@ void DesignDocument::cutSelected() deleteSelected(); } +void DesignDocument::duplicateSelected() +{ + DesignDocumentView view{m_externalDependencies}; + currentModel()->attachView(&view); + const QList selectedNodes = view.selectedModelNodes(); + currentModel()->detachView(&view); + + rewriterView()->executeInTransaction("DesignDocument::duplicateSelected", [this, selectedNodes]() { + moveNodesToPosition(selectedNodes, {}); + }); +} + void DesignDocument::paste() { pasteToPosition({}); diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 4750908f64a..043444159a8 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -98,6 +98,7 @@ public: void deleteSelected(); void copySelected(); void cutSelected(); + void duplicateSelected(); void paste(); void pasteToPosition(const std::optional &position); void selectAll(); From 8bb3c8f9237d05aad6d880c87a6e2382e5e72457 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 4 Nov 2022 15:41:28 +0200 Subject: [PATCH 43/71] QmlDesigner: Don't cache possible imports until code model has settled Code model can take a couple of seconds to fully resolve when a new project is launched for the first time, so we avoid caching possible imports until we detect no changes in the count of possible imports. Fixes: QDS-8128 Change-Id: I0d35b1eb2d5872f646c141067652645d2e2f106f Reviewed-by: Thomas Hartmann Reviewed-by: Mahmoud Badri Reviewed-by: Qt CI Bot Reviewed-by: --- .../qmldesigner/designercore/model/texttomodelmerger.cpp | 8 ++++++++ .../qmldesigner/designercore/model/texttomodelmerger.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 3b3ef034ff6..65704bc3a53 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -1158,6 +1158,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH if (!errors.isEmpty()) { m_rewriterView->setErrors(errors); setActive(false); + clearPossibleImportKeys(); return false; } if (!justSanityCheck) @@ -1179,6 +1180,12 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH setActive(false); + // Clear possible imports cache if code model hasn't settled yet + const int importKeysSize = m_possibleImportKeys.size(); + if (m_previousPossibleImportsSize != importKeysSize) + m_possibleImportKeys.clear(); + m_previousPossibleImportsSize = importKeysSize; + return true; } catch (Exception &e) { DocumentMessage error(&e); @@ -2452,6 +2459,7 @@ QList TextToModelMerger::getQMLSingletons() const void TextToModelMerger::clearPossibleImportKeys() { m_possibleImportKeys.clear(); + m_previousPossibleImportsSize = -1; } QString TextToModelMerger::textAt(const Document::Ptr &doc, diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h index 4b2f7ae990a..6bf0b2b84ed 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.h @@ -151,6 +151,7 @@ private: QmlJS::ViewerContext m_vContext; QSet > m_qrcMapping; QSet m_possibleImportKeys; + int m_previousPossibleImportsSize = -1; bool m_hasVersionlessImport = false; }; From e3e5524f88a0919ad2491c8ce83d5104bfa9daed Mon Sep 17 00:00:00 2001 From: Amr Essam Date: Fri, 11 Nov 2022 10:07:53 +0200 Subject: [PATCH 44/71] QmlDesigner: crash when dragging an effect twice to component in 2D When an effect is dragged twice, same effect or other effect it caused QDS to crash, in layer mode the effect is replaced, otherwise effect is added upon previous effect Task-number: QDS-8172 Change-Id: I2a3682b21492de0d0cc62bce9bd2965cedfbc826 Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- .../qmldesigner/components/formeditor/dragtool.cpp | 7 +++---- .../qmldesigner/designercore/include/qmlitemnode.h | 6 +++--- .../qmldesigner/designercore/model/qmlitemnode.cpp | 13 +++++-------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp index 1ab170fc1c3..fe345024182 100644 --- a/src/plugins/qmldesigner/components/formeditor/dragtool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/dragtool.cpp @@ -230,8 +230,8 @@ void DragTool::dropEvent(const QList &itemList, QGraphicsSceneD QString effectPath; const QStringList assetPaths = QString::fromUtf8(event->mimeData() ->data(Constants::MIME_TYPE_ASSETS)).split(','); - for (auto &path : assetPaths) { - auto assetType = AssetsLibraryWidget::getAssetTypeAndData(path).first; + for (const QString &path : assetPaths) { + const QString assetType = AssetsLibraryWidget::getAssetTypeAndData(path).first; if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) { effectPath = path; break; @@ -266,8 +266,7 @@ void DragTool::dropEvent(const QList &itemList, QGraphicsSceneD return; } - QmlItemNode effectNode = QmlItemNode:: - createQmlItemNodeForEffect(view(), parentQmlItemNode, effectName); + QmlItemNode::createQmlItemNodeForEffect(view(), parentQmlItemNode, effectName); view()->setSelectedModelNodes({parentQmlItemNode}); view()->resetPuppet(); diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h index ada5887621a..61c38dd5042 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h @@ -60,9 +60,9 @@ public: const QPointF &position, NodeAbstractProperty parentproperty, bool executeInTransaction = true); - static QmlItemNode createQmlItemNodeForEffect(AbstractView *view, - const QmlItemNode &parentNode, - const QString &effectName); + static void createQmlItemNodeForEffect(AbstractView *view, + const QmlItemNode &parentNode, + const QString &effectName); QList children() const; QList resources() const; QList allDirectSubNodes() const; diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index 7a818808158..ca2bb3c5a51 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -5,6 +5,7 @@ #include #include "nodelistproperty.h" #include "nodehints.h" +#include "nodeproperty.h" #include "variantproperty.h" #include "bindingproperty.h" #include "qmlanchors.h" @@ -161,9 +162,9 @@ static bool useLayerEffect() return settings->value(layerEffectEntry, true).toBool(); } -QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view, - const QmlItemNode &parentNode, - const QString &effectName) +void QmlItemNode::createQmlItemNodeForEffect(AbstractView *view, + const QmlItemNode &parentNode, + const QString &effectName) { QmlItemNode newQmlItemNode; @@ -174,7 +175,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view, if (!view->model()->hasImport(import, true, true)) view->model()->changeImports({import}, {}); } catch (const Exception &) { - QTC_ASSERT(false, return QmlItemNode()); + QTC_ASSERT(false, return); } TypeName type(effectName.toUtf8()); @@ -190,10 +191,6 @@ QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view, } else { parentNode.modelNode().variantProperty("layer.enabled").setValue(true); } - - QTC_ASSERT(newQmlItemNode.isValid(), return QmlItemNode()); - - return newQmlItemNode; } bool QmlItemNode::isValid() const From 61c133f48a3e7f0afc8f5f8baba01e3d311709ef Mon Sep 17 00:00:00 2001 From: Samuel Ghinet Date: Tue, 25 Oct 2022 18:24:19 +0300 Subject: [PATCH 45/71] QmlDesigner Fix: Select Background Color doesn't clear Environment Color checkbox Task-number: QDS-7439 Change-Id: I5546e02f7cc2d0bcf3197f94a6ccc557cfb84e7b Reviewed-by: Qt CI Bot Reviewed-by: Mahmoud Badri --- .../edit3d/backgroundcolorselection.cpp | 35 ++++++++++-------- .../edit3d/backgroundcolorselection.h | 6 ++-- .../components/edit3d/edit3dview.cpp | 36 ++++++++++++------- .../components/edit3d/edit3dview.h | 5 +-- .../components/edit3d/edit3dviewconfig.h | 20 +++++++---- .../qmldesignerexternaldependencies.cpp | 4 +-- 6 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp index be4970e7c1e..07d65cb3c33 100644 --- a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp +++ b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.cpp @@ -13,12 +13,13 @@ using namespace QmlDesigner; void BackgroundColorSelection::showBackgroundColorSelectionWidget(QWidget *parent, const QByteArray &key, AbstractView *view, - View3DActionType actionType) + View3DActionType actionType, + const std::function &colorSelected) { if (m_dialog) return; - m_dialog = BackgroundColorSelection::createColorDialog(parent, key, view, actionType); + m_dialog = BackgroundColorSelection::createColorDialog(parent, key, view, actionType, colorSelected); QTC_ASSERT(m_dialog, return); QObject::connect(m_dialog, &QWidget::destroyed, m_dialog, [&]() { @@ -29,32 +30,36 @@ void BackgroundColorSelection::showBackgroundColorSelectionWidget(QWidget *paren QColorDialog *BackgroundColorSelection::createColorDialog(QWidget *parent, const QByteArray &key, AbstractView *view, - View3DActionType actionType) + View3DActionType actionType, + const std::function &colorSelected) { auto dialog = new QColorDialog(parent); dialog->setModal(true); dialog->setAttribute(Qt::WA_DeleteOnClose); - QList oldColorConfig = Edit3DViewConfig::load(key); + QList oldColorConfig = Edit3DViewConfig::loadColor(key); dialog->show(); - QObject::connect(dialog, - &QColorDialog::currentColorChanged, - dialog, + QObject::connect(dialog, &QColorDialog::currentColorChanged, dialog, [actionType, view](const QColor &color) { - Edit3DViewConfig::set(view, actionType, color); + Edit3DViewConfig::setColor(view, actionType, color); }); - QObject::connect(dialog, &QColorDialog::colorSelected, dialog, [key](const QColor &color) { - Edit3DViewConfig::save(key, color); - }); + QObject::connect(dialog, &QColorDialog::colorSelected, dialog, + [key, colorSelected](const QColor &color) { + if (colorSelected) + colorSelected(); - if (Edit3DViewConfig::isValid(oldColorConfig)) { - QObject::connect(dialog, &QColorDialog::rejected, dialog, [actionType, oldColorConfig, view]() { - Edit3DViewConfig::set(view, actionType, oldColorConfig); - }); + Edit3DViewConfig::saveColor(key, color); + }); + + if (Edit3DViewConfig::isColorValid(oldColorConfig)) { + QObject::connect(dialog, &QColorDialog::rejected, dialog, + [actionType, oldColorConfig, view]() { + Edit3DViewConfig::setColor(view, actionType, oldColorConfig); + }); } return dialog; diff --git a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.h b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.h index 061c5b7ea7a..25663ad886b 100644 --- a/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.h +++ b/src/plugins/qmldesigner/components/edit3d/backgroundcolorselection.h @@ -25,13 +25,15 @@ public: static void showBackgroundColorSelectionWidget(QWidget *parent, const QByteArray &key, AbstractView *view, - View3DActionType actionType); + View3DActionType actionType, + const std::function &colorSelected = {}); private: static QColorDialog *createColorDialog(QWidget *parent, const QByteArray &key, AbstractView *view, - View3DActionType actionType); + View3DActionType actionType, + const std::function &colorSelected); inline static QColorDialog *m_dialog = nullptr; }; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index cbf78003754..2159c3c9ee8 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -315,19 +315,25 @@ void Edit3DView::setSeeker(SeekerSlider *slider) m_seeker = slider; } -Edit3DAction *Edit3DView::createSelectBackgrounColorAction() +Edit3DAction *Edit3DView::createSelectBackgroundColorAction(QAction *syncBackgroundColorAction) { QString description = QCoreApplication::translate("SelectBackgroundColorAction", "Select Background Color"); QString tooltip = QCoreApplication::translate("SelectBackgroundColorAction", "Select a color for the background of the 3D view."); - auto operation = [this](const SelectionContext &) { + auto operation = [this, syncBackgroundColorAction](const SelectionContext &) { BackgroundColorSelection::showBackgroundColorSelectionWidget( edit3DWidget(), DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, this, - View3DActionType::SelectBackgroundColor); + View3DActionType::SelectBackgroundColor, + [this, syncBackgroundColorAction]() { + if (syncBackgroundColorAction->isChecked()) { + Edit3DViewConfig::set(this, View3DActionType::SyncBackgroundColor, false); + syncBackgroundColorAction->setChecked(false); + } + }); }; return new Edit3DAction(Constants::EDIT3D_EDIT_SELECT_BACKGROUND_COLOR, @@ -370,21 +376,26 @@ Edit3DAction *Edit3DView::createGridColorSelectionAction() tooltip); } -Edit3DAction *Edit3DView::createResetColorAction() +Edit3DAction *Edit3DView::createResetColorAction(QAction *syncBackgroundColorAction) { QString description = QCoreApplication::translate("ResetEdit3DColorsAction", "Reset Colors"); QString tooltip = QCoreApplication::translate("ResetEdit3DColorsAction", "Reset the background color and the color of the " "grid lines of the 3D view to the default values."); - auto operation = [&](const SelectionContext &) { + auto operation = [this, syncBackgroundColorAction](const SelectionContext &) { QList bgColors = {QRgb(0x222222), QRgb(0x999999)}; - Edit3DViewConfig::set(this, View3DActionType::SelectBackgroundColor, bgColors); - Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors); + Edit3DViewConfig::setColor(this, View3DActionType::SelectBackgroundColor, bgColors); + Edit3DViewConfig::saveColor(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors); QColor gridColor{0xaaaaaa}; - Edit3DViewConfig::set(this, View3DActionType::SelectGridColor, gridColor); - Edit3DViewConfig::save(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, gridColor); + Edit3DViewConfig::setColor(this, View3DActionType::SelectGridColor, gridColor); + Edit3DViewConfig::saveColor(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, gridColor); + + if (syncBackgroundColorAction->isChecked()) { + Edit3DViewConfig::set(this, View3DActionType::SyncBackgroundColor, false); + syncBackgroundColorAction->setChecked(false); + } }; return new Edit3DAction(QmlDesigner::Constants::EDIT3D_EDIT_RESET_BACKGROUND_COLOR, @@ -772,10 +783,11 @@ void Edit3DView::createEdit3DActions() m_visibilityToggleActions << m_showCameraFrustumAction; m_visibilityToggleActions << m_showParticleEmitterAction; - m_backgroundColorActions << createSelectBackgrounColorAction(); + Edit3DAction *syncBackgroundColorAction = createSyncBackgroundColorAction(); + m_backgroundColorActions << createSelectBackgroundColorAction(syncBackgroundColorAction->action()); m_backgroundColorActions << createGridColorSelectionAction(); - m_backgroundColorActions << createSyncBackgroundColorAction(); - m_backgroundColorActions << createResetColorAction(); + m_backgroundColorActions << syncBackgroundColorAction; + m_backgroundColorActions << createResetColorAction(syncBackgroundColorAction->action()); } QVector Edit3DView::leftActions() const diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index b3c7be17a0e..eaa881d5b1e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -15,6 +15,7 @@ QT_BEGIN_NAMESPACE class QInputEvent; +class QAction; QT_END_NAMESPACE namespace QmlDesigner { @@ -77,9 +78,9 @@ private: void checkImports(); void handleEntriesChanged(); - Edit3DAction *createSelectBackgrounColorAction(); + Edit3DAction *createSelectBackgroundColorAction(QAction *syncBackgroundColorAction); Edit3DAction *createGridColorSelectionAction(); - Edit3DAction *createResetColorAction(); + Edit3DAction *createResetColorAction(QAction *syncBackgroundColorAction); Edit3DAction *createSyncBackgroundColorAction(); QPointer m_edit3DWidget; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h b/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h index 2bee2d2b3bd..267e27042c9 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dviewconfig.h @@ -14,7 +14,7 @@ namespace QmlDesigner { class Edit3DViewConfig { public: - static QList load(const char key[]) + static QList loadColor(const char key[]) { QVariant var = QmlDesignerPlugin::settings().value(key); @@ -28,20 +28,26 @@ public: }); } - static void set(AbstractView *view, View3DActionType type, const QList &colorConfig) + static void setColor(AbstractView *view, View3DActionType type, const QList &colorConfig) { if (colorConfig.size() == 1) - set(view, type, colorConfig.at(0)); + setColor(view, type, colorConfig.at(0)); else setVariant(view, type, QVariant::fromValue(colorConfig)); } - static void set(AbstractView *view, View3DActionType type, const QColor &color) + static void setColor(AbstractView *view, View3DActionType type, const QColor &color) { setVariant(view, type, QVariant::fromValue(color)); } - static void save(const QByteArray &key, const QList &colorConfig) + template + static void set(AbstractView *view, View3DActionType type, const T &value) + { + setVariant(view, type, QVariant::fromValue(value)); + } + + static void saveColor(const QByteArray &key, const QList &colorConfig) { QStringList colorNames = Utils::transform(colorConfig, [](const QColor &color) { return color.name(); @@ -50,12 +56,12 @@ public: saveVariant(key, QVariant::fromValue(colorNames)); } - static void save(const QByteArray &key, const QColor &color) + static void saveColor(const QByteArray &key, const QColor &color) { saveVariant(key, QVariant::fromValue(color.name())); } - static bool isValid(const QList &colorConfig) { return !colorConfig.isEmpty(); } + static bool isColorValid(const QList &colorConfig) { return !colorConfig.isEmpty(); } private: static void setVariant(AbstractView *view, View3DActionType type, const QVariant &colorConfig) diff --git a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp index 7cff56d272b..cc872abbf6e 100644 --- a/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp +++ b/src/plugins/qmldesigner/qmldesignerexternaldependencies.cpp @@ -62,12 +62,12 @@ QString ExternalDependencies::currentProjectDirPath() const QList ExternalDependencies::designerSettingsEdit3DViewBackgroundColor() const { - return Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR); + return Edit3DViewConfig::loadColor(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR); } QColor ExternalDependencies::designerSettingsEdit3DViewGridColor() const { - QList gridColorList = Edit3DViewConfig::load(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR); + QList gridColorList = Edit3DViewConfig::loadColor(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR); if (!gridColorList.isEmpty()) return gridColorList.front(); From cf86bc789f20b44d20122bb7863819423e0fd0b7 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 9 Nov 2022 13:50:43 +0100 Subject: [PATCH 46/71] QmlDesigner: Add insight constants Change-Id: I58f398a329b79a346061b192e2fbff40a9b9ec6d Reviewed-by: Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/qmldesignerconstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 92565d36308..7b32ea297b9 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -121,7 +121,7 @@ const char EVENT_NAVIGATORVIEW_TIME[] = "navigatorView"; const char EVENT_DESIGNMODE_TIME[] = "designMode"; const char EVENT_MATERIALEDITOR_TIME[] = "materialEditor"; const char EVENT_MATERIALBROWSER_TIME[] = "materialBrowser"; - +const char EVENT_INSIGHT_TIME[] = "insight"; const char PROPERTY_EDITOR_CLASSNAME_PROPERTY[] = "__classNamePrivateInternal"; From f7e7bcd877f69f3851e244662e424a6d29ebd16f Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 9 Nov 2022 13:50:01 +0100 Subject: [PATCH 47/71] QmlDesigner: Add link error switch in RewriterView Add a switch in RewriterView to disable link error checks. Change-Id: I6bac2c6c92872463c2246e67e803a6724973fae7 Reviewed-by: Reviewed-by: Thomas Hartmann --- .../qmldesigner/designercore/include/rewriterview.h | 13 ++++++++----- .../designercore/model/texttomodelmerger.cpp | 6 ++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h index 9671cd23b43..d95d811261c 100644 --- a/src/plugins/qmldesigner/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h @@ -127,11 +127,13 @@ public: QString convertTypeToImportAlias(const QString &type) const; - bool checkSemanticErrors() const - { return m_checkErrors; } + bool checkSemanticErrors() const { return m_checkSemanticErrors; } - void setCheckSemanticErrors(bool b) - { m_checkErrors = b; } + void setCheckSemanticErrors(bool b) { m_checkSemanticErrors = b; } + + bool checkLinkErrors() const { return m_checkLinkErrors; } + + void setCheckLinkErrors(bool b) { m_checkLinkErrors = b; } QString pathForImport(const Import &import); @@ -191,7 +193,8 @@ private: //variables TextModifier *m_textModifier = nullptr; int transactionLevel = 0; bool m_modificationGroupActive = false; - bool m_checkErrors = true; + bool m_checkSemanticErrors = true; + bool m_checkLinkErrors = true; DifferenceHandling m_differenceHandling; QScopedPointer m_positionStorage; diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 65704bc3a53..9857451a4e8 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -1139,8 +1139,10 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH m_scopeChain = QSharedPointer( new ScopeChain(ctxt.scopeChain())); - qCInfo(rewriterBenchmark) << "linked:" << time.elapsed(); - collectLinkErrors(&errors, ctxt); + if (view()->checkLinkErrors()) { + qCInfo(rewriterBenchmark) << "linked:" << time.elapsed(); + collectLinkErrors(&errors, ctxt); + } setupPossibleImports(snapshot, m_vContext); From dbca9418ff420279d028e7a143020d0eb022cad8 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Thu, 27 Oct 2022 14:41:01 +0200 Subject: [PATCH 48/71] QmlDesigner: Fix CheckBox spacing Change-Id: Ie4b365e67886ee20dc6632da118c561d0e93c95f Reviewed-by: Thomas Hartmann Reviewed-by: --- .../imports/StudioControls/CheckBox.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml index 0803049f6ea..cf7c588a3ce 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml @@ -32,7 +32,7 @@ T.CheckBox { implicitContentHeight + topPadding + bottomPadding, implicitIndicatorHeight + topPadding + bottomPadding) - spacing: StudioTheme.Values.checkBoxSpacing + spacing: checkBoxLabel.visible ? StudioTheme.Values.checkBoxSpacing : 0 hoverEnabled: true activeFocusOnTab: false @@ -85,7 +85,7 @@ T.CheckBox { text: myCheckBox.text font: myCheckBox.font color: StudioTheme.Values.themeTextColor - visible: text !== "" + visible: checkBoxLabel.text !== "" } states: [ From ff5e6a154b526fcb5f74986ddb4d63d5348d668d Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 9 Nov 2022 13:48:28 +0100 Subject: [PATCH 49/71] QmlDesigner: Add hasSignalHandlerProperty function Change-Id: If1616f87c4dfebc121aad842c0b35ae63ddc8dbd Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designercore/include/modelnode.h | 1 + src/plugins/qmldesigner/designercore/model/modelnode.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index 80a26a7b985..6c2f424cf1c 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -136,6 +136,7 @@ public: bool hasProperty(const PropertyName &name) const; bool hasVariantProperty(const PropertyName &name) const; bool hasBindingProperty(const PropertyName &name) const; + bool hasSignalHandlerProperty(const PropertyName &name) const; bool hasNodeAbstractProperty(const PropertyName &name) const; bool hasDefaultNodeAbstractProperty() const; bool hasDefaultNodeListProperty() const; diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index 09a5d653b30..564c1203297 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -889,6 +889,11 @@ bool ModelNode::hasBindingProperty(const PropertyName &name) const return hasProperty(name) && m_internalNode->property(name)->isBindingProperty(); } +bool ModelNode::hasSignalHandlerProperty(const PropertyName &name) const +{ + return hasProperty(name) && m_internalNode->property(name)->isSignalHandlerProperty(); +} + bool ModelNode::hasNodeAbstractProperty(const PropertyName &name) const { return hasProperty(name) && m_internalNode->property(name)->isNodeAbstractProperty(); From 1b6fd9f32856234272099764bd7b28a36ccf9337 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 8 Nov 2022 16:31:41 +0100 Subject: [PATCH 50/71] QmlDesigner: Update SpinBox Update SpinBox to the state of RealSpinBox. Change-Id: Ib4d622edbf3d3cfb22adc7b410a97f348e235270 Reviewed-by: Thomas Hartmann --- .../imports/StudioControls/SpinBox.qml | 69 ++++-- .../imports/StudioControls/SpinBoxInput.qml | 200 +++++++++++++++--- 2 files changed, 225 insertions(+), 44 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml index c61c9d705e0..e20aa3634b3 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml @@ -19,10 +19,14 @@ T.SpinBox { property bool edit: spinBoxInput.activeFocus // This property is used to indicate the global hover state - property bool hover: (mySpinBox.hovered || actionIndicator.hover) && mySpinBox.enabled + property bool hover: (spinBoxInput.hover || actionIndicator.hover || spinBoxIndicatorUp.hover + || spinBoxIndicatorDown.hover || sliderIndicator.hover) + && mySpinBox.enabled property bool drag: false property bool sliderDrag: sliderPopup.drag + property bool dirty: false // user modification flag + property alias actionIndicatorVisible: actionIndicator.visible property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight @@ -35,12 +39,22 @@ T.SpinBox { property real __sliderIndicatorWidth: StudioTheme.Values.sliderIndicatorWidth property real __sliderIndicatorHeight: StudioTheme.Values.sliderIndicatorHeight + property alias __devicePixelRatio: spinBoxInput.devicePixelRatio + property alias pixelsPerUnit: spinBoxInput.pixelsPerUnit + + property alias compressedValueTimer: myTimer + + property string preFocusText: "" + signal compressedValueModified + signal dragStarted + signal dragEnded + signal dragging // Use custom wheel handling due to bugs property bool __wheelEnabled: false wheelEnabled: false - hoverEnabled: true // TODO + hoverEnabled: true width: StudioTheme.Values.defaultControlWidth height: StudioTheme.Values.defaultControlHeight @@ -82,12 +96,11 @@ T.SpinBox { myControl: mySpinBox iconFlip: -1 visible: mySpinBox.spinBoxIndicatorVisible - //hover: mySpinBox.up.hovered // TODO QTBUG-74688 pressed: mySpinBox.up.pressed x: actionIndicator.width + StudioTheme.Values.border y: StudioTheme.Values.border - width: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 - height: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 + width: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 + height: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value < mySpinBox.to : mySpinBox.value > mySpinBox.to @@ -97,12 +110,11 @@ T.SpinBox { id: spinBoxIndicatorDown myControl: mySpinBox visible: mySpinBox.spinBoxIndicatorVisible - //hover: mySpinBox.down.hovered // TODO QTBUG-74688 pressed: mySpinBox.down.pressed x: actionIndicator.width + StudioTheme.Values.border y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height - width: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 - height: spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 + width: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorWidth : 0 + height: mySpinBox.spinBoxIndicatorVisible ? mySpinBox.__spinBoxIndicatorHeight : 0 enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value > mySpinBox.from : mySpinBox.value < mySpinBox.from @@ -111,6 +123,23 @@ T.SpinBox { contentItem: SpinBoxInput { id: spinBoxInput myControl: mySpinBox + + function handleEditingFinished() { + mySpinBox.focus = false + + // Keep the dirty state before calling setValueFromInput(), + // it will be set to false (cleared) internally + var valueModified = mySpinBox.dirty + + mySpinBox.setValueFromInput() + myTimer.stop() + + // Only trigger the signal, if the value was modified + if (valueModified) + mySpinBox.compressedValueModified() + } + + onEditingFinished: spinBoxInput.handleEditingFinished() } background: Rectangle { @@ -216,7 +245,7 @@ T.SpinBox { id: myTimer repeat: false running: false - interval: 100 + interval: 400 onTriggered: mySpinBox.compressedValueModified() } @@ -224,9 +253,10 @@ T.SpinBox { onFocusChanged: mySpinBox.setValueFromInput() onDisplayTextChanged: spinBoxInput.text = mySpinBox.displayText onActiveFocusChanged: { - if (mySpinBox.activeFocus) - // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + if (mySpinBox.activeFocus) { // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + mySpinBox.preFocusText = spinBoxInput.text spinBoxInput.selectAll() + } if (sliderPopup.opened && !mySpinBox.activeFocus) sliderPopup.close() @@ -265,8 +295,11 @@ T.SpinBox { mySpinBox.stepSize = currStepSize } - if (event.key === Qt.Key_Escape) - mySpinBox.focus = false + if (event.key === Qt.Key_Escape) { + spinBoxInput.text = mySpinBox.preFocusText + mySpinBox.dirty = true + spinBoxInput.handleEditingFinished() + } // FIX: This is a temporary fix for QTBUG-74239 if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) @@ -274,13 +307,13 @@ T.SpinBox { } function clamp(v, lo, hi) { - if (v < lo || v > hi) - return Math.min(Math.max(lo, v), hi) - - return v + return (v < lo || v > hi) ? Math.min(Math.max(lo, v), hi) : v } function setValueFromInput() { + if (!mySpinBox.dirty) + return + // FIX: This is a temporary fix for QTBUG-74239 var currValue = mySpinBox.value @@ -298,5 +331,7 @@ T.SpinBox { if (mySpinBox.value !== currValue) mySpinBox.valueModified() + + mySpinBox.dirty = false } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml index dab26a07d59..f1735f96a0e 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml @@ -14,6 +14,9 @@ TextInput { property bool drag: false property bool hover: mouseArea.containsMouse && textInput.enabled + property int devicePixelRatio: 1 + property int pixelsPerUnit: 10 + z: 2 font: myControl.font color: StudioTheme.Values.themeTextColor @@ -75,38 +78,197 @@ TextInput { } } - TapHandler { - id: tapHandler - acceptedDevices: PointerDevice.Mouse - enabled: true - onTapped: { - textInput.forceActiveFocus() - textInput.deselect() // QTBUG-75862 + Item { + id: dragModifierWorkaround + Keys.onPressed: function(event) { + event.accepted = true + + if (event.modifiers & Qt.ControlModifier) { + mouseArea.stepSize = myControl.minStepSize + mouseArea.calcValue() + } + + if (event.modifiers & Qt.ShiftModifier) { + mouseArea.stepSize = myControl.maxStepSize + mouseArea.calcValue() + } } + Keys.onReleased: function(event) { + event.accepted = true + mouseArea.stepSize = myControl.realStepSize + mouseArea.calcValue() + } + } + + // Ensure that we get Up and Down key press events first + Keys.onShortcutOverride: function(event) { + event.accepted = (event.key === Qt.Key_Up || event.key === Qt.Key_Down) } MouseArea { id: mouseArea + + property real stepSize: myControl.stepSize + + // Properties to store the state of a drag operation + property bool dragging: false + property bool hasDragged: false + property bool potentialDragStart: false + + property int initialValue: myControl.value // value on drag operation starts + + property int pressStartX: 0 + property int dragStartX: 0 + property int translationX: 0 + + property int dragDirection: 0 + property int totalUnits: 0 // total number of units dragged + property int units: 0 + + property real __pixelsPerUnit: textInput.devicePixelRatio * textInput.pixelsPerUnit + anchors.fill: parent enabled: true hoverEnabled: true propagateComposedEvents: true acceptedButtons: Qt.LeftButton cursorShape: Qt.PointingHandCursor - onPressed: function(mouse) { mouse.accepted = false } - onWheel: function(wheel) { - if (!myControl.__wheelEnabled) + preventStealing: true + + onPositionChanged: function(mouse) { + if (!mouseArea.dragging + && !myControl.edit + && Math.abs(mouseArea.pressStartX - mouse.x) > StudioTheme.Values.dragThreshold + && mouse.buttons === Qt.LeftButton + && mouseArea.potentialDragStart) { + mouseArea.dragging = true + mouseArea.potentialDragStart = false + mouseArea.initialValue = myControl.value + mouseArea.cursorShape = Qt.ClosedHandCursor + mouseArea.dragStartX = mouse.x + + myControl.drag = true + myControl.dragStarted() + // Force focus on the non visible component to receive key events + dragModifierWorkaround.forceActiveFocus() + textInput.deselect() + } + + if (!mouseArea.dragging) return + mouse.accepted = true + + var translationX = mouse.x - mouseArea.dragStartX + + // Early return if mouse didn't move along x-axis + if (translationX === 0) + return + + var currentDragDirection = Math.sign(translationX) + + // Has drag direction changed + if (currentDragDirection !== mouseArea.dragDirection) { + mouseArea.translationX = 0 + mouseArea.dragDirection = currentDragDirection + mouseArea.totalUnits = mouseArea.units + } + + mouseArea.translationX += translationX + mouseArea.calcValue() + //myControl.realValueModified() + } + + onClicked: function(mouse) { + if (textInput.edit) + mouse.accepted = false + + if (mouseArea.hasDragged) { + mouseArea.hasDragged = false + return + } + + textInput.forceActiveFocus() + textInput.deselect() // QTBUG-75862 + } + + onPressed: function(mouse) { + if (textInput.edit) + mouse.accepted = false + + mouseArea.potentialDragStart = true + mouseArea.pressStartX = mouse.x + } + + onReleased: function(mouse) { + if (textInput.edit) + mouse.accepted = false + + mouseArea.endDrag() + } + + function endDrag() { + if (!mouseArea.dragging) + return + + mouseArea.dragging = false + mouseArea.hasDragged = true + + if (myControl.compressedValueTimer.running) { + myControl.compressedValueTimer.stop() + mouseArea.calcValue() + myControl.compressedValueModified() + } + mouseArea.cursorShape = Qt.PointingHandCursor + myControl.drag = false + myControl.dragEnded() + // Avoid active focus on the component after dragging + dragModifierWorkaround.focus = false + textInput.focus = false + myControl.focus = false + + mouseArea.translationX = 0 + mouseArea.units = 0 + mouseArea.totalUnits = 0 + } + + function calcValue() { + var minUnit = (myControl.from - mouseArea.initialValue) / mouseArea.stepSize + var maxUnit = (myControl.to - mouseArea.initialValue) / mouseArea.stepSize + + var units = Math.trunc(mouseArea.translationX / mouseArea.__pixelsPerUnit) + mouseArea.units = Math.min(Math.max(mouseArea.totalUnits + units, minUnit), maxUnit) + myControl.value = mouseArea.initialValue + (mouseArea.units * mouseArea.stepSize) + + if (mouseArea.dragging) + myControl.dragging() + } + + onWheel: function(wheel) { + if (!myControl.__wheelEnabled) { + wheel.accepted = false + return + } + + // Set stepSize according to used modifier key + if (wheel.modifiers & Qt.ControlModifier) + mouseArea.stepSize = myControl.minStepSize + + if (wheel.modifiers & Qt.ShiftModifier) + mouseArea.stepSize = myControl.maxStepSize + var val = myControl.valueFromText(textInput.text, myControl.locale) if (myControl.value !== val) myControl.value = val var currValue = myControl.value - myControl.value += wheel.angleDelta.y / 120 + myControl.value += (wheel.angleDelta.y / 120 * mouseArea.stepSize) if (currValue !== myControl.value) myControl.valueModified() + + // Reset stepSize + mouseArea.stepSize = myControl.stepSize } } @@ -119,14 +281,6 @@ TextInput { target: textInputBackground color: StudioTheme.Values.themeControlBackground } - PropertyChanges { - target: dragHandler - enabled: true - } - PropertyChanges { - target: tapHandler - enabled: true - } PropertyChanges { target: mouseArea cursorShape: Qt.PointingHandCursor @@ -156,14 +310,6 @@ TextInput { target: textInputBackground color: StudioTheme.Values.themeControlBackgroundInteraction } - PropertyChanges { - target: dragHandler - enabled: false - } - PropertyChanges { - target: tapHandler - enabled: false - } PropertyChanges { target: mouseArea cursorShape: Qt.IBeamCursor From a43f5db5827a96faa679a00ce643739f86615d1c Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 2 Nov 2022 16:42:40 +0100 Subject: [PATCH 51/71] QmlDesigner: Drop static_cast from connections These signals are not overloaded anymore in Qt 6. Simplify widget creation in CurveEditorStyleDialog. Change-Id: I4937db8c3dad10e7c0b2aa007739d71ae5992486 Reviewed-by: Knud Dollereder --- .../detail/curveeditorstyledialog.cpp | 123 +++++++++--------- .../designercore/instances/puppetstarter.cpp | 2 +- 2 files changed, 59 insertions(+), 66 deletions(-) diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp index 6bf93d73a0e..78a256cc906 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/curveeditorstyledialog.cpp @@ -82,73 +82,66 @@ CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget connect(m_printButton, &QPushButton::released, this, &CurveEditorStyleDialog::printStyle); - auto intChanged = [this](int) { emitStyleChanged(); }; - auto doubleChanged = [this](double) { emitStyleChanged(); }; - auto colorChanged = [this]() { emitStyleChanged(); }; - - auto intSignal = static_cast(&QSpinBox::valueChanged); - auto doubleSignal = static_cast(&QDoubleSpinBox::valueChanged); - - connect(m_background, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_backgroundAlternate, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_fontColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_gridColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_canvasMargin, doubleSignal, doubleChanged); - connect(m_zoomInWidth, intSignal, intChanged); - connect(m_zoomInHeight, intSignal, intChanged); - connect(m_timeAxisHeight, doubleSignal, doubleChanged); - connect(m_timeOffsetLeft, doubleSignal, doubleChanged); - connect(m_timeOffsetRight, doubleSignal, doubleChanged); - connect(m_rangeBarColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_rangeBarCapsColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_valueAxisWidth, doubleSignal, doubleChanged); - connect(m_valueOffsetTop, doubleSignal, doubleChanged); - connect(m_valueOffsetBottom, doubleSignal, doubleChanged); - connect(m_handleSize, doubleSignal, doubleChanged); - connect(m_handleLineWidth, doubleSignal, doubleChanged); - connect(m_handleColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_handleSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_keyframeSize, doubleSignal, doubleChanged); - connect(m_keyframeColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_keyframeSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_curveWidth, doubleSignal, doubleChanged); - connect(m_curveColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_curveSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged); - connect(m_treeMargins, doubleSignal, doubleChanged); - connect(m_playheadWidth, doubleSignal, doubleChanged); - connect(m_playheadRadius, doubleSignal, doubleChanged); - connect(m_playheadColor, &StyleEditor::ColorControl::valueChanged, colorChanged); + class WidgetAdder + { + public: + WidgetAdder(CurveEditorStyleDialog *dialog, QVBoxLayout *box) + : m_dialog(dialog), m_box(box) {} + void add(const QString &title, StyleEditor::ColorControl *widget) { + QObject::connect(widget, &StyleEditor::ColorControl::valueChanged, + m_dialog, &CurveEditorStyleDialog::emitStyleChanged); + addToLayout(title, widget); + } + void add(const QString &title, QSpinBox *widget) { + QObject::connect(widget, &QSpinBox::valueChanged, + m_dialog, &CurveEditorStyleDialog::emitStyleChanged); + addToLayout(title, widget); + } + void add(const QString &title, QDoubleSpinBox *widget) { + QObject::connect(widget, &QDoubleSpinBox::valueChanged, + m_dialog, &CurveEditorStyleDialog::emitStyleChanged); + addToLayout(title, widget); + } + private: + void addToLayout(const QString &title, QWidget *widget){ + m_box->addLayout(createRow(title, widget)); + } + CurveEditorStyleDialog *m_dialog; + QVBoxLayout *m_box; + }; auto *box = new QVBoxLayout; - box->addLayout(createRow("Background Color", m_background)); - box->addLayout(createRow("Alternate Background Color", m_backgroundAlternate)); - box->addLayout(createRow("Font Color", m_fontColor)); - box->addLayout(createRow("Grid Color", m_gridColor)); - box->addLayout(createRow("Canvas Margin", m_canvasMargin)); - box->addLayout(createRow("Zoom In Width", m_zoomInWidth)); - box->addLayout(createRow("Zoom In Height", m_zoomInHeight)); - box->addLayout(createRow("Time Axis Height", m_timeAxisHeight)); - box->addLayout(createRow("Time Axis Left Offset", m_timeOffsetLeft)); - box->addLayout(createRow("Time Axis Right Offset", m_timeOffsetRight)); - box->addLayout(createRow("Range Bar Color", m_rangeBarColor)); - box->addLayout(createRow("Range Bar Caps Color", m_rangeBarCapsColor)); - box->addLayout(createRow("Value Axis Width", m_valueAxisWidth)); - box->addLayout(createRow("Value Axis Top Offset", m_valueOffsetTop)); - box->addLayout(createRow("Value Axis Bottom Offset", m_valueOffsetBottom)); - box->addLayout(createRow("Handle Size", m_handleSize)); - box->addLayout(createRow("Handle Line Width", m_handleLineWidth)); - box->addLayout(createRow("Handle Color", m_handleColor)); - box->addLayout(createRow("Handle Selection Color", m_handleSelectionColor)); - box->addLayout(createRow("Keyframe Size", m_keyframeSize)); - box->addLayout(createRow("Keyframe Color", m_keyframeColor)); - box->addLayout(createRow("Keyframe Selection Color", m_keyframeSelectionColor)); - box->addLayout(createRow("Curve Width", m_curveWidth)); - box->addLayout(createRow("Curve Color", m_curveColor)); - box->addLayout(createRow("Curve Selection Color", m_curveSelectionColor)); - box->addLayout(createRow("Treeview margins", m_treeMargins)); - box->addLayout(createRow("Playhead width", m_playheadWidth)); - box->addLayout(createRow("Playhead radius", m_playheadRadius)); - box->addLayout(createRow("Playhead color", m_playheadColor)); + + WidgetAdder adder(this, box); + adder.add("Background Color", m_background); + adder.add("Alternate Background Color", m_backgroundAlternate); + adder.add("Font Color", m_fontColor); + adder.add("Grid Color", m_gridColor); + adder.add("Canvas Margin", m_canvasMargin); + adder.add("Zoom In Width", m_zoomInWidth); + adder.add("Zoom In Height", m_zoomInHeight); + adder.add("Time Axis Height", m_timeAxisHeight); + adder.add("Time Axis Left Offset", m_timeOffsetLeft); + adder.add("Time Axis Right Offset", m_timeOffsetRight); + adder.add("Range Bar Color", m_rangeBarColor); + adder.add("Range Bar Caps Color", m_rangeBarCapsColor); + adder.add("Value Axis Width", m_valueAxisWidth); + adder.add("Value Axis Top Offset", m_valueOffsetTop); + adder.add("Value Axis Bottom Offset", m_valueOffsetBottom); + adder.add("Handle Size", m_handleSize); + adder.add("Handle Line Width", m_handleLineWidth); + adder.add("Handle Color", m_handleColor); + adder.add("Handle Selection Color", m_handleSelectionColor); + adder.add("Keyframe Size", m_keyframeSize); + adder.add("Keyframe Color", m_keyframeColor); + adder.add("Keyframe Selection Color", m_keyframeSelectionColor); + adder.add("Curve Width", m_curveWidth); + adder.add("Curve Color", m_curveColor); + adder.add("Curve Selection Color", m_curveSelectionColor); + adder.add("Treeview margins", m_treeMargins); + adder.add("Playhead width", m_playheadWidth); + adder.add("Playhead radius", m_playheadRadius); + adder.add("Playhead color", m_playheadColor); box->addWidget(m_printButton); setLayout(box); diff --git a/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp b/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp index 0b2d0f6df43..268f43eb42d 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetstarter.cpp @@ -31,7 +31,7 @@ QProcessUniquePointer puppetProcess(const QString &puppetPath, puppetProcess.get(), &QProcess::kill); QObject::connect(puppetProcess.get(), - static_cast(&QProcess::finished), + &QProcess::finished, processFinishCallback); if (forwardOutput == puppetMode || forwardOutput == "all") { From 63d30351a67edaed447f0474f19feb53dda970a2 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Tue, 8 Nov 2022 15:45:05 +0200 Subject: [PATCH 52/71] QmlDesigner: Add "Select Parent" to 3d Context Menu "Select Parent" action is added to the context menu of the Edit3DWidget. Task-number: QDS-8199 Change-Id: Iff6ce50eba966bea60f1b09f497632c3ff290c27 Reviewed-by: Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- .../components/edit3d/edit3dwidget.cpp | 26 ++++-- .../components/edit3d/edit3dwidget.h | 1 + .../designercore/include/modelnode.h | 1 + .../designercore/model/modelnode.cpp | 90 +++++++++++++++++++ 4 files changed, 113 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 91ee59666d3..e2da1c48135 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -9,6 +9,7 @@ #include "edit3dvisibilitytogglesmenu.h" #include "metainfo.h" #include "modelnodeoperations.h" +#include "nodeabstractproperty.h" #include "qmldesignerconstants.h" #include "qmldesignerplugin.h" #include "qmlvisualnode.h" @@ -217,6 +218,19 @@ void Edit3DWidget::createContextMenu() }); m_contextMenu->addSeparator(); + + m_selectParentAction = m_contextMenu->addAction(tr("Select Parent"), [&] { + ModelNode parentNode = ModelNode::lowestCommonAncestor(view()->selectedModelNodes()); + if (!parentNode.isValid()) + return; + + if (!parentNode.isRootNode() && view()->isSelectedModelNode(parentNode)) + parentNode = parentNode.parentProperty().parentModelNode(); + + view()->setSelectedModelNode(parentNode); + }); + + m_contextMenu->addSeparator(); } bool Edit3DWidget::isPasteAvailable() const @@ -372,19 +386,21 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode const bool isValid = modelNode.isValid(); const bool isModel = modelNode.metaInfo().isQtQuick3DModel(); - const bool isNotRoot = isValid && !modelNode.isRootNode(); const bool isCamera = isValid && modelNode.metaInfo().isQtQuick3DCamera(); const bool isSingleComponent = view()->hasSingleSelectedModelNode() && modelNode.isComponent(); + const bool anyNodeSelected = view()->hasSelectedModelNodes(); + const bool selectionExcludingRoot = anyNodeSelected && !view()->rootModelNode().isSelected(); m_editComponentAction->setEnabled(isSingleComponent); m_editMaterialAction->setEnabled(isModel); - m_duplicateAction->setEnabled(isNotRoot); - m_copyAction->setEnabled(isNotRoot); + m_duplicateAction->setEnabled(selectionExcludingRoot); + m_copyAction->setEnabled(selectionExcludingRoot); m_pasteAction->setEnabled(isPasteAvailable()); - m_deleteAction->setEnabled(isNotRoot); - m_fitSelectedAction->setEnabled(isNotRoot); + m_deleteAction->setEnabled(selectionExcludingRoot); + m_fitSelectedAction->setEnabled(anyNodeSelected); m_alignCameraAction->setEnabled(isCamera); m_alignViewAction->setEnabled(isCamera); + m_selectParentAction->setEnabled(selectionExcludingRoot); m_contextMenu->popup(mapToGlobal(pos)); } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index 38ff56e67ad..25948d5d9aa 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -71,6 +71,7 @@ private: QPointer m_fitSelectedAction; QPointer m_alignCameraAction; QPointer m_alignViewAction; + QPointer m_selectParentAction; QPointer m_createSubMenu; ModelNode m_contextMenuTarget; QVector3D m_contextMenuPos3d; diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index 6c2f424cf1c..c9c78588004 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -222,6 +222,7 @@ public: void setLocked(bool value); static bool isThisOrAncestorLocked(const ModelNode &node); + static ModelNode lowestCommonAncestor(const QList &nodes); qint32 internalId() const; diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index 564c1203297..ced1a0de44b 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -1313,6 +1313,96 @@ bool ModelNode::isThisOrAncestorLocked(const ModelNode &node) return isThisOrAncestorLocked(node.parentProperty().parentModelNode()); } +/*! + * \brief The lowest common ancestor node for node1 and node2. If one of the nodes (Node A) is + * the ancestor of the other node, the return value is Node A and not the parent of Node A. + * \param node1 First node + * \param node2 Second node + * \param depthOfLCA Depth of the return value + * \param depthOfNode1 Depth of node1. Use this parameter for optimization + * \param depthOfNode2 Depth of node2. Use this parameter for optimization + */ +static ModelNode lowestCommonAncestor(const ModelNode &node1, + const ModelNode &node2, + int &depthOfLCA, + const int &depthOfNode1 = -1, + const int &depthOfNode2 = -1) +{ + Q_ASSERT(node1.isValid() && node2.isValid()); + + auto depthOfNode = [] (const ModelNode &node) -> int { + int depth = 0; + ModelNode parentNode = node; + while (!parentNode.isRootNode()) { + depth++; + parentNode = parentNode.parentProperty().parentModelNode(); + } + return depth; + }; + + if (node1 == node2) { + depthOfLCA = (depthOfNode1 < 0) + ? ((depthOfNode2 < 0) ? depthOfNode(node1) : depthOfNode2) + : depthOfNode1; + return node1; + } + + if (node1.isRootNode()) { + depthOfLCA = 0; + return node1; + } + + if (node2.isRootNode()) { + depthOfLCA = 0; + return node2; + } + + ModelNode nodeLower = node1; + ModelNode nodeHigher = node2; + int depthLower = (depthOfNode1 < 0) ? depthOfNode(nodeLower) : depthOfNode1; + int depthHigher = (depthOfNode2 < 0) ? depthOfNode(nodeHigher) :depthOfNode2; + + if (depthLower > depthHigher) { + std::swap(depthLower, depthHigher); + std::swap(nodeLower, nodeHigher); + } + + int depthDiff = depthHigher - depthLower; + while (depthDiff--) + nodeHigher = nodeHigher.parentProperty().parentModelNode(); + + while (nodeLower != nodeHigher) { + nodeLower = nodeLower.parentProperty().parentModelNode(); + nodeHigher = nodeHigher.parentProperty().parentModelNode(); + --depthLower; + } + + depthOfLCA = depthLower; + return nodeLower; +} + +/*! + * \brief The lowest common node containing all nodes. If one of the nodes (Node A) is + * the ancestor of the other nodes, the return value is Node A and not the parent of Node A. + */ +ModelNode ModelNode::lowestCommonAncestor(const QList &nodes) +{ + if (nodes.isEmpty()) + return {}; + + ModelNode accumulatedNode = nodes.first(); + int accumulatedNodeDepth = -1; + Utils::span nodesExceptFirst(nodes.constBegin() + 1, nodes.constEnd()); + for (const ModelNode &node : nodesExceptFirst) { + accumulatedNode = QmlDesigner::lowestCommonAncestor(accumulatedNode, + node, + accumulatedNodeDepth, + accumulatedNodeDepth); + } + + return accumulatedNode; +} + void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList) { model()->d->setScriptFunctions(m_internalNode, scriptFunctionList); From 8c7ed5a03eb777126f5c4a2d5caf69232b26945c Mon Sep 17 00:00:00 2001 From: Amr Essam Date: Mon, 14 Nov 2022 09:25:46 +0200 Subject: [PATCH 53/71] QmlDesigner: Add effect placeholder icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Placeholder icon until final icons are provided Task-number: QDS-7713 Change-Id: Ic66f0603ed7088584ea0df6af9f977e732065d3c Reviewed-by: Tomi Korpipää Reviewed-by: Reviewed-by: Mahmoud Badri --- .../components/assetslibrary/assetslibraryiconprovider.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp index 870da80f735..7d878185378 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryiconprovider.cpp @@ -36,6 +36,8 @@ QPixmap AssetsLibraryIconProvider::requestPixmap(const QString &id, QSize *size, type = "sound"; else if (AssetsLibraryModel::supportedVideoSuffixes().contains(suffix)) type = "video"; + else if (AssetsLibraryModel::supportedEffectMakerSuffixes().contains(suffix)) + type = "default"; QString pathTemplate = QString(":/AssetsLibrary/images/asset_%1%2.png").arg(type); QString path = pathTemplate.arg('_' + QString::number(requestedSize.width())); From b10c135a1026b3d379ec7cf47907ab08c7dc5ba4 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 10 Nov 2022 16:56:10 +0100 Subject: [PATCH 54/71] qmldesigner: remove delayedResetView(); Change-Id: Ie577b6b686a10e4e3525ba858a70bea0b4077566 Reviewed-by: Mahmoud Badri --- .../materialeditor/materialeditorview.cpp | 16 +++------------- .../materialeditor/materialeditorview.h | 1 - 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index 58bb81434fb..b1594f80f93 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -320,16 +320,6 @@ MaterialEditorView *MaterialEditorView::instance() return s_instance; } -void MaterialEditorView::delayedResetView() -{ - // TODO: it seems the delayed reset is not needed. Leaving it commented out for now just in case it - // turned out to be needed. Otherwise will be removed after a small testing period. -// if (m_timerId) -// killTimer(m_timerId); -// m_timerId = startTimer(50); - resetView(); -} - void MaterialEditorView::timerEvent(QTimerEvent *timerEvent) { if (m_timerId == timerEvent->timerId()) @@ -929,7 +919,7 @@ void MaterialEditorView::currentStateChanged(const ModelNode &node) { QmlModelState newQmlModelState(node); Q_ASSERT(newQmlModelState.isValid()); - delayedResetView(); + resetView(); } void MaterialEditorView::instancePropertyChanged(const QList > &propertyList) @@ -964,7 +954,7 @@ void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName & { if (node == m_selectedMaterial) { m_qmlBackEnd->contextObject()->setCurrentType(QString::fromLatin1(typeName)); - delayedResetView(); + resetView(); } } @@ -972,7 +962,7 @@ void MaterialEditorView::rootNodeTypeChanged(const QString &type, int, int) { if (rootModelNode() == m_selectedMaterial) { m_qmlBackEnd->contextObject()->setCurrentType(type); - delayedResetView(); + resetView(); } } diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h index 0e4581e48cb..5c0a59d3a0e 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h @@ -98,7 +98,6 @@ private: void requestPreviewRender(); void applyMaterialToSelectedModels(const ModelNode &material, bool add = false); - void delayedResetView(); void setupQmlBackend(); void commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value); From 889e999f32bb2a0c7759e390455d4cfefc333a98 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 14 Nov 2022 14:37:04 +0200 Subject: [PATCH 55/71] QmlDesigner: Clear material preview cache on detach The previews are cached based on modelnode internal id, which can overlap between documents, resulting in briefly showing incorrect preview when new document is opened. Also, never clearing the cache leads to leaking memory. Fixed the issue by clearing the preview cache whenever all materials are removed from browser (model detach and material library deletion). Change-Id: Idad39fef62871c4e94f35604e643c7195ae9ec81 Reviewed-by: Mahmoud Badri Reviewed-by: --- .../components/materialbrowser/materialbrowserview.cpp | 2 ++ .../materialbrowser/materialbrowserwidget.cpp | 10 ++++++++++ .../components/materialbrowser/materialbrowserwidget.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 86d6c69b59f..0f05ed0b39b 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -212,6 +212,7 @@ bool MaterialBrowserView::isTexture(const ModelNode &node) const void MaterialBrowserView::modelAboutToBeDetached(Model *model) { m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport); + m_widget->clearPreviewCache(); if (m_propertyGroupsLoaded) { m_propertyGroupsLoaded = false; @@ -301,6 +302,7 @@ void MaterialBrowserView::nodeAboutToBeRemoved(const ModelNode &removedNode) // removing the material editor node if (removedNode.id() == Constants::MATERIAL_LIB_ID) { m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport); + m_widget->clearPreviewCache(); return; } diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index ccbd972daa4..d9a3539d249 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -62,6 +62,11 @@ public: m_pixmaps.insert(node.internalId(), pixmap); } + void clearPixmapCache() + { + m_pixmaps.clear(); + } + QPixmap requestPixmap(const QString &id, QSize *size, [[maybe_unused]] const QSize &requestedSize) override @@ -257,6 +262,11 @@ QQuickWidget *MaterialBrowserWidget::quickWidget() const return m_quickWidget.data(); } +void MaterialBrowserWidget::clearPreviewCache() +{ + m_previewImageProvider->clearPixmapCache(); +} + QPointer MaterialBrowserWidget::materialBrowserModel() const { return m_materialBrowserModel; diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h index 902883aa778..d1c0ef7c8a6 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h @@ -54,6 +54,8 @@ public: QQuickWidget *quickWidget() const; + void clearPreviewCache(); + protected: bool eventFilter(QObject *obj, QEvent *event) override; From 873ca6d3913efadebf32bac4ae6f8d637660c1c1 Mon Sep 17 00:00:00 2001 From: Samuel Ghinet Date: Thu, 27 Oct 2022 15:52:50 +0300 Subject: [PATCH 56/71] QmlDesigner: Fix scene environment color for 3D view There were two problems: * When the user checked "Use Scene Environment Color", the initial color set as background color was not the one configured in the "Scene Environment" clear color. The user had to change this color manually. * If the "Use Scene Environment Color" is checked, then, upon the user clicking "Reset View", the background color was changed to a wrong value. Also, fixed an error message in QML. Task-number: QDS-7436 Change-Id: If42ef1a4532244f3326f5a27a082371aa77d78d8 Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml | 9 +++++++-- src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml | 9 +++++++-- .../instances/qt5informationnodeinstanceserver.cpp | 13 +++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml index 672aca03c6a..8c69212c952 100644 --- a/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml +++ b/src/tools/qml2puppet/mockfiles/qt5/EditView3D.qml @@ -202,8 +202,13 @@ Item { if ("selectBackgroundColor" in viewStates) { if (Array.isArray(viewStates.selectBackgroundColor)) { var colors = viewStates.selectBackgroundColor - backgroundGradientColorStart = colors[0]; - backgroundGradientColorEnd = colors[1]; + if (colors.length === 1) { + backgroundGradientColorStart = colors[0]; + backgroundGradientColorEnd = colors[0]; + } else { + backgroundGradientColorStart = colors[0]; + backgroundGradientColorEnd = colors[1]; + } } else { var color = viewStates.selectBackgroundColor backgroundGradientColorStart = color; diff --git a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml index 915feea4f2d..819f1e2be90 100644 --- a/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml +++ b/src/tools/qml2puppet/mockfiles/qt6/EditView3D.qml @@ -196,8 +196,13 @@ Item { if ("selectBackgroundColor" in viewStates) { if (Array.isArray(viewStates.selectBackgroundColor)) { var colors = viewStates.selectBackgroundColor - backgroundGradientColorStart = colors[0]; - backgroundGradientColorEnd = colors[1]; + if (colors.length === 1) { + backgroundGradientColorStart = colors[0]; + backgroundGradientColorEnd = colors[0]; + } else { + backgroundGradientColorStart = colors[0]; + backgroundGradientColorEnd = colors[1]; + } } else { var color = viewStates.selectBackgroundColor backgroundGradientColorStart = color; diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 1021a56823f..70d2571e847 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -1912,6 +1912,19 @@ void Qt5InformationNodeInstanceServer::setup3DEditView( m_editView3DSetupDone = true; + auto activeView = qobject_cast(m_active3DView); + if (activeView) { + QQuick3DSceneEnvironment *activeEnv = activeView->environment(); + QColor clearColor = activeEnv->clearColor(); + + if (clearColor.isValid() && helper) { + ServerNodeInstance activeSceneInstance = active3DSceneInstance(); + const QString sceneId = activeSceneInstance.id(); + + helper->setSceneEnvironmentColor(sceneId, clearColor); + } + } + if (toolStates.contains({})) { // Update tool state to an existing no-scene state before updating the active scene to // ensure the previous state is inherited properly in all cases. From 4c468e79f7b76d0261251f9b754ee5c4c284793d Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Thu, 27 Oct 2022 14:40:38 +0200 Subject: [PATCH 57/71] Update 3rdparty json Change-Id: Ia6ecadac49eec73b1a3ccf8086aec42ccfea8f5e Reviewed-by: Ulf Hermann Reviewed-by: Eike Ziller Reviewed-by: Thomas Hartmann Reviewed-by: Qt CI Bot --- src/libs/3rdparty/json/json.hpp | 23584 +++++++++++++++++------------- 1 file changed, 13691 insertions(+), 9893 deletions(-) diff --git a/src/libs/3rdparty/json/json.hpp b/src/libs/3rdparty/json/json.hpp index c66d8243ad3..e11f5296884 100644 --- a/src/libs/3rdparty/json/json.hpp +++ b/src/libs/3rdparty/json/json.hpp @@ -1,64 +1,164 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.6.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 6 -#define NLOHMANN_JSON_VERSION_PATCH 1 - #include // all_of, find, for_each -#include // assert -#include // and, not, or #include // nullptr_t, ptrdiff_t, size_t #include // hash, less #include // initializer_list -#include // istream, ostream +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr -#include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap #include // vector // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // transform #include // array -#include // and, not #include // forward_list #include // inserter, front_inserter, end #include // map @@ -70,392 +170,2205 @@ SOFTWARE. #include // valarray // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // nullptr_t #include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif #include // runtime_error #include // to_string +#include // vector -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // array #include // size_t - -namespace nlohmann -{ -namespace detail -{ -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. - -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors - -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal - -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; - - protected: - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} - - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; - - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; - -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } - - private: - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } - - private: - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } - - private: - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating other library errors - -This exception is thrown in case of errors that cannot be classified with the -other exception types. - -Exceptions have ids 5xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range - -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - static other_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); - } - - private: - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail -} // namespace nlohmann +#include // uint8_t +#include // string // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -#include // pair -// This file contains all internal macro definitions +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them +// #include + + // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -469,41 +2382,129 @@ class other_error : public exception #endif #endif -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS #endif // disable documentation warnings on clang #if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" #endif -// allow for portable deprecation warnings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #define JSON_DEPRECATED __attribute__((deprecated)) -#elif defined(_MSC_VER) - #define JSON_DEPRECATED __declspec(deprecated) -#else - #define JSON_DEPRECATED -#endif - -// allow for portable nodiscard warnings -#if defined(__has_cpp_attribute) - #if __has_cpp_attribute(nodiscard) - #define JSON_NODISCARD [[nodiscard]] - #elif __has_cpp_attribute(gnu::warn_unused_result) - #define JSON_NODISCARD [[gnu::warn_unused_result]] - #else - #define JSON_NODISCARD - #endif -#else - #define JSON_NODISCARD -#endif - -// allow to disable exceptions +// allow disabling exceptions #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) #define JSON_THROW(exception) throw exception #define JSON_TRY try @@ -512,9 +2513,9 @@ class other_error : public exception #else #include #define JSON_THROW(exception) std::abort() - #define JSON_TRY if (true) - #define JSON_CATCH(exception) if (false) - #define JSON_INTERNAL_CATCH(exception) if (false) + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) #endif // override exception macros @@ -537,21 +2538,17 @@ class other_error : public exception #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER #endif -// manual branch prediction -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #define JSON_LIKELY(x) __builtin_expect(x, 1) - #define JSON_UNLIKELY(x) __builtin_expect(x, 0) -#else - #define JSON_LIKELY(x) x - #define JSON_UNLIKELY(x) x +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) #endif -// C++ language standard detection -#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private #endif /*! @@ -559,30 +2556,30 @@ class other_error : public exception @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They @@ -594,635 +2591,243 @@ class other_error : public exception class StringType, class BooleanType, class NumberIntegerType, \ class NumberUnsignedType, class NumberFloatType, \ template class AllocatorType, \ - template class JSONSerializer> + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> #define NLOHMANN_BASIC_JSON_TPL \ basic_json + AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> -// #include +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } -#include // not -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type - -namespace nlohmann -{ -namespace detail -{ -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -template -using uncvref_t = typename std::remove_cv::type>::type; - -// implementation of C++14 index_sequence and affiliates -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence -{ - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ } -}; -template -struct merge_and_renumber; +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif -template -using index_sequence_for = make_index_sequence; +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // not -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval - -// #include - - -#include // random_access_iterator_tag - -// #include - - -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include - -// #include - - -// http://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template