Explorar el Código

New class: Fb2HeadModel

Kandrashin Denis hace 13 años
padre
commit
65f86090fd
Se han modificado 4 ficheros con 320 adiciones y 52 borrados
  1. 53 51
      source/fb2edit.pro
  2. 177 0
      source/fb2head.cpp
  3. 85 0
      source/fb2head.h
  4. 5 1
      source/fb2main.cpp

+ 53 - 51
source/fb2edit.pro

@@ -1,51 +1,53 @@
-HEADERS = \
-    fb2app.h \
-    fb2main.h \
-    fb2read.h \
-    fb2tree.h \
-    fb2save.h \
-    fb2view.h \
-    fb2xml.h \
-    fb2xml2.h
-
-SOURCES = \
-    fb2app.cpp \
-    fb2main.cpp \
-    fb2read.cpp \
-    fb2tree.cpp \
-    fb2save.cpp \
-    fb2view.cpp \
-    fb2xml.cpp \
-    fb2xml2.cpp
-
-RESOURCES = \
-    res/fb2edit.qrc
-
-TARGET = fb2edit
-
-TRANSLATIONS = ts/ru.ts
-
-VERSION = 0.01.1
-
-QT += xml
-QT += webkit
-QT += network
-
-LIBS += -lqscintilla2
-
-OTHER_FILES += res/style.css
-
-if (win32) {
-
-    INCLUDEPATH += ../libxml2/include
-    LIBS += -L../libxml2/lib -llibxml2
-
-    INCLUDEPATH += ../iconv/include
-    LIBS += -L../iconv/lib -liconv
-
-} else {
-
-    INCLUDEPATH += /usr/include/libxml2
-    LIBS += -lxml2
-
-}
+HEADERS = \
+    fb2app.h \
+    fb2head.h \
+    fb2main.h \
+    fb2read.h \
+    fb2tree.h \
+    fb2save.h \
+    fb2view.h \
+    fb2xml.h \
+    fb2xml2.h
+
+SOURCES = \
+    fb2app.cpp \
+    fb2head.cpp \
+    fb2main.cpp \
+    fb2read.cpp \
+    fb2tree.cpp \
+    fb2save.cpp \
+    fb2view.cpp \
+    fb2xml.cpp \
+    fb2xml2.cpp
+
+RESOURCES = \
+    res/fb2edit.qrc
+
+TARGET = fb2edit
+
+TRANSLATIONS = ts/ru.ts
+
+VERSION = 0.01.1
+
+QT += xml
+QT += webkit
+QT += network
+
+LIBS += -lqscintilla2
+
+OTHER_FILES += res/style.css
+
+if (win32) {
+
+    INCLUDEPATH += ../libxml2/include
+    LIBS += -L../libxml2/lib -llibxml2
+
+    INCLUDEPATH += ../iconv/include
+    LIBS += -L../iconv/lib -liconv
+
+} else {
+
+    INCLUDEPATH += /usr/include/libxml2
+    LIBS += -lxml2
+
+}

+ 177 - 0
source/fb2head.cpp

@@ -0,0 +1,177 @@
+#include "fb2head.h"
+
+#include <QtDebug>
+#include <QWebFrame>
+#include <QWebPage>
+#include <QWebView>
+#include <QTreeView>
+
+Fb2HeadItem::Fb2HeadItem(QWebElement &element, Fb2HeadItem *parent)
+    : QObject(parent)
+    , m_element(element)
+    , m_parent(parent)
+{
+    m_name = element.tagName().toLower();
+    QString style = element.attribute("class").toLower();
+    if (m_name == "div") {
+        if (style == "title") {
+            m_text = element.toPlainText().simplified().left(255);
+            if (m_parent) m_parent->m_text += m_text += " ";
+        } else if (style == "subtitle") {
+            m_text = element.toPlainText().simplified().left(255);
+        }
+        if (!style.isEmpty()) m_name = style;
+    } else if (m_name == "img") {
+        m_text = element.attribute("alt");
+    }
+    m_id = element.attribute("id");
+    addChildren(element);
+}
+
+Fb2HeadItem::~Fb2HeadItem()
+{
+    foreach (Fb2HeadItem * item, m_list) {
+        delete item;
+    }
+}
+
+void Fb2HeadItem::addChildren(QWebElement &parent)
+{
+    QWebElement child = parent.firstChild();
+    while (!child.isNull()) {
+        QString tag = child.tagName().toLower();
+        if (tag == "div") {
+            QString style = child.attribute("style");
+            if (style != "display:none") m_list << new Fb2HeadItem(child, this);
+        } else if (tag == "img") {
+            m_list << new Fb2HeadItem(child, this);
+        } else {
+            addChildren(child);
+        }
+        child = child.nextSibling();
+    }
+}
+
+Fb2HeadItem * Fb2HeadItem::item(const QModelIndex &index) const
+{
+    int row = index.row();
+    if (row < 0 || row >= m_list.size()) return NULL;
+    return m_list[row];
+}
+
+Fb2HeadItem * Fb2HeadItem::item(int row) const
+{
+    if (row < 0 || row >= m_list.size()) return NULL;
+    return m_list[row];
+}
+
+QString Fb2HeadItem::text(int col) const
+{
+    switch (col) {
+        case 0: return QString("<%1>").arg(m_name);
+        case 2: if (m_list.count() == 0) return m_element.toPlainText().simplified();
+    }
+    return QString();
+}
+
+//---------------------------------------------------------------------------
+//  Fb2HeadModel
+//---------------------------------------------------------------------------
+
+Fb2HeadModel::Fb2HeadModel(QWebView &view, QObject *parent)
+    : QAbstractItemModel(parent)
+    , m_view(view)
+    , m_root(NULL)
+{
+    QWebElement doc = view.page()->mainFrame()->documentElement();
+    QWebElement body = doc.findFirst("div.description");
+    if (body.isNull()) return;
+    m_root = new Fb2HeadItem(body);
+}
+
+Fb2HeadModel::~Fb2HeadModel()
+{
+    if (m_root) delete m_root;
+}
+
+void Fb2HeadModel::expand(QTreeView *view)
+{
+    QModelIndex parent = QModelIndex();
+    int count = rowCount(parent);
+    for (int i = 0; i < count; i++) {
+        QModelIndex child = index(i, 0, parent);
+        Fb2HeadItem *node = item(child);
+        if (node && node->name() == "body") view->expand(child);
+    }
+}
+
+Fb2HeadItem * Fb2HeadModel::item(const QModelIndex &index) const
+{
+    if (index.isValid()) {
+        return static_cast<Fb2HeadItem*>(index.internalPointer());
+    } else {
+        return m_root;
+    }
+}
+
+int Fb2HeadModel::columnCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    return 3;
+}
+
+QModelIndex Fb2HeadModel::index(int row, int column, const QModelIndex &parent) const
+{
+    if (!m_root || row < 0 || column < 0) return QModelIndex();
+    if (Fb2HeadItem *owner = item(parent)) {
+        if (Fb2HeadItem *child = owner->item(row)) {
+            return createIndex(row, column, (void*)child);
+        }
+    }
+    return QModelIndex();
+}
+
+QModelIndex Fb2HeadModel::parent(const QModelIndex &child) const
+{
+    if (Fb2HeadItem * node = static_cast<Fb2HeadItem*>(child.internalPointer())) {
+        if (Fb2HeadItem * parent = node->parent()) {
+            if (Fb2HeadItem * owner = parent->parent()) {
+                return createIndex(owner->index(parent), 0, (void*)parent);
+            }
+        }
+    }
+    return QModelIndex();
+}
+
+int Fb2HeadModel::rowCount(const QModelIndex &parent) const
+{
+    if (parent.column() > 0) return 0;
+    Fb2HeadItem *owner = item(parent);
+    return owner ? owner->count() : 0;
+}
+
+QVariant Fb2HeadModel::data(const QModelIndex &index, int role) const
+{
+    if (role != Qt::DisplayRole) return QVariant();
+    Fb2HeadItem * i = item(index);
+    return i ? i->text(index.column()) : QVariant();
+}
+
+QVariant Fb2HeadModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+        switch (section) {
+            case 0: return tr("Tag");
+            case 1: return tr("Description");
+            case 2: return tr("Value");
+        }
+    }
+    return QVariant();
+}
+
+void Fb2HeadModel::select(const QModelIndex &index)
+{
+    Fb2HeadItem *node = item(index);
+    if (!node || node->id().isEmpty()) return;
+    m_view.page()->mainFrame()->scrollToAnchor(node->id());
+}

+ 85 - 0
source/fb2head.h

@@ -0,0 +1,85 @@
+#ifndef FB2HEAD_H
+#define FB2HEAD_H
+
+#include <QAbstractItemModel>
+#include <QWebElement>
+#include <QWebView>
+
+QT_BEGIN_NAMESPACE
+class QTreeView;
+QT_END_NAMESPACE
+
+class Fb2HeadItem: public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit Fb2HeadItem(QWebElement &element, Fb2HeadItem *parent = 0);
+
+    virtual ~Fb2HeadItem();
+
+    Fb2HeadItem * item(const QModelIndex &index) const;
+
+    Fb2HeadItem * item(int row) const;
+
+    int index(Fb2HeadItem * child) const {
+        return m_list.indexOf(child);
+    }
+
+    int count() const {
+        return m_list.size();
+    }
+
+    Fb2HeadItem * parent() const {
+        return m_parent;
+    }
+
+    QString text(int col = 0) const;
+
+    const QString & id() const {
+        return m_id;
+    }
+
+    const QString & name() const {
+        return m_name;
+    }
+
+private:
+    void addChildren(QWebElement &parent);
+
+private:
+    QList<Fb2HeadItem*> m_list;
+    QWebElement m_element;
+    QString m_name;
+    QString m_text;
+    Fb2HeadItem * m_parent;
+    QString m_id;
+};
+
+class Fb2HeadModel: public QAbstractItemModel
+{
+    Q_OBJECT
+
+public:
+    explicit Fb2HeadModel(QWebView &view, QObject *parent = 0);
+    virtual ~Fb2HeadModel();
+    void select(const QModelIndex &index);
+    void expand(QTreeView *view);
+
+public:
+    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+    virtual QModelIndex parent(const QModelIndex &child) const;
+    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+protected:
+    Fb2HeadItem * item(const QModelIndex &index) const;
+
+private:
+    QWebView & m_view;
+    Fb2HeadItem * m_root;
+};
+
+#endif // FB2HEAD_H

+ 5 - 1
source/fb2main.cpp

@@ -8,7 +8,7 @@
 #include "fb2read.h"
 #include "fb2tree.h"
 #include "fb2view.h"
-#include "fb2main.h"
+#include "fb2head.h"
 
 #include <Qsci/qsciscintilla.h>
 #include <Qsci/qscilexerxml.h>
@@ -419,6 +419,10 @@ void Fb2MainWindow::createHead()
         textEdit->setParent(NULL);
         setCentralWidget(headTree);
         textEdit->setParent(this);
+
+        Fb2HeadModel *model = new Fb2HeadModel(*textEdit, treeView);
+        headTree->setModel(model);
+        model->expand(headTree);
     } else {
         setCentralWidget(headTree);
     }