QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
qgslayoutitemscalebar.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutitemscalebar.cpp
3 -------------------------
4 begin : November 2017
5 copyright : (C) 2017 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
19#include <cmath>
20
21#include "qgsdistancearea.h"
22#include "qgsfillsymbol.h"
23#include "qgsfillsymbollayer.h"
24#include "qgsfontutils.h"
25#include "qgslayout.h"
26#include "qgslayoutitemmap.h"
29#include "qgslayoututils.h"
30#include "qgslinesymbol.h"
31#include "qgslinesymbollayer.h"
32#include "qgsmessagelog.h"
33#include "qgsnumericformat.h"
35#include "qgsproject.h"
36#include "qgsrectangle.h"
37#include "qgsscalebarrenderer.h"
39#include "qgssettings.h"
42#include "qgssymbollayerutils.h"
43#include "qgsunittypes.h"
44
45#include <QAbstractTextDocumentLayout>
46#include <QDomDocument>
47#include <QDomElement>
48#include <QFontMetricsF>
49#include <QPainter>
50#include <QString>
51#include <QTextDocument>
52
53#include "moc_qgslayoutitemscalebar.cpp"
54
55using namespace Qt::StringLiterals;
56
63
68
70{
71 return QgsApplication::getThemeIcon( u"/mLayoutItemScaleBar.svg"_s );
72}
73
78
80{
82
83 const QgsScaleBarRenderer::ScaleBarContext scaleContext = createScaleContext();
84 if ( !scaleContext.isValid() )
85 return QgsLayoutSize();
86
87 return QgsLayoutSize( mStyle->calculateBoxSize( context, mSettings, scaleContext ), Qgis::LayoutUnit::Millimeters );
88}
89
91{
92 if ( !mStyle )
93 return;
94
95 const QgsScaleBarRenderer::ScaleBarContext scaleContext = createScaleContext();
96 if ( !scaleContext.isValid() )
97 {
98 if ( mLayout->renderContext().isPreviewRender() )
99 {
100 // No initial render available - so draw some preview text alerting user
101 QPainter *painter = context.renderContext().painter();
102
103 const double scale = context.renderContext().convertToPainterUnits( 1, Qgis::RenderUnit::Millimeters );
104 const QRectF thisPaintRect = QRectF( 0, 0, rect().width() * scale, rect().height() * scale );
105
106 painter->setBrush( QBrush( QColor( 255, 125, 125, 125 ) ) );
107 painter->setPen( Qt::NoPen );
108 painter->drawRect( thisPaintRect );
109 painter->setBrush( Qt::NoBrush );
110
111 painter->setPen( QColor( 200, 0, 0, 255 ) );
112 QTextDocument td;
113 td.setTextWidth( thisPaintRect.width() );
114 td.setHtml(
115 u"<span style=\"color: rgb(200,0,0);\"><b>%1</b><br>%2</span>"_s.arg( tr( "Invalid scale!" ), tr( "The scale bar cannot be rendered due to invalid settings or an incompatible linked map extent." ) )
116 );
117 painter->setClipRect( thisPaintRect );
118 QAbstractTextDocumentLayout::PaintContext ctx;
119 td.documentLayout()->draw( painter, ctx );
120 }
121 return;
122 }
123
125 {
126 // compatibility code - ScalebarLineColor and ScalebarLineWidth are deprecated
128 std::unique_ptr< QgsLineSymbol > sym( mSettings.lineSymbol()->clone() );
131 sym->setWidth( mDataDefinedProperties.valueAsDouble( QgsLayoutObject::DataDefinedProperty::ScalebarLineWidth, expContext, mSettings.lineWidth() ) );
133 sym->setColor( mDataDefinedProperties.valueAsColor( QgsLayoutObject::DataDefinedProperty::ScalebarLineColor, expContext, mSettings.lineColor() ) );
135 mSettings.setLineSymbol( sym.release() );
136 }
138 {
139 // compatibility code - ScalebarLineColor and ScalebarLineWidth are deprecated
141 std::unique_ptr< QgsFillSymbol > sym( mSettings.fillSymbol()->clone() );
143 sym->setColor( mDataDefinedProperties.valueAsColor( QgsLayoutObject::DataDefinedProperty::ScalebarFillColor, expContext, mSettings.fillColor() ) );
145 mSettings.setFillSymbol( sym.release() );
146 }
148 {
149 // compatibility code - ScalebarLineColor and ScalebarLineWidth are deprecated
151 std::unique_ptr< QgsFillSymbol > sym( mSettings.alternateFillSymbol()->clone() );
153 sym->setColor( mDataDefinedProperties.valueAsColor( QgsLayoutObject::DataDefinedProperty::ScalebarFillColor2, expContext, mSettings.fillColor2() ) );
155 mSettings.setAlternateFillSymbol( sym.release() );
156 }
157
158 mStyle->draw( context.renderContext(), mSettings, scaleContext );
159}
160
162{
163 if ( !mStyle )
164 {
165 mSettings.setNumberOfSegments( nSegments );
166 return;
167 }
168 mSettings.setNumberOfSegments( nSegments );
170}
171
173{
174 if ( !mStyle )
175 {
176 mSettings.setUnitsPerSegment( units );
177 return;
178 }
179 mSettings.setUnitsPerSegment( units );
180 refreshSegmentMillimeters();
182}
183
184
186{
187 if ( !mStyle )
188 {
189 mSettings.setSegmentSizeMode( mode );
190 return;
191 }
192 mSettings.setSegmentSizeMode( mode );
193 refreshSegmentMillimeters();
195}
196
198{
199 if ( !mStyle )
200 {
201 mSettings.setMinimumBarWidth( minWidth );
202 return;
203 }
204 mSettings.setMinimumBarWidth( minWidth );
205 refreshSegmentMillimeters();
207}
208
210{
211 if ( !mStyle )
212 {
213 mSettings.setMaximumBarWidth( maxWidth );
214 return;
215 }
216 mSettings.setMaximumBarWidth( maxWidth );
217 refreshSegmentMillimeters();
219}
220
222{
223 return mSettings.textFormat();
224}
225
227{
228 mSettings.setTextFormat( format );
230 emit changed();
231}
232
234{
235 return mSettings.lineSymbol();
236}
237
239{
240 mSettings.setLineSymbol( symbol );
241}
242
244{
245 return mSettings.divisionLineSymbol();
246}
247
249{
250 mSettings.setDivisionLineSymbol( symbol );
251}
252
254{
255 return mSettings.subdivisionLineSymbol();
256}
257
259{
260 mSettings.setSubdivisionLineSymbol( symbol );
261}
262
264{
265 return mSettings.fillSymbol();
266}
267
269{
270 mSettings.setFillSymbol( symbol );
271}
272
274{
275 return mSettings.alternateFillSymbol();
276}
277
279{
280 mSettings.setAlternateFillSymbol( symbol );
281}
282
284{
285 if ( !mStyle )
286 {
287 mSettings.setNumberOfSegmentsLeft( nSegmentsLeft );
288 return;
289 }
290 mSettings.setNumberOfSegmentsLeft( nSegmentsLeft );
292}
293
295{
296 if ( !mStyle )
297 {
298 mSettings.setBoxContentSpace( space );
299 return;
300 }
301 mSettings.setBoxContentSpace( space );
303}
304
306{
307 disconnectCurrentMap();
308
309 mMap = map;
310
311 if ( !map )
312 {
313 return;
314 }
315
316 connect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemScaleBar::updateScale );
317 connect( mMap, &QObject::destroyed, this, &QgsLayoutItemScaleBar::disconnectCurrentMap );
318
319 refreshSegmentMillimeters();
320 emit changed();
321}
322
323void QgsLayoutItemScaleBar::disconnectCurrentMap()
324{
325 if ( !mMap )
326 {
327 return;
328 }
329
330 disconnect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemScaleBar::updateScale );
331 disconnect( mMap, &QObject::destroyed, this, &QgsLayoutItemScaleBar::disconnectCurrentMap );
332 mMap = nullptr;
333}
334
339
341{
342 if ( mMethod == method )
343 return;
344
345 mMethod = method;
346 refreshSegmentMillimeters();
348}
349
350void QgsLayoutItemScaleBar::refreshUnitsPerSegment( const QgsExpressionContext *context )
351{
353 {
354 double unitsPerSegment = mSettings.unitsPerSegment();
355 bool ok = false;
357
358 if ( !ok )
359 {
360 QgsMessageLog::logMessage( tr( "Scalebar units per segment expression eval error" ) );
361 }
362 else
363 {
365 }
366 }
367}
368
369void QgsLayoutItemScaleBar::refreshMinimumBarWidth( const QgsExpressionContext *context )
370{
372 {
373 double minimumBarWidth = mSettings.minimumBarWidth();
374
375 bool ok = false;
377
378 if ( !ok )
379 {
380 QgsMessageLog::logMessage( tr( "Scalebar minimum segment width expression eval error" ) );
381 }
382 else
383 {
385 }
386 }
387}
388
389void QgsLayoutItemScaleBar::refreshMaximumBarWidth( const QgsExpressionContext *context )
390{
392 {
393 double maximumBarWidth = mSettings.maximumBarWidth();
394
395 bool ok = false;
397
398 if ( !ok )
399 {
400 QgsMessageLog::logMessage( tr( "Scalebar maximum segment width expression eval error" ) );
401 }
402 else
403 {
405 }
406 }
407}
408
409void QgsLayoutItemScaleBar::refreshNumberOfSegmentsLeft( const QgsExpressionContext *context )
410{
412 {
413 int leftSegments = mSettings.numberOfSegmentsLeft();
414
415 bool ok = false;
416 leftSegments = mDataDefinedProperties.valueAsInt( QgsLayoutObject::DataDefinedProperty::ScalebarLeftSegments, *context, leftSegments, &ok );
417
418 if ( !ok )
419 {
420 QgsMessageLog::logMessage( tr( "Scalebar left segment count expression eval error" ) );
421 }
422 else
423 {
424 setNumberOfSegmentsLeft( leftSegments );
425 }
426 }
427}
428
429void QgsLayoutItemScaleBar::refreshNumberOfSegmentsRight( const QgsExpressionContext *context )
430{
432 {
433 int rightSegments = mSettings.numberOfSegments();
434
435 bool ok = false;
436 rightSegments = mDataDefinedProperties.valueAsInt( QgsLayoutObject::DataDefinedProperty::ScalebarRightSegments, *context, rightSegments, &ok );
437
438 if ( !ok )
439 {
440 QgsMessageLog::logMessage( tr( "Scalebar left segment count expression eval error" ) );
441 }
442 else
443 {
444 setNumberOfSegments( rightSegments );
445 }
446 }
447}
448
450{
452
453 bool forceUpdate = false;
454
457 {
458 double height = mSettings.height();
459
460 bool ok = false;
462
463 if ( !ok )
464 {
465 QgsMessageLog::logMessage( tr( "Scalebar height expression eval error" ) );
466 }
467 else
468 {
469 setHeight( height );
470 }
471
472 forceUpdate = true;
473 }
474
477 {
478 double height = mSettings.subdivisionsHeight();
479
480 bool ok = false;
482
483 if ( !ok )
484 {
485 QgsMessageLog::logMessage( tr( "Scalebar subdivision height expression eval error" ) );
486 }
487 else
488 {
490 }
491
492 forceUpdate = true;
493 }
494
496 {
497 refreshNumberOfSegmentsLeft( &context );
498 forceUpdate = true;
499 }
500
502 {
503 refreshNumberOfSegmentsRight( &context );
504 forceUpdate = true;
505 }
506
509 {
510 int segments = mSettings.numberOfSubdivisions();
511
512 bool ok = false;
514
515 if ( !ok )
516 {
517 QgsMessageLog::logMessage( tr( "Scalebar number of subdivisions expression eval error" ) );
518 }
519 else
520 {
521 setNumberOfSubdivisions( segments );
522 }
523
524 forceUpdate = true;
525 }
526
527
529 {
530 refreshUnitsPerSegment( &context );
531 forceUpdate = true;
532 }
533
535 {
536 refreshMinimumBarWidth( &context );
537 forceUpdate = true;
538 }
539
541 {
542 refreshMaximumBarWidth( &context );
543 forceUpdate = true;
544 }
545
546 // updates data defined properties and redraws item to match
547 // -- Deprecated --
549 {
550 forceUpdate = true;
551 }
553 {
554 forceUpdate = true;
555 }
557 {
558 forceUpdate = true;
559 }
561 {
562 forceUpdate = true;
563 }
564
565 if ( forceUpdate )
566 {
568 update();
569 }
570
572}
573
574void QgsLayoutItemScaleBar::refreshSegmentMillimeters()
575{
576 if ( mMap )
577 {
578 //get mm dimension of composer map
579 const QRectF composerItemRect = mMap->rect();
580
581 const double currentMapWidth = mapWidth();
582 if ( qgsDoubleNear( currentMapWidth, 0 ) || std::isnan( currentMapWidth ) )
583 {
584 mSegmentMillimeters = std::numeric_limits< double >::quiet_NaN();
585 return;
586 }
587
588 switch ( mSettings.segmentSizeMode() )
589 {
591 {
592 //calculate size depending on mNumUnitsPerSegment
593 mSegmentMillimeters = composerItemRect.width() / currentMapWidth * mSettings.unitsPerSegment();
594 break;
595 }
596
598 {
599 if ( mSettings.maximumBarWidth() < mSettings.minimumBarWidth() )
600 {
601 mSegmentMillimeters = 0;
602 }
603 else
604 {
605 const double nSegments = ( mSettings.numberOfSegmentsLeft() != 0 ) + mSettings.numberOfSegments();
606 // unitsPerSegments which fit minBarWidth resp. maxBarWidth
607 const double minUnitsPerSeg = ( mSettings.minimumBarWidth() * currentMapWidth ) / ( nSegments * composerItemRect.width() );
608 const double maxUnitsPerSeg = ( mSettings.maximumBarWidth() * currentMapWidth ) / ( nSegments * composerItemRect.width() );
609 mSettings.setUnitsPerSegment( QgsLayoutUtils::calculatePrettySize( minUnitsPerSeg, maxUnitsPerSeg ) );
610 mSegmentMillimeters = composerItemRect.width() / currentMapWidth * mSettings.unitsPerSegment();
611 }
612 break;
613 }
614 }
615 }
616}
617
618double QgsLayoutItemScaleBar::mapWidth() const
619{
620 if ( !mMap )
621 {
622 return 0.0;
623 }
624
625 const QgsRectangle mapExtent = mMap->extent();
626 if ( mSettings.units() == Qgis::DistanceUnit::Unknown )
627 {
628 return mapExtent.width();
629 }
630 else
631 {
632 QgsDistanceArea da;
633 da.setSourceCrs( mMap->crs(), mLayout->project()->transformContext() );
634 da.setEllipsoid( mLayout->project()->ellipsoid() );
635
637
638 QList< double > yValues;
639 switch ( mMethod )
640 {
642 yValues << mapExtent.yMaximum();
643 break;
644
646 yValues << 0.5 * ( mapExtent.yMaximum() + mapExtent.yMinimum() );
647 break;
648
649
651 yValues << mapExtent.yMinimum();
652 break;
653
655 yValues << mapExtent.yMaximum();
656 yValues << 0.5 * ( mapExtent.yMaximum() + mapExtent.yMinimum() );
657 yValues << mapExtent.yMinimum();
658 break;
659
661 if ( mMap->crs().mapUnits() == Qgis::DistanceUnit::Degrees )
662 {
663 yValues << 0;
664 }
665 else
666 {
667 // this method is only for degree based systems, so just fallback to default if not degree based
668 yValues << 0.5 * ( mapExtent.yMaximum() + mapExtent.yMinimum() );
669 }
670 break;
671 }
672
673 double sumValidMeasures = 0;
674 int validMeasureCount = 0;
675
676 for ( const double y : std::as_const( yValues ) )
677 {
678 try
679 {
680 double measure = da.measureLine( QgsPointXY( mapExtent.xMinimum(), y ), QgsPointXY( mapExtent.xMaximum(), y ) );
681 if ( std::isnan( measure ) )
682 {
683 // TODO report errors to user
684 QgsDebugError( u"An error occurred while calculating length"_s );
685 continue;
686 }
687
688 measure /= QgsUnitTypes::fromUnitToUnitFactor( mSettings.units(), units );
689 sumValidMeasures += measure;
690 validMeasureCount++;
691 }
692 catch ( QgsCsException & )
693 {
694 // TODO report errors to user
695 QgsDebugError( u"An error occurred while calculating length"_s );
696 continue;
697 }
698 }
699
700 if ( validMeasureCount == 0 )
701 return std::numeric_limits< double >::quiet_NaN();
702
703 return sumValidMeasures / validMeasureCount;
704 }
705}
706
707QgsScaleBarRenderer::ScaleBarContext QgsLayoutItemScaleBar::createScaleContext() const
708{
709 QgsScaleBarRenderer::ScaleBarContext scaleContext;
710 scaleContext.size = rect().size();
711 scaleContext.segmentWidth = mSegmentMillimeters;
712 scaleContext.scale = mMap ? mMap->scale() : 1.0;
713 scaleContext.flags = mStyle->flags();
714 return scaleContext;
715}
716
718{
719 mSettings.setLabelVerticalPlacement( placement );
721 emit changed();
722}
723
725{
726 mSettings.setLabelHorizontalPlacement( placement );
728 emit changed();
729}
730
732{
733 mSettings.setAlignment( a );
735 emit changed();
736}
737
739{
740 mSettings.setUnits( u );
741 refreshSegmentMillimeters();
743 emit changed();
744}
745
747{
749 return mSettings.lineJoinStyle();
751}
752
754{
756 if ( mSettings.lineJoinStyle() == style )
757 {
758 //no change
759 return;
760 }
761 mSettings.setLineJoinStyle( style );
763 update();
764 emit changed();
765}
766
768{
770 return mSettings.lineCapStyle();
772}
773
775{
777 if ( mSettings.lineCapStyle() == style )
778 {
779 //no change
780 return;
781 }
782 mSettings.setLineCapStyle( style );
784 update();
785 emit changed();
786}
787
789{
790 //style
791 mStyle = std::make_unique< QgsSingleBoxScaleBarRenderer >();
792
793 //default to no background
794 setBackgroundEnabled( false );
795
796 //get default composer font from settings
797 const QgsSettings settings;
798 const QString defaultFontString = settings.value( u"LayoutDesigner/defaultFont"_s, QVariant(), QgsSettings::Gui ).toString();
799 QgsTextFormat format;
800 QFont f;
801 if ( !defaultFontString.isEmpty() )
802 {
803 QgsFontUtils::setFontFamily( f, defaultFontString );
804 }
805 format.setFont( f );
806 format.setSize( 12.0 );
808
809 mSettings.setTextFormat( format );
810
811 mSettings.setUnits( Qgis::DistanceUnit::Unknown );
813
814 emit changed();
815}
816
818{
819 return renderer->applyDefaultSettings( mSettings );
820}
821
823{
824 if ( !mMap )
826
827 const QgsCoordinateReferenceSystem crs = mMap->crs();
828 // start with crs units
829 Qgis::DistanceUnit unit = crs.mapUnits();
831 {
832 // geographic CRS, use metric units
834 }
835
836 // try to pick reasonable choice between metric / imperial units
837 const double widthInSelectedUnits = mapWidth();
838 if ( std::isnan( widthInSelectedUnits ) )
839 return unit;
840
841 const double initialUnitsPerSegment = widthInSelectedUnits / 10.0; //default scalebar width equals half the map width
842 switch ( unit )
843 {
845 {
846 if ( initialUnitsPerSegment > 1000.0 )
847 {
849 }
850 break;
851 }
853 {
854 if ( initialUnitsPerSegment > 5419.95 )
855 {
857 }
858 break;
859 }
860 default:
861 break;
862 }
863
864 return unit;
865}
866
868{
869 mSettings.setUnits( units );
870 if ( mMap )
871 {
872 double upperMagnitudeMultiplier = 1.0;
873 const double widthInSelectedUnits = mapWidth();
874 if ( !std::isnan( widthInSelectedUnits ) )
875 {
876 const double initialUnitsPerSegment = widthInSelectedUnits / 10.0; //default scalebar width equals half the map width
877 mSettings.setUnitsPerSegment( initialUnitsPerSegment );
878
880 upperMagnitudeMultiplier = 1;
881
882 const double segmentWidth = initialUnitsPerSegment / upperMagnitudeMultiplier;
883 const int segmentMagnitude = std::floor( std::log10( segmentWidth ) );
884 double unitsPerSegment = upperMagnitudeMultiplier * ( std::pow( 10.0, segmentMagnitude ) );
885 const double multiplier = std::floor( ( widthInSelectedUnits / ( unitsPerSegment * 10.0 ) ) / 2.5 ) * 2.5;
886
887 if ( multiplier > 0 )
888 {
889 unitsPerSegment = unitsPerSegment * multiplier;
890 }
891 mSettings.setUnitsPerSegment( unitsPerSegment );
892 mSettings.setMapUnitsPerScaleBarUnit( upperMagnitudeMultiplier );
893
894 mSettings.setNumberOfSegments( 2 );
895 mSettings.setNumberOfSegmentsLeft( 0 );
896 }
897 }
898
899 refreshSegmentMillimeters();
901 emit changed();
902}
903
905{
906 if ( !mStyle )
907 return;
908
910
911 const QgsScaleBarRenderer::ScaleBarContext scaleContext = createScaleContext();
912 if ( !scaleContext.isValid() )
913 return;
914
915 const double widthMM = mStyle->calculateBoxSize( context, mSettings, scaleContext ).width();
916 QgsLayoutSize currentSize = sizeWithUnits();
917 currentSize.setWidth( mLayout->renderContext().measurementConverter().convert( QgsLayoutMeasurement( widthMM, Qgis::LayoutUnit::Millimeters ), currentSize.units() ).length() );
918 attemptResize( currentSize );
919 update();
920 emit changed();
921}
922
924{
925 //Don't adjust box size for numeric scale bars:
926 if ( mStyle && mStyle->id() != "Numeric"_L1 )
927 {
929 }
930 QgsLayoutItem::update();
931}
932
933void QgsLayoutItemScaleBar::updateScale()
934{
935 refreshSegmentMillimeters();
936 //Don't adjust box size for numeric scale bars:
937 if ( mStyle && mStyle->id() != "Numeric"_L1 )
938 {
940 }
941 update();
942}
943
944void QgsLayoutItemScaleBar::setStyle( const QString &styleName )
945{
946 //switch depending on style name
947 std::unique_ptr< QgsScaleBarRenderer> renderer( QgsApplication::scaleBarRendererRegistry()->renderer( styleName ) );
948 if ( renderer )
949 {
950 mStyle = std::move( renderer );
951 }
953 emit changed();
954}
955
957{
958 if ( mStyle )
959 {
960 return mStyle->id();
961 }
962 else
963 {
964 return QString();
965 }
966}
967
969{
970 return mSettings.numericFormat();
971}
972
974{
975 mSettings.setNumericFormat( format );
976}
977
979{
980 return mSettings.textFormat().font();
981}
982
984{
986 mSettings.setFont( font );
989 emit changed();
990}
991
993{
994 QColor color = mSettings.textFormat().color();
995 color.setAlphaF( mSettings.textFormat().opacity() );
996 return color;
997}
998
999void QgsLayoutItemScaleBar::setFontColor( const QColor &color )
1000{
1001 mSettings.textFormat().setColor( color );
1002 mSettings.textFormat().setOpacity( color.alphaF() );
1003}
1004
1006{
1008 return mSettings.fillColor();
1010}
1011
1012void QgsLayoutItemScaleBar::setFillColor( const QColor &color )
1013{
1015 mSettings.setFillColor( color );
1017}
1018
1020{
1022 return mSettings.fillColor2();
1024}
1025
1026void QgsLayoutItemScaleBar::setFillColor2( const QColor &color )
1027{
1029 mSettings.setFillColor2( color );
1031}
1032
1034{
1036 return mSettings.lineColor();
1038}
1039
1040void QgsLayoutItemScaleBar::setLineColor( const QColor &color )
1041{
1043 mSettings.setLineColor( color );
1045}
1046
1048{
1050 return mSettings.lineWidth();
1052}
1053
1055{
1057 mSettings.setLineWidth( width );
1059}
1060
1062{
1064 return mSettings.pen();
1066}
1067
1069{
1071 return mSettings.brush();
1073}
1074
1076{
1078 return mSettings.brush2();
1080}
1081
1082bool QgsLayoutItemScaleBar::writePropertiesToElement( QDomElement &composerScaleBarElem, QDomDocument &doc, const QgsReadWriteContext &rwContext ) const
1083{
1084 composerScaleBarElem.setAttribute( u"height"_s, QString::number( mSettings.height() ) );
1085 composerScaleBarElem.setAttribute( u"labelBarSpace"_s, QString::number( mSettings.labelBarSpace() ) );
1086 composerScaleBarElem.setAttribute( u"boxContentSpace"_s, QString::number( mSettings.boxContentSpace() ) );
1087 composerScaleBarElem.setAttribute( u"numSegments"_s, mSettings.numberOfSegments() );
1088 composerScaleBarElem.setAttribute( u"numSegmentsLeft"_s, mSettings.numberOfSegmentsLeft() );
1089 composerScaleBarElem.setAttribute( u"numSubdivisions"_s, mSettings.numberOfSubdivisions() );
1090 composerScaleBarElem.setAttribute( u"subdivisionsHeight"_s, mSettings.subdivisionsHeight() );
1091 composerScaleBarElem.setAttribute( u"numUnitsPerSegment"_s, QString::number( mSettings.unitsPerSegment() ) );
1092 composerScaleBarElem.setAttribute( u"segmentSizeMode"_s, static_cast< int >( mSettings.segmentSizeMode() ) );
1093 composerScaleBarElem.setAttribute( u"minBarWidth"_s, mSettings.minimumBarWidth() );
1094 composerScaleBarElem.setAttribute( u"maxBarWidth"_s, mSettings.maximumBarWidth() );
1095 composerScaleBarElem.setAttribute( u"segmentMillimeters"_s, QString::number( mSegmentMillimeters ) );
1096 composerScaleBarElem.setAttribute( u"numMapUnitsPerScaleBarUnit"_s, QString::number( mSettings.mapUnitsPerScaleBarUnit() ) );
1097 composerScaleBarElem.setAttribute( u"method"_s, qgsEnumValueToKey( mMethod ) );
1098
1099 const QDomElement textElem = mSettings.textFormat().writeXml( doc, rwContext );
1100 composerScaleBarElem.appendChild( textElem );
1101
1103 // kept just for allowing projects to open in QGIS < 3.14, remove for 4.0
1104 composerScaleBarElem.setAttribute( u"outlineWidth"_s, QString::number( mSettings.lineWidth() ) );
1105 composerScaleBarElem.setAttribute( u"lineJoinStyle"_s, QgsSymbolLayerUtils::encodePenJoinStyle( mSettings.lineJoinStyle() ) );
1106 composerScaleBarElem.setAttribute( u"lineCapStyle"_s, QgsSymbolLayerUtils::encodePenCapStyle( mSettings.lineCapStyle() ) );
1107 //pen color
1108 QDomElement strokeColorElem = doc.createElement( u"strokeColor"_s );
1109 strokeColorElem.setAttribute( u"red"_s, QString::number( mSettings.lineColor().red() ) );
1110 strokeColorElem.setAttribute( u"green"_s, QString::number( mSettings.lineColor().green() ) );
1111 strokeColorElem.setAttribute( u"blue"_s, QString::number( mSettings.lineColor().blue() ) );
1112 strokeColorElem.setAttribute( u"alpha"_s, QString::number( mSettings.lineColor().alpha() ) );
1113 composerScaleBarElem.appendChild( strokeColorElem );
1115
1116 composerScaleBarElem.setAttribute( u"unitLabel"_s, mSettings.unitLabel() );
1117 composerScaleBarElem.setAttribute( u"unitType"_s, QgsUnitTypes::encodeUnit( mSettings.units() ) );
1118
1119 QDomElement numericFormatElem = doc.createElement( u"numericFormat"_s );
1120 mSettings.numericFormat()->writeXml( numericFormatElem, doc, rwContext );
1121 composerScaleBarElem.appendChild( numericFormatElem );
1122
1123 //style
1124 if ( mStyle )
1125 {
1126 composerScaleBarElem.setAttribute( u"style"_s, mStyle->id() );
1127 }
1128
1129 //map id
1130 if ( mMap )
1131 {
1132 composerScaleBarElem.setAttribute( u"mapUuid"_s, mMap->uuid() );
1133 }
1134
1135 //colors
1136
1138 // kept just for allowing projects to open in QGIS < 3.14, remove for 4.0
1139
1140 //fill color
1141 QDomElement fillColorElem = doc.createElement( u"fillColor"_s );
1142 fillColorElem.setAttribute( u"red"_s, QString::number( mSettings.fillColor().red() ) );
1143 fillColorElem.setAttribute( u"green"_s, QString::number( mSettings.fillColor().green() ) );
1144 fillColorElem.setAttribute( u"blue"_s, QString::number( mSettings.fillColor().blue() ) );
1145 fillColorElem.setAttribute( u"alpha"_s, QString::number( mSettings.fillColor().alpha() ) );
1146 composerScaleBarElem.appendChild( fillColorElem );
1147
1148 //fill color 2
1149 QDomElement fillColor2Elem = doc.createElement( u"fillColor2"_s );
1150 fillColor2Elem.setAttribute( u"red"_s, QString::number( mSettings.fillColor2().red() ) );
1151 fillColor2Elem.setAttribute( u"green"_s, QString::number( mSettings.fillColor2().green() ) );
1152 fillColor2Elem.setAttribute( u"blue"_s, QString::number( mSettings.fillColor2().blue() ) );
1153 fillColor2Elem.setAttribute( u"alpha"_s, QString::number( mSettings.fillColor2().alpha() ) );
1154 composerScaleBarElem.appendChild( fillColor2Elem );
1155
1157
1158 //label vertical/horizontal placement
1159 composerScaleBarElem.setAttribute( u"labelVerticalPlacement"_s, QString::number( static_cast< int >( mSettings.labelVerticalPlacement() ) ) );
1160 composerScaleBarElem.setAttribute( u"labelHorizontalPlacement"_s, QString::number( static_cast< int >( mSettings.labelHorizontalPlacement() ) ) );
1161
1162 //alignment
1163 composerScaleBarElem.setAttribute( u"alignment"_s, QString::number( static_cast< int >( mSettings.alignment() ) ) );
1164
1165 QDomElement lineSymbol = doc.createElement( u"lineSymbol"_s );
1166 const QDomElement symbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mSettings.lineSymbol(), doc, rwContext );
1167 lineSymbol.appendChild( symbolElem );
1168 composerScaleBarElem.appendChild( lineSymbol );
1169
1170 QDomElement divisionSymbol = doc.createElement( u"divisionLineSymbol"_s );
1171 const QDomElement divisionSymbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mSettings.divisionLineSymbol(), doc, rwContext );
1172 divisionSymbol.appendChild( divisionSymbolElem );
1173 composerScaleBarElem.appendChild( divisionSymbol );
1174
1175 QDomElement subdivisionSymbol = doc.createElement( u"subdivisionLineSymbol"_s );
1176 const QDomElement subdivisionSymbolElem = QgsSymbolLayerUtils::saveSymbol( QString(), mSettings.subdivisionLineSymbol(), doc, rwContext );
1177 subdivisionSymbol.appendChild( subdivisionSymbolElem );
1178 composerScaleBarElem.appendChild( subdivisionSymbol );
1179
1180 QDomElement fillSymbol1Elem = doc.createElement( u"fillSymbol1"_s );
1181 const QDomElement symbol1Elem = QgsSymbolLayerUtils::saveSymbol( QString(), mSettings.fillSymbol(), doc, rwContext );
1182 fillSymbol1Elem.appendChild( symbol1Elem );
1183 composerScaleBarElem.appendChild( fillSymbol1Elem );
1184
1185 QDomElement fillSymbol2Elem = doc.createElement( u"fillSymbol2"_s );
1186 const QDomElement symbol2Elem = QgsSymbolLayerUtils::saveSymbol( QString(), mSettings.alternateFillSymbol(), doc, rwContext );
1187 fillSymbol2Elem.appendChild( symbol2Elem );
1188 composerScaleBarElem.appendChild( fillSymbol2Elem );
1189
1190 return true;
1191}
1192
1193
1194bool QgsLayoutItemScaleBar::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &, const QgsReadWriteContext &context )
1195{
1196 mSettings.setHeight( itemElem.attribute( u"height"_s, u"5.0"_s ).toDouble() );
1197 mSettings.setLabelBarSpace( itemElem.attribute( u"labelBarSpace"_s, u"3.0"_s ).toDouble() );
1198 mSettings.setBoxContentSpace( itemElem.attribute( u"boxContentSpace"_s, u"1.0"_s ).toDouble() );
1199 mSettings.setNumberOfSegments( itemElem.attribute( u"numSegments"_s, u"2"_s ).toInt() );
1200 mSettings.setNumberOfSegmentsLeft( itemElem.attribute( u"numSegmentsLeft"_s, u"0"_s ).toInt() );
1201 mSettings.setNumberOfSubdivisions( itemElem.attribute( u"numSubdivisions"_s, u"1"_s ).toInt() );
1202 mSettings.setSubdivisionsHeight( itemElem.attribute( u"subdivisionsHeight"_s, u"1.5"_s ).toDouble() );
1203 mSettings.setUnitsPerSegment( itemElem.attribute( u"numUnitsPerSegment"_s, u"1.0"_s ).toDouble() );
1204 mSettings.setSegmentSizeMode( static_cast<Qgis::ScaleBarSegmentSizeMode >( itemElem.attribute( u"segmentSizeMode"_s, u"0"_s ).toInt() ) );
1205 mSettings.setMinimumBarWidth( itemElem.attribute( u"minBarWidth"_s, u"50"_s ).toDouble() );
1206 mSettings.setMaximumBarWidth( itemElem.attribute( u"maxBarWidth"_s, u"150"_s ).toDouble() );
1207 mSegmentMillimeters = itemElem.attribute( u"segmentMillimeters"_s, u"0.0"_s ).toDouble();
1208 mSettings.setMapUnitsPerScaleBarUnit( itemElem.attribute( u"numMapUnitsPerScaleBarUnit"_s, u"1.0"_s ).toDouble() );
1209
1210 // default to horizontal bottom to keep same behavior for older projects
1211 mMethod = qgsEnumKeyToValue( itemElem.attribute( u"method"_s ), Qgis::ScaleCalculationMethod::HorizontalBottom );
1212
1213 const QDomElement lineSymbolElem = itemElem.firstChildElement( u"lineSymbol"_s );
1214 bool foundLineSymbol = false;
1215 if ( !lineSymbolElem.isNull() )
1216 {
1217 const QDomElement symbolElem = lineSymbolElem.firstChildElement( u"symbol"_s );
1218 std::unique_ptr< QgsLineSymbol > lineSymbol( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
1219 if ( lineSymbol )
1220 {
1221 mSettings.setLineSymbol( lineSymbol.release() );
1222 foundLineSymbol = true;
1223 }
1224 }
1225 const QDomElement divisionSymbolElem = itemElem.firstChildElement( u"divisionLineSymbol"_s );
1226 if ( !divisionSymbolElem.isNull() )
1227 {
1228 const QDomElement symbolElem = divisionSymbolElem.firstChildElement( u"symbol"_s );
1229 std::unique_ptr< QgsLineSymbol > lineSymbol( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
1230 if ( lineSymbol )
1231 {
1232 mSettings.setDivisionLineSymbol( lineSymbol.release() );
1233 }
1234 }
1235 else if ( foundLineSymbol )
1236 {
1237 mSettings.setDivisionLineSymbol( mSettings.lineSymbol()->clone() );
1238 }
1239 const QDomElement subdivisionSymbolElem = itemElem.firstChildElement( u"subdivisionLineSymbol"_s );
1240 if ( !subdivisionSymbolElem.isNull() )
1241 {
1242 const QDomElement symbolElem = subdivisionSymbolElem.firstChildElement( u"symbol"_s );
1243 std::unique_ptr< QgsLineSymbol > lineSymbol( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( symbolElem, context ) );
1244 if ( lineSymbol )
1245 {
1246 mSettings.setSubdivisionLineSymbol( lineSymbol.release() );
1247 }
1248 }
1249 else if ( foundLineSymbol )
1250 {
1251 mSettings.setSubdivisionLineSymbol( mSettings.lineSymbol()->clone() );
1252 }
1253
1254 if ( !foundLineSymbol )
1255 {
1256 // old project compatibility
1257 auto lineSymbol = std::make_unique< QgsLineSymbol >();
1258 auto lineSymbolLayer = std::make_unique< QgsSimpleLineSymbolLayer >();
1259 lineSymbolLayer->setWidth( itemElem.attribute( u"outlineWidth"_s, u"0.3"_s ).toDouble() );
1260 lineSymbolLayer->setWidthUnit( Qgis::RenderUnit::Millimeters );
1261 lineSymbolLayer->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( itemElem.attribute( u"lineJoinStyle"_s, u"miter"_s ) ) );
1262 lineSymbolLayer->setPenCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( itemElem.attribute( u"lineCapStyle"_s, u"square"_s ) ) );
1263
1264 //stroke color
1265 const QDomNodeList strokeColorList = itemElem.elementsByTagName( u"strokeColor"_s );
1266 if ( !strokeColorList.isEmpty() )
1267 {
1268 const QDomElement strokeColorElem = strokeColorList.at( 0 ).toElement();
1269 bool redOk, greenOk, blueOk, alphaOk;
1270 int strokeRed, strokeGreen, strokeBlue, strokeAlpha;
1271
1272 strokeRed = strokeColorElem.attribute( u"red"_s ).toDouble( &redOk );
1273 strokeGreen = strokeColorElem.attribute( u"green"_s ).toDouble( &greenOk );
1274 strokeBlue = strokeColorElem.attribute( u"blue"_s ).toDouble( &blueOk );
1275 strokeAlpha = strokeColorElem.attribute( u"alpha"_s ).toDouble( &alphaOk );
1276
1277 if ( redOk && greenOk && blueOk && alphaOk )
1278 {
1279 lineSymbolLayer->setColor( QColor( strokeRed, strokeGreen, strokeBlue, strokeAlpha ) );
1280 }
1281 }
1282 else
1283 {
1284 lineSymbolLayer->setColor( QColor( itemElem.attribute( u"penColor"_s, u"#000000"_s ) ) );
1285 }
1286
1287 // need to translate the deprecated ScalebarLineWidth and ScalebarLineColor properties to symbol properties,
1288 // and then remove them from the scalebar so they don't interfere and apply to other compatibility workarounds
1293
1294 lineSymbol->changeSymbolLayer( 0, lineSymbolLayer.release() );
1295 mSettings.setLineSymbol( lineSymbol->clone() );
1296 mSettings.setDivisionLineSymbol( lineSymbol->clone() );
1297 mSettings.setSubdivisionLineSymbol( lineSymbol.release() );
1298 }
1299
1300 mSettings.setUnitLabel( itemElem.attribute( u"unitLabel"_s ) );
1301
1302 const QDomNodeList textFormatNodeList = itemElem.elementsByTagName( u"text-style"_s );
1303 if ( !textFormatNodeList.isEmpty() )
1304 {
1305 const QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
1306 mSettings.textFormat().readXml( textFormatElem, context );
1307 }
1308 else
1309 {
1310 QFont f;
1311 if ( !QgsFontUtils::setFromXmlChildNode( f, itemElem, u"scaleBarFont"_s ) )
1312 {
1313 f.fromString( itemElem.attribute( u"font"_s, QString() ) );
1314 }
1315 mSettings.textFormat().setFont( f );
1316 if ( f.pointSizeF() > 0 )
1317 {
1318 mSettings.textFormat().setSize( f.pointSizeF() );
1319 mSettings.textFormat().setSizeUnit( Qgis::RenderUnit::Points );
1320 }
1321 else if ( f.pixelSize() > 0 )
1322 {
1323 mSettings.textFormat().setSize( f.pixelSize() );
1324 mSettings.textFormat().setSizeUnit( Qgis::RenderUnit::Pixels );
1325 }
1326 }
1327
1328 const QDomNodeList numericFormatNodeList = itemElem.elementsByTagName( u"numericFormat"_s );
1329 if ( !numericFormatNodeList.isEmpty() )
1330 {
1331 const QDomElement numericFormatElem = numericFormatNodeList.at( 0 ).toElement();
1332 mSettings.setNumericFormat( QgsApplication::numericFormatRegistry()->createFromXml( numericFormatElem, context ) );
1333 }
1334
1335 const QDomElement fillSymbol1Elem = itemElem.firstChildElement( u"fillSymbol1"_s );
1336 bool foundFillSymbol1 = false;
1337 if ( !fillSymbol1Elem.isNull() )
1338 {
1339 const QDomElement symbolElem = fillSymbol1Elem.firstChildElement( u"symbol"_s );
1340 std::unique_ptr< QgsFillSymbol > fillSymbol( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) );
1341 if ( fillSymbol )
1342 {
1343 mSettings.setFillSymbol( fillSymbol.release() );
1344 foundFillSymbol1 = true;
1345 }
1346 }
1347 if ( !foundFillSymbol1 )
1348 {
1349 // old project compatibility
1350 auto fillSymbol = std::make_unique< QgsFillSymbol >();
1351 auto fillSymbolLayer = std::make_unique< QgsSimpleFillSymbolLayer >();
1352 fillSymbolLayer->setStrokeStyle( Qt::NoPen );
1353
1354 //fill color
1355 const QDomNodeList fillColorList = itemElem.elementsByTagName( u"fillColor"_s );
1356 if ( !fillColorList.isEmpty() )
1357 {
1358 const QDomElement fillColorElem = fillColorList.at( 0 ).toElement();
1359 bool redOk, greenOk, blueOk, alphaOk;
1360 int fillRed, fillGreen, fillBlue, fillAlpha;
1361
1362 fillRed = fillColorElem.attribute( u"red"_s ).toDouble( &redOk );
1363 fillGreen = fillColorElem.attribute( u"green"_s ).toDouble( &greenOk );
1364 fillBlue = fillColorElem.attribute( u"blue"_s ).toDouble( &blueOk );
1365 fillAlpha = fillColorElem.attribute( u"alpha"_s ).toDouble( &alphaOk );
1366
1367 if ( redOk && greenOk && blueOk && alphaOk )
1368 {
1369 fillSymbolLayer->setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
1370 }
1371 }
1372 else
1373 {
1374 fillSymbolLayer->setColor( QColor( itemElem.attribute( u"brushColor"_s, u"#000000"_s ) ) );
1375 }
1376
1377 // need to translate the deprecated ScalebarFillColor property to symbol properties,
1378 // and then remove them from the scalebar so they don't interfere and apply to other compatibility workarounds
1381
1382 fillSymbol->changeSymbolLayer( 0, fillSymbolLayer.release() );
1383 mSettings.setFillSymbol( fillSymbol.release() );
1384 }
1385
1386 const QDomElement fillSymbol2Elem = itemElem.firstChildElement( u"fillSymbol2"_s );
1387 bool foundFillSymbol2 = false;
1388 if ( !fillSymbol2Elem.isNull() )
1389 {
1390 const QDomElement symbolElem = fillSymbol2Elem.firstChildElement( u"symbol"_s );
1391 std::unique_ptr< QgsFillSymbol > fillSymbol( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) );
1392 if ( fillSymbol )
1393 {
1394 mSettings.setAlternateFillSymbol( fillSymbol.release() );
1395 foundFillSymbol2 = true;
1396 }
1397 }
1398 if ( !foundFillSymbol2 )
1399 {
1400 // old project compatibility
1401 auto fillSymbol = std::make_unique< QgsFillSymbol >();
1402 auto fillSymbolLayer = std::make_unique< QgsSimpleFillSymbolLayer >();
1403 fillSymbolLayer->setStrokeStyle( Qt::NoPen );
1404
1405 //fill color 2
1406
1407 const QDomNodeList fillColor2List = itemElem.elementsByTagName( u"fillColor2"_s );
1408 if ( !fillColor2List.isEmpty() )
1409 {
1410 const QDomElement fillColor2Elem = fillColor2List.at( 0 ).toElement();
1411 bool redOk, greenOk, blueOk, alphaOk;
1412 int fillRed, fillGreen, fillBlue, fillAlpha;
1413
1414 fillRed = fillColor2Elem.attribute( u"red"_s ).toDouble( &redOk );
1415 fillGreen = fillColor2Elem.attribute( u"green"_s ).toDouble( &greenOk );
1416 fillBlue = fillColor2Elem.attribute( u"blue"_s ).toDouble( &blueOk );
1417 fillAlpha = fillColor2Elem.attribute( u"alpha"_s ).toDouble( &alphaOk );
1418
1419 if ( redOk && greenOk && blueOk && alphaOk )
1420 {
1421 fillSymbolLayer->setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
1422 }
1423 }
1424 else
1425 {
1426 fillSymbolLayer->setColor( QColor( itemElem.attribute( u"brush2Color"_s, u"#ffffff"_s ) ) );
1427 }
1428
1429 // need to translate the deprecated ScalebarFillColor2 property to symbol properties,
1430 // and then remove them from the scalebar so they don't interfere and apply to other compatibility workarounds
1433
1434 fillSymbol->changeSymbolLayer( 0, fillSymbolLayer.release() );
1435 mSettings.setAlternateFillSymbol( fillSymbol.release() );
1436 }
1437
1438 //font color
1439 const QDomNodeList textColorList = itemElem.elementsByTagName( u"textColor"_s );
1440 if ( !textColorList.isEmpty() )
1441 {
1442 const QDomElement textColorElem = textColorList.at( 0 ).toElement();
1443 bool redOk, greenOk, blueOk, alphaOk;
1444 int textRed, textGreen, textBlue, textAlpha;
1445
1446 textRed = textColorElem.attribute( u"red"_s ).toDouble( &redOk );
1447 textGreen = textColorElem.attribute( u"green"_s ).toDouble( &greenOk );
1448 textBlue = textColorElem.attribute( u"blue"_s ).toDouble( &blueOk );
1449 textAlpha = textColorElem.attribute( u"alpha"_s ).toDouble( &alphaOk );
1450
1451 if ( redOk && greenOk && blueOk && alphaOk )
1452 {
1453 mSettings.textFormat().setColor( QColor( textRed, textGreen, textBlue, textAlpha ) );
1454 }
1455 }
1456 else if ( itemElem.hasAttribute( u"fontColor"_s ) )
1457 {
1458 QColor c;
1459 c.setNamedColor( itemElem.attribute( u"fontColor"_s, u"#000000"_s ) );
1460 mSettings.textFormat().setColor( c );
1461 }
1462
1463 //style
1464 setStyle( itemElem.attribute( u"style"_s, QString() ) );
1465
1466 //call attemptResize after setStyle to ensure the appropriate size limitations are applied
1467 attemptResize( QgsLayoutSize::decodeSize( itemElem.attribute( u"size"_s ) ) );
1468
1469 if ( itemElem.attribute( u"unitType"_s ).isEmpty() )
1470 {
1472 switch ( itemElem.attribute( u"units"_s ).toInt() )
1473 {
1474 case 0:
1476 break;
1477 case 1:
1479 break;
1480 case 2:
1482 break;
1483 case 3:
1485 break;
1486 }
1487 mSettings.setUnits( u );
1488 }
1489 else
1490 {
1491 mSettings.setUnits( QgsUnitTypes::decodeDistanceUnit( itemElem.attribute( u"unitType"_s ) ) );
1492 }
1493
1494 mSettings.setLabelVerticalPlacement( static_cast< Qgis::ScaleBarDistanceLabelVerticalPlacement >( itemElem.attribute( u"labelVerticalPlacement"_s, u"0"_s ).toInt() ) );
1495 mSettings.setLabelHorizontalPlacement( static_cast< Qgis::ScaleBarDistanceLabelHorizontalPlacement >( itemElem.attribute( u"labelHorizontalPlacement"_s, u"0"_s ).toInt() ) );
1496
1497 mSettings.setAlignment( static_cast< Qgis::ScaleBarAlignment >( itemElem.attribute( u"alignment"_s, u"0"_s ).toInt() ) );
1498
1499 //map
1500 disconnectCurrentMap();
1501 mMap = nullptr;
1502 mMapUuid = itemElem.attribute( u"mapUuid"_s );
1503 return true;
1504}
1505
1506
1508{
1509 if ( mLayout && !mMapUuid.isEmpty() )
1510 {
1511 disconnectCurrentMap();
1512 mMap = qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mMapUuid, true ) );
1513 if ( mMap )
1514 {
1515 connect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemScaleBar::updateScale );
1516 connect( mMap, &QObject::destroyed, this, &QgsLayoutItemScaleBar::disconnectCurrentMap );
1517 }
1518 }
1519
1520 updateScale();
1521}
1522
1524{
1525 QgsStyleTextFormatEntity entity( mSettings.textFormat() );
1526 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) )
1527 return false;
1528
1529 return true;
1530}
1531
ScaleBarDistanceLabelHorizontalPlacement
Scale bar distance label horizontal placement.
Definition qgis.h:5507
ScaleBarDistanceLabelVerticalPlacement
Scale bar distance label vertical placement.
Definition qgis.h:5493
@ Millimeters
Millimeters.
Definition qgis.h:5361
ScaleBarAlignment
Scalebar alignment.
Definition qgis.h:5464
DistanceUnit
Units of distance.
Definition qgis.h:5170
@ Feet
Imperial feet.
Definition qgis.h:5173
@ Miles
Terrestrial miles.
Definition qgis.h:5176
@ Meters
Meters.
Definition qgis.h:5171
@ Unknown
Unknown distance unit.
Definition qgis.h:5220
@ Degrees
Degrees, for planar geographic CRS distance measurements.
Definition qgis.h:5177
@ NauticalMiles
Nautical miles.
Definition qgis.h:5174
@ Kilometers
Kilometers.
Definition qgis.h:5172
@ Millimeters
Millimeters.
Definition qgis.h:5341
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5345
@ Pixels
Pixels.
Definition qgis.h:5343
ScaleCalculationMethod
Scale calculation logic.
Definition qgis.h:5447
@ HorizontalTop
Calculate horizontally, across top of map.
Definition qgis.h:5448
@ HorizontalMiddle
Calculate horizontally, across midle of map.
Definition qgis.h:5449
@ AtEquator
Always calculate the scale at the equator, regardless of the actual visible map extent....
Definition qgis.h:5452
@ HorizontalAverage
Calculate horizontally, using the average of the top, middle and bottom scales.
Definition qgis.h:5451
@ HorizontalBottom
Calculate horizontally, across bottom of map.
Definition qgis.h:5450
ScaleBarSegmentSizeMode
Modes for setting size for scale bar segments.
Definition qgis.h:5479
@ FitWidth
Scale bar segment size is calculated to fit a size range.
Definition qgis.h:5481
@ Fixed
Scale bar segment size is fixed to a map unit.
Definition qgis.h:5480
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
static QgsScaleBarRendererRegistry * scaleBarRendererRegistry()
Gets the registry of available scalebar renderers.
static QgsNumericFormatRegistry * numericFormatRegistry()
Gets the registry of available numeric formats.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Represents a coordinate reference system (CRS).
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
Qgis::DistanceUnit lengthUnits() const
Returns the units of distance for length calculations made by this object.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
static void setFontFamily(QFont &font, const QString &family)
Sets the family for a font object.
void extentChanged()
Emitted when the map's extent changes.
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
void setNumberOfSegments(int segments)
Sets the number of segments included in the scalebar.
Q_DECL_DEPRECATED QBrush brush() const
Returns the primary brush for the scalebar.
Q_DECL_DEPRECATED QColor fillColor2() const
Returns the secondary color used for fills in the scalebar.
Q_DECL_DEPRECATED double lineWidth() const
Returns the line width in millimeters for lines in the scalebar.
QIcon icon() const override
Returns the item's icon.
Q_DECL_DEPRECATED void setFillColor(const QColor &color)
Sets the color used for fills in the scalebar.
QgsLineSymbol * divisionLineSymbol() const
Returns the line symbol used to render the scalebar divisions (only used for some scalebar types).
QgsFillSymbol * alternateFillSymbol() const
Returns the secondary fill symbol used to render the scalebar (only used for some scalebar types).
Q_DECL_DEPRECATED QBrush brush2() const
Returns the secondary brush for the scalebar.
double height() const
Returns the scalebar height (in millimeters).
void setMinimumBarWidth(double minWidth)
Sets the minimum width (in millimeters) for scale bar segments.
QgsFillSymbol * fillSymbol() const
Returns the primary fill symbol used to render the scalebar (only used for some scalebar types).
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
Q_DECL_DEPRECATED QColor fontColor() const
Returns the color used for drawing text in the scalebar.
void setMaximumBarWidth(double maxWidth)
Sets the maximum width (in millimeters) for scale bar segments.
Q_DECL_DEPRECATED QColor fillColor() const
Returns the color used for fills in the scalebar.
void setNumericFormat(QgsNumericFormat *format)
Sets the numeric format used for numbers in the scalebar.
Q_DECL_DEPRECATED void setLineColor(const QColor &color)
Sets the color used for lines in the scalebar.
void setDivisionLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used to render the scalebar divisions (only used for some scalebar types).
Q_DECL_DEPRECATED QColor lineColor() const
Returns the color used for lines in the scalebar.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
void update()
Adjusts the scale bar box size and updates the item.
void setFillSymbol(QgsFillSymbol *symbol)
Sets the primary fill symbol used to render the scalebar (only used for some scalebar types).
double unitsPerSegment() const
Returns the number of scalebar units per segment.
void setAlignment(Qgis::ScaleBarAlignment alignment)
Sets the scalebar alignment.
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
bool applyDefaultRendererSettings(QgsScaleBarRenderer *renderer)
Applies any default settings relating to the specified renderer to the item.
double minimumBarWidth() const
Returns the minimum width (in millimeters) for scale bar segments.
QgsLineSymbol * subdivisionLineSymbol() const
Returns the line symbol used to render the scalebar subdivisions (only used for some scalebar types).
Q_DECL_DEPRECATED QFont font() const
Returns the font used for drawing text in the scalebar.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
void setAlternateFillSymbol(QgsFillSymbol *symbol)
Sets the secondary fill symbol used to render the scalebar (only used for some scalebar types).
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used to render the scalebar (only used for some scalebar types).
void setStyle(const QString &name)
Sets the scale bar style by name.
Q_DECL_DEPRECATED void setFillColor2(const QColor &color)
Sets the secondary color used for fills in the scalebar.
void applyDefaultSettings()
Applies the default scalebar settings to the scale bar.
void setLabelVerticalPlacement(Qgis::ScaleBarDistanceLabelVerticalPlacement placement)
Sets the vertical placement of text labels.
void setLabelHorizontalPlacement(Qgis::ScaleBarDistanceLabelHorizontalPlacement placement)
Sets the horizontal placement of text labels.
void setHeight(double height)
Sets the scalebar height (in millimeters).
Q_DECL_DEPRECATED Qt::PenCapStyle lineCapStyle() const
Returns the cap style used for drawing lines in the scalebar.
void setSubdivisionsHeight(double height)
Sets the scalebar subdivisions height (in millimeters) for segments included in the right part of the...
void setNumberOfSegmentsLeft(int segments)
Sets the number of segments included in the left part of the scalebar.
Qgis::DistanceUnit units() const
Returns the distance units used by the scalebar.
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::DataDefinedProperty::AllProperties) override
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
Q_DECL_DEPRECATED Qt::PenJoinStyle lineJoinStyle() const
Returns the join style used for drawing lines in the scalebar.
void setTextFormat(const QgsTextFormat &format)
Sets the text format used for drawing text in the scalebar.
void setUnits(Qgis::DistanceUnit units)
Sets the distance units used by the scalebar.
void setLinkedMap(QgsLayoutItemMap *map)
Sets the map item linked to the scalebar.
QgsLayoutSize minimumSize() const override
Returns the minimum allowed size of the item, if applicable, or an empty size if item can be freely r...
Q_DECL_DEPRECATED void setLineJoinStyle(Qt::PenJoinStyle style)
Sets the join style used when drawing the lines in the scalebar.
void setSegmentSizeMode(Qgis::ScaleBarSegmentSizeMode mode)
Sets the size mode for scale bar segments.
QgsLineSymbol * lineSymbol() const
Returns the line symbol used to render the scalebar (only used for some scalebar types).
double maximumBarWidth() const
Returns the maximum width (in millimeters) for scale bar segments.
Q_DECL_DEPRECATED void setFontColor(const QColor &color)
Sets the color used for drawing text in the scalebar.
Q_DECL_DEPRECATED void setLineWidth(double width)
Sets the line width in millimeters for lines in the scalebar.
Q_DECL_DEPRECATED QPen pen() const
Returns the pen used for drawing outlines in the scalebar.
void setBoxContentSpace(double space)
Sets the space (margin) between the scalebar box and content in millimeters.
const QgsNumericFormat * numericFormat() const
Returns the numeric format used for numbers in the scalebar.
void setUnitLabel(const QString &label)
Sets the label for units.
QString style() const
Returns the scale bar style name.
ExportLayerBehavior exportLayerBehavior() const override
Returns the behavior of this item during exporting to layered exports (e.g.
QgsTextFormat textFormat() const
Returns the text format used for drawing text in the scalebar.
Q_DECL_DEPRECATED void setLineCapStyle(Qt::PenCapStyle style)
Sets the cap style used when drawing the lines in the scalebar.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void resizeToMinimumWidth()
Resizes the scale bar to its minimum width, without changing the height.
void setUnitsPerSegment(double units)
Sets the number of scalebar units per segment.
static QgsLayoutItemScaleBar * create(QgsLayout *layout)
Returns a new scale bar item for the specified layout.
void setMethod(Qgis::ScaleCalculationMethod method)
Sets the scale calculation method, which determines how the bar's scale will be calculated.
Q_DECL_DEPRECATED void setFont(const QFont &font)
Sets the font used for drawing text in the scalebar.
Qgis::DistanceUnit guessUnits() const
Attempts to guess the most reasonable unit choice for the scalebar, given the current linked map's sc...
void setSubdivisionLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used to render the scalebar subdivisions (only used for some scalebar types).
void applyDefaultSize(Qgis::DistanceUnit units=Qgis::DistanceUnit::Meters)
Applies the default size to the scale bar (scale bar 1/5 of map item width).
Qgis::ScaleCalculationMethod method() const
Returns the scale calculation method, which determines how the bar's scale will be calculated.
void setNumberOfSubdivisions(int subdivisions)
Sets the number of subdivisions for segments included in the right part of the scalebar (only used fo...
QgsLayoutItemScaleBar(QgsLayout *layout)
Constructor for QgsLayoutItemScaleBar, with the specified parent layout.
friend class QgsLayout
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::DataDefinedProperty::AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
QgsLayoutItem(QgsLayout *layout, bool manageZValue=true)
Constructor for QgsLayoutItem, with the specified parent layout.
friend class QgsLayoutItemMap
void refreshItemSize()
Refreshes an item's size by rechecking it against any possible item fixed or minimum sizes.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
virtual QString displayName() const
Gets item display name.
virtual void attemptResize(const QgsLayoutSize &size, bool includesFrame=false)
Attempts to resize the item to a specified target size.
virtual QString uuid() const
Returns the item identification string.
ExportLayerBehavior
Behavior of item when exporting to layered outputs.
@ CanGroupWithItemsOfSameType
Item can only be placed on layers with other items of the same type, but multiple items of this type ...
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
Provides a method of storing measurements for use in QGIS layouts using a variety of different measur...
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the object's property collection, used for data defined overrides.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
QPointer< QgsLayout > mLayout
DataDefinedProperty
Data defined properties for different item types.
@ ScalebarMinimumWidth
Scalebar segment minimum width.
@ ScalebarRightSegments
Number of segments on the right of 0.
@ ScalebarLineColor
Scalebar line color (deprecated, use data defined properties on scalebar line symbol instead).
@ ScalebarRightSegmentSubdivisions
Number of subdivisions per segment on right of 0.
@ ScalebarMaximumWidth
Scalebar segment maximum width.
@ ScalebarFillColor2
Scalebar secondary fill color (deprecated, use data defined properties on scalebar fill symbol 2 inst...
@ ScalebarSubdivisionHeight
Scalebar subdivision height.
@ ScalebarFillColor
Scalebar fill color (deprecated, use data defined properties on scalebar fill symbol 1 instead).
@ ScalebarLineWidth
Scalebar line width (deprecated, use data defined properties on scalebar line symbol instead).
@ ScalebarLeftSegments
Number of segments on the left of 0.
@ ScalebarSegmentWidth
Scalebar width in map units of a single segment.
@ AllProperties
All properties for item.
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
static QgsLayoutSize decodeSize(const QString &string)
Decodes a size from a string.
void setWidth(const double width)
Sets the width for the size.
Qgis::LayoutUnit units() const
Returns the units for the size.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static double calculatePrettySize(double minimumSize, double maximumSize)
Calculates a "pretty" size which falls between the range [minimumSize, maximumSize].
A line symbol type, for rendering LineString and MultiLineString geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Abstract base class for numeric formatters, which allow for formatting a numeric value for display.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
A store for object properties.
A container for the context for various read/write operations on objects.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
Abstract base class for scale bar renderers.
virtual bool applyDefaultSettings(QgsScaleBarSettings &settings) const
Applies any default settings relating to the scalebar to the passed settings object.
double unitsPerSegment() const
Returns the number of scalebar units per segment.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A text format entity for QgsStyle databases.
Definition qgsstyle.h:1451
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
Container for all settings relating to text rendering.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE Qgis::DistanceUnit decodeDistanceUnit(const QString &string, bool *ok=nullptr)
Decodes a distance unit from a string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7176
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7504
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7157
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7503
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6975
#define QgsDebugError(str)
Definition qgslogger.h:59
Contains parameters regarding scalebar calculations.
QSizeF size
Destination size for scalebar.
bool isValid() const
Returns true if the context has valid settings.
QgsScaleBarRenderer::Flags flags
Scalebar renderer flags.
double segmentWidth
The width, in millimeters, of each individual segment drawn.
Contains information relating to the style entity currently being visited.