File indexing completed on 2024-04-14 03:48:02

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Abhinav Gangwar <abhgang@gmail.com>
0004 //
0005 
0006 #include "RemoteIconLoader.h"
0007 
0008 // Qt
0009 #include <QDebug>
0010 #include <QString>
0011 #include <QHash>
0012 #include <QUrl>
0013 #include <QImage>
0014 #include <QByteArray>
0015 #include <QFileInfo>
0016 #include <QCryptographicHash>
0017 
0018 // Marble
0019 #include "HttpDownloadManager.h"
0020 #include "FileStoragePolicy.h"
0021 #include "MarbleDirs.h"
0022 #include "MarbleGlobal.h"
0023 #include "MarbleDebug.h"
0024 
0025 namespace Marble
0026 {
0027 
0028 class RemoteIconLoaderPrivate
0029 {
0030     public:
0031         RemoteIconLoaderPrivate()
0032             : m_storagePolicy(MarbleDirs::localPath() + QLatin1String("/cache/icons/")),
0033               m_downloadManager( &m_storagePolicy )
0034         { 
0035         }
0036         QHash<QUrl, QImage> m_iconCache;
0037         FileStoragePolicy m_storagePolicy;
0038         HttpDownloadManager m_downloadManager;
0039 
0040         /**
0041          * Returns true if the icon for Url(=url) is available in cache
0042          */
0043         bool isCached( const QUrl& url ) const;
0044 
0045         /**
0046          * Returns icon for the url passes in argument
0047          */
0048         QImage cachedIcon( const QUrl& url ) const;
0049 
0050         /**
0051          * Returns true if icon is locally present on disk
0052          */
0053         bool loadFromDiskCache( const QUrl& url );
0054 
0055         /**
0056          * Starts downloading icon if it isn't present cache and 
0057          * could not be found locally on disk
0058          */
0059         void initiateDownload( const QUrl& url );
0060 
0061         /**
0062          * Returns a name with which downloaded icon will be saved on disk
0063          */
0064         static QString cacheFileName(const QUrl &url);
0065 };
0066 
0067 bool RemoteIconLoaderPrivate::isCached( const QUrl& url ) const
0068 {
0069     return m_iconCache.contains( url );
0070 }
0071 
0072 QImage RemoteIconLoaderPrivate::cachedIcon( const QUrl& url ) const
0073 {
0074     return m_iconCache.value( url );
0075 }
0076 
0077 bool RemoteIconLoaderPrivate::loadFromDiskCache( const QUrl& url )
0078 {
0079     QString path = MarbleDirs::localPath() + QLatin1String("/cache/icons/") + cacheFileName(url);
0080     QImage icon = QFile::exists( path ) ? QImage( path ) : QImage();
0081     if ( !icon.isNull() ) {
0082         m_iconCache.insert( url, icon );
0083         return true;
0084     }
0085     return false;
0086 }
0087 
0088 void RemoteIconLoaderPrivate::initiateDownload( const QUrl& url )
0089 {
0090     DownloadUsage usage = DownloadBrowse;
0091     m_downloadManager.setDownloadEnabled(true);
0092     QString fileName = cacheFileName( url );
0093     m_downloadManager.addJob(url, fileName, url.toString(), usage );
0094 }
0095 
0096 QString RemoteIconLoaderPrivate::cacheFileName(const QUrl &url)
0097 {
0098     const QString suffix = QFileInfo(url.path()).suffix();
0099     const QByteArray hash = QCryptographicHash::hash( url.toEncoded(), QCryptographicHash::Md5 ).toHex();
0100     const QString fileName = QString::fromLatin1(hash) + QLatin1Char('.') + suffix;
0101     return fileName;
0102 }
0103 
0104 RemoteIconLoader::RemoteIconLoader( QObject *parent )
0105     : QObject( parent ),
0106       d ( new RemoteIconLoaderPrivate() )
0107 {
0108     connect( &d->m_downloadManager, SIGNAL(downloadComplete(QByteArray,QString)), this,
0109             SLOT(storeIcon(QByteArray,QString)) );
0110 }
0111 
0112 RemoteIconLoader::~RemoteIconLoader()
0113 {
0114     delete d;
0115 }
0116 
0117 
0118 QImage RemoteIconLoader::load( const QUrl& url )
0119 {
0120     /*
0121      * If image has been downloaded previously then
0122      * return it from m_iconCache. All the downloaded
0123      * images in current running marble session are stored
0124      * in m_iconCache.
0125      */
0126     if ( d->isCached( url ) ) {
0127         return d->cachedIcon( url );
0128     }
0129 
0130     /*
0131      * All the downloaded images are saved on disk
0132      * at location cache/icons/ ( relative location ).
0133      * If the rquested icon is present at this location then
0134      * return it.
0135      */
0136     else if ( d->loadFromDiskCache( url ) ) {
0137         return d->cachedIcon( url );
0138     }
0139 
0140     // Otherwise initiate download
0141     else {
0142         d->initiateDownload( url );
0143     }
0144     return QImage();
0145 }
0146 
0147 
0148 void RemoteIconLoader::storeIcon( const QByteArray &data, const QString &fileName)
0149 {
0150     QImage icon = QImage::fromData( data );
0151     d->m_iconCache.insert( QUrl(fileName), icon );
0152     emit iconReady();
0153 }
0154 
0155 }
0156 
0157 #include "moc_RemoteIconLoader.cpp"