Browse Source

Save FB2 with images

Kandrashin Denis 13 years ago
parent
commit
f2c080b395
6 changed files with 93 additions and 20 deletions
  1. 41 4
      source/fb2save.cpp
  2. 10 0
      source/fb2save.h
  3. 17 1
      source/fb2view.cpp
  4. 5 3
      source/fb2view.h
  5. 20 11
      source/fb2xml2.cpp
  6. 0 1
      source/fb2xml2.h

+ 41 - 4
source/fb2save.cpp

@@ -24,9 +24,38 @@ Fb2SaveWriter::~Fb2SaveWriter()
 
 QString Fb2SaveWriter::getFile(const QString &path)
 {
-    return QString();
+    StringHash::const_iterator it = m_files.find(path);
+    if (it == m_files.end()) {
+        QString name = m_view.fileName(path);
+        if (name.isEmpty()) return QString();
+        m_files[name] = path;
+        m_names << name;
+        return name;
+    }
+    return it.value();
+}
+
+QString Fb2SaveWriter::getData(const QString &name)
+{
+    return m_view.fileData(name);
 }
 
+void Fb2SaveWriter::writeFiles()
+{
+    StringList::const_iterator it;
+    for (it = m_names.constBegin(); it != m_names.constEnd(); it++) {
+        QString name = *it;
+        if (name.isEmpty()) continue;
+        QString data = getData(name);
+        if (data.isEmpty()) continue;
+        writeStartElement("binary");
+        writeAttribute("id", name);
+        writeCharacters(data);
+        writeEndElement();
+    }
+}
+
+
 //---------------------------------------------------------------------------
 //  Fb2SaveHandler::BodyHandler
 //---------------------------------------------------------------------------
@@ -117,6 +146,12 @@ Fb2SaveHandler::RootHandler::RootHandler(Fb2SaveWriter &writer, const QString &n
     m_writer.writeAttribute("xmlns:l", "http://www.w3.org/1999/xlink");
 }
 
+void Fb2SaveHandler::RootHandler::EndTag(const QString &name)
+{
+    m_writer.writeFiles();
+    BodyHandler::EndTag(name);
+}
+
 //---------------------------------------------------------------------------
 //  Fb2SaveHandler::AnchorHandler
 //---------------------------------------------------------------------------
@@ -135,9 +170,11 @@ Fb2SaveHandler::AnchorHandler::AnchorHandler(BodyHandler *parent, const QString
 Fb2SaveHandler::ImageHandler::ImageHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &atts)
     : BodyHandler(parent, name, atts, "image")
 {
-    QString href = Value(atts, "href");
-    QString path = m_writer.getFile(href);
-    m_writer.writeAttribute("l:href", path);
+    QString href = Value(atts, "src");
+    QString file = m_writer.getFile(href);
+    if (file.isEmpty()) return;
+    file.prepend('#');
+    m_writer.writeAttribute("l:href", file);
     m_writer.writeEndElement();
 }
 

+ 10 - 0
source/fb2save.h

@@ -4,6 +4,8 @@
 #include "fb2xml.h"
 
 #include <QByteArray>
+#include <QHash>
+#include <QList>
 #include <QMutex>
 #include <QThread>
 #include <QXmlDefaultHandler>
@@ -17,8 +19,14 @@ public:
     explicit Fb2SaveWriter(Fb2WebView &view, QIODevice &device);
     virtual ~Fb2SaveWriter();
     QString getFile(const QString &path);
+    QString getData(const QString &name);
+    void writeFiles();
 private:
     Fb2WebView &m_view;
+    typedef QHash<QString, QString> StringHash;
+    typedef QList<QString> StringList;
+    StringHash m_files;
+    StringList m_names;
 };
 
 class Fb2SaveHandler : public Fb2XmlHandler
@@ -62,6 +70,8 @@ private:
     {
     public:
         explicit RootHandler(Fb2SaveWriter &writer, const QString &name, const QXmlAttributes &atts);
+    protected:
+        virtual void EndTag(const QString &name);
     };
 
     class AnchorHandler : public BodyHandler

+ 17 - 1
source/fb2view.cpp

@@ -119,7 +119,7 @@ bool Fb2WebView::save(QIODevice &device)
 
 QTemporaryFile * Fb2WebView::file(const QString &name)
 {
-    TemporaryMap::const_iterator it = m_files.find(name);
+    TemporaryHash::const_iterator it = m_files.find(name);
     if (it == m_files.end()) {
         it = m_files.insert(name, new QTemporaryFile());
         it.value()->open();
@@ -140,6 +140,22 @@ void Fb2WebView::data(QString name, QByteArray data)
     temp->open();
 }
 
+QString Fb2WebView::fileName(const QString &path)
+{
+    QHashIterator<QString, QTemporaryFile*> it(m_files);
+    while (it.hasNext()) {
+        it.next();
+        if (it.value()->fileName() == path) return it.key();
+    }
+    return QString();
+}
+
+QString Fb2WebView::fileData(const QString &name)
+{
+    QTemporaryFile * temp = file(name);
+    return temp->readAll().toBase64();
+}
+
 void Fb2WebView::html(QString name, QString html)
 {
     setHtml(html, QUrl::fromLocalFile(name));

+ 5 - 3
source/fb2view.h

@@ -2,7 +2,7 @@
 #define FB2VIEW_H
 
 #include <QByteArray>
-#include <QMap>
+#include <QHash>
 #include <QResizeEvent>
 #include <QTemporaryFile>
 #include <QTimer>
@@ -65,6 +65,8 @@ public:
     void load(const QString &filename);
     bool save(const QString &filename);
     bool save(QIODevice &device);
+    QString fileName(const QString &path);
+    QString fileData(const QString &name);
     QString toBodyXml();
     QString toXml();
 
@@ -97,8 +99,8 @@ private:
     QWebElement doc();
 
 private:
-    typedef QMap<QString, QTemporaryFile*> TemporaryMap;
-    TemporaryMap m_files;
+    typedef QHash<QString, QTemporaryFile*> TemporaryHash;
+    TemporaryHash m_files;
     QThread *m_thread;
 };
 

+ 20 - 11
source/fb2xml2.cpp

@@ -37,7 +37,8 @@ private:
     static void ignorableWhitespace(void* c, const xmlChar* ch, int len);
     static void internalSubset(void* c, const xmlChar* name, const xmlChar* publicId, const xmlChar* systemId);
 
-    static QString str(const xmlChar* text, int size = -1);
+    static QString C2S(const xmlChar* text, int size = -1);
+    static QString local(const QString &name);
 
     void parse(const QXmlInputSource* input);
 
@@ -63,7 +64,7 @@ HtmlReaderPrivate::HtmlReaderPrivate(HtmlReader* reader)
     this->locator.reset(new HtmlReaderLocator(reader));
 }
 
-QString HtmlReaderPrivate::str(const xmlChar* text, int size)
+QString HtmlReaderPrivate::C2S(const xmlChar* text, int size)
 {
     return QString::fromLocal8Bit(reinterpret_cast<const char*>(text), size);
 }
@@ -108,6 +109,11 @@ void HtmlReaderPrivate::endDocument(void* c)
     }
 }
 
+QString HtmlReaderPrivate::local(const QString &name)
+{
+    return name.mid(name.lastIndexOf(":"));
+}
+
 void HtmlReaderPrivate::startElement(void* c, const xmlChar* name, const xmlChar** attrs)
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
@@ -116,11 +122,13 @@ void HtmlReaderPrivate::startElement(void* c, const xmlChar* name, const xmlChar
         if (attrs) {
             int i = 0;
             while (attrs[i]) {
-                a.append(str(attrs[i]), "", "", str(attrs[i+1]));
+                QString qName = C2S(attrs[i]);
+                a.append(qName, "", local(qName), C2S(attrs[i+1]));
                 i += 2;
             }
         }
-        r->contenthandler->startElement("", "", str(name), a);
+        QString qName = C2S(name);
+        r->contenthandler->startElement("", local(qName), qName, a);
     }
 }
 
@@ -128,7 +136,8 @@ void HtmlReaderPrivate::endElement(void* c, const xmlChar* name)
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->contenthandler) {
-        r->contenthandler->endElement("", "", str(name));
+        QString qName = C2S(name);
+        r->contenthandler->endElement("", local(qName), qName);
     }
 }
 
@@ -136,7 +145,7 @@ void HtmlReaderPrivate::comment(void* c, const xmlChar* value)
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->lexicalhandler) {
-        r->lexicalhandler->comment(str(value));
+        r->lexicalhandler->comment(C2S(value));
     }
 }
 
@@ -146,7 +155,7 @@ void HtmlReaderPrivate::cdataBlock(void* c, const xmlChar* value, int len)
     if (r->lexicalhandler) {
         r->lexicalhandler->startCDATA();
         if (r->contenthandler) {
-            r->contenthandler->characters(str(value, len));
+            r->contenthandler->characters(C2S(value, len));
         }
         r->lexicalhandler->endCDATA();
     }
@@ -156,7 +165,7 @@ void HtmlReaderPrivate::processingInstruction(void* c, const xmlChar* target, co
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->contenthandler) {
-        r->contenthandler->processingInstruction(str(target), str(data));
+        r->contenthandler->processingInstruction(C2S(target), C2S(data));
     }
 }
 
@@ -164,7 +173,7 @@ void HtmlReaderPrivate::characters(void* c, const xmlChar* ch, int len)
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->contenthandler) {
-        r->contenthandler->characters(str(ch, len));
+        r->contenthandler->characters(C2S(ch, len));
     }
 }
 
@@ -172,7 +181,7 @@ void HtmlReaderPrivate::ignorableWhitespace(void* c, const xmlChar* ch, int len)
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->contenthandler) {
-        r->contenthandler->ignorableWhitespace(str(ch, len));
+        r->contenthandler->ignorableWhitespace(C2S(ch, len));
     }
 }
 
@@ -180,7 +189,7 @@ void HtmlReaderPrivate::internalSubset(void* c, const xmlChar* name, const xmlCh
 {
     HtmlReaderPrivate* r = reinterpret_cast<HtmlReaderPrivate*>(c);
     if (r->lexicalhandler) {
-        r->lexicalhandler->startDTD(str(name), str(publicId), str(systemId));
+        r->lexicalhandler->startDTD(C2S(name), C2S(publicId), C2S(systemId));
         r->lexicalhandler->endDTD();
     }
 

+ 0 - 1
source/fb2xml2.h

@@ -54,7 +54,6 @@ public:
     virtual bool parse(const QXmlInputSource& input);
     virtual bool parse(const QXmlInputSource* input);
 
-
 private:
     Q_DISABLE_COPY(HtmlReader)
     Q_DECLARE_PRIVATE(HtmlReader)