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 );
164 static bool isBase64Data(
const QString &path );
179 virtual bool checkReply( QNetworkReply *reply,
const QString &path )
const
194 virtual void onRemoteContentFetched(
const QString &url,
bool success );
231 const QString &typeString = QString(),
232 long maxCacheSize = 20000000,
233 int fileModifiedCheckTimeout = 30000 )
235 , mMaxCacheSize( maxCacheSize )
236 , mFileModifiedCheckTimeout( fileModifiedCheckTimeout )
237 , mTypeString( typeString.isEmpty() ? QObject::tr(
"Content" ) : typeString )
243 qDeleteAll( mEntryLookup );
254 if ( mLeastRecentEntry == mMostRecentEntry )
258 T *entry = mLeastRecentEntry;
259 while ( entry && ( mTotalSize > mMaxCacheSize ) )
262 entry =
static_cast< T *
>( entry->nextEntry );
264 takeEntryFromList( bkEntry );
265 mEntryLookup.remove( bkEntry->path, bkEntry );
266 mTotalSize -= bkEntry->dataSize();
284 QByteArray getContent(
const QString &path,
const QByteArray &missingContent,
const QByteArray &fetchingContent,
bool blocking =
false )
const;
288 const QMutexLocker locker( &mMutex );
289 mPendingRemoteUrls.remove( url );
291 T *nextEntry = mLeastRecentEntry;
292 while ( T *entry = nextEntry )
294 nextEntry =
static_cast< T *
>( entry->nextEntry );
295 if ( entry->path == url )
297 takeEntryFromList( entry );
298 mEntryLookup.remove( entry->path, entry );
299 mTotalSize -= entry->dataSize();
305 emit remoteContentFetched( url );
349 const QString path = entryTemplate->path;
350 T *currentEntry =
nullptr;
351 const QList<T *> entries = mEntryLookup.values( path );
353 for ( T *cacheEntry : entries )
355 if ( cacheEntry->isEqual( entryTemplate ) )
357 if ( mFileModifiedCheckTimeout <= 0 || cacheEntry->fileModifiedLastCheckTimer.hasExpired( mFileModifiedCheckTimeout ) )
359 if ( !modified.isValid() )
360 modified = QFileInfo( path ).lastModified();
362 if ( cacheEntry->fileModified != modified )
365 cacheEntry->fileModifiedLastCheckTimer.restart();
367 currentEntry = cacheEntry;
375 currentEntry = insertCacheEntry( entryTemplate );
379 delete entryTemplate;
380 entryTemplate =
nullptr;
381 ( void )entryTemplate;
382 takeEntryFromList( currentEntry );
383 if ( !mMostRecentEntry )
385 mMostRecentEntry = currentEntry;
386 mLeastRecentEntry = currentEntry;
390 mMostRecentEntry->nextEntry = currentEntry;
391 currentEntry->previousEntry = mMostRecentEntry;
392 currentEntry->nextEntry =
nullptr;
393 mMostRecentEntry = currentEntry;
408 long mMaxCacheSize = 20000000;
417 T *insertCacheEntry( T *entry )
419 entry->mFileModifiedCheckTimeout = mFileModifiedCheckTimeout;
421 if ( !entry->path.startsWith( QLatin1String(
"base64:" ) ) )
423 entry->fileModified = QFileInfo( entry->path ).lastModified();
424 entry->fileModifiedLastCheckTimer.start();
427 mEntryLookup.insert( entry->path, entry );
430 if ( !mMostRecentEntry )
432 mLeastRecentEntry = entry;
433 mMostRecentEntry = entry;
434 entry->previousEntry =
nullptr;
435 entry->nextEntry =
nullptr;
439 entry->previousEntry = mMostRecentEntry;
440 entry->nextEntry =
nullptr;
441 mMostRecentEntry->nextEntry = entry;
442 mMostRecentEntry = entry;
453 void takeEntryFromList( T *entry )
460 if ( entry->previousEntry )
462 entry->previousEntry->nextEntry = entry->nextEntry;
466 mLeastRecentEntry =
static_cast< T *
>( entry->nextEntry );
468 if ( entry->nextEntry )
470 entry->nextEntry->previousEntry = entry->previousEntry;
474 mMostRecentEntry =
static_cast< T *
>( entry->previousEntry );
481 void printEntryList()
483 QgsDebugMsgLevel( QStringLiteral(
"****************cache entry list*************************" ), 1 );
485 T *entry = mLeastRecentEntry;
490 entry =
static_cast< T *
>( entry->nextEntry );
495 QMultiHash< QString, T * > mEntryLookup;
498 int mFileModifiedCheckTimeout = 30000;
502 T *mLeastRecentEntry =
nullptr;
503 T *mMostRecentEntry =
nullptr;
505 mutable QCache< QString, QByteArray > mRemoteContentCache;
506 mutable QSet< QString > mPendingRemoteUrls;
510 friend class TestQgsSvgCache;
511 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)