diff --git a/src/rss/htmlbrowser.cpp b/src/rss/htmlbrowser.cpp new file mode 100644 index 000000000..8ed92fa67 --- /dev/null +++ b/src/rss/htmlbrowser.cpp @@ -0,0 +1,92 @@ +#include "htmlbrowser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fs_utils.h" + +HtmlBrowser::HtmlBrowser(QWidget* parent) + : QTextBrowser(parent) +{ + m_netManager = new QNetworkAccessManager(this); + m_diskCache = new QNetworkDiskCache(this); + m_diskCache->setCacheDirectory(QDir::cleanPath(fsutils::cacheLocation() + "/browser")); + m_diskCache->setMaximumCacheSize(50 * 1024 * 1024); + qDebug() << "HtmlBrowser cache path:" << m_diskCache->cacheDirectory() << " max size:" << m_diskCache->maximumCacheSize() / 1024 / 1024 << "MB"; + m_netManager->setCache(m_diskCache); + + connect(m_netManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(resourceLoaded(QNetworkReply*))); +} + +HtmlBrowser::~HtmlBrowser() +{ +} + +QVariant HtmlBrowser::loadResource(int type, const QUrl &name) +{ + if(type == QTextDocument::ImageResource) { + QUrl url(name); + if(url.scheme().isEmpty()) + url.setScheme("http"); + + QIODevice *dev = m_diskCache->data(url); + if(dev != 0) { + qDebug() << "HtmlBrowser::loadResource() cache " << url.toString(); + QByteArray res = dev->readAll(); + delete dev; + return res; + } + + if(!m_activeRequests.contains(url)) { + m_activeRequests.insert(url, true); + qDebug() << "HtmlBrowser::loadResource() get " << url.toString(); + QNetworkRequest req(url); + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + m_netManager->get(req); + } + + return QVariant(); + } + + return QTextBrowser::loadResource(type, name); +} + +void HtmlBrowser::resourceLoaded(QNetworkReply *reply) +{ + m_activeRequests.remove(reply->request().url()); + + if(reply->error() == QNetworkReply::NoError && reply->size() > 0) { + qDebug() << "HtmlBrowser::resourceLoaded() save " << reply->request().url().toString(); + } else { + // If resource failed to load, replace it with warning icon and store it in cache for 1 day. + // Otherwise HTMLBrowser will keep trying to download it every time article is displayed, + // since it's not possible to cache error responses. + QNetworkCacheMetaData metaData; + QNetworkCacheMetaData::AttributesMap atts; + metaData.setUrl(reply->request().url()); + metaData.setSaveToDisk(true); + atts[QNetworkRequest::HttpStatusCodeAttribute] = 200; + atts[QNetworkRequest::HttpReasonPhraseAttribute] = "Ok"; + metaData.setAttributes(atts); + metaData.setLastModified(QDateTime::currentDateTime()); + metaData.setExpirationDate(QDateTime::currentDateTime().addDays(1)); + QIODevice *dev = m_diskCache->prepare(metaData); + if(!dev) + return; + QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(32, 32).save(dev, "PNG"); + m_diskCache->insert(dev); + } + // Refresh the document display and keep scrollbars where they are + int sx = horizontalScrollBar()->value(); + int sy = verticalScrollBar()->value(); + document()->setHtml(document()->toHtml()); + horizontalScrollBar()->setValue(sx); + verticalScrollBar()->setValue(sy); +} diff --git a/src/rss/htmlbrowser.h b/src/rss/htmlbrowser.h new file mode 100644 index 000000000..7a8ffcea9 --- /dev/null +++ b/src/rss/htmlbrowser.h @@ -0,0 +1,30 @@ +#ifndef HTMLBROWSER_H +#define HTMLBROWSER_H + +#include +#include + +class QNetworkAccessManager; +class QNetworkDiskCache; +class QNetworkReply; + +class HtmlBrowser : public QTextBrowser +{ + Q_OBJECT + +public: + explicit HtmlBrowser(QWidget* parent = 0); + ~HtmlBrowser(); + + virtual QVariant loadResource(int type, const QUrl &name); + +protected: + QNetworkAccessManager *m_netManager; + QNetworkDiskCache *m_diskCache; + QHash m_activeRequests; + +protected slots: + void resourceLoaded(QNetworkReply *reply); +}; + +#endif // HTMLBROWSER_H diff --git a/src/rss/rss.pri b/src/rss/rss.pri index d820d17cd..e4d91389b 100644 --- a/src/rss/rss.pri +++ b/src/rss/rss.pri @@ -12,7 +12,8 @@ HEADERS += $$PWD/rss_imp.h \ $$PWD/rssdownloadrule.h \ $$PWD/rssdownloadrulelist.h \ $$PWD/cookiesdlg.h \ - $$PWD/rssparser.h + $$PWD/rssparser.h \ + $$PWD/htmlbrowser.h SOURCES += $$PWD/rss_imp.cpp \ $$PWD/rsssettingsdlg.cpp \ @@ -26,7 +27,8 @@ SOURCES += $$PWD/rss_imp.cpp \ $$PWD/rssdownloadrulelist.cpp \ $$PWD/cookiesdlg.cpp \ $$PWD/rssfile.cpp \ - $$PWD/rssparser.cpp + $$PWD/rssparser.cpp \ + $$PWD/htmlbrowser.cpp FORMS += $$PWD/rss.ui \ $$PWD/rsssettingsdlg.ui \ diff --git a/src/rss/rss.ui b/src/rss/rss.ui index 63bcd9c93..7d0d348bb 100644 --- a/src/rss/rss.ui +++ b/src/rss/rss.ui @@ -145,7 +145,11 @@ p, li { white-space: pre-wrap; } QAbstractItemView::SelectItems - + + + true + + @@ -224,6 +228,13 @@ p, li { white-space: pre-wrap; } + + + HtmlBrowser + QTextBrowser +
htmlbrowser.h
+
+