From 5566c5349dd4c54325cb19402440cf49f6b28ef0 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 7 Feb 2020 10:26:27 +1000 Subject: [PATCH] Fix deprecated api use in QgsDataDefinedSizeLegend, port away from ints to make more layout export friendly --- .../qgsdatadefinedsizelegend.sip.in | 2 +- .../layertree/qgslayertreemodellegendnode.cpp | 4 +- src/core/qgsdatadefinedsizelegend.cpp | 58 +++++++++---------- src/core/qgsdatadefinedsizelegend.h | 2 +- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/python/core/auto_generated/qgsdatadefinedsizelegend.sip.in b/python/core/auto_generated/qgsdatadefinedsizelegend.sip.in index 44c59adea575..925c5fbdf92c 100644 --- a/python/core/auto_generated/qgsdatadefinedsizelegend.sip.in +++ b/python/core/auto_generated/qgsdatadefinedsizelegend.sip.in @@ -150,7 +150,7 @@ Updates the list of classes, source symbol and title label from given symbol and Generates legend symbol items according to the configuration %End - void drawCollapsedLegend( QgsRenderContext &context, QSize *outputSize /Out/ = 0, int *labelXOffset /Out/ = 0 ) const; + void drawCollapsedLegend( QgsRenderContext &context, QSizeF *outputSize /Out/ = 0, double *labelXOffset /Out/ = 0 ) const; %Docstring Draw the legend if using LegendOneNodeForAll and optionally output size of the legend and x offset of labels (in painter units). If the painter in context is ``None``, it only does size calculation without actual rendering. diff --git a/src/core/layertree/qgslayertreemodellegendnode.cpp b/src/core/layertree/qgslayertreemodellegendnode.cpp index 8a82bba8e11f..2153765031db 100644 --- a/src/core/layertree/qgslayertreemodellegendnode.cpp +++ b/src/core/layertree/qgslayertreemodellegendnode.cpp @@ -1134,8 +1134,8 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsDataDefinedSizeLegendNode::draw( con ddsLegend.setFont( settings.style( QgsLegendStyle::SymbolLabel ).font() ); ddsLegend.setTextColor( settings.fontColor() ); - QSize contentSize; - int labelXOffset; + QSizeF contentSize; + double labelXOffset; ddsLegend.drawCollapsedLegend( context, &contentSize, &labelXOffset ); if ( ctx && ctx->painter ) diff --git a/src/core/qgsdatadefinedsizelegend.cpp b/src/core/qgsdatadefinedsizelegend.cpp index 05864e62ed52..d26d7c04f804 100644 --- a/src/core/qgsdatadefinedsizelegend.cpp +++ b/src/core/qgsdatadefinedsizelegend.cpp @@ -141,12 +141,12 @@ QgsLegendSymbolList QgsDataDefinedSizeLegend::legendSymbolList() const } -void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, QSize *outputSize, int *labelXOffset ) const +void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, QSizeF *outputSize, double *labelXOffset ) const { if ( mType != LegendCollapsed || mSizeClasses.isEmpty() || !mSymbol ) { if ( outputSize ) - *outputSize = QSize(); + *outputSize = QSizeF(); if ( labelXOffset ) *labelXOffset = 0; return; @@ -170,78 +170,76 @@ void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, Q // make sure we draw bigger symbols first std::sort( classes.begin(), classes.end(), []( const SizeClass & a, const SizeClass & b ) { return a.size > b.size; } ); - int hLengthLine = std::round( context.convertToPainterUnits( hLengthLineMM, QgsUnitTypes::RenderMillimeters ) ); - int hSpaceLineText = std::round( context.convertToPainterUnits( hSpaceLineTextMM, QgsUnitTypes::RenderMillimeters ) ); + double hLengthLine = context.convertToPainterUnits( hLengthLineMM, QgsUnitTypes::RenderMillimeters ); + double hSpaceLineText = context.convertToPainterUnits( hSpaceLineTextMM, QgsUnitTypes::RenderMillimeters ); int dpm = std::round( context.scaleFactor() * 1000 ); // scale factor = dots per millimeter // get font metrics - we need a temporary image just to get the metrics right for the given DPI QImage tmpImg( QSize( 1, 1 ), QImage::Format_ARGB32_Premultiplied ); tmpImg.setDotsPerMeterX( dpm ); tmpImg.setDotsPerMeterY( dpm ); - QFontMetrics fm( mFont, &tmpImg ); - int textHeight = fm.height(); - int leading = fm.leading(); - int minTextDistY = textHeight + leading; + QFontMetricsF fm( mFont, &tmpImg ); + double textHeight = fm.height(); + double leading = fm.leading(); + double minTextDistY = textHeight + leading; // // determine layout of the rendered elements // // find out how wide the text will be - int maxTextWidth = 0; + double maxTextWidth = 0; for ( const SizeClass &c : qgis::as_const( classes ) ) { - int w = fm.width( c.label ); - if ( w > maxTextWidth ) - maxTextWidth = w; + maxTextWidth = std::max( maxTextWidth, fm.boundingRect( c.label ).width() ); } // add extra width needed to handle varying rendering of font weight maxTextWidth += 1; // find out size of the largest symbol double largestSize = classes.at( 0 ).size; - int outputLargestSize = std::round( context.convertToPainterUnits( largestSize, s->sizeUnit(), s->sizeMapUnitScale() ) ); + double outputLargestSize = context.convertToPainterUnits( largestSize, s->sizeUnit(), s->sizeMapUnitScale() ); // find out top Y coordinate for individual symbol sizes - QList symbolTopY; + QList symbolTopY; for ( const SizeClass &c : qgis::as_const( classes ) ) { - int outputSymbolSize = std::round( context.convertToPainterUnits( c.size, s->sizeUnit(), s->sizeMapUnitScale() ) ); + double outputSymbolSize = context.convertToPainterUnits( c.size, s->sizeUnit(), s->sizeMapUnitScale() ); switch ( mVAlign ) { case AlignCenter: - symbolTopY << std::round( outputLargestSize / 2 - outputSymbolSize / 2 ); + symbolTopY << outputLargestSize / 2 - outputSymbolSize / 2; break; case AlignBottom: - symbolTopY << std::round( outputLargestSize - outputSymbolSize ); + symbolTopY << outputLargestSize - outputSymbolSize; break; } } // determine Y coordinate of texts: ideally they should be at the same level as symbolTopY // but we need to avoid overlapping texts, so adjust the vertical positions - int middleIndex = 0; // classes.count() / 2; // will get the ideal position - QList textCenterY; - int lastY = symbolTopY[middleIndex]; + double middleIndex = 0; // classes.count() / 2; // will get the ideal position + QList textCenterY; + double lastY = symbolTopY[middleIndex]; textCenterY << lastY; for ( int i = middleIndex + 1; i < classes.count(); ++i ) { - int symbolY = symbolTopY[i]; + double symbolY = symbolTopY[i]; if ( symbolY - lastY < minTextDistY ) symbolY = lastY + minTextDistY; textCenterY << symbolY; lastY = symbolY; } - int textTopY = textCenterY.first() - textHeight / 2; - int textBottomY = textCenterY.last() + textHeight / 2; - int totalTextHeight = textBottomY - textTopY; + double textTopY = textCenterY.first() - textHeight / 2; + double textBottomY = textCenterY.last() + textHeight / 2; + double totalTextHeight = textBottomY - textTopY; - int fullWidth = outputLargestSize + hLengthLine + hSpaceLineText + maxTextWidth; - int fullHeight = std::max( static_cast< int >( std::round( outputLargestSize ) ) - textTopY, totalTextHeight ); + double fullWidth = outputLargestSize + hLengthLine + hSpaceLineText + maxTextWidth; + double fullHeight = std::max( outputLargestSize - textTopY, totalTextHeight ); if ( outputSize ) - *outputSize = QSize( fullWidth, fullHeight ); + *outputSize = QSizeF( fullWidth, fullHeight ); if ( labelXOffset ) *labelXOffset = outputLargestSize + hLengthLine + hSpaceLineText; @@ -262,7 +260,7 @@ void QgsDataDefinedSizeLegend::drawCollapsedLegend( QgsRenderContext &context, Q { s->setSize( c.size ); - int outputSymbolSize = std::round( context.convertToPainterUnits( c.size, s->sizeUnit(), s->sizeMapUnitScale() ) ); + double outputSymbolSize = context.convertToPainterUnits( c.size, s->sizeUnit(), s->sizeMapUnitScale() ); double tx = ( outputLargestSize - outputSymbolSize ) / 2; p->save(); @@ -305,10 +303,10 @@ QImage QgsDataDefinedSizeLegend::collapsedLegendImage( QgsRenderContext &context return QImage(); // find out the size first - QSize contentSize; + QSizeF contentSize; drawCollapsedLegend( context, &contentSize ); - int padding = std::round( context.convertToPainterUnits( paddingMM, QgsUnitTypes::RenderMillimeters ) ); + double padding = context.convertToPainterUnits( paddingMM, QgsUnitTypes::RenderMillimeters ); int dpm = std::round( context.scaleFactor() * 1000 ); // scale factor = dots per millimeter QImage img( contentSize.width() + padding * 2, contentSize.height() + padding * 2, QImage::Format_ARGB32_Premultiplied ); diff --git a/src/core/qgsdatadefinedsizelegend.h b/src/core/qgsdatadefinedsizelegend.h index 074ba1f5cd52..16fc1a37fe04 100644 --- a/src/core/qgsdatadefinedsizelegend.h +++ b/src/core/qgsdatadefinedsizelegend.h @@ -133,7 +133,7 @@ class CORE_EXPORT QgsDataDefinedSizeLegend * If the painter in context is NULLPTR, it only does size calculation without actual rendering. * Does nothing if legend is not configured as collapsed. */ - void drawCollapsedLegend( QgsRenderContext &context, QSize *outputSize SIP_OUT = nullptr, int *labelXOffset SIP_OUT = nullptr ) const; + void drawCollapsedLegend( QgsRenderContext &context, QSizeF *outputSize SIP_OUT = nullptr, double *labelXOffset SIP_OUT = nullptr ) const; //! Returns output image that would be shown in the legend. Returns invalid image if legend is not configured as collapsed. QImage collapsedLegendImage( QgsRenderContext &context, const QColor &backgroundColor = Qt::transparent, double paddingMM = 1 ) const;