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 <[email protected]> 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 <[email protected]> - * Copyright (C) 2018 Adam Reichold <[email protected]> + * Copyright (C) 2018, Adam Reichold <[email protected]> + * Copyright (C) 2019, Albert Astals Cid <[email protected]> * * 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 <[email protected]> + * Copyright (C) 2019, Albert Astals Cid <[email protected]> * * 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 _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
