Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt WebKit
  4. How to generate TOC using DOM traversal
Forum Updated to NodeBB v4.3 + New Features

How to generate TOC using DOM traversal

Scheduled Pinned Locked Moved Qt WebKit
3 Posts 2 Posters 1.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • kalmaK Offline
    kalmaK Offline
    kalma
    wrote on last edited by
    #1

    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?

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      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 xml

      TARGET = HTML_TOC
      TEMPLATE = app

      SOURCES += main.cpp
      widget.cpp

      HEADERS += widget.h
      @

      widget.h
      @
      #ifndef WIDGET_H
      #define WIDGET_H

      #include <QtGui/QWidget>

      class QStandardItemModel;
      class QTreeView;

      class Widget : public QWidget
      {
      Q_OBJECT

      public:
      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&#40;&#41;;
      

      }
      @

      Hope this helps ;o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      0
      • kalmaK Offline
        kalmaK Offline
        kalma
        wrote on last edited by
        #3

        Hi jazzycamel

        This is generous!
        Thank you very much.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved