From 8fdcaa5cdf2e290b16b4bfa40c27d8efd9332168 Mon Sep 17 00:00:00 2001
From: Marco Bubke <marco.bubke@nokia.com>
Date: Tue, 5 Oct 2010 20:55:31 +0200
Subject: [PATCH] QmlDesigner.NodeInstances: Render in QPixmap

Fixes many graphics glitches, improve render speed.

Reviewed-By: Thomas Hartmann
---
 .../components/formeditor/formeditoritem.cpp  |  3 -
 .../designercore/include/nodeinstance.h       |  3 +-
 .../designercore/include/qmlitemnode.h        |  2 +-
 .../instances/graphicsobjectnodeinstance.cpp  | 57 ++++++++++++++-----
 .../instances/graphicsobjectnodeinstance.h    |  7 ++-
 .../designercore/instances/nodeinstance.cpp   |  7 ++-
 .../instances/nodeinstancesignalspy.cpp       |  4 +-
 .../instances/nodeinstancesignalspy.h         |  3 +-
 .../instances/nodeinstanceview.cpp            |  5 ++
 .../instances/objectnodeinstance.cpp          |  6 +-
 .../instances/objectnodeinstance.h            |  4 +-
 .../designercore/model/qmlitemnode.cpp        |  2 +-
 .../designercore/model/qmlmodelview.cpp       |  3 +-
 13 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
index be4a479ef88..c6717ab5346 100644
--- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
+++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp
@@ -270,13 +270,10 @@ void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
         return;
 
     painter->save();
-    painter->setRenderHint(QPainter::Antialiasing, true);
 
     if (isContentVisible())
         qmlItemNode().paintInstance(painter);
 
-    painter->setRenderHint(QPainter::Antialiasing, false);
-
     if (!qmlItemNode().isRootModelNode())
         paintBoundingRect(painter);
 
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstance.h b/src/plugins/qmldesigner/designercore/include/nodeinstance.h
index 0b5a223d38d..bdf7ec5410d 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstance.h
@@ -84,7 +84,7 @@ public:
     NodeInstance(const NodeInstance &other);
     NodeInstance& operator=(const NodeInstance &other);
 
-    void paint(QPainter *painter) const;
+    void paint(QPainter *painter);
 
     NodeInstance parent() const;
     bool hasParent() const;
@@ -127,6 +127,7 @@ public:
 
     bool isValid() const;
     void makeInvalid();
+    void renderPixmapNextPaint();
     bool hasContent() const;
     bool isResizable() const;
     bool isMovable() const;
diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
index 5500f5eeb05..91fdc853b88 100644
--- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
+++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h
@@ -80,7 +80,7 @@ public:
     int instancePenWidth() const;
 
 
-    void paintInstance(QPainter *painter) const;
+    void paintInstance(QPainter *painter);
 
     void selectNode();
     void deselectNode();
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
index 83232f53f28..5f1f61e7534 100644
--- a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.cpp
@@ -34,6 +34,8 @@
 #include "private/qgraphicsitem_p.h"
 #include <QStyleOptionGraphicsItem>
 #include "nodemetainfo.h"
+#include <QPixmap>
+#include <QSizeF>
 
 namespace QmlDesigner {
 namespace Internal {
@@ -41,7 +43,8 @@ namespace Internal {
 GraphicsObjectNodeInstance::GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent)
    : ObjectNodeInstance(graphicsObject),
    m_hasContent(hasContent),
-   m_isMovable(true)
+   m_isMovable(true),
+   m_renderPixmapIsDirty(true)
 {
 }
 
@@ -171,6 +174,34 @@ void initOption(QGraphicsItem *item, QStyleOptionGraphicsItem *option, const QTr
     privateItem->initStyleOption(option, transform, QRegion());
 }
 
+void GraphicsObjectNodeInstance::renderPixmap()
+{
+    QRectF boundingRect = graphicsObject()->boundingRect();
+    QSize boundingSize = boundingRect.size().toSize();
+
+    if (m_renderPixmap.size() != boundingSize) {
+        m_renderPixmap = QPixmap(boundingSize);
+    }
+
+    if (m_renderPixmap.isNull())
+        return;
+
+    m_renderPixmap.fill(Qt::transparent);
+
+    QPainter painter(&m_renderPixmap);
+    painter.translate(-boundingRect.topLeft());
+
+    if (hasContent()) {
+        QStyleOptionGraphicsItem option;
+        initOption(graphicsObject(), &option, painter.transform());
+        graphicsObject()->paint(&painter, &option);
+
+    }
+
+    foreach(QGraphicsItem *graphicsItem, graphicsObject()->childItems())
+        paintRecursively(graphicsItem, &painter);
+}
+
 void GraphicsObjectNodeInstance::paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const
 {
     QGraphicsObject *graphicsObject = graphicsItem->toGraphicsObject();
@@ -193,21 +224,13 @@ void GraphicsObjectNodeInstance::paintRecursively(QGraphicsItem *graphicsItem, Q
     }
 }
 
-void GraphicsObjectNodeInstance::paint(QPainter *painter) const
+void GraphicsObjectNodeInstance::paint(QPainter *painter)
 {
     if (graphicsObject()) {
-        painter->save();
-        if (hasContent()) {
-            QStyleOptionGraphicsItem option;
-            initOption(graphicsObject(), &option, painter->transform());
-            graphicsObject()->paint(painter, &option);
-
-        }
-
-        foreach(QGraphicsItem *graphicsItem, graphicsObject()->childItems())
-            paintRecursively(graphicsItem, painter);
-
-        painter->restore();
+        if (m_renderPixmapIsDirty)
+            renderPixmap();
+        if (!m_renderPixmap.isNull())
+            painter->drawPixmap(graphicsObject()->boundingRect().topLeft(), m_renderPixmap);
     }
 }
 
@@ -241,5 +264,11 @@ void GraphicsObjectNodeInstance::setMovable(bool movable)
     m_isMovable = movable;
 }
 
+void GraphicsObjectNodeInstance::renderPixmapNextPaint()
+{
+    if (graphicsObject() && QGraphicsItemPrivate::get(graphicsObject())->dirty /*|| QGraphicsItemPrivate::get(graphicsObject())->dirtyChildren*/)
+        m_renderPixmapIsDirty = true;
+}
+
 } // namespace Internal
 } // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
index 45200acd273..3aec7833d78 100644
--- a/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/graphicsobjectnodeinstance.h
@@ -44,7 +44,7 @@ class GraphicsObjectNodeInstance : public ObjectNodeInstance
 public:
     GraphicsObjectNodeInstance(QGraphicsObject *graphicsObject, bool hasContent);
 
-    void paint(QPainter *painter) const;
+    void paint(QPainter *painter);
 
     bool isTopLevel() const;
     bool isGraphicsObject() const;
@@ -77,13 +77,18 @@ public:
     bool isMovable() const;
     void setMovable(bool movable);
 
+    void renderPixmapNextPaint();
+
 protected:
+    void renderPixmap();
     QGraphicsObject *graphicsObject() const;
     void paintRecursively(QGraphicsItem *graphicsItem, QPainter *painter) const;
     static QPair<QGraphicsObject*, bool> createGraphicsObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
 private: // variables
     bool m_hasContent;
     bool m_isMovable;
+    QPixmap m_renderPixmap;
+    bool m_renderPixmapIsDirty;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
index acf2c0fb151..af94af11d6d 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp
@@ -115,7 +115,7 @@ NodeInstance &NodeInstance::operator=(const NodeInstance &other)
 \brief Paints the NodeInstance with this painter.
 \param painter used QPainter
 */
-void NodeInstance::paint(QPainter *painter) const
+void NodeInstance::paint(QPainter *painter)
 {
     m_nodeInstance->paint(painter);
 }
@@ -461,6 +461,11 @@ void NodeInstance::makeInvalid()
     m_nodeInstance.clear();
 }
 
+void NodeInstance::renderPixmapNextPaint()
+{
+    m_nodeInstance->renderPixmapNextPaint();
+}
+
 bool NodeInstance::hasContent() const
 {
     return m_nodeInstance->hasContent();
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
index 70a10a7544a..376ce9d1aa5 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp
@@ -26,10 +26,10 @@ void NodeInstanceSignalSpy::setObjectNodeInstance(const ObjectNodeInstance::Poin
 
 void NodeInstanceSignalSpy::registerObject(QObject *spiedObject, const QString &prefix)
 {
-    if (registeredObjectList.contains(spiedObject)) // prevent cycles
+    if (m_registeredObjectList.contains(spiedObject)) // prevent cycles
         return;
 
-    registeredObjectList.append(spiedObject);
+    m_registeredObjectList.append(spiedObject);
     for (int index = QObject::staticMetaObject.propertyOffset();
          index < spiedObject->metaObject()->propertyCount();
          index++) {
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
index 94cef6d2321..85cc4d79812 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h
@@ -27,8 +27,9 @@ protected:
 private:
     int methodeOffset;
     QHash<int, QString> m_indexPropertyHash;
-    QObjectList registeredObjectList;
+    QObjectList m_registeredObjectList;
     ObjectNodeInstanceWeakPointer m_objectNodeInstance;
+    QMetaObject m_metaObject;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index 30b5d43acd5..dd0a94983c8 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -578,9 +578,14 @@ void NodeInstanceView::notifyPropertyChange(const ModelNode &node, const QString
 {
     if (m_blockStatePropertyChanges)
         return;
+
     if (!node.isValid())
         return;
 
+    if (hasInstanceForNode(node))
+        instanceForNode(node).renderPixmapNextPaint();
+
+
     emitInstancePropertyChange(QList<QPair<ModelNode, QString> >() << qMakePair(node, propertyName));
 }
 
diff --git a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
index f543f9de3ea..64230d32336 100644
--- a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.cpp
@@ -911,7 +911,7 @@ QVariant ObjectNodeInstance::resetValue(const QString &propertyName) const
     return m_resetValueHash.value(propertyName);
 }
 
-void ObjectNodeInstance::paint(QPainter * /*painter*/) const
+void ObjectNodeInstance::paint(QPainter * /*painter*/)
 {
 }
 
@@ -1025,6 +1025,10 @@ void ObjectNodeInstance::doComponentComplete()
 
 }
 
+void ObjectNodeInstance::renderPixmapNextPaint()
+{
+
+}
 }
 }
 
diff --git a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
index 2f7715d1032..aed1bd38a30 100644
--- a/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
+++ b/src/plugins/qmldesigner/designercore/instances/objectnodeinstance.h
@@ -97,7 +97,7 @@ public:
     NodeInstanceView *nodeInstanceView() const;
     void setNodeInstanceView(NodeInstanceView *view);
     virtual void initializePropertyWatcher(const Pointer &objectNodeInstance);
-    virtual void paint(QPainter *painter) const;
+    virtual void paint(QPainter *painter);
 
     virtual bool isTopLevel() const;
 
@@ -188,6 +188,8 @@ public:
 
     virtual void doComponentComplete();
 
+    virtual void renderPixmapNextPaint();
+
 protected:
     static QObject *createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *parentContext);
 
diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
index 8a6369475ac..bf067bb9389 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp
@@ -246,7 +246,7 @@ int QmlItemNode::instancePenWidth() const
     return nodeInstance().penWidth();
 }
 
-void QmlItemNode::paintInstance(QPainter *painter) const
+void QmlItemNode::paintInstance(QPainter *painter)
 {
     if (nodeInstance().isValid())
         nodeInstance().paint(painter);
diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
index 646c9455984..4d1246ac459 100644
--- a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
+++ b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp
@@ -327,7 +327,8 @@ static bool isTransformProperty(const QString &name)
                                                          << "scale"
                                                          << "transformOrigin"
                                                          << "paintedWidth"
-                                                         << "paintedHeight");
+                                                         << "paintedHeight"
+                                                         << "border.width");
 
     return transformProperties.contains(name);
 }
-- 
GitLab