27 #include <QApplication>    28 #include <QCoreApplication>    30 #include <QDomDocument>    31 #include <QDomElement>    37 #include <QNetworkReply>    38 #include <QNetworkRequest>    40 #include <QImageReader>    41 #include <QSvgRenderer>    45 QgsImageCacheEntry::QgsImageCacheEntry( 
const QString &path, QSize size, 
const bool keepAspectRatio, 
const double opacity )
    48   , keepAspectRatio( keepAspectRatio )
    55   const QgsImageCacheEntry *otherImage = 
dynamic_cast< const QgsImageCacheEntry * 
>( other );
    57   if ( !otherImage || otherImage->keepAspectRatio != keepAspectRatio || otherImage->size != size || otherImage->path != path || otherImage->opacity != opacity )
    63 int QgsImageCacheEntry::dataSize()
 const    66   if ( !image.isNull() )
    68     size += ( image.width() * image.height() * 32 );
    73 void QgsImageCacheEntry::dump()
 const    75   QgsDebugMsgLevel( QStringLiteral( 
"path: %1, size %2x%3" ).arg( path ).arg( size.width() ).arg( size.height() ), 3 );
    84   mMissingSvg = QStringLiteral( 
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
    87   if ( QFile::exists( downloadingSvgPath ) )
    89     QFile file( downloadingSvgPath );
    90     if ( file.open( QIODevice::ReadOnly ) )
    92       mFetchingSvg = file.readAll();
    96   if ( mFetchingSvg.isEmpty() )
    98     mFetchingSvg = QStringLiteral( 
"<svg width='10' height='10'><text x='5' y='10' font-size='10' text-anchor='middle'>?</text></svg>" ).toLatin1();
   104 QImage 
QgsImageCache::pathAsImage( 
const QString &f, 
const QSize size, 
const bool keepAspectRatio, 
const double opacity, 
bool &fitsInCache, 
bool blocking )
   106   const QString file = f.trimmed();
   108   if ( file.isEmpty() )
   111   QMutexLocker locker( &
mMutex );
   115   QgsImageCacheEntry *currentEntry = 
findExistingEntry( 
new QgsImageCacheEntry( file, size, keepAspectRatio, opacity ) );
   122   if ( currentEntry->image.isNull() )
   124     long cachedDataSize = 0;
   125     result = renderImage( file, size, keepAspectRatio, opacity, blocking );
   126     cachedDataSize += result.width() * result.height() * 32;
   130       currentEntry->image = QImage();
   134       mTotalSize += ( result.width() * result.height() * 32 );
   135       currentEntry->image = result;
   141     result = currentEntry->image;
   149   if ( path.isEmpty() )
   153   if ( !path.startsWith( QStringLiteral( 
"base64:" ) ) && QFile::exists( path ) )
   155     QImageReader reader( path );
   156     if ( reader.size().isValid() )
   157       return reader.size();
   159       return QImage( path ).size();
   163     QByteArray ba = 
getContent( path, QByteArray( 
"broken" ), QByteArray( 
"fetching" ), blocking );
   165     if ( ba != 
"broken" && ba != 
"fetching" )
   167       QBuffer buffer( &ba );
   168       buffer.open( QIODevice::ReadOnly );
   170       QImageReader reader( &buffer );
   173       const QSize s = reader.size();
   176       QImage im = reader.read();
   177       return im.isNull() ? QSize() : im.size();
   183 QImage QgsImageCache::renderImage( 
const QString &path, QSize size, 
const bool keepAspectRatio, 
const double opacity, 
bool blocking )
 const   187   if ( !path.startsWith( QStringLiteral( 
"base64:" ) ) && QFile::exists( path ) )
   193     QByteArray ba = 
getContent( path, QByteArray( 
"broken" ), QByteArray( 
"fetching" ), blocking );
   195     if ( ba == 
"broken" )
   198       if ( size.width() == 0 )
   199         size.setWidth( size.height() );
   200       if ( size.height() == 0 )
   201         size.setHeight( size.width() );
   203       im = QImage( size, QImage::Format_ARGB32_Premultiplied );
   207       QSvgRenderer r( mMissingSvg );
   209       QSizeF s( r.viewBox().size() );
   210       s.scale( size.width(), size.height(), Qt::KeepAspectRatio );
   211       QRectF rect( ( size.width() - s.width() ) / 2, ( size.height() - s.height() ) / 2, s.width(), s.height() );
   212       r.render( &p, rect );
   214     else if ( ba == 
"fetching" )
   217       if ( size.width() == 0 )
   218         size.setWidth( size.height() );
   219       if ( size.height() == 0 )
   220         size.setHeight( size.width() );
   223       im = QImage( size, QImage::Format_ARGB32_Premultiplied );
   227       QSvgRenderer r( mFetchingSvg );
   229       QSizeF s( r.viewBox().size() );
   230       s.scale( size.width(), size.height(), Qt::KeepAspectRatio );
   231       QRectF rect( ( size.width() - s.width() ) / 2, ( size.height() - s.height() ) / 2, s.width(), s.height() );
   232       r.render( &p, rect );
   236       QBuffer buffer( &ba );
   237       buffer.open( QIODevice::ReadOnly );
   239       QImageReader reader( &buffer );
   244   if ( !im.hasAlphaChannel() )
   245     im = im.convertToFormat( QImage::Format_ARGB32 );
   251   if ( !size.isValid() || size.isNull() || im.size() == size )
   254   else if ( keepAspectRatio && size.height() == 0 )
   255     return im.scaledToWidth( size.width(), Qt::SmoothTransformation );
   257   else if ( keepAspectRatio && size.width() == 0 )
   258     return im.scaledToHeight( size.height(), Qt::SmoothTransformation );
   260     return im.scaled( size, keepAspectRatio ? Qt::KeepAspectRatio : Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
 QByteArray getContent(const QString &path, const QByteArray &missingContent, const QByteArray &fetchingContent, bool blocking=false) const
Gets the file content corresponding to the given path. 
 
static void multiplyOpacity(QImage &image, double factor)
Multiplies opacity of image pixel values by a factor. 
 
Abstract base class for file content caches, such as SVG or raster image caches. 
 
QgsImageCache(QObject *parent=nullptr)
Constructor for QgsImageCache, with the specified parent object. 
 
static QString defaultThemePath()
Returns the path to the default theme directory. 
 
Base class for entries in a QgsAbstractContentCache. 
 
void remoteContentFetched(const QString &url)
Emitted when the cache has finished retrieving content from a remote url. 
 
#define QgsDebugMsgLevel(str, level)
 
void remoteImageFetched(const QString &url)
Emitted when the cache has finished retrieving an image file from a remote url. 
 
QgsImageCacheEntry * findExistingEntry(QgsImageCacheEntry *entryTemplate)
Returns the existing entry from the cache which matches entryTemplate (deleting entryTemplate when do...
 
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path. 
 
long mMaxCacheSize
Maximum cache size. 
 
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false)
Returns the specified path rendered as an image. 
 
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...