1
0
Kandrashin Denis 13 жил өмнө
parent
commit
1d99c8baa4

+ 1 - 1
source/fb2html.cpp

@@ -79,7 +79,7 @@ void Fb2SubtitleCmd::undo()
 //  Fb2DeleteCmd
 //---------------------------------------------------------------------------
 
-Fb2DeleteCmd::Fb2DeleteCmd(Fb2TextPage &page, Fb2TextElement &element, QUndoCommand *parent)
+Fb2DeleteCmd::Fb2DeleteCmd(Fb2TextPage &page, const Fb2TextElement &element, QUndoCommand *parent)
     : QUndoCommand(parent)
     , m_element(element)
     , m_page(page)

+ 1 - 1
source/fb2html.h

@@ -47,7 +47,7 @@ private:
 class Fb2DeleteCmd : public QUndoCommand
 {
 public:
-    explicit Fb2DeleteCmd(Fb2TextPage &page, Fb2TextElement &element, QUndoCommand *parent = 0);
+    explicit Fb2DeleteCmd(Fb2TextPage &page, const Fb2TextElement &element, QUndoCommand *parent = 0);
     virtual void undo();
     virtual void redo();
 private:

+ 107 - 19
source/fb2tree.cpp

@@ -24,36 +24,42 @@ Fb2TreeItem::Fb2TreeItem(QWebElement &element, Fb2TreeItem *parent, int number)
     , m_parent(parent)
     , m_number(number)
 {
-    m_name = element.tagName().toLower();
-    QString style = element.attribute("class").toLower();
+    init();
+    addChildren(element);
+}
+
+Fb2TreeItem::~Fb2TreeItem()
+{
+    foreach (Fb2TreeItem * item, m_list) {
+        delete item;
+    }
+}
+
+void Fb2TreeItem::init()
+{
+    m_text = QString();
+    m_name = m_element.tagName().toLower();
+    QString style = m_element.attribute("class").toLower();
     if (m_name == "div") {
         if (style == "title") {
-            m_text = title(element);
+            m_text = title();
             if (m_parent) m_parent->m_text += m_text += " ";
         } else if (style == "subtitle") {
-            m_text = title(element);
+            m_text = title();
         } else if (style == "body") {
-            m_body = element.attribute("fb2_name");
+            m_body = m_element.attribute("fb2_name");
         }
         if (!style.isEmpty()) m_name = style;
     } else if (m_name == "img") {
         m_name = "image";
-        QUrl url = element.attribute("src");
+        QUrl url = m_element.attribute("src");
         m_text = url.fragment();
     }
-    addChildren(element);
-}
-
-Fb2TreeItem::~Fb2TreeItem()
-{
-    foreach (Fb2TreeItem * item, m_list) {
-        delete item;
-    }
 }
 
-QString Fb2TreeItem::title(const QWebElement &element)
+QString Fb2TreeItem::title()
 {
-    return element.toPlainText().left(255).simplified();
+    return m_element.toPlainText().left(255).simplified();
 }
 
 void Fb2TreeItem::addChildren(QWebElement &parent, bool direct, bool header)
@@ -175,6 +181,12 @@ int Fb2TreeModel::columnCount(const QModelIndex &parent) const
     return 1;
 }
 
+QModelIndex Fb2TreeModel::index(Fb2TreeItem *item, int column) const
+{
+    Fb2TreeItem *parent = item->parent();
+    return parent ? createIndex(parent->index(item), column, (void*)item) : QModelIndex();
+}
+
 QModelIndex Fb2TreeModel::index(int row, int column, const QModelIndex &parent) const
 {
     if (!m_root || row < 0 || column < 0) return QModelIndex();
@@ -316,7 +328,6 @@ bool Fb2TreeModel::removeRows(int row, int count, const QModelIndex &parent)
     beginRemoveRows(parent, row, last);
     for (int i = last; i >= row; i--) {
         if (Fb2TreeItem * child = owner->takeAt(i)) {
-//            child->element().removeFromDocument();
             Fb2TextPage & page = *m_view.page();
             page.undoStack()->beginMacro("Delete element");
             page.undoStack()->push(new Fb2DeleteCmd(page, child->element()));
@@ -328,6 +339,79 @@ bool Fb2TreeModel::removeRows(int row, int count, const QModelIndex &parent)
     return true;
 }
 
+void Fb2TreeModel::children(QWebElement parent, Fb2ElementList &list)
+{
+    QWebElement child = parent.firstChild();
+    while (!child.isNull()) {
+        QString tag = child.tagName().toLower();
+        if (tag == "div") {
+            list << child;
+        } else if (tag == "img") {
+            list << child;
+        } else {
+            children(child, list);
+        }
+        child = child.nextSibling();
+    }
+}
+
+
+void Fb2TreeModel::update(Fb2TreeItem &owner)
+{
+    owner.init();
+    Fb2ElementList list;
+    children(owner.element(), list);
+
+    int pos = 0;
+    QModelIndex index = this->index(&owner);
+    for (QList<QWebElement>::iterator it = list.begin(); it != list.end(); it++) {
+        Fb2TreeItem * child = 0;
+        QWebElement element = *it;
+        int count = owner.count();
+        for (int i = pos; i < count; i++) {
+            if (owner.item(i)->element() == element) {
+                child = owner.item(i);
+                if (i > pos) {
+                    beginMoveRows(index, i, i, index, pos);
+                    owner.insert(owner.takeAt(i), pos);
+                    endMoveRows();
+                    break;
+                }
+            }
+        }
+        if (child) {
+            QString old = child->text();
+            update(*child);
+            if (old != child->text()) {
+                QModelIndex i = this->index(child);
+                emit dataChanged(i, i);
+            }
+        } else {
+            Fb2TreeItem * child = new Fb2TreeItem(element);
+            beginInsertRows(index, pos, pos);
+            owner.insert(child, pos);
+            endInsertRows();
+        }
+        pos++;
+    }
+
+    int last = owner.count() - 1;
+    if (pos <= last) {
+        beginRemoveRows(index, pos, last);
+        for (int i = last; i >= pos; i--) delete owner.takeAt(i);
+        endRemoveRows();
+    }
+}
+
+void Fb2TreeModel::update()
+{
+    if (!m_root) return;
+    QWebElement doc = m_view.page()->mainFrame()->documentElement();
+    QWebElement body = doc.findFirst("body");
+    if (m_root->element() != body) *m_root = body;
+    update(*m_root);
+}
+
 //---------------------------------------------------------------------------
 //  Fb2TreeView
 //---------------------------------------------------------------------------
@@ -478,8 +562,12 @@ void Fb2TreeView::selectTree()
 
 void Fb2TreeView::updateTree()
 {
-    Fb2TreeModel * model = new Fb2TreeModel(m_view, this);
-    setModel(model);
+    if (Fb2TreeModel * m = model()) {
+        m->update();
+    } else {
+        m = new Fb2TreeModel(m_view, this);
+        setModel(m);
+    }
     selectTree();
 }
 

+ 15 - 1
source/fb2tree.hpp

@@ -30,6 +30,11 @@ public:
 
     Fb2TreeItem * item(int row) const;
 
+    Fb2TreeItem & operator=(const QWebElement &element) {
+        m_element = element;
+        return *this;
+    }
+
     int index(Fb2TreeItem * child) const {
         return m_list.indexOf(child);
     }
@@ -69,9 +74,11 @@ public:
 
     Fb2TreeItem * content(const Fb2TreeModel &model, int number, QModelIndex &index) const;
 
+    void init();
+
 private:
-    QString static title(const QWebElement &element);
     void addChildren(QWebElement &parent, bool direct = true, bool header = false);
+    QString title();
 
 private:
     QList<Fb2TreeItem*> m_list;
@@ -90,12 +97,14 @@ class Fb2TreeModel: public QAbstractItemModel
 public:
     explicit Fb2TreeModel(Fb2TextEdit &view, QObject *parent = 0);
     virtual ~Fb2TreeModel();
+    QModelIndex index(Fb2TreeItem *item, int column = 0) const;
     QModelIndex index(const QString &location) const;
     Fb2TextEdit & view() { return m_view; }
     void selectText(const QModelIndex &index);
     QModelIndex move(const QModelIndex &index, int dx, int dy);
     QModelIndex append(const QModelIndex &parent);
     Fb2TreeItem * item(const QModelIndex &index) const;
+    void update();
 
 public:
     virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
@@ -105,6 +114,11 @@ public:
     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
     virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
 
+private:
+    typedef QList<QWebElement> Fb2ElementList;
+    void children(QWebElement parent, Fb2ElementList &list);
+    void update(Fb2TreeItem &item);
+
 private:
     Fb2TextEdit & m_view;
     Fb2TreeItem * m_root;