QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgshollowscalebarrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgshollowscalebarrenderer.cpp
3  --------------------------------
4  begin : March 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "qgsscalebarsettings.h"
19 #include "qgslayoututils.h"
20 #include "qgssymbol.h"
21 #include "qgsfillsymbollayer.h"
22 #include "qgstextrenderer.h"
23 #include "qgslinesymbol.h"
24 #include "qgsfillsymbol.h"
25 #include <QList>
26 #include <QPainter>
27 
29 {
30  return QStringLiteral( "hollow" );
31 }
32 
34 {
35  return QObject::tr( "Hollow" );
36 }
37 
38 QgsScaleBarRenderer::Flags QgsHollowScaleBarRenderer::flags() const
39 {
50 }
51 
53 {
54  return 8;
55 }
56 
58 {
59  return new QgsHollowScaleBarRenderer( *this );
60 }
61 
62 void QgsHollowScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBarSettings &settings, const ScaleBarContext &scaleContext ) const
63 {
64  if ( !context.painter() )
65  {
66  return;
67  }
68  QPainter *painter = context.painter();
69 
70  const double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
71  const double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
72  const QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
73  const double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
74  const double barHeight = context.convertToPainterUnits( settings.height(), QgsUnitTypes::RenderMillimeters );
75 
76  painter->save();
77  context.setPainterFlagsUsingContext( painter );
78 
79  std::unique_ptr< QgsLineSymbol > lineSymbol( settings.lineSymbol()->clone() );
80  lineSymbol->startRender( context );
81 
82  std::unique_ptr< QgsFillSymbol > fillSymbol1( settings.fillSymbol()->clone() );
83  fillSymbol1->startRender( context );
84 
85  std::unique_ptr< QgsFillSymbol > fillSymbol2( settings.alternateFillSymbol()->clone() );
86  fillSymbol2->startRender( context );
87 
88  painter->setPen( Qt::NoPen );
89  painter->setBrush( Qt::NoBrush );
90 
91  bool useColor = true; //alternate brush color/white
92  const double xOffset = firstLabelXOffset( settings, context, scaleContext );
93 
94  const QList<double> positions = segmentPositions( context, scaleContext, settings );
95  const QList<double> widths = segmentWidths( scaleContext, settings );
96 
97  // draw the fill
98  double minX = 0;
99  double maxX = 0;
100  QgsFillSymbol *currentSymbol = nullptr;
101  for ( int i = 0; i < positions.size(); ++i )
102  {
103  if ( useColor ) //alternating colors
104  {
105  currentSymbol = fillSymbol1.get();
106  }
107  else //secondary fill
108  {
109  currentSymbol = fillSymbol2.get();
110  }
111 
112  const double thisX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
113  const double thisWidth = context.convertToPainterUnits( widths.at( i ), QgsUnitTypes::RenderMillimeters );
114 
115  if ( i == 0 )
116  minX = thisX;
117  if ( i == positions.size() - 1 )
118  maxX = thisX + thisWidth;
119 
120  const QRectF segmentRect( thisX, barTopPosition, thisWidth, barHeight );
121  currentSymbol->renderPolygon( QPolygonF()
122  << segmentRect.topLeft()
123  << segmentRect.topRight()
124  << segmentRect.bottomRight()
125  << segmentRect.bottomLeft()
126  << segmentRect.topLeft(), nullptr, nullptr, context );
127  useColor = !useColor;
128  }
129 
130  // and then the lines
131  // note that we do this layer-by-layer, to avoid ugliness where the lines touch the outer rect
132  for ( int layer = 0; layer < lineSymbol->symbolLayerCount(); ++layer )
133  {
134  // horizontal lines
135  bool drawLine = false;
136  for ( int i = 0; i < positions.size(); ++i )
137  {
138  drawLine = !drawLine;
139  if ( !drawLine )
140  continue;
141 
142  const double lineX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
143  const double lineLength = context.convertToPainterUnits( widths.at( i ), QgsUnitTypes::RenderMillimeters );
144  lineSymbol->renderPolyline( QPolygonF()
145  << QPointF( lineX, barTopPosition + barHeight / 2.0 )
146  << QPointF( lineX + lineLength, barTopPosition + barHeight / 2.0 ),
147  nullptr, context, layer );
148  }
149 
150  // vertical lines
151  for ( int i = 1; i < positions.size(); ++i )
152  {
153  const double lineX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
154  lineSymbol->renderPolyline( QPolygonF()
155  << QPointF( lineX, barTopPosition )
156  << QPointF( lineX, barTopPosition + barHeight ),
157  nullptr, context, layer );
158  }
159 
160  // outside line
161  lineSymbol->renderPolyline( QPolygonF()
162  << QPointF( minX, barTopPosition )
163  << QPointF( maxX, barTopPosition )
164  << QPointF( maxX, barTopPosition + barHeight )
165  << QPointF( minX, barTopPosition + barHeight )
166  << QPointF( minX, barTopPosition ),
167  nullptr, context, layer );
168  }
169 
170  lineSymbol->stopRender( context );
171  fillSymbol1->stopRender( context );
172  fillSymbol2->stopRender( context );
173  painter->restore();
174 
175  //draw labels using the default method
176  drawDefaultLabels( context, settings, scaleContext );
177 }
178 
180 {
181  // null the fill symbols by default
182  std::unique_ptr< QgsFillSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
183  std::unique_ptr< QgsSimpleFillSymbolLayer > fillSymbolLayer = std::make_unique< QgsSimpleFillSymbolLayer >();
184  fillSymbolLayer->setColor( QColor( 0, 0, 0 ) );
185  fillSymbolLayer->setBrushStyle( Qt::NoBrush );
186  fillSymbolLayer->setStrokeStyle( Qt::NoPen );
187  fillSymbol->changeSymbolLayer( 0, fillSymbolLayer->clone() );
188  settings.setFillSymbol( fillSymbol.release() );
189 
190  fillSymbol = std::make_unique< QgsFillSymbol >();
191  fillSymbolLayer->setColor( QColor( 255, 255, 255 ) );
192  fillSymbol->changeSymbolLayer( 0, fillSymbolLayer.release() );
193  settings.setAlternateFillSymbol( fillSymbol.release() );
194 
195  return true;
196 }
197 
198 
199 
QgsScaleBarSettings::height
double height() const
Returns the scalebar height (in millimeters).
Definition: qgsscalebarsettings.h:550
QgsScaleBarSettings::lineSymbol
QgsLineSymbol * lineSymbol() const
Returns the line symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:193
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:169
QgsScaleBarRenderer::ScaleBarContext
Contains parameters regarding scalebar calculations.
Definition: qgsscalebarrenderer.h:70
QgsScaleBarRenderer::Flag::FlagUsesUnitLabel
@ FlagUsesUnitLabel
Renderer uses the QgsScaleBarSettings::unitLabel() setting.
QgsHollowScaleBarRenderer::id
QString id() const override
Returns the unique ID for this renderer.
Definition: qgshollowscalebarrenderer.cpp:28
QgsHollowScaleBarRenderer::flags
Flags flags() const override
Returns the scalebar rendering flags, which dictates the renderer's behavior.
Definition: qgshollowscalebarrenderer.cpp:38
qgstextrenderer.h
QgsScaleBarRenderer::segmentWidths
QList< double > segmentWidths(const QgsScaleBarRenderer::ScaleBarContext &scaleContext, const QgsScaleBarSettings &settings) const
Returns a list of widths of each segment of the scalebar.
Definition: qgsscalebarrenderer.cpp:396
QgsLineSymbol::clone
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgslinesymbol.cpp:303
QgsScaleBarRenderer::Flag::FlagUsesFillSymbol
@ FlagUsesFillSymbol
Renderer utilizes the scalebar fill symbol (see QgsScaleBarSettings::fillSymbol() )
QgsScaleBarRenderer::Flag::FlagUsesAlternateFillSymbol
@ FlagUsesAlternateFillSymbol
Renderer utilizes the alternate scalebar fill symbol (see QgsScaleBarSettings::alternateFillSymbol() ...
QgsTextRenderer::fontMetrics
static QFontMetricsF fontMetrics(QgsRenderContext &context, const QgsTextFormat &format, double scaleFactor=1.0)
Returns the font metrics for the given text format, when rendered in the specified render context.
Definition: qgstextrenderer.cpp:280
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsScaleBarSettings::fillSymbol
QgsFillSymbol * fillSymbol() const
Returns the primary fill symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:223
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QgsScaleBarRenderer::Flag::FlagUsesLabelHorizontalPlacement
@ FlagUsesLabelHorizontalPlacement
Renderer uses the QgsScaleBarSettings::labelHorizontalPlacement() setting.
QgsHollowScaleBarRenderer::sortKey
int sortKey() const override
Returns a sorting key value, where renderers with a lower sort key will be shown earlier in lists.
Definition: qgshollowscalebarrenderer.cpp:52
QgsHollowScaleBarRenderer::clone
QgsHollowScaleBarRenderer * clone() const override
Returns a clone of the renderer.
Definition: qgshollowscalebarrenderer.cpp:57
QgsHollowScaleBarRenderer::QgsHollowScaleBarRenderer
QgsHollowScaleBarRenderer()=default
Constructor for QgsHollowScaleBarRenderer.
qgsscalebarsettings.h
qgslayoututils.h
QgsHollowScaleBarRenderer::visibleName
QString visibleName() const override
Returns the user friendly, translated name for the renderer.
Definition: qgshollowscalebarrenderer.cpp:33
QgsScaleBarSettings::labelBarSpace
double labelBarSpace() const
Returns the spacing (in millimeters) between labels and the scalebar.
Definition: qgsscalebarsettings.h:562
QgsScaleBarRenderer::Flag::FlagUsesLabelVerticalPlacement
@ FlagUsesLabelVerticalPlacement
Renderer uses the QgsScaleBarSettings::labelVerticalPlacement() setting.
QgsScaleBarSettings::boxContentSpace
double boxContentSpace() const
Returns the spacing (margin) between the scalebar box and content in millimeters.
Definition: qgsscalebarsettings.h:602
QgsScaleBarSettings::labelVerticalPlacement
LabelVerticalPlacement labelVerticalPlacement() const
Returns the vertical placement of text labels.
Definition: qgsscalebarsettings.h:575
QgsScaleBarSettings::textFormat
QgsTextFormat & textFormat()
Returns the text format used for drawing text in the scalebar.
Definition: qgsscalebarsettings.h:268
QgsScaleBarRenderer::Flag::FlagUsesLineSymbol
@ FlagUsesLineSymbol
Renderer utilizes the scalebar line symbol (see QgsScaleBarSettings::lineSymbol() )
QgsScaleBarSettings
The QgsScaleBarSettings class stores the appearance and layout settings for scalebar drawing with Qgs...
Definition: qgsscalebarsettings.h:40
QgsScaleBarRenderer::Flag::FlagRespectsMapUnitsPerScaleBarUnit
@ FlagRespectsMapUnitsPerScaleBarUnit
Renderer respects the QgsScaleBarSettings::mapUnitsPerScaleBarUnit() setting.
QgsHollowScaleBarRenderer::draw
void draw(QgsRenderContext &context, const QgsScaleBarSettings &settings, const QgsScaleBarRenderer::ScaleBarContext &scaleContext) const override
Draws the scalebar using the specified settings and scaleContext to a destination render context.
Definition: qgshollowscalebarrenderer.cpp:62
QgsScaleBarRenderer::firstLabelXOffset
Q_DECL_DEPRECATED double firstLabelXOffset(const QgsScaleBarSettings &settings) const
Returns the x-offset (in millimeters) used for the first label in the scalebar.
Definition: qgsscalebarrenderer.cpp:311
qgsfillsymbollayer.h
QgsFillSymbol::renderPolygon
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol using the given render context.
Definition: qgsfillsymbol.cpp:39
qgshollowscalebarrenderer.h
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
QgsScaleBarSettings::LabelAboveSegment
@ LabelAboveSegment
Labels are drawn above the scalebar.
Definition: qgsscalebarsettings.h:68
QgsHollowScaleBarRenderer::applyDefaultSettings
bool applyDefaultSettings(QgsScaleBarSettings &settings) const override
Applies any default settings relating to the scalebar to the passed settings object.
Definition: qgshollowscalebarrenderer.cpp:179
QgsScaleBarRenderer::drawDefaultLabels
void drawDefaultLabels(QgsRenderContext &context, const QgsScaleBarSettings &settings, const QgsScaleBarRenderer::ScaleBarContext &scaleContext) const
Draws default scalebar labels using the specified settings and scaleContext to a destination render c...
Definition: qgsscalebarrenderer.cpp:30
QgsScaleBarRenderer::Flag::FlagRespectsUnits
@ FlagRespectsUnits
Renderer respects the QgsScaleBarSettings::units() setting.
QgsScaleBarSettings::setFillSymbol
void setFillSymbol(QgsFillSymbol *symbol)
Sets the primary fill symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:228
QgsFillSymbol::clone
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgsfillsymbol.cpp:144
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
QgsScaleBarRenderer::Flag::FlagUsesLabelBarSpace
@ FlagUsesLabelBarSpace
Renderer uses the QgsScaleBarSettings::labelBarSpace() setting.
QgsScaleBarRenderer::Flag::FlagUsesSegments
@ FlagUsesSegments
Renderer uses the scalebar segments.
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsScaleBarSettings::setAlternateFillSymbol
void setAlternateFillSymbol(QgsFillSymbol *symbol)
Sets the secondary fill symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:238
QgsScaleBarSettings::alternateFillSymbol
QgsFillSymbol * alternateFillSymbol() const
Returns the secondary fill symbol used to render the scalebar (only used for some scalebar types).
Definition: qgsscalebarsettings.cpp:233
qgsfillsymbol.h
qgssymbol.h
QgsHollowScaleBarRenderer
Scalebar style that draws a single box with alternating color for the segments, with horizontal lines...
Definition: qgshollowscalebarrenderer.h:31
qgslinesymbol.h
QgsScaleBarRenderer::segmentPositions
Q_DECL_DEPRECATED QList< double > segmentPositions(const QgsScaleBarRenderer::ScaleBarContext &scaleContext, const QgsScaleBarSettings &settings) const
Returns a list of positions for each segment within the scalebar.
Definition: qgsscalebarrenderer.cpp:341