aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hartmann <thomas.hartmann@qt.io>2022-02-09 13:37:05 +0100
committerThomas Hartmann <thomas.hartmann@qt.io>2022-02-09 17:49:59 +0000
commitcea31a2c4f16a8cdba279b2834cc3f795b22cf13 (patch)
tree694e914bb9cabfc48f3ffb918efe70773e781253
parent3bd96e7e739a3a8decc2f0b1fc9832b7acf5d64d (diff)
QmlDesigner: Add cache for instances
When detaching the NodeInstanceView from a model we insert all instances for this model into a cache. The cache currently takes a maximum of 20 models. If the model is reattached we use the existing instances, instead of creating new ones. We also recycle the state previews. Outdated data will be overridden by new data once the puppet is sending the respective commands. Task-number: QDS-6121 Change-Id: I15b5628afc5579ba8a03dca23ba5809e55022f3d Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
-rw-r--r--src/plugins/qmldesigner/designercore/include/modelcache.h81
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h19
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp45
3 files changed, 141 insertions, 4 deletions
diff --git a/src/plugins/qmldesigner/designercore/include/modelcache.h b/src/plugins/qmldesigner/designercore/include/modelcache.h
new file mode 100644
index 0000000000..bd4704294d
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/include/modelcache.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 <model.h>
+
+#include <utils/optional.h>
+
+#include <QHash>
+#include <QQueue>
+
+namespace QmlDesigner {
+
+template<class DataType>
+class ModelCache
+{
+public:
+ ModelCache(int max = 20)
+ : m_maxEntries(max)
+ {}
+
+ void insert(Model *model, const DataType &data)
+ {
+ QObject::connect(model, &Model::destroyed, [this](QObject *o) {
+ QObject *deletedModel = o;
+
+ if (deletedModel) {
+ m_content.remove(deletedModel);
+ m_queue.removeAll(deletedModel);
+ }
+ });
+
+ m_content.insert(model, data);
+ if (!m_queue.contains(model))
+ m_queue.append(model);
+ if (m_queue.length() > m_maxEntries) {
+ QObject *first = m_queue.takeFirst();
+ m_content.remove(first);
+ }
+ }
+
+ Utils::optional<DataType> take(Model *model)
+ {
+ if (!m_content.contains(model))
+ return {};
+ m_queue.removeOne(model);
+ return m_content.take(model);
+ }
+
+private:
+ QHash<QObject *, DataType> m_content;
+ QQueue<QObject *> m_queue;
+ int m_maxEntries = 20;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index e29498e143..48ecd4119f 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -27,6 +27,7 @@
#include "qmldesignercorelib_global.h"
#include "abstractview.h"
+#include "modelcache.h"
#include <modelnode.h>
#include <nodeinstance.h>
@@ -232,11 +233,29 @@ private: // functions
PropertyChangeFlags flags);
private:
+ struct NodeInstanceCacheData
+ {
+ NodeInstanceCacheData(const QHash<ModelNode, NodeInstance> &i,
+ const QHash<ModelNode, QImage> &p)
+ : instances(i)
+ , previewImages(p)
+ {}
+
+ NodeInstanceCacheData() = default;
+
+ QHash<ModelNode, NodeInstance> instances;
+ QHash<ModelNode, QImage> previewImages;
+ };
+
+ QList<NodeInstance> loadInstancesFromCache(const QList<ModelNode> &nodeList,
+ const NodeInstanceCacheData &cache);
+
QHash<QString, ModelNodePreviewImageData> m_imageDataMap;
NodeInstance m_rootNodeInstance;
NodeInstance m_activeStateInstance;
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
+ ModelCache<NodeInstanceCacheData> m_nodeInstanceCache;
QHash<ModelNode, QImage> m_statePreviewImage;
ConnectionManagerInterface &m_connectionManager;
std::unique_ptr<NodeInstanceServerProxy> m_nodeInstanceServer;
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 5b83b63795..48391fe4b9 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -265,6 +265,9 @@ void NodeInstanceView::modelAboutToBeDetached(Model * model)
{
m_connectionManager.setCrashCallback({});
+ m_nodeInstanceCache.insert(model,
+ NodeInstanceCacheData(m_nodeInstanceHash, m_statePreviewImage));
+
removeAllInstanceNodeRelationships();
if (m_nodeInstanceServer) {
m_nodeInstanceServer->clearScene(createClearSceneCommand());
@@ -935,10 +938,16 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
QList<ModelNode> nodeList = allModelNodes();
QList<NodeInstance> instanceList;
- for (const ModelNode &node : std::as_const(nodeList)) {
- NodeInstance instance = loadNode(node);
- if (!isSkippedNode(node))
- instanceList.append(instance);
+ Utils::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);
+ }
}
nodeList = filterNodesForSkipItems(nodeList);
@@ -1942,4 +1951,32 @@ void NodeInstanceView::maybeResetOnPropertyChange(const PropertyName &name, cons
resetPuppet();
}
+QList<NodeInstance> NodeInstanceView::loadInstancesFromCache(const QList<ModelNode> &nodeList,
+ const NodeInstanceCacheData &cache)
+{
+ QList<NodeInstance> instanceList;
+
+ auto previews = cache.previewImages;
+ auto iterator = previews.begin();
+ while (iterator != previews.end()) {
+ if (iterator.key().isValid())
+ m_statePreviewImage.insert(iterator.key(), iterator.value());
+ iterator++;
+ }
+
+ for (const ModelNode &node : std::as_const(nodeList)) {
+ NodeInstance instance = cache.instances.value(node);
+ if (instance.isValid())
+ insertInstanceRelationships(instance);
+ else
+ instance = loadNode(node);
+
+ if (node.isRootNode())
+ m_rootNodeInstance = instance;
+ if (!isSkippedNode(node))
+ instanceList.append(instanceForModelNode(node));
+ }
+
+ return instanceList;
}
+} // namespace QmlDesigner