| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #include "vtableofcontent.h"
- #include "vconstants.h"
- #include <QXmlStreamReader>
- #include <QDebug>
- VTableOfContent::VTableOfContent()
- : m_file(NULL), m_type(VTableOfContentType::Anchor)
- {
- }
- VTableOfContent::VTableOfContent(const VFile *p_file)
- : m_file(p_file), m_type(VTableOfContentType::Anchor)
- {
- }
- void VTableOfContent::update(const VFile *p_file,
- const QVector<VTableOfContentItem> &p_table,
- VTableOfContentType p_type)
- {
- m_file = p_file;
- m_table = p_table;
- m_type = p_type;
- }
- static bool parseTocUl(QXmlStreamReader &p_xml,
- QVector<VTableOfContentItem> &p_table,
- int p_level);
- static bool parseTocLi(QXmlStreamReader &p_xml,
- QVector<VTableOfContentItem> &p_table,
- int p_level)
- {
- Q_ASSERT(p_xml.isStartElement() && p_xml.name() == "li");
- if (p_xml.readNextStartElement()) {
- if (p_xml.name() == "a") {
- QString anchor = p_xml.attributes().value("href").toString().mid(1);
- QString name;
- if (p_xml.readNext()) {
- if (p_xml.tokenString() == "Characters") {
- name = p_xml.text().toString();
- } else if (!p_xml.isEndElement()) {
- qWarning() << "TOC HTML <a> should be ended by </a>" << p_xml.name();
- return false;
- }
- VTableOfContentItem header(name, p_level, anchor, p_table.size());
- p_table.append(header);
- } else {
- // Error
- return false;
- }
- } else if (p_xml.name() == "ul") {
- // Such as header 3 under header 1 directly
- VTableOfContentItem header(c_emptyHeaderName, p_level, "", p_table.size());
- p_table.append(header);
- parseTocUl(p_xml, p_table, p_level + 1);
- } else {
- qWarning() << "TOC HTML <li> should contain <a> or <ul>" << p_xml.name();
- return false;
- }
- }
- while (p_xml.readNext()) {
- if (p_xml.isEndElement()) {
- if (p_xml.name() == "li") {
- return true;
- }
- continue;
- }
- if (p_xml.name() == "ul") {
- // Nested unordered list
- if (!parseTocUl(p_xml, p_table, p_level + 1)) {
- return false;
- }
- } else {
- return false;
- }
- }
- return true;
- }
- static bool parseTocUl(QXmlStreamReader &p_xml,
- QVector<VTableOfContentItem> &p_table,
- int p_level)
- {
- bool ret = true;
- Q_ASSERT(p_xml.isStartElement() && p_xml.name() == "ul");
- while (p_xml.readNextStartElement()) {
- if (p_xml.name() == "li") {
- if (!parseTocLi(p_xml, p_table, p_level)) {
- ret = false;
- break;
- }
- } else {
- qWarning() << "TOC HTML <ul> should contain <li>" << p_xml.name();
- ret = false;
- break;
- }
- }
- return ret;
- }
- bool VTableOfContent::parseTableFromHtml(const QString &p_html)
- {
- bool ret = true;
- m_table.clear();
- if (!p_html.isEmpty()) {
- QXmlStreamReader xml(p_html);
- if (xml.readNextStartElement()) {
- if (xml.name() == "ul") {
- ret = parseTocUl(xml, m_table, 1);
- } else {
- qWarning() << "TOC HTML does not start with <ul>" << p_html;
- ret = false;
- }
- }
- if (xml.hasError()) {
- qWarning() << "fail to parse TOC in HTML" << p_html;
- ret = false;
- }
- }
- return ret;
- }
- int VTableOfContent::indexOfItemByAnchor(const QString &p_anchor) const
- {
- if (p_anchor.isEmpty()
- || isEmpty()
- || m_type != VTableOfContentType::Anchor) {
- return -1;
- }
- for (int i = 0; i < m_table.size(); ++i) {
- if (m_table[i].m_anchor == p_anchor) {
- return i;
- }
- }
- return -1;
- }
- int VTableOfContent::indexOfItemByBlockNumber(int p_blockNumber) const
- {
- if (p_blockNumber == -1
- || isEmpty()
- || m_type != VTableOfContentType::BlockNumber) {
- return -1;
- }
- for (int i = m_table.size() - 1; i >= 0; --i) {
- if (!m_table[i].isEmpty()
- && m_table[i].m_blockNumber <= p_blockNumber) {
- return i;
- }
- }
- return -1;
- }
- bool VTableOfContent::operator==(const VTableOfContent &p_outline) const
- {
- return m_file == p_outline.getFile()
- && m_type == p_outline.getType()
- && m_table == p_outline.getTable();
- }
|