[poppler] qt5/demos

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 10 16:07:35 UTC 2019


 qt5/demos/toc.cpp |  145 ++++++++++++++++++++++++++++++++++++++++++++----------
 qt5/demos/toc.h   |    6 +-
 2 files changed, 124 insertions(+), 27 deletions(-)

New commits:
commit 8da4d536cc2b982365483ee873f859b346efeff0
Author: Albert Astals Cid <aacid at kde.org>
Date:   Wed Jan 9 09:58:43 2019 +0100

    qt5: demo: Actually use the lazy toc model lazyly

diff --git a/qt5/demos/toc.cpp b/qt5/demos/toc.cpp
index db47c676..1efdc16a 100644
--- a/qt5/demos/toc.cpp
+++ b/qt5/demos/toc.cpp
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008, Pino Toscano <pino at kde.org>
- * Copyright (C) 2018 Adam Reichold <adam.reichold at t-online.de>
+ * Copyright (C) 2018, Adam Reichold <adam.reichold at t-online.de>
+ * Copyright (C) 2019, Albert Astals Cid <aacid at kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,40 +22,116 @@
 
 #include <poppler-qt5.h>
 
+#include <QtGui/QStandardItemModel>
 #include <QtWidgets/QHeaderView>
 #include <QtWidgets/QTreeWidget>
 
-static void fillToc(const QVector<Poppler::OutlineItem> &items, QTreeWidget *tree, QTreeWidgetItem *parentItem)
+#include <QDebug>
+
+struct Node
+{
+    Node(Poppler::OutlineItem &&item, int row, Node *parent)
+        : m_row(row), m_parent(parent), m_item(std::move(item))
+    {
+    }
+
+    ~Node()
+    {
+        qDeleteAll(m_children);
+    }
+
+    Node(const Node &) = delete;
+    Node& operator=(const Node &) = delete;
+
+    int m_row;
+    Node *m_parent;
+    Poppler::OutlineItem m_item;
+    QVector<Node *> m_children;
+};
+
+class TocModel : public QAbstractItemModel
 {
-    QTreeWidgetItem *newitem = nullptr;
-    for (const auto &item : items) {
-        if (item.isNull()) {
-            continue;
+    Q_OBJECT
+    public:
+        TocModel(QVector<Poppler::OutlineItem> &&items, QObject *parent)
+            : QAbstractItemModel(parent)
+        {
+            for (int i = 0; i < items.count(); ++i) {
+                m_topItems << new Node(std::move(items[i]), i, nullptr);
+            }
         }
 
-        if (!parentItem) {
-            newitem = new QTreeWidgetItem(tree, newitem);
-        } else {
-            newitem = new QTreeWidgetItem(parentItem, newitem);
+        ~TocModel()
+        {
+            qDeleteAll(m_topItems);
         }
-        newitem->setText(0, item.name());
 
-        if (item.isOpen()) {
-            tree->expandItem(newitem);
+        QVariant data(const QModelIndex &index, int role) const override
+        {
+            if (role != Qt::DisplayRole)
+                return {};
+
+            Node *n = static_cast<Node*>(index.internalPointer());
+            return n->m_item.name();
         }
 
-        const auto children = item.children();
-        if (!children.isEmpty()) {
-            fillToc(children, tree, newitem);
+        QModelIndex index(int row, int column, const QModelIndex &parent) const override
+        {
+            Node *p = static_cast<Node*>(parent.internalPointer());
+            const QVector<Node *> &children = p ? p->m_children : m_topItems;
+
+            return createIndex(row, column, children[row]);
         }
-    }
-}
 
+        QModelIndex parent(const QModelIndex &child) const override
+        {
+            Node *n = static_cast<Node*>(child.internalPointer());
+            if (n->m_parent == nullptr)
+                return QModelIndex();
+            else
+                return createIndex(n->m_parent->m_row, 0, n->m_parent);
+        }
+
+        int rowCount(const QModelIndex &parent) const override
+        {
+            Node *n = static_cast<Node*>(parent.internalPointer());
+            if (!n) {
+                return m_topItems.count();
+            }
+
+            if (n->m_children.isEmpty() && !n->m_item.isNull()) {
+                QVector<Poppler::OutlineItem> items = n->m_item.children();
+                for (int i = 0; i < items.count(); ++i) {
+                    n->m_children << new Node(std::move(items[i]), i, n);
+                }
+            }
+
+            return n->m_children.count();
+        }
+
+        bool hasChildren(const QModelIndex &parent) const override
+        {
+            Node *n = static_cast<Node*>(parent.internalPointer());
+            if (!n)
+                return true;
+
+            return n->m_item.hasChildren();
+        }
+
+        int columnCount(const QModelIndex &parent) const override
+        {
+            return 1;
+        }
+
+    private:
+        QVector<Node *> m_topItems;
+
+};
 
 TocDock::TocDock(QWidget *parent)
     : AbstractInfoDock(parent)
 {
-    m_tree = new QTreeWidget(this);
+    m_tree = new QTreeView(this);
     setWidget(m_tree);
     m_tree->setAlternatingRowColors(true);
     m_tree->header()->hide();
@@ -66,22 +143,40 @@ TocDock::~TocDock()
 {
 }
 
+void TocDock::expandItemModels(const QModelIndex &parent)
+{
+    TocModel *model = static_cast<TocModel*>(m_tree->model());
+    for (int i = 0; i < model->rowCount(parent); ++i) {
+        QModelIndex index = model->index(i, 0, parent);
+        Node *n = static_cast<Node*>(index.internalPointer());
+        if (n->m_item.isOpen()) {
+            m_tree->setExpanded(index, true);
+            expandItemModels(index);
+        }
+    }
+}
+
 void TocDock::fillInfo()
 {
-    const auto outline = document()->outline();
+    auto outline = document()->outline();
     if (!outline.isEmpty()) {
-        fillToc(outline, m_tree, nullptr);
+        TocModel *model = new TocModel(std::move(outline), this);
+        m_tree->setModel(model);
+
+        expandItemModels(QModelIndex());
     } else {
-        QTreeWidgetItem *item = new QTreeWidgetItem();
-        item->setText(0, tr("No TOC"));
+        QStandardItemModel *model = new QStandardItemModel(this);
+        QStandardItem *item = new QStandardItem(tr("No TOC"));
         item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
-        m_tree->addTopLevelItem(item);
+        model->appendRow(item);
+        m_tree->setModel(model);
     }
 }
 
 void TocDock::documentClosed()
 {
-    m_tree->clear();
+    m_tree->setModel(nullptr);
     AbstractInfoDock::documentClosed();
 }
 
+#include "toc.moc"
diff --git a/qt5/demos/toc.h b/qt5/demos/toc.h
index d18a3555..d7f015ff 100644
--- a/qt5/demos/toc.h
+++ b/qt5/demos/toc.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2019, Albert Astals Cid <aacid at kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +22,7 @@
 
 #include "abstractinfodock.h"
 
-class QTreeWidget;
+class QTreeView;
 
 class TocDock : public AbstractInfoDock
 {
@@ -35,9 +36,10 @@ public:
 
 protected:
     void fillInfo() override;
+    void expandItemModels(const QModelIndex &parent);
 
 private:
-    QTreeWidget *m_tree;
+    QTreeView *m_tree;
 };
 
 #endif


More information about the poppler mailing list