18#ifndef QGSABSTRACTCONTENTCACHE_H
19#define QGSABSTRACTCONTENTCACHE_H
35#include <QNetworkReply>
37#include <QRecursiveMutex>
42using namespace Qt::StringLiterals;
211 virtual bool checkReply( QNetworkReply *reply,
const QString &path )
const
226 virtual void onRemoteContentFetched(
const QString &url,
bool success );
263 const QString &typeString = QString(),
264 long maxCacheSize = 20000000,
265 int fileModifiedCheckTimeout = 30000 )
268 , mFileModifiedCheckTimeout( fileModifiedCheckTimeout )
269 , mTypeString( typeString.isEmpty() ? QObject::tr(
"Content" ) : typeString )
275 qDeleteAll( mEntryLookup );
280 const QMutexLocker locker( &
mMutex );
282 const QList<T *> entries = mEntryLookup.values( path );
283 if ( entries.isEmpty() )
286 for ( T *entry : entries )
288 takeEntryFromList( entry );
289 mEntryLookup.remove( path, entry );
305 if ( mLeastRecentEntry == mMostRecentEntry )
309 T *entry = mLeastRecentEntry;
313 entry =
static_cast< T *
>( entry->nextEntry );
315 takeEntryFromList( bkEntry );
316 mEntryLookup.remove( bkEntry->path, bkEntry );
335 QByteArray getContent(
const QString &path,
const QByteArray &missingContent,
const QByteArray &fetchingContent,
bool blocking =
false )
const;
339 const QMutexLocker locker( &
mMutex );
340 mPendingRemoteUrls.remove( url );
342 T *nextEntry = mLeastRecentEntry;
343 while ( T *entry = nextEntry )
345 nextEntry =
static_cast< T *
>( entry->nextEntry );
346 if ( entry->path == url )
348 takeEntryFromList( entry );
349 mEntryLookup.remove( entry->path, entry );
400 const QString path = entryTemplate->path;
401 T *currentEntry =
nullptr;
402 const QList<T *> entries = mEntryLookup.values( path );
404 for ( T *cacheEntry : entries )
406 if ( cacheEntry->isEqual( entryTemplate ) )
408 if ( mFileModifiedCheckTimeout <= 0 || cacheEntry->fileModifiedLastCheckTimer.hasExpired( mFileModifiedCheckTimeout ) )
410 if ( !modified.isValid() )
411 modified = QFileInfo( path ).lastModified();
413 if ( cacheEntry->fileModified != modified )
416 cacheEntry->fileModifiedLastCheckTimer.restart();
418 currentEntry = cacheEntry;
426 currentEntry = insertCacheEntry( entryTemplate );
430 delete entryTemplate;
431 entryTemplate =
nullptr;
432 ( void )entryTemplate;
433 takeEntryFromList( currentEntry );
434 if ( !mMostRecentEntry )
436 mMostRecentEntry = currentEntry;
437 mLeastRecentEntry = currentEntry;
441 mMostRecentEntry->nextEntry = currentEntry;
442 currentEntry->previousEntry = mMostRecentEntry;
443 currentEntry->nextEntry =
nullptr;
444 mMostRecentEntry = currentEntry;
468 T *insertCacheEntry( T *entry )
470 entry->mFileModifiedCheckTimeout = mFileModifiedCheckTimeout;
472 if ( !entry->path.startsWith(
"base64:"_L1 ) )
474 entry->fileModified = QFileInfo( entry->path ).lastModified();
475 entry->fileModifiedLastCheckTimer.start();
478 mEntryLookup.insert( entry->path, entry );
481 if ( !mMostRecentEntry )
483 mLeastRecentEntry = entry;
484 mMostRecentEntry = entry;
485 entry->previousEntry =
nullptr;
486 entry->nextEntry =
nullptr;
490 entry->previousEntry = mMostRecentEntry;
491 entry->nextEntry =
nullptr;
492 mMostRecentEntry->nextEntry = entry;
493 mMostRecentEntry = entry;
504 void takeEntryFromList( T *entry )
511 if ( entry->previousEntry )
513 entry->previousEntry->nextEntry = entry->nextEntry;
517 mLeastRecentEntry =
static_cast< T *
>( entry->nextEntry );
519 if ( entry->nextEntry )
521 entry->nextEntry->previousEntry = entry->previousEntry;
525 mMostRecentEntry =
static_cast< T *
>( entry->previousEntry );
532 void printEntryList()
534 QgsDebugMsgLevel( u
"****************cache entry list*************************"_s, 1 );
536 T *entry = mLeastRecentEntry;
541 entry =
static_cast< T *
>( entry->nextEntry );
546 QMultiHash< QString, T * > mEntryLookup;
549 int mFileModifiedCheckTimeout = 30000;
553 T *mLeastRecentEntry =
nullptr;
554 T *mMostRecentEntry =
nullptr;
556 mutable QCache< QString, QByteArray > mRemoteContentCache;
557 mutable QSet< QString > mPendingRemoteUrls;
void remoteContentFetched(const QString &url)
Emitted when the cache has finished retrieving content from a remote url.
static bool parseEmbeddedStringData(const QString &path, QString *mimeType=nullptr, QString *data=nullptr)
Parses a path to determine if it represents a embedded string data, and if so, extracts the component...
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...
static bool parseBase64DataUrl(const QString &path, QString *mimeType=nullptr, QString *data=nullptr)
Parses a path to determine if it represents a base 64 encoded HTML data URL, and if so,...
QgsAbstractContentCacheBase(QObject *parent)
Constructor for QgsAbstractContentCacheBase, with the specified parent object.
virtual bool invalidateCacheEntry(const QString &path)
Invalidates a cache entry for the specified path.
static bool isBase64Data(const QString &path)
Returns true if path represents base64 encoded data.
virtual int dataSize() const =0
Returns the memory usage in bytes for the entry.
QgsAbstractContentCacheEntry * nextEntry
Entries are kept on a linked list, sorted by last access.
virtual void dump() const =0
Dumps debugging strings containing the item's properties.
int mFileModifiedCheckTimeout
Timeout before re-checking whether the file modified date has changed.
virtual ~QgsAbstractContentCacheEntry()=default
QElapsedTimer fileModifiedLastCheckTimer
Time since last check of file modified date.
QgsAbstractContentCacheEntry(const QgsAbstractContentCacheEntry &rh)=delete
QgsAbstractContentCacheEntry & operator=(const QgsAbstractContentCacheEntry &rh)=delete
QgsAbstractContentCacheEntry(const QString &path)
Constructor for QgsAbstractContentCacheEntry for an entry relating to the specified path.
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.
QgsAbstractContentCacheEntry * previousEntry
Entries are kept on a linked list, sorted by last access.
QDateTime fileModified
Timestamp when file was last modified.
bool operator==(const QgsAbstractContentCacheEntry &other) const
long mMaxCacheSize
Maximum cache size.
bool invalidateCacheEntry(const QString &path) override
Invalidates a cache entry for the specified path.
friend class TestQgsImageCache
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.
long mTotalSize
Estimated total size of all cached content.
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).
friend class TestQgsSvgCache
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)