42 , mEmbeddedInParent( false )
48 return qobject_cast<QgsLayerTreeModel *>( parent() );
53 return Qt::ItemIsEnabled;
79 double itemHeight = std::max(
static_cast< double >( ctx && ctx->
patchSize.height() > 0 ? ctx->
patchSize.height() : settings.
symbolSize().height() ), textHeight );
90 const QString text =
data( Qt::DisplayRole ).toString();
91 json[ QStringLiteral(
"title" ) ] = text;
97 QIcon symbolIcon =
data( Qt::DecorationRole ).value<QIcon>();
98 if ( symbolIcon.isNull() )
105 size.setWidth( ctx->
patchSize.width( ) );
107 size.setHeight( ctx->
patchSize.height( ) );
116 symbolIcon.paint( ctx->
painter,
118 static_cast< int >( ctx->
top + ( itemHeight - size.height() ) / 2 ),
119 static_cast< int >( size.width() ),
120 static_cast< int >( size.height() ) );
124 symbolIcon.paint( ctx->
painter,
125 static_cast< int >( ctx->
columnRight - size.width() ),
126 static_cast< int >( ctx->
top + ( itemHeight - size.height() ) / 2 ),
127 static_cast< int >( size.width() ),
128 static_cast< int >( size.height() ) );
137 const QIcon icon =
data( Qt::DecorationRole ).value<QIcon>();
139 return QJsonObject();
141 const QImage image( icon.pixmap( settings.
symbolSize().width(), settings.
symbolSize().height() ).toImage() );
142 QByteArray byteArray;
143 QBuffer buffer( &byteArray );
144 image.save( &buffer,
"PNG" );
145 const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
148 json[ QStringLiteral(
"icon" ) ] = base64;
154 QSizeF labelSize( 0, 0 );
164 labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * ( settings.
lineSpacing() + textDescent );
166 double labelXMin = 0.0;
167 double labelXMax = 0.0;
196 if ( labelSize.height() < symbolSize.height() )
197 labelY += symbolSize.height() / 2 - labelSize.height() / 2;
199 labelY += textHeight;
202 for ( QStringList::ConstIterator itemPart = lines.constBegin(); itemPart != lines.constEnd(); ++itemPart )
205 labelSize.rwidth() = std::max( lineWidth,
double( labelSize.width() ) );
213 settings.
drawText( ctx->
painter, labelXMin, labelY, *itemPart, symbolLabelFont );
217 settings.
drawText( ctx->
painter, labelXMax - lineWidth, labelY, *itemPart, symbolLabelFont );
220 case Qt::AlignHCenter:
221 settings.
drawText( ctx->
painter, labelXMin + ( labelXMax - labelXMin - lineWidth ) / 2.0, labelY, *itemPart, symbolLabelFont );
225 if ( itemPart != ( lines.end() - 1 ) )
226 labelY += textDescent + settings.
lineSpacing() + textHeight;
238 , mSymbolUsesMapUnits( false )
245 connect( nodeLayer, &QObject::destroyed,
this, [ = ]() {
mLayerNode =
nullptr; } );
254 return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
256 return Qt::ItemIsEnabled;
288 if ( !mTextOnSymbolLabel.isEmpty() && context )
292 int wInt = ceil( w ), hInt = ceil( h );
293 if ( wInt > minSz.width() ) minSz.setWidth( wInt );
294 if ( hInt > minSz.height() ) minSz.setHeight( hInt );
311 QString layerName = legendlabel.isNull() ?
mLayerNode->
name() : legendlabel.toString();
338 return mCustomSymbol.get();
343 mCustomSymbol.reset(
symbol );
351 std::unique_ptr< QgsSymbol > s(
symbol );
353 if ( !vlayer || !vlayer->
renderer() )
378 if ( !vlayer || !vlayer->
renderer() )
382 for (
const auto &item : symbolList )
403 std::unique_ptr<QgsRenderContext> context = qgis::make_unique<QgsRenderContext>( );
404 context->setScaleFactor( dpi / 25.4 );
405 context->setRendererScale( scale );
409 return context.release();
412 void QgsSymbolLegendNode::checkAll(
bool state )
415 if ( !vlayer || !vlayer->
renderer() )
419 for (
const auto &item : symbolList )
430 if ( role == Qt::DisplayRole )
434 else if ( role == Qt::EditRole )
438 else if ( role == Qt::DecorationRole )
440 if ( mPixmap.isNull() || mPixmap.size() != mIconSize )
448 if ( !mTextOnSymbolLabel.isEmpty() && context )
450 QPainter painter( &pix );
451 painter.setRenderHint( QPainter::Antialiasing );
452 context->setPainter( &painter );
453 QFontMetricsF fm( mTextOnSymbolTextFormat.
scaledFont( *context ) );
454 qreal yBaselineVCenter = ( mIconSize.height() + fm.ascent() - fm.descent() ) / 2;
456 QStringList() << mTextOnSymbolLabel, *context, mTextOnSymbolTextFormat );
461 pix = QPixmap( mIconSize );
462 pix.fill( Qt::transparent );
469 else if ( role == Qt::CheckStateRole )
475 if ( !vlayer || !vlayer->
renderer() )
494 if ( role != Qt::CheckStateRole )
501 if ( !vlayer || !vlayer->
renderer() )
526 std::unique_ptr< QgsRenderContext > tempRenderContext;
532 tempRenderContext = qgis::make_unique< QgsRenderContext >();
535 tempRenderContext->setScaleFactor( settings.
dpi() / 25.4 );
536 tempRenderContext->setRendererScale( settings.
mapScale() );
540 tempRenderContext->setForceVectorOutput(
true );
541 tempRenderContext->setPainter( ctx ? ctx->
painter :
nullptr );
546 tempRenderContext->setExpressionContext( expContext );
547 context = tempRenderContext.get();
553 double height = desiredHeight;
554 double width = desiredWidth;
557 double widthOffset = 0;
558 double heightOffset = 0;
563 double size = markerSymbol->size( *context ) / context->
scaleFactor();
566 if ( width < desiredWidth )
568 widthOffset = ( desiredWidth - width ) / 2.0;
570 if ( height < desiredHeight )
572 heightOffset = ( desiredHeight - height ) / 2.0;
578 double currentYCoord = ctx->
top + ( itemHeight - desiredHeight ) / 2;
586 opacity =
static_cast<int >( std::round( 255 * vectorLayer->opacity() ) );
590 p->setRenderHint( QPainter::Antialiasing );
596 p->translate( ctx->
columnLeft + widthOffset, currentYCoord + heightOffset );
599 p->translate( ctx->
columnRight - widthOffset - width, currentYCoord + heightOffset );
603 p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
608 if ( opacity != 255 && useAdvancedEffects )
614 const QSize symbolSize(
static_cast< int >( std::round( width * dotsPerMM ) ),
static_cast<int >( std::round( height * dotsPerMM ) ) );
615 const QSize tempImageSize( symbolSize.width() + maxBleed * 2, symbolSize.height() + maxBleed * 2 );
616 QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 );
617 tempImage.fill( Qt::transparent );
618 QPainter imagePainter( &tempImage );
620 imagePainter.setRenderHint( QPainter::Antialiasing );
622 imagePainter.translate( maxBleed, maxBleed );
624 imagePainter.translate( -maxBleed, -maxBleed );
627 imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
628 imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
631 p->drawImage( -maxBleed, -maxBleed, tempImage );
635 s->
drawPreviewIcon( p, QSize(
static_cast< int >( std::round( width * dotsPerMM ) ),
static_cast< int >( std::round( height * dotsPerMM ) ) ), context,
false,
nullptr, &
patchShape );
638 if ( !mTextOnSymbolLabel.isEmpty() )
640 QFontMetricsF fm( mTextOnSymbolTextFormat.
scaledFont( *context ) );
641 qreal yBaselineVCenter = ( height * dotsPerMM + fm.ascent() - fm.descent() ) / 2;
643 QStringList() << mTextOnSymbolLabel, *context, mTextOnSymbolTextFormat );
649 return QSizeF( std::max( width + 2 * widthOffset,
static_cast< double >( desiredWidth ) ),
650 std::max( height + 2 * heightOffset,
static_cast< double >( desiredHeight ) ) );
655 const QgsSymbol *s = mCustomSymbol ? mCustomSymbol.get() : mItem.
symbol();
658 return QJsonObject();
678 QImage img( pix.toImage().convertToFormat( QImage::Format_ARGB32_Premultiplied ) );
682 opacity = ( 255 * vectorLayer->opacity() );
684 if ( opacity != 255 )
687 painter.begin( &img );
688 painter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
689 painter.fillRect( pix.rect(), QColor( 0, 0, 0, opacity ) );
693 QByteArray byteArray;
694 QBuffer buffer( &byteArray );
695 img.save( &buffer,
"PNG" );
696 const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
699 json[ QStringLiteral(
"icon" ) ] = base64;
712 if ( mSymbolUsesMapUnits )
720 void QgsSymbolLegendNode::updateLabel()
729 if ( showFeatureCount && vl )
732 mLabel += QStringLiteral(
" [%1]" ).arg( count != -1 ? QLocale().toString( count ) : tr(
"N/A" ) );
752 if ( label.isEmpty() )
756 else if ( mLabel.contains(
"[%" ) )
768 else if ( label.contains(
"[%" ) )
803 if ( role == Qt::DisplayRole || role == Qt::EditRole )
805 else if ( role == Qt::DecorationRole )
824 if ( role == Qt::DecorationRole )
826 return QPixmap::fromImage( mImage );
828 else if ( role == Qt::SizeHintRole )
830 return mImage.size();
837 Q_UNUSED( itemHeight )
846 mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
851 mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
860 QByteArray byteArray;
861 QBuffer buffer( &byteArray );
862 mImage.save( &buffer,
"PNG" );
863 const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
866 json[ QStringLiteral(
"icon" ) ] = base64;
881 if ( role == Qt::DecorationRole )
888 else if ( role == Qt::DisplayRole || role == Qt::EditRole )
903 if ( ctx->
patchSize.width() < size.width() )
904 offsetX = ( size.width() - ctx->
patchSize.width() ) / 2.0;
909 size.setHeight( ctx->
patchSize.height() );
915 QColor itemColor = mColor;
919 itemColor.setAlpha( rasterRenderer->opacity() * 255.0 );
921 ctx->
painter->setBrush( itemColor );
928 pen.setJoinStyle( Qt::MiterJoin );
933 ctx->
painter->setPen( Qt::NoPen );
940 ctx->
painter->drawRect( QRectF( ctx->
columnLeft + offsetX, ctx->
top + ( itemHeight - size.height() ) / 2,
941 size.width(), size.height() ) );
945 ctx->
painter->drawRect( QRectF( ctx->
columnRight - size.width() - offsetX, ctx->
top + ( itemHeight - size.height() ) / 2,
946 size.width(), size.height() ) );
955 QImage img = QImage( settings.
symbolSize().toSize(), QImage::Format_ARGB32 );
956 img.fill( Qt::transparent );
958 QPainter painter( &img );
959 painter.setRenderHint( QPainter::Antialiasing );
961 QColor itemColor = mColor;
965 itemColor.setAlpha( rasterRenderer->opacity() * 255.0 );
967 painter.setBrush( itemColor );
974 pen.setJoinStyle( Qt::MiterJoin );
975 painter.setPen( pen );
979 painter.setPen( Qt::NoPen );
982 painter.drawRect( QRectF( 0, 0, settings.
symbolSize().width(), settings.
symbolSize().height() ) );
984 QByteArray byteArray;
985 QBuffer buffer( &byteArray );
986 img.save( &buffer,
"PNG" );
987 const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
990 json[ QStringLiteral(
"icon" ) ] = base64;
1002 QImage QgsWmsLegendNode::getLegendGraphic()
const
1004 if ( ! mValid && ! mFetcher )
1019 Q_ASSERT( ! mFetcher );
1038 if ( role == Qt::DecorationRole )
1040 return QPixmap::fromImage( getLegendGraphic() );
1042 else if ( role == Qt::SizeHintRole )
1044 return getLegendGraphic().size();
1051 Q_UNUSED( itemHeight )
1064 QRectF( QPointF( 0, 0 ), mImage.size() ) );
1067 case Qt::AlignRight:
1073 QRectF( QPointF( 0, 0 ), mImage.size() ) );
1082 QByteArray byteArray;
1083 QBuffer buffer( &byteArray );
1084 mImage.save( &buffer,
"PNG" );
1085 const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
1088 json[ QStringLiteral(
"icon" ) ] = base64;
1093 QImage QgsWmsLegendNode::renderMessage(
const QString &msg )
const
1095 const int fontHeight = 10;
1096 const int margin = fontHeight / 2;
1097 const int nlines = 1;
1099 const int w = 512, h = fontHeight * nlines + margin * ( nlines + 1 );
1100 QImage image( w, h, QImage::Format_ARGB32_Premultiplied );
1102 painter.begin( &image );
1103 painter.setPen( QColor( 255, 0, 0 ) );
1104 painter.setFont( QFont( QStringLiteral(
"Chicago" ), fontHeight ) );
1105 painter.fillRect( 0, 0, w, h, QColor( 255, 255, 255 ) );
1106 painter.drawText( 0, margin + fontHeight, msg );
1113 void QgsWmsLegendNode::getLegendGraphicProgress( qint64 cur, qint64 tot )
1115 QString msg = QStringLiteral(
"Downloading... %1/%2" ).arg( cur ).arg( tot );
1117 mImage = renderMessage( msg );
1121 void QgsWmsLegendNode::getLegendGraphicErrored(
const QString &msg )
1123 if ( ! mFetcher )
return;
1125 mImage = renderMessage( msg );
1137 void QgsWmsLegendNode::getLegendGraphicFinished(
const QImage &image )
1139 if ( ! mFetcher )
return;
1142 if ( ! image.isNull() )
1144 if ( image != mImage )
1178 if ( role == Qt::DecorationRole )
1181 return QPixmap::fromImage( mImage );
1183 else if ( role == Qt::SizeHintRole )
1186 return mImage.size();
1195 std::unique_ptr< QgsRenderContext > tempRenderContext;
1200 tempRenderContext = qgis::make_unique< QgsRenderContext >();
1203 tempRenderContext->setScaleFactor( settings.
dpi() / 25.4 );
1204 tempRenderContext->setRendererScale( settings.
mapScale() );
1206 tempRenderContext->setMapToPixel(
QgsMapToPixel( 1 / ( settings.
mmPerMapUnit() * tempRenderContext->scaleFactor() ) ) );
1207 tempRenderContext->setForceVectorOutput(
true );
1208 tempRenderContext->setPainter( ctx ? ctx->
painter :
nullptr );
1215 tempRenderContext->setExpressionContext( expContext );
1216 context = tempRenderContext.get();
1233 double labelXOffset;
1237 context->
painter()->restore();
1246 void QgsDataDefinedSizeLegendNode::cacheImage()
const
1248 if ( mImage.isNull() )
1254 Q_ASSERT( context );
1255 context->setScaleFactor( 96 / 25.4 );