How to generate TOC using DOM traversal
-
Qt 5.3.0, win7
Hi
Am trying to generate an hierarchical TOC of my html docs embedded in my application's resource tree and later to view the contents using QTreeView; the DOM traversal example does that for the whole html document structure; I want this done only for <h1><h2><h3>, it sounds tricky "recursive" as I could only extract one level for now using the following code:@
QStandardItemMode *TOCModel = new QStandardItemMode(this);
QStandardItem *parentItem = TOCModel->invisibleRootItem();
QWebFrame *frame = ui->webView->page()->mainFrame();
QWebElementCollection subtitles = frame->findAllElements("h4");
foreach (QWebElement element, subtitles) {
QStandardItem *item = new QStandardItem(element.toPlainText());
parentItem->appendRow(item);
}
ui->treeView->setModel(TOCModel );
@Is there any hints or perhaps sample of how to do that in less painful way?
-
You do need to do DOM traversal. The full working example below does what you want (naively) using the QtXml framework:
HTML_TOC.pro
@
QT += core gui xmlTARGET = HTML_TOC
TEMPLATE = appSOURCES += main.cpp
widget.cppHEADERS += widget.h
@widget.h
@
#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
class QStandardItemModel;
class QTreeView;class Widget : public QWidget
{
Q_OBJECTpublic:
Widget(QWidget *parent = 0);
~Widget();private:
QStandardItemModel *model;
QTreeView *treeView;
};#endif // WIDGET_H
@widget.cpp
@
#include "widget.h"#include <QtGui>
#include <QtCore>
#include <QtXml>Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QString html=
"<!DOCTYPE html>\n"
"<html>"
" <head>"
" <title>Document</title>"
" </head>"
" <body>"
" <h1>Document</h1>"
" <p>Some text.</p>"
" <h2>Sub Heading Level 2</h2>"
" <p>Some more text.</p>"
" <h3>Sub Heading Level 3</h3>"
" <p>Yet more text.</p>"
" <h2>Another Sub Heading Level 2</h2>"
" <p>Some final text.</p>"
" </body>"
"</html>";QDomDocument document; QString errorMsg; int errorLine, errorColumn; bool ok=document.setContent(html, false, &errorMsg, &errorLine, &errorColumn); if(!ok){ qDebug() << "Parse Failure:" << errorMsg << errorLine << errorColumn; return; } model=new QStandardItemModel(this); QStandardItem *parentItem=model->invisibleRootItem(); QDomNodeList bodyElements=document.elementsByTagName("body"); QDomNode body=bodyElements.at(0); Q_ASSERT(body.nodeName()=="body"); int headingLevel=1; QDomElement heading=body.firstChildElement("h1"); while(!heading.isNull()){ QStandardItem *item=new QStandardItem(heading.firstChild().nodeValue()); parentItem->appendRow(item); QDomElement next=heading.nextSiblingElement(QString("h%1").arg(headingLevel+1)); if(!next.isNull()) { headingLevel+=1; parentItem=item; } else{ next=heading.nextSiblingElement(QString("h%1").arg(headingLevel)); if(next.isNull()&&headingLevel>1){ headingLevel-=1; next=heading.nextSiblingElement(QString("h%1").arg(headingLevel)); parentItem=parentItem->parent(); } } heading=next; } treeView=new QTreeView(this); treeView->setModel(model); QVBoxLayout *l=new QVBoxLayout(this); l->addWidget(treeView);
}
Widget::~Widget(){}
@main.cpp
@
#include <QtGui/QApplication>
#include "widget.h"int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();return a.exec();
}
@Hope this helps ;o)
-
Hi jazzycamel
This is generous!
Thank you very much.