try batch rendering of list items
2 files changed, 67 insertions(+), 57 deletions(-)

M quickitemdelegate.cpp
M quickitemdelegate.h
M quickitemdelegate.cpp +65 -56
@@ 13,13 13,18 @@ 
 #include <QtDebug>
 #include "quickitemdelegate.h"
 
+namespace {
+constexpr int BATCH_SIZE = 10;
+}
+
 QuickItemDelegate::QuickItemDelegate(QObject *parent)
     : QStyledItemDelegate(parent),
       engine_(new QQmlEngine(this)),
       component_(new QQmlComponent(engine_, this)),
       //renderControl_(new QQuickRenderControl(this)),
       window_(std::make_unique<QQuickWindow>(/*renderControl_*/)),
-      imageCache_()
+      image_(),
+      imageOffset_(0)
 {
     // XXX
     /*

          
@@ 36,51 41,58 @@ QuickItemDelegate::QuickItemDelegate(QOb
 
     // XXX
     auto *context = engine_->rootContext();
-    context->setContextProperty(QStringLiteral("itemIndex"), {});
-    context->setContextProperty(QStringLiteral("itemText"), {});
+    context->setContextProperty(QStringLiteral("model_"), nullptr);
+    context->setContextProperty(QStringLiteral("offset_"), imageOffset_);
 
     component_->setData(QByteArrayLiteral(R"(
         import QtQuick 2.12
 
-        Row {
+        ListView {
             anchors.fill: parent
-            spacing: 4
-            leftPadding: 4
-            rightPadding: 4
+            model: model_
+            contentY: 28 * offset_
+            delegate: Row {
+                anchors.left: parent.left
+                anchors.right: parent.right
+                height: 28
+                spacing: 4
+                leftPadding: 4
+                rightPadding: 4
 
-            Rectangle {
-                anchors.verticalCenter: parent.verticalCenter
-                width: indexText.width + 4
-                height: indexText.height + 4
-                color: "#ccc"
-                Text {
-                    id: indexText
-                    anchors.centerIn: parent
-                    text: "#" + itemIndex
-                }
-            }
-
-            Text {
-                anchors.verticalCenter: parent.verticalCenter
-                text: itemText
-            }
-
-            Text {
-                anchors.verticalCenter: parent.verticalCenter
-                color: "gray"
-                Timer {
-                    interval: 1000
-                    running: true
-                    repeat: true
-                    onTriggered: {
-                        parent.text = Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss");
+                Rectangle {
+                    anchors.verticalCenter: parent.verticalCenter
+                    width: indexText.width + 4
+                    height: indexText.height + 4
+                    color: "#ccc"
+                    Text {
+                        id: indexText
+                        anchors.centerIn: parent
+                        text: "#" + model.index
                     }
                 }
-            }
+
+                Text {
+                    anchors.verticalCenter: parent.verticalCenter
+                    // TODO: text: model.modelData
+                }
 
-            Image {
-                anchors.verticalCenter: parent.verticalCenter
-                source: "file:/usr/share/icons/Tango/16x16/emotes/face-crying.png"
+                Text {
+                    anchors.verticalCenter: parent.verticalCenter
+                    color: "gray"
+                    Timer {
+                        interval: 1000
+                        running: true
+                        repeat: true
+                        onTriggered: {
+                            parent.text = Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss");
+                        }
+                    }
+                }
+
+                Image {
+                    anchors.verticalCenter: parent.verticalCenter
+                    source: "file:/usr/share/icons/Tango/16x16/emotes/face-crying.png"
+                }
             }
         }
         )"), QUrl());  // TODO

          
@@ 90,7 102,7 @@ QuickItemDelegate::QuickItemDelegate(QOb
     Q_ASSERT(item);
     item->setParentItem(window_->contentItem());
     window_->create();
-    window_->resize(100, 28);
+    window_->resize(100, 28 * BATCH_SIZE);
 }
 
 QuickItemDelegate::~QuickItemDelegate() = default;

          
@@ 98,22 110,19 @@ QuickItemDelegate::~QuickItemDelegate() 
 void QuickItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                               const QModelIndex &index) const
 {
-    QImage image;
-    if (index.row() < imageCache_.size()) {
-        // TODO: invalidate cache if model data changed
-        image = imageCache_.at(index.row());
-    }
-
-    if (image.isNull() || image.width() < option.rect.width()) {
-        window_->resize(option.rect.size());
+    // TODO: invalidate cache if model data changed
+    // TODO: better batch offset selection
+    if (image_.isNull() || index.row() < imageOffset_ || index.row() >= imageOffset_ + BATCH_SIZE) {
+        // TODO: batch size
+        window_->resize(option.rect.width(), 28 * BATCH_SIZE);
+        imageOffset_ = index.row() / BATCH_SIZE * BATCH_SIZE;
         auto *context = engine_->rootContext();
-        context->setContextProperty(QStringLiteral("itemIndex"), index.row());
-        context->setContextProperty(QStringLiteral("itemText"), index.data());
-        image = window_->grabWindow();
-        if (imageCache_.size() <= index.row()) {
-            imageCache_.resize(index.row() + 1);
-        }
-        imageCache_[index.row()] = image;
+        context->setContextProperty(
+            QStringLiteral("model_"),
+            const_cast<QObject *>(static_cast<const QObject *>(index.model())));
+        context->setContextProperty(QStringLiteral("offset_"), imageOffset_);
+        // TODO: synchronized?
+        image_ = window_->grabWindow();
     }
 
     /*

          
@@ 123,8 132,8 @@ void QuickItemDelegate::paint(QPainter *
     */
     painter->save();
     painter->setClipRect(option.rect);
-    // TODO: synchronized?
-    painter->drawImage(option.rect.left(), option.rect.top(), image);
+    painter->drawImage(option.rect.left(), option.rect.top(), image_,
+                       0, 28 * (index.row() - imageOffset_), image_.width(), 28);
     //painter->drawImage(0, 0, renderControl_->grab());
     painter->restore();
 }

          
@@ 133,5 142,5 @@ QSize QuickItemDelegate::sizeHint(const 
                                   const QModelIndex &/*index*/) const
 {
     // TODO
-    return window_->size();
+    return {100, 28};
 }

          
M quickitemdelegate.h +2 -1
@@ 27,7 27,8 @@ private:
     QQmlComponent *component_;
     QQuickRenderControl *renderControl_;
     std::unique_ptr<QQuickWindow> window_;
-    mutable QVector<QImage> imageCache_;  // TODO: LRU
+    mutable QImage image_;  // TODO: LRU
+    mutable int imageOffset_;
 };
 
 #endif // QUICKITEMDELEGATE_H