Ver Fonte

New class: Fb2SaveHandler

Kandrashin Denis há 13 anos atrás
pai
commit
4fe8fc6957
9 ficheiros alterados com 439 adições e 73 exclusões
  1. 4 2
      source/fb2edit.pro
  2. 49 46
      source/fb2read.cpp
  3. 9 9
      source/fb2read.h
  4. 240 0
      source/fb2save.cpp
  5. 111 0
      source/fb2save.h
  6. 18 3
      source/fb2view.cpp
  7. 5 10
      source/fb2view.h
  8. 1 1
      source/fb2xml.cpp
  9. 2 2
      source/fb2xml.h

+ 4 - 2
source/fb2edit.pro

@@ -4,7 +4,8 @@ HEADERS = \
     fb2read.h \
     fb2tree.h \
     fb2view.h \
-    fb2xml.h
+    fb2xml.h \
+    fb2save.h
 
 SOURCES = \
     fb2app.cpp \
@@ -12,7 +13,8 @@ SOURCES = \
     fb2read.cpp \
     fb2tree.cpp \
     fb2view.cpp \
-    fb2xml.cpp
+    fb2xml.cpp \
+    fb2save.cpp
 
 RESOURCES = \
     res/fb2edit.qrc

+ 49 - 46
source/fb2read.cpp

@@ -61,6 +61,8 @@ Fb2ReadWriter::Fb2ReadWriter(Fb2ReadThread &thread)
     , m_thread(thread)
     , m_id(0)
 {
+    setAutoFormatting(true);
+    setAutoFormattingIndent(2);
 }
 
 QString Fb2ReadWriter::addFile(const QString &name, const QByteArray &data)
@@ -113,7 +115,7 @@ Fb2ReadHandler::RootHandler::RootHandler(Fb2ReadWriter &writer, const QString &n
 Fb2XmlHandler::NodeHandler * Fb2ReadHandler::RootHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     switch (toKeyword(name)) {
-        case Body   : return new BodyHandler(m_writer, name, attributes, "div", name);
+        case Body   : return new TextHandler(m_writer, name, attributes, "div", name);
         case Descr  : return new DescrHandler(m_writer, name);
         case Binary : return new BinaryHandler(m_writer, name, attributes);
         default: return NULL;
@@ -201,44 +203,44 @@ Fb2ReadHandler::TitleHandler::TitleHandler(Fb2ReadWriter &writer, const QString
 
 Fb2XmlHandler::NodeHandler * Fb2ReadHandler::TitleHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
-    if (name == "annotation") return new BodyHandler(m_writer, name, attributes, "div", name);
+    if (name == "annotation") return new TextHandler(m_writer, name, attributes, "div", name);
     return new HeadHandler(m_writer, name, true);
 }
 
 //---------------------------------------------------------------------------
-//  Fb2ReadHandler::BodyHandler
+//  Fb2ReadHandler::TextHandler
 //---------------------------------------------------------------------------
 
-FB2_BEGIN_KEYHASH(Fb2ReadHandler::BodyHandler)
-    FB2_KEY( Section, "annotation" );
-    FB2_KEY( Section, "author"     );
-    FB2_KEY( Section, "cite"       );
-    FB2_KEY( Section, "date"       );
-    FB2_KEY( Section, "epigraph"   );
-    FB2_KEY( Section, "poem"       );
-    FB2_KEY( Section, "section"    );
-    FB2_KEY( Section, "stanza"     );
-    FB2_KEY( Section, "subtitle"   );
-    FB2_KEY( Section, "title"      );
-
-    FB2_KEY( Anchor, "a"    );
-    FB2_KEY( Table, "table" );
-    FB2_KEY( Image, "image" );
-
-    FB2_KEY( Parag, "empty-line" );
-    FB2_KEY( Parag, "p"          );
-    FB2_KEY( Parag, "v"          );
-
-    FB2_KEY( Style,    "style"         );
-    FB2_KEY( Strong,   "strong"        );
-    FB2_KEY( Emphas,   "emphasis"      );
-    FB2_KEY( Strike,   "strikethrough" );
-    FB2_KEY( Sub,      "sub"           );
-    FB2_KEY( Sup,      "sup"           );
-    FB2_KEY( Code,     "code"          );
+FB2_BEGIN_KEYHASH(Fb2ReadHandler::TextHandler)
+    FB2_KEY( Section , "annotation"    );
+    FB2_KEY( Section , "author"        );
+    FB2_KEY( Section , "cite"          );
+    FB2_KEY( Section , "date"          );
+    FB2_KEY( Section , "epigraph"      );
+    FB2_KEY( Section , "poem"          );
+    FB2_KEY( Section , "section"       );
+    FB2_KEY( Section , "stanza"        );
+    FB2_KEY( Section , "subtitle"      );
+    FB2_KEY( Section , "title"         );
+
+    FB2_KEY( Anchor  , "a"             );
+    FB2_KEY( Table   , "table"         );
+    FB2_KEY( Image   , "image"         );
+
+    FB2_KEY( Parag   , "empty-line"    );
+    FB2_KEY( Parag   , "p"             );
+    FB2_KEY( Parag   , "v"             );
+
+    FB2_KEY( Style   , "style"         );
+    FB2_KEY( Strong  , "strong"        );
+    FB2_KEY( Emphas  , "emphasis"      );
+    FB2_KEY( Strike  , "strikethrough" );
+    FB2_KEY( Sub     , "sub"           );
+    FB2_KEY( Sup     , "sup"           );
+    FB2_KEY( Code    , "code"          );
 FB2_END_KEYHASH
 
-Fb2ReadHandler::BodyHandler::BodyHandler(Fb2ReadWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
+Fb2ReadHandler::TextHandler::TextHandler(Fb2ReadWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
     : BaseHandler(writer, name)
     , m_parent(NULL)
     , m_tag(tag)
@@ -247,7 +249,7 @@ Fb2ReadHandler::BodyHandler::BodyHandler(Fb2ReadWriter &writer, const QString &n
     Init(attributes);
 }
 
-Fb2ReadHandler::BodyHandler::BodyHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
+Fb2ReadHandler::TextHandler::TextHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
     : BaseHandler(parent->m_writer, name)
     , m_parent(parent)
     , m_tag(tag)
@@ -256,7 +258,7 @@ Fb2ReadHandler::BodyHandler::BodyHandler(BodyHandler *parent, const QString &nam
     Init(attributes);
 }
 
-void Fb2ReadHandler::BodyHandler::Init(const QXmlAttributes &attributes)
+void Fb2ReadHandler::TextHandler::Init(const QXmlAttributes &attributes)
 {
     if (m_tag.isEmpty()) return;
     m_writer.writeStartElement(m_tag);
@@ -273,7 +275,7 @@ void Fb2ReadHandler::BodyHandler::Init(const QXmlAttributes &attributes)
     }
 }
 
-Fb2XmlHandler::NodeHandler * Fb2ReadHandler::BodyHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::TextHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     QString tag, style;
     switch (toKeyword(name)) {
@@ -288,15 +290,15 @@ Fb2XmlHandler::NodeHandler * Fb2ReadHandler::BodyHandler::NewTag(const QString &
         case Sub       : tag = "sub"; break;
         case Sup       : tag = "sup"; break;
     }
-    return new BodyHandler(this, name, attributes, tag, style);
+    return new TextHandler(this, name, attributes, tag, style);
 }
 
-void Fb2ReadHandler::BodyHandler::TxtTag(const QString &text)
+void Fb2ReadHandler::TextHandler::TxtTag(const QString &text)
 {
     m_writer.writeCharacters(text);
 }
 
-void Fb2ReadHandler::BodyHandler::EndTag(const QString &name)
+void Fb2ReadHandler::TextHandler::EndTag(const QString &name)
 {
     Q_UNUSED(name);
     if (m_tag.isEmpty()) return;
@@ -304,7 +306,7 @@ void Fb2ReadHandler::BodyHandler::EndTag(const QString &name)
     m_writer.writeEndElement();
 }
 
-bool Fb2ReadHandler::BodyHandler::isNotes() const
+bool Fb2ReadHandler::TextHandler::isNotes() const
 {
     if (m_style == "notes") return true;
     return m_parent ? m_parent->isNotes() : false;
@@ -314,8 +316,8 @@ bool Fb2ReadHandler::BodyHandler::isNotes() const
 //  Fb2ReadHandler::AnchorHandler
 //---------------------------------------------------------------------------
 
-Fb2ReadHandler::AnchorHandler::AnchorHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes)
-    : BodyHandler(parent, name, attributes, "a")
+Fb2ReadHandler::AnchorHandler::AnchorHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes)
+    : TextHandler(parent, name, attributes, "a")
 {
     QString href = Value(attributes, "href");
     m_writer.writeAttribute("href", href);
@@ -325,8 +327,8 @@ Fb2ReadHandler::AnchorHandler::AnchorHandler(BodyHandler *parent, const QString
 //  Fb2ReadHandler::ImageHandler
 //---------------------------------------------------------------------------
 
-Fb2ReadHandler::ImageHandler::ImageHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes)
-    : BodyHandler(parent, name, attributes, "img")
+Fb2ReadHandler::ImageHandler::ImageHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes)
+    : TextHandler(parent, name, attributes, "img")
 {
     QString href = Value(attributes, "href");
     while (href.left(1) == "#") href.remove(0, 1);
@@ -366,11 +368,12 @@ Fb2ReadHandler::Fb2ReadHandler(Fb2ReadThread &thread)
     : Fb2XmlHandler()
     , m_writer(thread)
 {
-    m_writer.setAutoFormatting(true);
-    m_writer.setAutoFormattingIndent(2);
 }
 
-Fb2XmlHandler::NodeHandler * Fb2ReadHandler::CreateRoot(const QString &name)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::CreateRoot(const QString &name, const QXmlAttributes &attributes)
 {
-    return new RootHandler(m_writer, name);
+    Q_UNUSED(attributes);
+    if (name == "fictionbook") return new RootHandler(m_writer, name);
+    m_error = QObject::tr("The file is not an FB2 file.");
+    return 0;
 }

+ 9 - 9
source/fb2read.h

@@ -115,7 +115,7 @@ private:
         virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     };
 
-    class BodyHandler : public BaseHandler
+    class TextHandler : public BaseHandler
     {
         FB2_BEGIN_KEYLIST
             Section,
@@ -132,8 +132,8 @@ private:
             Code,
        FB2_END_KEYLIST
     public:
-        explicit BodyHandler(Fb2ReadWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
-        explicit BodyHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
+        explicit TextHandler(Fb2ReadWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
+        explicit TextHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
     protected:
         virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
         virtual void TxtTag(const QString &text);
@@ -142,21 +142,21 @@ private:
         void Init(const QXmlAttributes &attributes);
         bool isNotes() const;
     protected:
-        BodyHandler *m_parent;
+        TextHandler *m_parent;
         QString m_tag;
         QString m_style;
     };
 
-    class AnchorHandler : public BodyHandler
+    class AnchorHandler : public TextHandler
     {
     public:
-        explicit AnchorHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes);
+        explicit AnchorHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes);
     };
 
-    class ImageHandler : public BodyHandler
+    class ImageHandler : public TextHandler
     {
     public:
-        explicit ImageHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes);
+        explicit ImageHandler(TextHandler *parent, const QString &name, const QXmlAttributes &attributes);
     };
 
     class BinaryHandler : public BaseHandler
@@ -172,7 +172,7 @@ private:
     };
 
 protected:
-    virtual NodeHandler * CreateRoot(const QString &name);
+    virtual NodeHandler * CreateRoot(const QString &name, const QXmlAttributes &attributes);
 
 private:
     Fb2ReadWriter m_writer;

+ 240 - 0
source/fb2save.cpp

@@ -0,0 +1,240 @@
+#include <QtGui>
+#include <QtDebug>
+
+#include "fb2save.h"
+
+//---------------------------------------------------------------------------
+//  Fb2SaveThread
+//---------------------------------------------------------------------------
+
+Fb2SaveThread::Fb2SaveThread(QObject *parent, const QString &filename)
+    : QThread(parent)
+    , m_filename(filename)
+    , m_abort(false)
+{
+}
+
+Fb2SaveThread::~Fb2SaveThread()
+{
+    stop();
+    wait();
+}
+
+void Fb2SaveThread::stop()
+{
+    QMutexLocker locker(&mutex);
+    Q_UNUSED(locker);
+    m_abort = true;
+}
+
+void Fb2SaveThread::run()
+{
+    if (parse()) emit html(m_filename, m_html);
+}
+
+void Fb2SaveThread::onFile(const QString &name, const QString &path)
+{
+    emit file(name, path);
+}
+
+bool Fb2SaveThread::parse()
+{
+    QFile file(m_filename);
+    if (!file.open(QFile::ReadOnly | QFile::Text)) {
+        qCritical() << QObject::tr("Cannot read file %1: %2.").arg(m_filename).arg(file.errorString());
+        return false;
+    }
+    Fb2SaveHandler handler(*this);
+    QXmlSimpleReader reader;
+    reader.setContentHandler(&handler);
+    reader.setErrorHandler(&handler);
+    QXmlInputSource source(&file);
+    return reader.parse(source);
+}
+
+//---------------------------------------------------------------------------
+//  Fb2SaveWriter
+//---------------------------------------------------------------------------
+
+Fb2SaveWriter::Fb2SaveWriter(Fb2SaveThread &thread)
+    : QXmlStreamWriter(thread.data())
+    , m_thread(thread)
+    , m_id(0)
+{
+    setAutoFormatting(true);
+    setAutoFormattingIndent(2);
+}
+
+QString Fb2SaveWriter::addFile(const QString &name, const QByteArray &data)
+{
+    QString path = getFile(name);
+    QFile file(path);
+    if (file.open(QIODevice::WriteOnly)) {
+        file.write(data);
+        m_thread.onFile(name, path);
+    }
+    return path;
+}
+
+QString Fb2SaveWriter::getFile(const QString &name)
+{
+    StringHash::const_iterator i = m_hash.find(name);
+    if (i == m_hash.end()) {
+        QTemporaryFile file;
+        file.setAutoRemove(false);
+        file.open();
+        return m_hash.insert(name, file.fileName()).value();
+    } else {
+        return i.value();
+    }
+}
+
+QString Fb2SaveWriter::newId()
+{
+    return QString("FB2E%1").arg(++m_id);
+}
+
+//---------------------------------------------------------------------------
+//  Fb2SaveHandler::BodyHandler
+//---------------------------------------------------------------------------
+
+FB2_BEGIN_KEYHASH(Fb2SaveHandler::BodyHandler)
+    FB2_KEY( Section , "div"           );
+    FB2_KEY( Section , "annotation"    );
+    FB2_KEY( Section , "author"        );
+    FB2_KEY( Section , "cite"          );
+    FB2_KEY( Section , "date"          );
+    FB2_KEY( Section , "epigraph"      );
+    FB2_KEY( Section , "poem"          );
+    FB2_KEY( Section , "section"       );
+    FB2_KEY( Section , "stanza"        );
+    FB2_KEY( Section , "subtitle"      );
+    FB2_KEY( Section , "title"         );
+
+    FB2_KEY( Anchor  , "a"             );
+    FB2_KEY( Table   , "table"         );
+    FB2_KEY( Image   , "image"         );
+
+    FB2_KEY( Parag   , "empty-line"    );
+    FB2_KEY( Parag   , "p"             );
+    FB2_KEY( Parag   , "v"             );
+
+    FB2_KEY( Strong  , "b"             );
+    FB2_KEY( Emphas  , "i"             );
+    FB2_KEY( Strike  , "strike"        );
+    FB2_KEY( Sub     , "sub"           );
+    FB2_KEY( Sup     , "sup"           );
+    FB2_KEY( Code    , "tt"            );
+FB2_END_KEYHASH
+
+Fb2SaveHandler::BodyHandler::BodyHandler(Fb2SaveWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
+    : NodeHandler(name)
+    , m_writer(writer)
+    , m_tag(tag)
+    , m_style(style)
+{
+    Init(attributes);
+}
+
+Fb2SaveHandler::BodyHandler::BodyHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
+    : NodeHandler(name)
+    , m_writer(parent->m_writer)
+    , m_tag(tag)
+    , m_style(style)
+{
+    Init(attributes);
+}
+
+void Fb2SaveHandler::BodyHandler::Init(const QXmlAttributes &attributes)
+{
+    if (m_tag.isEmpty()) return;
+    m_writer.writeStartElement(m_tag);
+/*
+    QString id = Value(attributes, "id");
+    if (!id.isEmpty()) {
+        if (m_style == "section" && isNotes()) m_style = "note";
+        m_writer.writeAttribute("id", id);
+    } else if (m_tag == "div" || m_tag == "img") {
+        m_writer.writeAttribute("id", m_writer.newId());
+    }
+    if (!m_style.isEmpty()) {
+        if (m_style == "body" && Value(attributes, "name").toLower() == "notes") m_style = "notes";
+        m_writer.writeAttribute("class", m_style);
+    }
+*/
+}
+
+Fb2XmlHandler::NodeHandler * Fb2SaveHandler::BodyHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+{
+    QString tag, style;
+    switch (toKeyword(name)) {
+        case Anchor    : return new AnchorHandler(this, name, attributes);
+        case Image     : return new ImageHandler(this, name, attributes);
+        case Section   : tag = "div"; style = name; break;
+        case Parag     : tag = "p";   break;
+
+        case Strong    : tag = "strong"        ; break;
+        case Emphas    : tag = "emphasis"      ; break;
+        case Strike    : tag = "strikethrough" ; break;
+        case Code      : tag = "cide"          ; break;
+        case Sub       : tag = "sub"           ; break;
+        case Sup       : tag = "sup"           ; break;
+    }
+    return new BodyHandler(this, name, attributes, tag, style);
+}
+
+void Fb2SaveHandler::BodyHandler::TxtTag(const QString &text)
+{
+    m_writer.writeCharacters(text);
+}
+
+void Fb2SaveHandler::BodyHandler::EndTag(const QString &name)
+{
+    Q_UNUSED(name);
+    if (m_tag.isEmpty()) return;
+    if (m_tag == "div") m_writer.writeCharacters(" ");
+    m_writer.writeEndElement();
+}
+
+//---------------------------------------------------------------------------
+//  Fb2SaveHandler::AnchorHandler
+//---------------------------------------------------------------------------
+
+Fb2SaveHandler::AnchorHandler::AnchorHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes)
+    : BodyHandler(parent, name, attributes, "a")
+{
+    QString href = Value(attributes, "href");
+    m_writer.writeAttribute("href", href);
+}
+
+//---------------------------------------------------------------------------
+//  Fb2SaveHandler::ImageHandler
+//---------------------------------------------------------------------------
+
+Fb2SaveHandler::ImageHandler::ImageHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes)
+    : BodyHandler(parent, name, attributes, "img")
+{
+    QString href = Value(attributes, "href");
+    while (href.left(1) == "#") href.remove(0, 1);
+    QString path = m_writer.getFile(href);
+    m_writer.writeAttribute("src", path);
+    m_writer.writeAttribute("alt", href);
+}
+
+//---------------------------------------------------------------------------
+//  Fb2SaveHandler
+//---------------------------------------------------------------------------
+
+Fb2SaveHandler::Fb2SaveHandler(Fb2SaveThread &thread)
+    : Fb2XmlHandler()
+    , m_writer(thread)
+{
+}
+
+Fb2XmlHandler::NodeHandler * Fb2SaveHandler::CreateRoot(const QString &name, const QXmlAttributes &attributes)
+{
+    if (name == "body") return new BodyHandler(m_writer, name, attributes, "fictionbook");
+    m_error = QObject::tr("The tag <body> was not found.");
+    return 0;
+}
+

+ 111 - 0
source/fb2save.h

@@ -0,0 +1,111 @@
+#ifndef Fb2Save_H
+#define Fb2Save_H
+
+#include "fb2xml.h"
+
+#include <QByteArray>
+#include <QMutex>
+#include <QThread>
+#include <QXmlDefaultHandler>
+#include <QXmlStreamWriter>
+
+class Fb2SaveThread : public QThread
+{
+    Q_OBJECT
+
+public:
+    Fb2SaveThread(QObject *parent, const QString &filename);
+    ~Fb2SaveThread();
+    void onFile(const QString &name, const QString &path);
+    QString * data() { return &m_html; }
+
+signals:
+    void file(QString name, QString path);
+    void html(QString name, QString html);
+
+public slots:
+    void stop();
+
+protected:
+    void run();
+
+private:
+    bool parse();
+
+private:
+    const QString m_filename;
+    QString m_html;
+    bool m_abort;
+    QMutex mutex;
+};
+
+class Fb2SaveWriter : public QXmlStreamWriter
+{
+public:
+    explicit Fb2SaveWriter(Fb2SaveThread &thread);
+    QString addFile(const QString &name, const QByteArray &data);
+    QString getFile(const QString &name);
+    QString newId();
+private:
+    typedef QHash<QString, QString> StringHash;
+    Fb2SaveThread &m_thread;
+    StringHash m_hash;
+    int m_id;
+};
+
+class Fb2SaveHandler : public Fb2XmlHandler
+{
+public:
+    explicit Fb2SaveHandler(Fb2SaveThread &thread);
+
+private:
+    class BodyHandler : public NodeHandler
+    {
+        FB2_BEGIN_KEYLIST
+            Section,
+            Anchor,
+            Table,
+            Image,
+            Parag,
+            Strong,
+            Emphas,
+            Strike,
+            Sub,
+            Sup,
+            Code,
+       FB2_END_KEYLIST
+    public:
+        explicit BodyHandler(Fb2SaveWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
+        explicit BodyHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
+    protected:
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
+        virtual void TxtTag(const QString &text);
+        virtual void EndTag(const QString &name);
+    protected:
+        void Init(const QXmlAttributes &attributes);
+    protected:
+        Fb2SaveWriter &m_writer;
+        QString m_tag;
+        QString m_style;
+    };
+
+    class AnchorHandler : public BodyHandler
+    {
+    public:
+        explicit AnchorHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes);
+    };
+
+    class ImageHandler : public BodyHandler
+    {
+    public:
+        explicit ImageHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes);
+    };
+
+protected:
+    virtual NodeHandler * CreateRoot(const QString &name, const QXmlAttributes &attributes);
+
+private:
+    Fb2SaveWriter m_writer;
+};
+
+#endif // Fb2Save_H

+ 18 - 3
source/fb2view.cpp

@@ -32,15 +32,30 @@ Fb2WebView::~Fb2WebView()
     foreach (QString value, m_files) QFile::remove(value);
 }
 
+QWebElement Fb2WebView::doc()
+{
+    return page()->mainFrame()->documentElement();
+}
+
 QString Fb2WebView::toXml()
 {
-    return page()->mainFrame()->documentElement().toOuterXml();
+    return doc().toOuterXml();
+}
+
+QString Fb2WebView::toBodyXml()
+{
+    QWebElement child = doc().firstChild();
+    while (!child.isNull()) {
+        if (child.tagName().toLower() == "body") {
+            return child.toOuterXml();
+        }
+    }
+    return QString();
 }
 
 void Fb2WebView::fixContents()
 {
-    QWebElement doc = page()->mainFrame()->documentElement();
-    foreach (QWebElement span, doc.findAll("span.apple-style-span[style]")) {
+    foreach (QWebElement span, doc().findAll("span.apple-style-span[style]")) {
         span.removeAttribute("style");
     }
 }

+ 5 - 10
source/fb2view.h

@@ -5,6 +5,7 @@
 #include <QResizeEvent>
 #include <QTimer>
 #include <QThread>
+#include <QWebElement>
 #include <QWebView>
 
 class Fb2BaseWebView : public QWebView
@@ -45,6 +46,7 @@ public:
     explicit Fb2WebView(QWidget *parent = 0);
     virtual ~Fb2WebView();
     void load(const QString &filename);
+    QString toBodyXml();
     QString toXml();
 
     bool UndoEnabled();
@@ -62,16 +64,6 @@ signals:
 public slots:
     void file(QString name, QString path);
     void html(QString name, QString html);
-/*
-    void Undo();
-    void Redo();
-    void Cut();
-    void Copy();
-    void Paste();
-    void Bold();
-    void Italic();
-    void Strike();
-*/
     void zoomIn();
     void zoomOut();
     void zoomOrig();
@@ -79,6 +71,9 @@ public slots:
 private slots:
     void fixContents();
 
+private:
+    QWebElement doc();
+
 private:
     typedef QHash<QString, QString> StringHash;
     StringHash m_files;

+ 1 - 1
source/fb2xml.cpp

@@ -68,7 +68,7 @@ bool Fb2XmlHandler::startElement(const QString & namespaceURI, const QString & l
     Q_UNUSED(localName);
     const QString name = qName.toLower();
     if (m_handler) return m_handler->doStart(name, attributes);
-    return m_handler = CreateRoot(name);
+    return m_handler = CreateRoot(name, attributes);
 }
 
 static bool isWhiteSpace(const QString &str)

+ 2 - 2
source/fb2xml.h

@@ -62,9 +62,9 @@ protected:
     };
 
 protected:
-    virtual NodeHandler * CreateRoot(const QString &name) = 0;
+    virtual NodeHandler * CreateRoot(const QString &name, const QXmlAttributes &attributes) = 0;
 
-private:
+protected:
     NodeHandler * m_handler;
     QString m_error;
 };