Selaa lähdekoodia

Show images in QWebView by using temp files

Kandrashin Denis 13 vuotta sitten
vanhempi
commit
dd6ceda928
5 muutettua tiedostoa jossa 103 lisäystä ja 186 poistoa
  1. 0 1
      source/fb2edit.pro
  2. 56 23
      source/fb2read.cpp
  3. 30 20
      source/fb2read.h
  4. 11 100
      source/fb2view.cpp
  5. 6 42
      source/fb2view.h

+ 0 - 1
source/fb2edit.pro

@@ -21,6 +21,5 @@ VERSION = 0.01.1
 
 QT += xml
 QT += webkit
-QT += network
 
 LIBS += -lqscintilla2

+ 56 - 23
source/fb2read.cpp

@@ -29,12 +29,12 @@ void Fb2ReadThread::stop()
 
 void Fb2ReadThread::run()
 {
-    if (parse()) emit html(m_html);
+    if (parse()) emit html(m_filename, m_html);
 }
 
-void Fb2ReadThread::onImage(const QString &name, const QByteArray &data)
+void Fb2ReadThread::onFile(const QString &name, const QString &path)
 {
-    emit image(name, data);
+    emit file(name, path);
 }
 
 bool Fb2ReadThread::parse()
@@ -44,7 +44,7 @@ bool Fb2ReadThread::parse()
         qCritical() << QObject::tr("Cannot read file %1:\n%2.").arg(m_filename).arg(file.errorString());
         return false;
     }
-    Fb2Handler handler(*this, m_html);
+    Fb2Handler handler(*this);
     QXmlSimpleReader reader;
     reader.setContentHandler(&handler);
     reader.setErrorHandler(&handler);
@@ -52,6 +52,40 @@ bool Fb2ReadThread::parse()
     return reader.parse(source);
 }
 
+//---------------------------------------------------------------------------
+//  Fb2HtmlWriter
+//---------------------------------------------------------------------------
+
+Fb2HtmlWriter::Fb2HtmlWriter(Fb2ReadThread &thread)
+    : QXmlStreamWriter(thread.data())
+    , m_thread(thread)
+{
+}
+
+QString Fb2HtmlWriter::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 Fb2HtmlWriter::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();
+    }
+}
+
 //---------------------------------------------------------------------------
 //  Fb2Handler::BaseHandler
 //---------------------------------------------------------------------------
@@ -127,9 +161,8 @@ FB2_BEGIN_KEYHASH(RootHandler)
     insert("binary", Binary);
 FB2_END_KEYHASH
 
-Fb2Handler::RootHandler::RootHandler(Fb2ReadThread &thread, QXmlStreamWriter &writer, const QString &name)
+Fb2Handler::RootHandler::RootHandler(Fb2HtmlWriter &writer, const QString &name)
     : BaseHandler(name)
-    , m_thread(thread)
     , m_writer(writer)
 {
     m_writer.writeStartElement("html");
@@ -147,7 +180,7 @@ Fb2Handler::BaseHandler * Fb2Handler::RootHandler::NewTag(const QString &name, c
     switch (toKeyword(name)) {
         case Body   : return new BodyHandler(m_writer, name, attributes, "div", name);
         case Descr  : return new DescrHandler(m_writer, name);
-        case Binary : return new BinaryHandler(m_thread, name, attributes);
+        case Binary : return new BinaryHandler(m_writer, name, attributes);
         default: return NULL;
     }
 }
@@ -228,7 +261,7 @@ FB2_BEGIN_KEYHASH(BodyHandler)
     FB2_KEY( Code,     "code"          );
 FB2_END_KEYHASH
 
-Fb2Handler::BodyHandler::BodyHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
+Fb2Handler::BodyHandler::BodyHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style)
     : BaseHandler(name)
     , m_writer(writer)
 {
@@ -269,7 +302,7 @@ void Fb2Handler::BodyHandler::TxtTag(const QString &text)
 //  Fb2Handler::AnchorHandler
 //---------------------------------------------------------------------------
 
-Fb2Handler::AnchorHandler::AnchorHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes)
+Fb2Handler::AnchorHandler::AnchorHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes)
     : BodyHandler(writer, name, attributes, "a")
 {
     QString href = Value(attributes, "href");
@@ -280,45 +313,45 @@ Fb2Handler::AnchorHandler::AnchorHandler(QXmlStreamWriter &writer, const QString
 //  Fb2Handler::ImageHandler
 //---------------------------------------------------------------------------
 
-Fb2Handler::ImageHandler::ImageHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes)
+Fb2Handler::ImageHandler::ImageHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes)
     : BodyHandler(writer, name, attributes, "img")
 {
     QString href = Value(attributes, "href");
     while (href.left(1) == "#") href.remove(0, 1);
-    writer.writeAttribute("src", href);
+    QString path = writer.getFile(href);
+    writer.writeAttribute("src", path);
+    writer.writeAttribute("alt", href);
 }
 
 //---------------------------------------------------------------------------
 //  Fb2Handler::BinaryHandler
 //---------------------------------------------------------------------------
 
-Fb2Handler::BinaryHandler::BinaryHandler(Fb2ReadThread &thread, const QString &name, const QXmlAttributes &attributes)
+Fb2Handler::BinaryHandler::BinaryHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes)
     : BaseHandler(name)
-    , m_thread(thread)
+    , m_writer(writer)
     , m_file(Value(attributes, "id"))
 {
 }
 
-void Fb2Handler::BinaryHandler::TxtTag(const QString &text)
+Fb2Handler::BinaryHandler::~BinaryHandler()
 {
-    m_text += text;
+    QByteArray in; in.append(m_text);
+    if (!m_file.isEmpty()) m_writer.addFile(m_file, QByteArray::fromBase64(in));
 }
 
-void Fb2Handler::BinaryHandler::EndTag(const QString &name)
+void Fb2Handler::BinaryHandler::TxtTag(const QString &text)
 {
-    Q_UNUSED(name);
-    QByteArray in; in.append(m_text);
-    if (!m_file.isEmpty()) m_thread.onImage(m_file, QByteArray::fromBase64(in));
+    m_text += text;
 }
 
 //---------------------------------------------------------------------------
 //  Fb2Handler
 //---------------------------------------------------------------------------
 
-Fb2Handler::Fb2Handler(Fb2ReadThread &thread, QString &string)
+Fb2Handler::Fb2Handler(Fb2ReadThread &thread)
     : QXmlDefaultHandler()
-    , m_writer(&string)
-    , m_thread(thread)
+    , m_writer(thread)
     , m_handler(NULL)
 {
     m_writer.setAutoFormatting(true);
@@ -340,7 +373,7 @@ bool Fb2Handler::startElement(const QString & namespaceURI, const QString & loca
     qCritical() << name;
 
     if (name == "fictionbook") {
-        m_handler = new RootHandler(m_thread, m_writer, name);
+        m_handler = new RootHandler(m_writer, name);
         return true;
     } else {
         m_error = QObject::tr("The file is not an FB2 file.");

+ 30 - 20
source/fb2read.h

@@ -19,11 +19,12 @@ class Fb2ReadThread : public QThread
 public:
     Fb2ReadThread(QObject *parent, const QString &filename);
     ~Fb2ReadThread();
-    void onImage(const QString &name, const QByteArray &data);
+    void onFile(const QString &name, const QString &path);
+    QString * data() { return &m_html; }
 
 signals:
-    void image(QString name, QByteArray data);
-    void html(QString html);
+    void file(QString name, QString path);
+    void html(QString name, QString html);
 
 public slots:
     void stop();
@@ -41,6 +42,17 @@ private:
     QMutex mutex;
 };
 
+class Fb2HtmlWriter : public QXmlStreamWriter
+{
+public:
+    explicit Fb2HtmlWriter(Fb2ReadThread &thread);
+    QString addFile(const QString &name, const QByteArray &data);
+    QString getFile(const QString &name);
+private:
+    typedef QHash<QString, QString> StringHash;
+    Fb2ReadThread &m_thread;
+    StringHash m_hash;
+};
 
 #define FB2_BEGIN_KEYLIST private: enum Keyword {
 
@@ -51,7 +63,7 @@ static Keyword toKeyword(const QString &name); private:
 class Fb2Handler : public QXmlDefaultHandler
 {
 public:
-    explicit Fb2Handler(Fb2ReadThread &thread, QString &string);
+    explicit Fb2Handler(Fb2ReadThread &thread);
     virtual ~Fb2Handler();
     bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes);
     bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
@@ -90,13 +102,12 @@ private:
             Binary,
         FB2_END_KEYLIST
     public:
-        explicit RootHandler(Fb2ReadThread &thread, QXmlStreamWriter &writer, const QString &name);
+        explicit RootHandler(Fb2HtmlWriter &writer, const QString &name);
         virtual ~RootHandler();
     protected:
         virtual BaseHandler * NewTag(const QString & name, const QXmlAttributes &attributes);
     private:
-        Fb2ReadThread &m_thread;
-        QXmlStreamWriter &m_writer;
+        Fb2HtmlWriter &m_writer;
     };
 
     class DescrHandler : public BaseHandler
@@ -106,11 +117,11 @@ private:
             Publish,
         FB2_END_KEYLIST
     public:
-        explicit DescrHandler(QXmlStreamWriter &writer, const QString &name) : BaseHandler(name), m_writer(writer) {}
+        explicit DescrHandler(Fb2HtmlWriter &writer, const QString &name) : BaseHandler(name), m_writer(writer) {}
     protected:
         virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     protected:
-        QXmlStreamWriter &m_writer;
+        Fb2HtmlWriter &m_writer;
     };
 
     class HeaderHandler : public BaseHandler
@@ -125,11 +136,11 @@ private:
             Cover,
         FB2_END_KEYLIST
     public:
-        explicit HeaderHandler(QXmlStreamWriter &writer, const QString &name) : BaseHandler(name), m_writer(writer) {}
+        explicit HeaderHandler(Fb2HtmlWriter &writer, const QString &name) : BaseHandler(name), m_writer(writer) {}
     protected:
         virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     protected:
-        QXmlStreamWriter &m_writer;
+        Fb2HtmlWriter &m_writer;
     };
 
     class BodyHandler : public BaseHandler
@@ -149,43 +160,42 @@ private:
             Code,
        FB2_END_KEYLIST
     public:
-        explicit BodyHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
+        explicit BodyHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
         virtual ~BodyHandler();
         virtual void TxtTag(const QString &text);
     protected:
         virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     protected:
-        QXmlStreamWriter &m_writer;
+        Fb2HtmlWriter &m_writer;
     };
 
     class AnchorHandler : public BodyHandler
     {
     public:
-        explicit AnchorHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes);
+        explicit AnchorHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes);
     };
 
     class ImageHandler : public BodyHandler
     {
     public:
-        explicit ImageHandler(QXmlStreamWriter &writer, const QString &name, const QXmlAttributes &attributes);
+        explicit ImageHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes);
     };
 
     class BinaryHandler : public BaseHandler
     {
     public:
-        explicit BinaryHandler(Fb2ReadThread &thread, const QString &name, const QXmlAttributes &attributes);
+        explicit BinaryHandler(Fb2HtmlWriter &writer, const QString &name, const QXmlAttributes &attributes);
+        virtual ~BinaryHandler();
     protected:
         virtual void TxtTag(const QString &text);
-        virtual void EndTag(const QString &name);
     private:
-        Fb2ReadThread &m_thread;
+        Fb2HtmlWriter &m_writer;
         QString m_file;
         QString m_text;
     };
 
 private:
-    QXmlStreamWriter m_writer;
-    Fb2ReadThread & m_thread;
+    Fb2HtmlWriter m_writer;
     RootHandler * m_handler;
     QString m_error;
 };

+ 11 - 100
source/fb2view.cpp

@@ -2,98 +2,6 @@
 #include "fb2read.h"
 
 #include <QtDebug>
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QWebSecurityOrigin>
-
-//---------------------------------------------------------------------------
-//  Fb2ImageReply
-//---------------------------------------------------------------------------
-
-Fb2ImageReply::Fb2ImageReply(QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QByteArray &data)
-    : QNetworkReply()
-    , content(data)
-    , offset(0)
-{
-/*
-    QString path = "/home/user/tmp" + request.url().path();
-    qCritical() << path;
-    QFile file(path);
-    file.open(QFile::WriteOnly);
-    file.write(content);
-    file.close();
-*/
-    qCritical() << tr("Image: %1 - %2").arg(request.url().toString()).arg(content.size());
-    setRequest(request);
-    setUrl(request.url());
-    setOperation(op);
-    open(ReadOnly | Unbuffered);
-    setHeader(QNetworkRequest::ContentLengthHeader, QVariant(content.size()));
-    QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
-    QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
-}
-
-void Fb2ImageReply::abort()
-{
-    close();
-}
-
-qint64 Fb2ImageReply::bytesAvailable() const
-{
-    return content.size() - offset;
-}
-
-bool Fb2ImageReply::isSequential() const
-{
-    return true;
-}
-
-qint64 Fb2ImageReply::readData(char *data, qint64 maxSize)
-{
-    if (offset < content.size()) {
-        qint64 number = qMin(maxSize, content.size() - offset);
-        memcpy(data, content.constData() + offset, number);
-        offset += number;
-        return number;
-    } else {
-        return -1;
-    }
-}
-
-//---------------------------------------------------------------------------
-//  Fb2NetworkAccessManager
-//
-//    http://doc.trolltech.com/qq/32/qq32-webkit-protocols.html
-//---------------------------------------------------------------------------
-
-Fb2NetworkAccessManager::Fb2NetworkAccessManager(QObject *parent)
-    : QNetworkAccessManager(parent)
-{
-}
-
-QNetworkReply * Fb2NetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
-{
-    if (request.url().scheme() == "fb2") return imageRequest(op, request);
-    return QNetworkAccessManager::createRequest(op, request, outgoingData);
-}
-
-QNetworkReply * Fb2NetworkAccessManager::imageRequest(Operation op, const QNetworkRequest &request)
-{
-    QString file = request.url().path();
-    while (file.left(1) == "/") file.remove(0, 1);
-    ImageMap::const_iterator i = m_images.find(file);
-    if (i == m_images.end()) {
-        qCritical() << "Not found: " << file;
-        return 0;
-    } else {
-        return new Fb2ImageReply(op, request, i.value());
-    }
-}
-
-void Fb2NetworkAccessManager::insert(const QString &file, const QByteArray &data)
-{
-    m_images.insert(file, data);
-}
 
 //---------------------------------------------------------------------------
 //  Fb2WebView
@@ -111,27 +19,30 @@ Fb2WebView::Fb2WebView(QWidget *parent)
     settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
     settings->setAttribute(QWebSettings::PluginsEnabled, false);
     settings->setAttribute(QWebSettings::ZoomTextOnly, true);
-    page()->setNetworkAccessManager(&m_network);
+}
+
+Fb2WebView::~Fb2WebView()
+{
+    foreach (QString value, m_files) QFile::remove(value);
 }
 
 bool Fb2WebView::load(const QString &filename)
 {
     if (m_thread) return false;
     m_thread = new Fb2ReadThread(this, filename);
-    connect(m_thread, SIGNAL(image(QString, QByteArray)), SLOT(image(QString, QByteArray)));
-    connect(m_thread, SIGNAL(html(QString)), SLOT(html(QString)));
+    connect(m_thread, SIGNAL(file(QString, QString)), SLOT(file(QString, QString)));
+    connect(m_thread, SIGNAL(html(QString, QString)), SLOT(html(QString, QString)));
     m_thread->start();
 }
 
-void Fb2WebView::image(QString file, QByteArray data)
+void Fb2WebView::file(QString name, QString path)
 {
-    m_network.insert(file, data);
-    qCritical() << file;
+    m_files.insert(name, path);
 }
 
-void Fb2WebView::html(QString html)
+void Fb2WebView::html(QString name, QString html)
 {
-    setHtml(html, QUrl("fb2://s/"));
+    setHtml(html, QUrl::fromLocalFile(name));
     if (m_thread) m_thread->deleteLater();
     m_thread = 0;
 }

+ 6 - 42
source/fb2view.h

@@ -1,50 +1,12 @@
 #ifndef FB2VIEW_H
 #define FB2VIEW_H
 
-#include <QMap>
-#include <QNetworkAccessManager>
-#include <QNetworkReply>
+#include <QHash>
 #include <QResizeEvent>
 #include <QTimer>
 #include <QThread>
 #include <QWebView>
 
-class Fb2ImageReply : public QNetworkReply
-{
-    Q_OBJECT
-public:
-    explicit Fb2ImageReply(QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QByteArray &data);
-    void abort();
-    qint64 bytesAvailable() const;
-    bool isSequential() const;
-
-protected:
-    qint64 readData(char *data, qint64 maxSize);
-
-private:
-    QByteArray content;
-    qint64 offset;
-};
-
-class Fb2NetworkAccessManager : public QNetworkAccessManager
-{
-    Q_OBJECT
-public:
-    explicit Fb2NetworkAccessManager(QObject *parent = 0);
-    void insert(const QString &file, const QByteArray &data);
-
-protected:
-    virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData = 0);
-
-private:
-    QNetworkReply *imageRequest(Operation op, const QNetworkRequest &request);
-
-private:
-    typedef QMap<QString, QByteArray> ImageMap;
-    ImageMap m_images;
-
-};
-
 class Fb2BaseWebView : public QWebView
 {
     Q_OBJECT
@@ -81,19 +43,21 @@ class Fb2WebView : public Fb2BaseWebView
     Q_OBJECT
 public:
     explicit Fb2WebView(QWidget *parent = 0);
+    virtual ~Fb2WebView();
     bool load(const QString &filename);
     
 signals:
     
 public slots:
-    void image(QString file, QByteArray data);
-    void html(QString html);
+    void file(QString name, QString path);
+    void html(QString name, QString html);
     void zoomIn();
     void zoomOut();
     void zoomOrig();
 
 private:
-    Fb2NetworkAccessManager m_network;
+    typedef QHash<QString, QString> StringHash;
+    StringHash m_files;
     QThread *m_thread;
 };