From 07abe301396f9b0fbfca67d4b4f6df6b9fdf6e82 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Tue, 2 Apr 2013 13:25:14 +0200 Subject: use a qnetworkdiskcache for images instead of custom provider --- board.cpp | 17 ++----- global.h | 2 - imagecache.cpp | 16 ++++++ imagecache.h | 13 +++++ imagenetworkaccessmanager.cpp | 23 +++++++++ imagenetworkaccessmanager.h | 23 +++++++++ imageprovider.cpp | 110 ------------------------------------------ imageprovider.h | 25 ---------- main.cpp | 9 ++-- tapasboard.pro | 6 ++- 10 files changed, 87 insertions(+), 157 deletions(-) create mode 100644 imagecache.cpp create mode 100644 imagecache.h create mode 100644 imagenetworkaccessmanager.cpp create mode 100644 imagenetworkaccessmanager.h delete mode 100644 imageprovider.cpp delete mode 100644 imageprovider.h diff --git a/board.cpp b/board.cpp index 1be4076..fc9e0ad 100644 --- a/board.cpp +++ b/board.cpp @@ -118,19 +118,6 @@ QString Board::bbcodeToRichText(QString text) const text.replace(pair.first, pair.second); } - // Unfortunately, we have to process images separately - static QRegExp img_bbcode("\\[img\\]([^[]*)\\[/img\\]", Qt::CaseInsensitive); - int pos = 0; - while ((pos = img_bbcode.indexIn(text, pos)) != -1) { - QString imageUrl = img_bbcode.cap(1); - QString providerUrl = image_provider->getProviderImageUrl(imageUrl); - qDebug() << "Image" << imageUrl << "->" << providerUrl; - text.replace(pos, img_bbcode.matchedLength(), ""); - } - - // HTML newlines - text.replace("\n", "
"); - return text; } @@ -323,7 +310,11 @@ void Board::initializeBbCode() _bbcodes << qMakePair(QRegExp("\\[url=([^]]*)\\]", Qt::CaseInsensitive), QString("")); _bbcodes << qMakePair(QRegExp("\\[/url\\]", Qt::CaseInsensitive), QString("")); + _bbcodes << qMakePair(QRegExp("\\[img\\]([^[]*)\\[/img\\]", Qt::CaseInsensitive), QString("")); + _bbcodes << qMakePair(QRegExp("\\[hr\\]", Qt::CaseInsensitive), QString("
")); + + _bbcodes << qMakePair(QRegExp("\n"), QString("
")); } void Board::fetchConfigIfOutdated() diff --git a/global.h b/global.h index 9eefb17..4ecc890 100644 --- a/global.h +++ b/global.h @@ -2,7 +2,6 @@ #define GLOBAL_H #include "boardmanager.h" -#include "imageprovider.h" /** Time the forum config settings should be considered up to date, in days. */ #define BOARD_CONFIG_TTL 2 @@ -30,6 +29,5 @@ // Some singletons extern BoardManager *board_manager; -extern ImageProvider *image_provider; #endif // GLOBAL_H diff --git a/imagecache.cpp b/imagecache.cpp new file mode 100644 index 0000000..e59ffdf --- /dev/null +++ b/imagecache.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include "global.h" +#include "imagecache.h" + +ImageCache::ImageCache(QObject *parent) : + QNetworkDiskCache(parent) +{ + QString cache_path = board_manager->getCachePath() + "/images"; + QDir dir; + if (!dir.mkpath(cache_path)) { + qWarning() << "Could not create image cache path" << cache_path; + } + setCacheDirectory(cache_path); +} diff --git a/imagecache.h b/imagecache.h new file mode 100644 index 0000000..2553c80 --- /dev/null +++ b/imagecache.h @@ -0,0 +1,13 @@ +#ifndef IMAGECACHE_H +#define IMAGECACHE_H + +#include + +class ImageCache : public QNetworkDiskCache +{ + Q_OBJECT +public: + explicit ImageCache(QObject *parent = 0); +}; + +#endif // IMAGECACHE_H diff --git a/imagenetworkaccessmanager.cpp b/imagenetworkaccessmanager.cpp new file mode 100644 index 0000000..ab4509b --- /dev/null +++ b/imagenetworkaccessmanager.cpp @@ -0,0 +1,23 @@ +#include + +#include "imagecache.h" +#include "imagenetworkaccessmanager.h" + +ImageNetworkAccessManager::ImageNetworkAccessManager(QObject *parent) : + QNetworkAccessManager(parent) +{ + setCache(new ImageCache); +} + +QNetworkReply * ImageNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) +{ + QNetworkRequest new_request(request); + new_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, + QNetworkRequest::PreferCache); + return QNetworkAccessManager::createRequest(op, new_request, outgoingData); +} + +QNetworkAccessManager * ImageNetworkAccessManagerFactory::create(QObject *parent) +{ + return new ImageNetworkAccessManager(parent); +} diff --git a/imagenetworkaccessmanager.h b/imagenetworkaccessmanager.h new file mode 100644 index 0000000..9dfb586 --- /dev/null +++ b/imagenetworkaccessmanager.h @@ -0,0 +1,23 @@ +#ifndef IMAGENETWORKACCESSMANAGER_H +#define IMAGENETWORKACCESSMANAGER_H + +#include +#include + +class ImageNetworkAccessManager : public QNetworkAccessManager +{ + Q_OBJECT +public: + explicit ImageNetworkAccessManager(QObject *parent = 0); + +protected: + QNetworkReply * createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData); +}; + +class ImageNetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory +{ +public: + QNetworkAccessManager * create(QObject *parent); +}; + +#endif // IMAGENETWORKACCESSMANAGER_H diff --git a/imageprovider.cpp b/imageprovider.cpp deleted file mode 100644 index 6fb2807..0000000 --- a/imageprovider.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "global.h" -#include "imageprovider.h" - -// Warning: QML might call requestImage() from another thread. Be careful. - -ImageProvider::ImageProvider() : - QDeclarativeImageProvider(Image), - _cachePath(board_manager->getCachePath() + "/images"), - _manager(new QNetworkAccessManager) -{ - QDir dir; - if (!dir.mkpath(_cachePath)) { - qWarning() << "Could not create image cache path"; - } -} - -ImageProvider::~ImageProvider() -{ - delete _manager; -} - -QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) -{ - QString remoteUrl = QUrl::fromPercentEncoding(id.toUtf8()); - QString localPath = getCachedImagePath(remoteUrl); - - qDebug() << "Loading image for " << remoteUrl; - - if (!QFile::exists(localPath)) { - if (!fetchImage(remoteUrl)) { - qWarning() << "Failed to fetch remote image" << remoteUrl; - } - } else { - qDebug() << "Local file exists" << localPath; - } - - QImage image(localPath); - QImage result; - - if (image.isNull()) { - qWarning() << "Failed to load local image" << localPath; - } - - if (requestedSize.isValid()) { - result = image.scaled(requestedSize, Qt::KeepAspectRatio); - } else { - result = image; - } - if (size) { - *size = result.size(); - } - - return result; -} - -QString ImageProvider::getProviderImageUrl(const QString &remoteUrl) -{ - return "image://tapasboard/" + QString::fromUtf8(QUrl::toPercentEncoding(remoteUrl)); -} - -QString ImageProvider::getCachedImagePath(const QString &remoteUrl) -{ - static const QRegExp regexp("[^a-z0-9]+"); - QString url = remoteUrl.toLower(); - - // Grab the extension before applying the regexp - QString extension; - int dot_pos = url.lastIndexOf('.'); - - if (dot_pos != -1) { - extension = url.mid(dot_pos); - } - - url.replace(regexp, "_"); - - return _cachePath + "/" + url + extension; -} - -bool ImageProvider::fetchImage(const QString &remoteUrl) -{ - QString localPath = getCachedImagePath(remoteUrl); - - QNetworkRequest request(remoteUrl); - QNetworkReply *reply = _manager->get(request); - qDebug() << "Start download of" << remoteUrl; - - QEventLoop loop; - loop.connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - - loop.exec(); - - qDebug() << "End download of" << remoteUrl; - QFile localFile(localPath); - if (localFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - localFile.write(reply->readAll()); - localFile.close(); - } - - reply->deleteLater(); - - return true; -} diff --git a/imageprovider.h b/imageprovider.h deleted file mode 100644 index 43c8b28..0000000 --- a/imageprovider.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef IMAGEPROVIDER_H -#define IMAGEPROVIDER_H - -#include -#include - -class ImageProvider : public QDeclarativeImageProvider -{ -public: - ImageProvider(); - ~ImageProvider(); - - QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize = QSize()); - - QString getProviderImageUrl(const QString &remoteUrl); - QString getCachedImagePath(const QString &remoteUrl); - - bool fetchImage(const QString &remoteUrl); - -private: - QString _cachePath; - QNetworkAccessManager *_manager; -}; - -#endif // IMAGEPROVIDER_H diff --git a/main.cpp b/main.cpp index 3c8f813..52086e4 100644 --- a/main.cpp +++ b/main.cpp @@ -1,17 +1,17 @@ #include +#include #include #include "qmlapplicationviewer.h" #include "global.h" #include "board.h" -#include "imageprovider.h" +#include "imagenetworkaccessmanager.h" #include "favoritesmodel.h" #include "boardmodel.h" #include "forummodel.h" #include "topicmodel.h" BoardManager *board_manager; -ImageProvider *image_provider; Q_DECL_EXPORT int main(int argc, char *argv[]) { @@ -23,8 +23,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) QScopedPointer manager(new BoardManager); board_manager = manager.data(); // Set the global pointer to this singleton - QScopedPointer provider(new ImageProvider); - image_provider = provider.data(); + QScopedPointer image_nam_factory(new ImageNetworkAccessManagerFactory); qmlRegisterType("com.javispedro.tapasboard", 1, 0, "FavoritesModel"); qmlRegisterType("com.javispedro.tapasboard", 1, 0, "BoardModel"); @@ -32,7 +31,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) qmlRegisterType("com.javispedro.tapasboard", 1, 0, "TopicModel"); QmlApplicationViewer viewer; - viewer.engine()->addImageProvider("tapasboard", image_provider); + viewer.engine()->setNetworkAccessManagerFactory(image_nam_factory.data()); viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/tapasboard/main.qml")); viewer.showExpanded(); diff --git a/tapasboard.pro b/tapasboard.pro index a13dfc7..a1173d5 100644 --- a/tapasboard.pro +++ b/tapasboard.pro @@ -46,7 +46,8 @@ SOURCES += main.cpp \ topicmodel.cpp \ fetchpostsaction.cpp \ favoritesmodel.cpp \ - imageprovider.cpp + imagecache.cpp \ + imagenetworkaccessmanager.cpp # Please do not modify the following two lines. Required for deployment. include(qmlapplicationviewer/qmlapplicationviewer.pri) @@ -77,4 +78,5 @@ HEADERS += \ topicmodel.h \ fetchpostsaction.h \ favoritesmodel.h \ - imageprovider.h + imagecache.h \ + imagenetworkaccessmanager.h -- cgit v1.2.3