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 );
196 virtual bool checkReply( QNetworkReply *reply,
const QString &path )
const
211 virtual void onRemoteContentFetched(
const QString &url,
bool success );
248 const QString &typeString = QString(),
249 long maxCacheSize = 20000000,
250 int fileModifiedCheckTimeout = 30000 )
252 , mMaxCacheSize( maxCacheSize )
253 , mFileModifiedCheckTimeout( fileModifiedCheckTimeout )
254 , mTypeString( typeString.isEmpty() ? QObject::tr(
"Content" ) : typeString )
260 qDeleteAll( mEntryLookup );
271 if ( mLeastRecentEntry == mMostRecentEntry )
275 T *entry = mLeastRecentEntry;
276 while ( entry && ( mTotalSize > mMaxCacheSize ) )
279 entry =
static_cast< T *
>( entry->nextEntry );
281 takeEntryFromList( bkEntry );
282 mEntryLookup.remove( bkEntry->path, bkEntry );
283 mTotalSize -= bkEntry->dataSize();
301 QByteArray getContent(
const QString &path,
const QByteArray &missingContent,
const QByteArray &fetchingContent,
bool blocking =
false )
const;
305 const QMutexLocker locker( &mMutex );
306 mPendingRemoteUrls.remove( url );
308 T *nextEntry = mLeastRecentEntry;
309 while ( T *entry = nextEntry )
311 nextEntry =
static_cast< T *
>( entry->nextEntry );
312 if ( entry->path == url )
314 takeEntryFromList( entry );
315 mEntryLookup.remove( entry->path, entry );
316 mTotalSize -= entry->dataSize();
322 emit remoteContentFetched( url );
366 const QString path = entryTemplate->path;
367 T *currentEntry =
nullptr;
368 const QList<T *> entries = mEntryLookup.values( path );
370 for ( T *cacheEntry : entries )
372 if ( cacheEntry->isEqual( entryTemplate ) )
374 if ( mFileModifiedCheckTimeout <= 0 || cacheEntry->fileModifiedLastCheckTimer.hasExpired( mFileModifiedCheckTimeout ) )
376 if ( !modified.isValid() )
377 modified = QFileInfo( path ).lastModified();
379 if ( cacheEntry->fileModified != modified )
382 cacheEntry->fileModifiedLastCheckTimer.restart();
384 currentEntry = cacheEntry;
392 currentEntry = insertCacheEntry( entryTemplate );
396 delete entryTemplate;
397 entryTemplate =
nullptr;
398 ( void )entryTemplate;
399 takeEntryFromList( currentEntry );
400 if ( !mMostRecentEntry )
402 mMostRecentEntry = currentEntry;
403 mLeastRecentEntry = currentEntry;
407 mMostRecentEntry->nextEntry = currentEntry;
408 currentEntry->previousEntry = mMostRecentEntry;
409 currentEntry->nextEntry =
nullptr;
410 mMostRecentEntry = currentEntry;
425 long mMaxCacheSize = 20000000;
434 T *insertCacheEntry( T *entry )
436 entry->mFileModifiedCheckTimeout = mFileModifiedCheckTimeout;
438 if ( !entry->path.startsWith( QLatin1String(
"base64:" ) ) )
440 entry->fileModified = QFileInfo( entry->path ).lastModified();
441 entry->fileModifiedLastCheckTimer.start();
444 mEntryLookup.insert( entry->path, entry );
447 if ( !mMostRecentEntry )
449 mLeastRecentEntry = entry;
450 mMostRecentEntry = entry;
451 entry->previousEntry =
nullptr;
452 entry->nextEntry =
nullptr;
456 entry->previousEntry = mMostRecentEntry;
457 entry->nextEntry =
nullptr;
458 mMostRecentEntry->nextEntry = entry;
459 mMostRecentEntry = entry;
470 void takeEntryFromList( T *entry )
477 if ( entry->previousEntry )
479 entry->previousEntry->nextEntry = entry->nextEntry;
483 mLeastRecentEntry =
static_cast< T *
>( entry->nextEntry );
485 if ( entry->nextEntry )
487 entry->nextEntry->previousEntry = entry->previousEntry;
491 mMostRecentEntry =
static_cast< T *
>( entry->previousEntry );
498 void printEntryList()
500 QgsDebugMsgLevel( QStringLiteral(
"****************cache entry list*************************" ), 1 );
502 T *entry = mLeastRecentEntry;
507 entry =
static_cast< T *
>( entry->nextEntry );
512 QMultiHash< QString, T * > mEntryLookup;
515 int mFileModifiedCheckTimeout = 30000;
519 T *mLeastRecentEntry =
nullptr;
520 T *mMostRecentEntry =
nullptr;
522 mutable QCache< QString, QByteArray > mRemoteContentCache;
523 mutable QSet< QString > mPendingRemoteUrls;
527 friend class TestQgsSvgCache;
528 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)