18#ifndef QGSABSTRACTCONTENTCACHE_H 
   19#define QGSABSTRACTCONTENTCACHE_H 
   31#include <QRecursiveMutex> 
   37#include <QNetworkReply> 
   77    int mFileModifiedCheckTimeout = 30000;
 
   93      return other.
path == path;
 
 
 
  157    static bool parseBase64DataUrl( 
const QString &path, QString *mimeType 
SIP_OUT = 
nullptr, QString *data 
SIP_OUT = 
nullptr );
 
  174    static bool parseEmbeddedStringData( 
const QString &path, QString *mimeType 
SIP_OUT = 
nullptr, QString *data 
SIP_OUT = 
nullptr );
 
  181    static bool isBase64Data( 
const QString &path );
 
  193    virtual bool invalidateCacheEntry( 
const QString &path );
 
  208    virtual bool checkReply( QNetworkReply *reply, 
const QString &path )
 const 
 
  223    virtual void onRemoteContentFetched( 
const QString &url, 
bool success );
 
 
  260                             const QString &typeString = QString(),
 
  261                             long maxCacheSize = 20000000,
 
  262                             int fileModifiedCheckTimeout = 30000 )
 
  264      , mMaxCacheSize( maxCacheSize )
 
  265      , mFileModifiedCheckTimeout( fileModifiedCheckTimeout )
 
  266      , mTypeString( typeString.isEmpty() ? QObject::tr( 
"Content" ) : typeString )
 
 
  272      qDeleteAll( mEntryLookup );
 
 
  277      const QMutexLocker locker( &mMutex );
 
  279      const QList<T *> entries = mEntryLookup.values( path );
 
  280      if ( entries.isEmpty() )
 
  283      for ( T *entry : entries )
 
  285        takeEntryFromList( entry );
 
  286        mEntryLookup.remove( path, entry );
 
  287        mTotalSize -= entry->dataSize();
 
 
  302      if ( mLeastRecentEntry == mMostRecentEntry )
 
  306      T *entry = mLeastRecentEntry;
 
  307      while ( entry && ( mTotalSize > mMaxCacheSize ) )
 
  310        entry = 
static_cast< T * 
>( entry->nextEntry );
 
  312        takeEntryFromList( bkEntry );
 
  313        mEntryLookup.remove( bkEntry->path, bkEntry );
 
  314        mTotalSize -= bkEntry->dataSize();
 
 
  332    QByteArray getContent( 
const QString &path, 
const QByteArray &missingContent, 
const QByteArray &fetchingContent, 
bool blocking = 
false ) 
const;
 
  336      const QMutexLocker locker( &mMutex );
 
  337      mPendingRemoteUrls.remove( url );
 
  339      T *nextEntry = mLeastRecentEntry;
 
  340      while ( T *entry = nextEntry )
 
  342        nextEntry = 
static_cast< T * 
>( entry->nextEntry );
 
  343        if ( entry->path == url )
 
  345          takeEntryFromList( entry );
 
  346          mEntryLookup.remove( entry->path, entry );
 
  347          mTotalSize -= entry->dataSize();
 
  353        emit remoteContentFetched( url );
 
 
  397      const QString path = entryTemplate->path;
 
  398      T *currentEntry = 
nullptr;
 
  399      const QList<T *> entries = mEntryLookup.values( path );
 
  401      for ( T *cacheEntry : entries )
 
  403        if ( cacheEntry->isEqual( entryTemplate ) )
 
  405          if ( mFileModifiedCheckTimeout <= 0 || cacheEntry->fileModifiedLastCheckTimer.hasExpired( mFileModifiedCheckTimeout ) )
 
  407            if ( !modified.isValid() )
 
  408              modified = QFileInfo( path ).lastModified();
 
  410            if ( cacheEntry->fileModified != modified )
 
  413              cacheEntry->fileModifiedLastCheckTimer.restart();
 
  415          currentEntry = cacheEntry;
 
  423        currentEntry = insertCacheEntry( entryTemplate );
 
  427        delete entryTemplate;
 
  428        entryTemplate = 
nullptr;
 
  429        ( void )entryTemplate;
 
  430        takeEntryFromList( currentEntry );
 
  431        if ( !mMostRecentEntry ) 
 
  433          mMostRecentEntry = currentEntry;
 
  434          mLeastRecentEntry = currentEntry;
 
  438          mMostRecentEntry->nextEntry = currentEntry;
 
  439          currentEntry->previousEntry = mMostRecentEntry;
 
  440          currentEntry->nextEntry = 
nullptr;
 
  441          mMostRecentEntry = currentEntry;
 
 
  456    long mMaxCacheSize = 20000000;
 
  465    T *insertCacheEntry( T *entry )
 
  467      entry->mFileModifiedCheckTimeout = mFileModifiedCheckTimeout;
 
  469      if ( !entry->path.startsWith( QLatin1String( 
"base64:" ) ) )
 
  471        entry->fileModified = QFileInfo( entry->path ).lastModified();
 
  472        entry->fileModifiedLastCheckTimer.start();
 
  475      mEntryLookup.insert( entry->path, entry );
 
  478      if ( !mMostRecentEntry ) 
 
  480        mLeastRecentEntry = entry;
 
  481        mMostRecentEntry = entry;
 
  482        entry->previousEntry = 
nullptr;
 
  483        entry->nextEntry = 
nullptr;
 
  487        entry->previousEntry = mMostRecentEntry;
 
  488        entry->nextEntry = 
nullptr;
 
  489        mMostRecentEntry->nextEntry = entry;
 
  490        mMostRecentEntry = entry;
 
  501    void takeEntryFromList( T *entry )
 
  508      if ( entry->previousEntry )
 
  510        entry->previousEntry->nextEntry = entry->nextEntry;
 
  514        mLeastRecentEntry = 
static_cast< T * 
>( entry->nextEntry );
 
  516      if ( entry->nextEntry )
 
  518        entry->nextEntry->previousEntry = entry->previousEntry;
 
  522        mMostRecentEntry = 
static_cast< T * 
>( entry->previousEntry );
 
  529    void printEntryList()
 
  531      QgsDebugMsgLevel( QStringLiteral( 
"****************cache entry list*************************" ), 1 );
 
  533      T *entry = mLeastRecentEntry;
 
  538        entry = 
static_cast< T * 
>( entry->nextEntry );
 
  543    QMultiHash< QString, T * > mEntryLookup;
 
  546    int mFileModifiedCheckTimeout = 30000;
 
  550    T *mLeastRecentEntry = 
nullptr;
 
  551    T *mMostRecentEntry = 
nullptr;
 
  553    mutable QCache< QString, QByteArray > mRemoteContentCache;
 
  554    mutable QSet< QString > mPendingRemoteUrls;
 
  558    friend class TestQgsSvgCache;
 
  559    friend class TestQgsImageCache;
 
 
A QObject derived base class for QgsAbstractContentCache.
 
void remoteContentFetched(const QString &url)
Emitted when the cache has finished retrieving content from a remote url.
 
virtual bool checkReply(QNetworkReply *reply, const QString &path) const
Runs additional checks on a network reply to ensure that the reply content is consistent with that re...
 
Base class for entries in a QgsAbstractContentCache.
 
virtual int dataSize() const =0
Returns the memory usage in bytes for the entry.
 
virtual void dump() const =0
Dumps debugging strings containing the item's properties.
 
virtual ~QgsAbstractContentCacheEntry()=default
 
QElapsedTimer fileModifiedLastCheckTimer
Time since last check of file modified date.
 
QgsAbstractContentCacheEntry(const QgsAbstractContentCacheEntry &rh)=delete
 
QgsAbstractContentCacheEntry & operator=(const QgsAbstractContentCacheEntry &rh)=delete
 
QString path
Represents the absolute path to a file, a remote URL, or a base64 encoded string.
 
virtual bool isEqual(const QgsAbstractContentCacheEntry *other) const =0
Tests whether this entry matches another entry.
 
QDateTime fileModified
Timestamp when file was last modified.
 
bool operator==(const QgsAbstractContentCacheEntry &other) const
 
Abstract base class for file content caches, such as SVG or raster image caches.
 
bool invalidateCacheEntry(const QString &path) override
Invalidates a cache entry for the specified path.
 
T * findExistingEntry(T *entryTemplate)
Returns the existing entry from the cache which matches entryTemplate (deleting entryTemplate when do...
 
~QgsAbstractContentCache() override
 
void onRemoteContentFetched(const QString &url, bool success) override
Triggered after remote content (i.e.
 
QgsAbstractContentCache(QObject *parent=nullptr, const QString &typeString=QString(), long maxCacheSize=20000000, int fileModifiedCheckTimeout=30000)
Constructor for QgsAbstractContentCache, with the specified parent object.
 
void trimToMaximumSize()
Removes the least used cache entries until the maximum cache size is under the predefined size limit.
 
bool waitForTaskFinished(QgsNetworkContentFetcherTask *task) const
Blocks the current thread until the task finishes (or user's preset network timeout expires)
 
static int timeout()
Returns the network timeout length, in milliseconds.
 
Handles HTTP network content fetching in a background task.
 
void fetched()
Emitted when the network content has been fetched, regardless of whether the fetch was successful or ...
 
TaskStatus status() const
Returns the current task status.
 
@ Complete
Task successfully completed.
 
bool waitForFinished(int timeout=30000)
Blocks the current thread until the task finishes or a maximum of timeout milliseconds.
 
#define QgsDebugMsgLevel(str, level)