215 lines
4.7 KiB
C++
215 lines
4.7 KiB
C++
#include "documentoutlinemodel.hpp"
|
|
#include <cassert>
|
|
#include <QModelIndex>
|
|
|
|
DocumentOutlineModel::DocumentOutlineModel() :
|
|
QAbstractItemModel(),
|
|
root()
|
|
{
|
|
|
|
}
|
|
|
|
void DocumentOutlineModel::clear()
|
|
{
|
|
beginBuild();
|
|
endBuild();
|
|
|
|
}
|
|
|
|
void DocumentOutlineModel::beginBuild()
|
|
{
|
|
beginResetModel();
|
|
root = Node {
|
|
nullptr,
|
|
"<ROOT>", "",
|
|
0, 0,
|
|
QList<Node> { },
|
|
};
|
|
}
|
|
|
|
void DocumentOutlineModel::appendH1(const QString &title, QString const & anchor)
|
|
{
|
|
root.children.append(Node {
|
|
&root,
|
|
title, anchor,
|
|
1, 0,
|
|
QList<Node> { },
|
|
});
|
|
}
|
|
|
|
void DocumentOutlineModel::appendH2(const QString &title, QString const & anchor)
|
|
{
|
|
auto & parent = ensureLevel1();
|
|
parent.children.append(Node {
|
|
&parent,
|
|
title, anchor,
|
|
2, parent.children.size() - 1,
|
|
QList<Node> { },
|
|
});
|
|
}
|
|
|
|
void DocumentOutlineModel::appendH3(const QString &title, QString const & anchor)
|
|
{
|
|
auto & parent = ensureLevel2();
|
|
parent.children.append(Node {
|
|
&parent,
|
|
title, anchor,
|
|
3, parent.children.size() - 1,
|
|
QList<Node> { },
|
|
});
|
|
}
|
|
|
|
void DocumentOutlineModel::endBuild()
|
|
{
|
|
int root_index = 0;
|
|
for(auto & h1 : this->root.children)
|
|
{
|
|
assert(h1.depth == 1);
|
|
assert(h1.parent == &this->root);
|
|
|
|
h1.index = root_index;
|
|
root_index += 1;
|
|
|
|
int group_index = 0;
|
|
for(auto & h2 : h1.children)
|
|
{
|
|
assert(h2.depth == 2);
|
|
assert(h2.parent == &h1);
|
|
|
|
h2.index = group_index;
|
|
group_index += 1;
|
|
|
|
int bottom_index = 0;
|
|
for(auto & h3 : h2.children)
|
|
{
|
|
assert(h3.depth == 3);
|
|
assert(h3.parent == &h2);
|
|
|
|
h3.index = bottom_index;
|
|
bottom_index += 1;
|
|
}
|
|
}
|
|
}
|
|
endResetModel();
|
|
}
|
|
|
|
QString DocumentOutlineModel::getTitle(const QModelIndex &index) const
|
|
{
|
|
if(not index.isValid())
|
|
return "";
|
|
|
|
Node const *childItem = static_cast<Node const *>(index.internalPointer());
|
|
|
|
return childItem->title;
|
|
}
|
|
|
|
QString DocumentOutlineModel::getAnchor(const QModelIndex &index) const
|
|
{
|
|
if(not index.isValid())
|
|
return "";
|
|
|
|
Node const *childItem = static_cast<Node const *>(index.internalPointer());
|
|
|
|
return childItem->anchor;
|
|
}
|
|
|
|
QModelIndex DocumentOutlineModel::index(int row, int column, const QModelIndex &parent) const
|
|
{
|
|
if (not hasIndex(row, column, parent))
|
|
return QModelIndex();
|
|
|
|
Node const * parentItem;
|
|
|
|
if (!parent.isValid())
|
|
parentItem = &this->root;
|
|
else
|
|
parentItem = static_cast<Node*>(parent.internalPointer());
|
|
|
|
Node const * childItem = &parentItem->children[row];
|
|
if (childItem)
|
|
return createIndex(row, column, reinterpret_cast<quintptr>(childItem));
|
|
return QModelIndex();
|
|
}
|
|
|
|
QModelIndex DocumentOutlineModel::parent(const QModelIndex &child) const
|
|
{
|
|
if (!child.isValid())
|
|
return QModelIndex();
|
|
|
|
Node const *childItem = static_cast<Node const *>(child.internalPointer());
|
|
Node const * parent = childItem->parent;
|
|
|
|
if (parent == &root)
|
|
return QModelIndex();
|
|
|
|
return createIndex(
|
|
parent->index,
|
|
0,
|
|
reinterpret_cast<quintptr>(parent));
|
|
}
|
|
|
|
int DocumentOutlineModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
Node const * parentItem;
|
|
if (parent.column() > 0)
|
|
return 0;
|
|
|
|
if (!parent.isValid())
|
|
parentItem = &root;
|
|
else
|
|
parentItem = static_cast<Node const *>(parent.internalPointer());
|
|
|
|
return parentItem->children.size();
|
|
}
|
|
|
|
int DocumentOutlineModel::columnCount(const QModelIndex &parent) const
|
|
{
|
|
Q_UNUSED(parent)
|
|
return 1;
|
|
}
|
|
|
|
QVariant DocumentOutlineModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid())
|
|
return QVariant();
|
|
|
|
if (index.column() != 0)
|
|
return QVariant();
|
|
|
|
if (role != Qt::DisplayRole)
|
|
return QVariant();
|
|
|
|
Node const *item = static_cast<Node const*>(index.internalPointer());
|
|
|
|
return item->title;
|
|
}
|
|
|
|
DocumentOutlineModel::Node & DocumentOutlineModel::ensureLevel1()
|
|
{
|
|
if(root.children.size() == 0) {
|
|
root.children.append(Node {
|
|
&root,
|
|
"<missing layer>", "",
|
|
1, 0,
|
|
QList<Node> { },
|
|
});
|
|
}
|
|
return root.children.last();
|
|
}
|
|
|
|
DocumentOutlineModel::Node & DocumentOutlineModel::ensureLevel2()
|
|
{
|
|
auto & parent = ensureLevel1();
|
|
|
|
if(parent.children.size() == 0) {
|
|
parent.children.append(Node {
|
|
&parent,
|
|
"<missing layer>", "",
|
|
2, 0,
|
|
QList<Node> { },
|
|
});
|
|
}
|
|
|
|
return parent.children.last();
|
|
}
|