18#ifndef QGSABSTRACTCONTENTCACHE_H
19#define QGSABSTRACTCONTENTCACHE_H
31#include <QRecursiveMutex>
37#include <QNetworkReply>
77 int mFileModifiedCheckTimeout = 30000;
93 return other.
path == path;
156 virtual bool checkReply( QNetworkReply *reply,
const QString &path )
const
171 virtual void onRemoteContentFetched(
const QString &url,
bool success );
208 const QString &typeString = QString(),
209 long maxCacheSize = 20000000,
210 int fileModifiedCheckTimeout = 30000 )
212 , mMaxCacheSize( maxCacheSize )
213 , mFileModifiedCheckTimeout( fileModifiedCheckTimeout )
214 , mTypeString( typeString.isEmpty() ? QObject::tr(
"Content" ) : typeString )
220 qDeleteAll( mEntryLookup );
231 if ( mLeastRecentEntry == mMostRecentEntry )
235 T *entry = mLeastRecentEntry;
236 while ( entry && ( mTotalSize > mMaxCacheSize ) )
239 entry =
static_cast< T *
>( entry->nextEntry );
241 takeEntryFromList( bkEntry );
242 mEntryLookup.remove( bkEntry->path, bkEntry );
243 mTotalSize -= bkEntry->dataSize();
261 QByteArray getContent(
const QString &path,
const QByteArray &missingContent,
const QByteArray &fetchingContent,
bool blocking =
false )
const;
265 const QMutexLocker locker( &mMutex );
266 mPendingRemoteUrls.remove( url );
268 T *nextEntry = mLeastRecentEntry;
269 while ( T *entry = nextEntry )
271 nextEntry =
static_cast< T *
>( entry->nextEntry );
272 if ( entry->path == url )
274 takeEntryFromList( entry );
275 mEntryLookup.remove( entry->path, entry );
276 mTotalSize -= entry->dataSize();
282 emit remoteContentFetched( url );
326 const QString path = entryTemplate->path;
327 T *currentEntry =
nullptr;
328 const QList<T *> entries = mEntryLookup.values( path );
330 for ( T *cacheEntry : entries )
332 if ( cacheEntry->isEqual( entryTemplate ) )
334 if ( mFileModifiedCheckTimeout <= 0 || cacheEntry->fileModifiedLastCheckTimer.hasExpired( mFileModifiedCheckTimeout ) )
336 if ( !modified.isValid() )
337 modified = QFileInfo( path ).lastModified();
339 if ( cacheEntry->fileModified != modified )
342 cacheEntry->fileModifiedLastCheckTimer.restart();
344 currentEntry = cacheEntry;
352 currentEntry = insertCacheEntry( entryTemplate );
356 delete entryTemplate;
357 entryTemplate =
nullptr;
358 ( void )entryTemplate;
359 takeEntryFromList( currentEntry );
360 if ( !mMostRecentEntry )
362 mMostRecentEntry = currentEntry;
363 mLeastRecentEntry = currentEntry;
367 mMostRecentEntry->nextEntry = currentEntry;
368 currentEntry->previousEntry = mMostRecentEntry;
369 currentEntry->nextEntry =
nullptr;
370 mMostRecentEntry = currentEntry;
385 long mMaxCacheSize = 20000000;
394 T *insertCacheEntry( T *entry )
396 entry->mFileModifiedCheckTimeout = mFileModifiedCheckTimeout;
398 if ( !entry->path.startsWith( QLatin1String(
"base64:" ) ) )
400 entry->fileModified = QFileInfo( entry->path ).lastModified();
401 entry->fileModifiedLastCheckTimer.start();
404 mEntryLookup.insert( entry->path, entry );
407 if ( !mMostRecentEntry )
409 mLeastRecentEntry = entry;
410 mMostRecentEntry = entry;
411 entry->previousEntry =
nullptr;
412 entry->nextEntry =
nullptr;
416 entry->previousEntry = mMostRecentEntry;
417 entry->nextEntry =
nullptr;
418 mMostRecentEntry->nextEntry = entry;
419 mMostRecentEntry = entry;
430 void takeEntryFromList( T *entry )
437 if ( entry->previousEntry )
439 entry->previousEntry->nextEntry = entry->nextEntry;
443 mLeastRecentEntry =
static_cast< T *
>( entry->nextEntry );
445 if ( entry->nextEntry )
447 entry->nextEntry->previousEntry = entry->previousEntry;
451 mMostRecentEntry =
static_cast< T *
>( entry->previousEntry );
458 void printEntryList()
460 QgsDebugMsgLevel( QStringLiteral(
"****************cache entry list*************************" ), 1 );
462 T *entry = mLeastRecentEntry;
467 entry =
static_cast< T *
>( entry->nextEntry );
472 QMultiHash< QString, T * > mEntryLookup;
475 int mFileModifiedCheckTimeout = 30000;
479 T *mLeastRecentEntry =
nullptr;
480 T *mMostRecentEntry =
nullptr;
482 mutable QCache< QString, QByteArray > mRemoteContentCache;
483 mutable QSet< QString > mPendingRemoteUrls;
487 friend class TestQgsSvgCache;
488 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.
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)