QGIS API Documentation  2.8.6-Wien
qgscomposerscalebar.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerscalebar.cpp
3  -------------------
4  begin : March 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : blazek@itc.it
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 
17 #include "qgscomposerscalebar.h"
18 #include "qgscomposermap.h"
19 #include "qgscomposition.h"
20 #include "qgscomposerutils.h"
21 #include "qgsdistancearea.h"
22 #include "qgsscalebarstyle.h"
24 #include "qgsmaprenderer.h"
27 #include "qgsticksscalebarstyle.h"
28 #include "qgsrectangle.h"
29 #include "qgsproject.h"
30 #include "qgssymbollayerv2utils.h"
31 #include <QDomDocument>
32 #include <QDomElement>
33 #include <QFontMetricsF>
34 #include <QPainter>
35 #include <QSettings>
36 #include <cmath>
37 
39  : QgsComposerItem( composition )
40  , mComposerMap( 0 )
41  , mNumUnitsPerSegment( 0 )
42  , mFontColor( QColor( 0, 0, 0 ) )
43  , mStyle( 0 )
44  , mSegmentMillimeters( 0.0 )
45  , mAlignment( Left )
46  , mUnits( MapUnits )
47  , mLineJoinStyle( Qt::MiterJoin )
48  , mLineCapStyle( Qt::SquareCap )
49 {
52 }
53 
55 {
56  delete mStyle;
57 }
58 
59 void QgsComposerScaleBar::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
60 {
61  Q_UNUSED( itemStyle );
62  Q_UNUSED( pWidget );
63  if ( !mStyle || !painter )
64  {
65  return;
66  }
67  if ( !shouldDrawItem() )
68  {
69  return;
70  }
71 
72  drawBackground( painter );
73 
74  //x-offset is half of first label width because labels are drawn centered
75  QString firstLabel = firstLabelString();
76  double firstLabelWidth = QgsComposerUtils::textWidthMM( mFont, firstLabel );
77 
78  mStyle->draw( painter, firstLabelWidth / 2 );
79 
80  //draw frame and selection boxes if necessary
81  drawFrame( painter );
82  if ( isSelected() )
83  {
84  drawSelectionBoxes( painter );
85  }
86 }
87 
89 {
90  if ( !mStyle )
91  {
92  mNumSegments = nSegments;
93  return;
94  }
95  double width = mStyle->calculateBoxSize().width();
96  mNumSegments = nSegments;
97  double widthAfter = mStyle->calculateBoxSize().width();
98  correctXPositionAlignment( width, widthAfter );
99  emit itemChanged();
100 }
101 
103 {
104  if ( !mStyle )
105  {
107  return;
108  }
109  double width = mStyle->calculateBoxSize().width();
112  double widthAfter = mStyle->calculateBoxSize().width();
113  correctXPositionAlignment( width, widthAfter );
114  emit itemChanged();
115 }
116 
118 {
119  if ( !mStyle )
120  {
121  mNumSegmentsLeft = nSegmentsLeft;
122  return;
123  }
124  double width = mStyle->calculateBoxSize().width();
125  mNumSegmentsLeft = nSegmentsLeft;
126  double widthAfter = mStyle->calculateBoxSize().width();
127  correctXPositionAlignment( width, widthAfter );
128  emit itemChanged();
129 }
130 
132 {
133  if ( !mStyle )
134  {
135  mBoxContentSpace = space;
136  return;
137  }
138  double width = mStyle->calculateBoxSize().width();
139  mBoxContentSpace = space;
140  double widthAfter = mStyle->calculateBoxSize().width();
141  correctXPositionAlignment( width, widthAfter );
142  emit itemChanged();
143 }
144 
146 {
147  if ( mComposerMap )
148  {
149  disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
150  disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
151  }
152  mComposerMap = map;
153 
154  if ( !map )
155  {
156  return;
157  }
158 
159  connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
160  connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
161 
163  emit itemChanged();
164 }
165 
167 {
168  if ( !mComposerMap )
169  {
170  return;
171  }
172 
173  disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
174  disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
175  mComposerMap = 0;
176 }
177 
179 {
180  if ( mComposerMap )
181  {
182  //get extent of composer map
183  QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() );
184 
185  //get mm dimension of composer map
186  QRectF composerItemRect = mComposerMap->rect();
187 
188  //calculate size depending on mNumUnitsPerSegment
189  mSegmentMillimeters = composerItemRect.width() / mapWidth() * mNumUnitsPerSegment;
190  }
191 }
192 
194 {
195  if ( !mComposerMap )
196  {
197  return 0.0;
198  }
199 
200  QgsRectangle composerMapRect = *( mComposerMap->currentMapExtent() );
201  if ( mUnits == MapUnits )
202  {
203  return composerMapRect.width();
204  }
205  else
206  {
207  QgsDistanceArea da;
210  da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", "WGS84" ) );
211 
213  double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ),
214  QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ),
215  units );
216  switch ( mUnits )
217  {
219  measure /= QGis::fromUnitToUnitFactor( QGis::Feet, units );
220  break;
222  measure /= QGis::fromUnitToUnitFactor( QGis::NauticalMiles, units );
223  break;
225  measure /= QGis::fromUnitToUnitFactor( QGis::Meters, units );
226  break;
228  //avoid warning
229  break;
230  }
231  return measure;
232  }
233 }
234 
236 {
237  mAlignment = a;
238  update();
239  emit itemChanged();
240 }
241 
243 {
244  mUnits = u;
246  emit itemChanged();
247 }
248 
250 {
251  if ( mLineJoinStyle == style )
252  {
253  //no change
254  return;
255  }
257  mPen.setJoinStyle( mLineJoinStyle );
258  update();
259  emit itemChanged();
260 }
261 
263 {
264  if ( mLineCapStyle == style )
265  {
266  //no change
267  return;
268  }
270  mPen.setCapStyle( mLineCapStyle );
271  update();
272  emit itemChanged();
273 }
274 
276 {
277  mNumSegments = 2;
278  mNumSegmentsLeft = 0;
279 
281 
282  //style
283  delete mStyle;
284  mStyle = new QgsSingleBoxScaleBarStyle( this );
285 
286  mHeight = 3;
287 
288  //default to no background
289  setBackgroundEnabled( false );
290 
291  mPen = QPen( Qt::black );
292  mPen.setJoinStyle( mLineJoinStyle );
293  mPen.setCapStyle( mLineCapStyle );
294  mPen.setWidthF( 1.0 );
295 
296  mBrush.setColor( Qt::black );
297  mBrush.setStyle( Qt::SolidPattern );
298 
299  mBrush2.setColor( Qt::white );
300  mBrush2.setStyle( Qt::SolidPattern );
301 
302  //get default composer font from settings
303  QSettings settings;
304  QString defaultFontString = settings.value( "/Composer/defaultFont" ).toString();
305  if ( !defaultFontString.isEmpty() )
306  {
307  mFont.setFamily( defaultFontString );
308  }
309  mFont.setPointSizeF( 12.0 );
310  mFontColor = QColor( 0, 0, 0 );
311 
312  mLabelBarSpace = 3.0;
313  mBoxContentSpace = 1.0;
314  emit itemChanged();
315 }
316 
318 {
319  if ( mComposerMap )
320  {
321  setUnits( u );
322  double upperMagnitudeMultiplier = 1.0;
323  double widthInSelectedUnits = mapWidth();
324  double initialUnitsPerSegment = widthInSelectedUnits / 10.0; //default scalebar width equals half the map width
325  setNumUnitsPerSegment( initialUnitsPerSegment );
326 
327  switch ( mUnits )
328  {
329  case MapUnits:
330  {
331  upperMagnitudeMultiplier = 1.0;
332  setUnitLabeling( tr( "units" ) );
333  break;
334  }
335  case Meters:
336  {
337  if ( initialUnitsPerSegment > 1000.0 )
338  {
339  upperMagnitudeMultiplier = 1000.0;
340  setUnitLabeling( tr( "km" ) );
341  }
342  else
343  {
344  upperMagnitudeMultiplier = 1.0;
345  setUnitLabeling( tr( "m" ) );
346  }
347  break;
348  }
349  case Feet:
350  {
351  if ( initialUnitsPerSegment > 5419.95 )
352  {
353  upperMagnitudeMultiplier = 5419.95;
354  setUnitLabeling( tr( "miles" ) );
355  }
356  else
357  {
358  upperMagnitudeMultiplier = 1.0;
359  setUnitLabeling( tr( "ft" ) );
360  }
361  break;
362  }
363  case NauticalMiles:
364  {
365  upperMagnitudeMultiplier = 1;
366  setUnitLabeling( tr( "Nm" ) );
367  break;
368  }
369  }
370 
371  double segmentWidth = initialUnitsPerSegment / upperMagnitudeMultiplier;
372  int segmentMagnitude = floor( log10( segmentWidth ) );
373  double unitsPerSegment = upperMagnitudeMultiplier * ( pow( 10.0, segmentMagnitude ) );
374  double multiplier = floor(( widthInSelectedUnits / ( unitsPerSegment * 10.0 ) ) / 2.5 ) * 2.5;
375 
376  if ( multiplier > 0 )
377  {
378  unitsPerSegment = unitsPerSegment * multiplier;
379  }
380  setNumUnitsPerSegment( unitsPerSegment );
381  setNumMapUnitsPerScaleBarUnit( upperMagnitudeMultiplier );
382 
383  setNumSegments( 4 );
384  setNumSegmentsLeft( 2 );
385  }
386 
388  adjustBoxSize();
389  emit itemChanged();
390 }
391 
393 {
394  if ( !mStyle )
395  {
396  return;
397  }
398 
399  QRectF box = mStyle->calculateBoxSize();
400  if ( rect().height() > box.height() )
401  {
402  //keep user specified item height if higher than minimum scale bar height
403  box.setHeight( rect().height() );
404  }
405 
406  //update rect for data defined size and position
407  QRectF newRect = evalItemRect( box, true );
408 
409  //scale bars have a minimum size, respect that regardless of data defined settings
410  if ( newRect.width() < box.width() )
411  {
412  newRect.setWidth( box.width() );
413  }
414  if ( newRect.height() < box.height() )
415  {
416  newRect.setHeight( box.height() );
417  }
418 
420 }
421 
422 void QgsComposerScaleBar::setSceneRect( const QRectF& rectangle )
423 {
424  QRectF box = mStyle->calculateBoxSize();
425  if ( rectangle.height() > box.height() )
426  {
427  //keep user specified item height if higher than minimum scale bar height
428  box.setHeight( rectangle.height() );
429  }
430  box.moveTopLeft( rectangle.topLeft() );
431 
432  //update rect for data defined size and position
433  QRectF newRect = evalItemRect( rectangle );
434 
435  //scale bars have a minimum size, respect that regardless of data defined settings
436  if ( newRect.width() < box.width() )
437  {
438  newRect.setWidth( box.width() );
439  }
440  if ( newRect.height() < box.height() )
441  {
442  newRect.setHeight( box.height() );
443  }
444 
446 }
447 
449 {
450  //Don't adjust box size for numeric scale bars:
451  if ( mStyle && mStyle->name() != "Numeric" )
452  {
453  adjustBoxSize();
454  }
455  QgsComposerItem::update();
456 }
457 
459 {
460  if ( !mStyle )
461  {
462  return;
463  }
464  double width = mStyle->calculateBoxSize().width();
466  double widthAfter = mStyle->calculateBoxSize().width();
467  correctXPositionAlignment( width, widthAfter );
468  update();
469  emit itemChanged();
470 }
471 
472 void QgsComposerScaleBar::segmentPositions( QList<QPair<double, double> >& posWidthList ) const
473 {
474  posWidthList.clear();
475  double mCurrentXCoord = mPen.widthF() + mBoxContentSpace;
476 
477  //left segments
478  double leftSegmentSize = mSegmentMillimeters / mNumSegmentsLeft;
479  for ( int i = 0; i < mNumSegmentsLeft; ++i )
480  {
481  posWidthList.push_back( qMakePair( mCurrentXCoord, leftSegmentSize ) );
482  mCurrentXCoord += leftSegmentSize;
483  }
484 
485  //right segments
486  for ( int i = 0; i < mNumSegments; ++i )
487  {
488  posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters ) );
489  mCurrentXCoord += mSegmentMillimeters;
490  }
491 }
492 
493 void QgsComposerScaleBar::setStyle( const QString& styleName )
494 {
495  delete mStyle;
496  mStyle = 0;
497 
498  //switch depending on style name
499  if ( styleName == "Single Box" )
500  {
501  mStyle = new QgsSingleBoxScaleBarStyle( this );
502  }
503  else if ( styleName == "Double Box" )
504  {
505  mStyle = new QgsDoubleBoxScaleBarStyle( this );
506  }
507  else if ( styleName == "Line Ticks Middle" || styleName == "Line Ticks Down" || styleName == "Line Ticks Up" )
508  {
509  QgsTicksScaleBarStyle* tickStyle = new QgsTicksScaleBarStyle( this );
510  if ( styleName == "Line Ticks Middle" )
511  {
513  }
514  else if ( styleName == "Line Ticks Down" )
515  {
517  }
518  else if ( styleName == "Line Ticks Up" )
519  {
521  }
522  mStyle = tickStyle;
523  }
524  else if ( styleName == "Numeric" )
525  {
526  mStyle = new QgsNumericScaleBarStyle( this );
527  }
528  emit itemChanged();
529 }
530 
532 {
533  if ( mStyle )
534  {
535  return mStyle->name();
536  }
537  else
538  {
539  return "";
540  }
541 }
542 
544 {
545  if ( mNumSegmentsLeft > 0 )
546  {
547  return QString::number( mNumUnitsPerSegment / mNumMapUnitsPerScaleBarUnit );
548  }
549  else
550  {
551  return "0";
552  }
553 }
554 
556 {
557  return mFont;
558 }
559 
560 void QgsComposerScaleBar::setFont( const QFont& font )
561 {
562  mFont = font;
563  update();
564  emit itemChanged();
565 }
566 
567 bool QgsComposerScaleBar::writeXML( QDomElement& elem, QDomDocument & doc ) const
568 {
569  if ( elem.isNull() )
570  {
571  return false;
572  }
573 
574  QDomElement composerScaleBarElem = doc.createElement( "ComposerScaleBar" );
575  composerScaleBarElem.setAttribute( "height", QString::number( mHeight ) );
576  composerScaleBarElem.setAttribute( "labelBarSpace", QString::number( mLabelBarSpace ) );
577  composerScaleBarElem.setAttribute( "boxContentSpace", QString::number( mBoxContentSpace ) );
578  composerScaleBarElem.setAttribute( "numSegments", mNumSegments );
579  composerScaleBarElem.setAttribute( "numSegmentsLeft", mNumSegmentsLeft );
580  composerScaleBarElem.setAttribute( "numUnitsPerSegment", QString::number( mNumUnitsPerSegment ) );
581  composerScaleBarElem.setAttribute( "segmentMillimeters", QString::number( mSegmentMillimeters ) );
582  composerScaleBarElem.setAttribute( "numMapUnitsPerScaleBarUnit", QString::number( mNumMapUnitsPerScaleBarUnit ) );
583  composerScaleBarElem.setAttribute( "font", mFont.toString() );
584  composerScaleBarElem.setAttribute( "outlineWidth", QString::number( mPen.widthF() ) );
585  composerScaleBarElem.setAttribute( "unitLabel", mUnitLabeling );
586  composerScaleBarElem.setAttribute( "units", mUnits );
587  composerScaleBarElem.setAttribute( "lineJoinStyle", QgsSymbolLayerV2Utils::encodePenJoinStyle( mLineJoinStyle ) );
588  composerScaleBarElem.setAttribute( "lineCapStyle", QgsSymbolLayerV2Utils::encodePenCapStyle( mLineCapStyle ) );
589 
590  //style
591  if ( mStyle )
592  {
593  composerScaleBarElem.setAttribute( "style", mStyle->name() );
594  }
595 
596  //map id
597  if ( mComposerMap )
598  {
599  composerScaleBarElem.setAttribute( "mapId", mComposerMap->id() );
600  }
601 
602  //colors
603 
604  //fill color
605  QDomElement fillColorElem = doc.createElement( "fillColor" );
606  QColor fillColor = mBrush.color();
607  fillColorElem.setAttribute( "red", QString::number( fillColor.red() ) );
608  fillColorElem.setAttribute( "green", QString::number( fillColor.green() ) );
609  fillColorElem.setAttribute( "blue", QString::number( fillColor.blue() ) );
610  fillColorElem.setAttribute( "alpha", QString::number( fillColor.alpha() ) );
611  composerScaleBarElem.appendChild( fillColorElem );
612 
613  //fill color 2
614  QDomElement fillColor2Elem = doc.createElement( "fillColor2" );
615  QColor fillColor2 = mBrush2.color();
616  fillColor2Elem.setAttribute( "red", QString::number( fillColor2.red() ) );
617  fillColor2Elem.setAttribute( "green", QString::number( fillColor2.green() ) );
618  fillColor2Elem.setAttribute( "blue", QString::number( fillColor2.blue() ) );
619  fillColor2Elem.setAttribute( "alpha", QString::number( fillColor2.alpha() ) );
620  composerScaleBarElem.appendChild( fillColor2Elem );
621 
622  //pen color
623  QDomElement strokeColorElem = doc.createElement( "strokeColor" );
624  QColor strokeColor = mPen.color();
625  strokeColorElem.setAttribute( "red", QString::number( strokeColor.red() ) );
626  strokeColorElem.setAttribute( "green", QString::number( strokeColor.green() ) );
627  strokeColorElem.setAttribute( "blue", QString::number( strokeColor.blue() ) );
628  strokeColorElem.setAttribute( "alpha", QString::number( strokeColor.alpha() ) );
629  composerScaleBarElem.appendChild( strokeColorElem );
630 
631  //font color
632  QDomElement fontColorElem = doc.createElement( "textColor" );
633  fontColorElem.setAttribute( "red", QString::number( mFontColor.red() ) );
634  fontColorElem.setAttribute( "green", QString::number( mFontColor.green() ) );
635  fontColorElem.setAttribute( "blue", QString::number( mFontColor.blue() ) );
636  fontColorElem.setAttribute( "alpha", QString::number( mFontColor.alpha() ) );
637  composerScaleBarElem.appendChild( fontColorElem );
638 
639  //alignment
640  composerScaleBarElem.setAttribute( "alignment", QString::number(( int ) mAlignment ) );
641 
642  elem.appendChild( composerScaleBarElem );
643  return _writeXML( composerScaleBarElem, doc );
644 }
645 
646 bool QgsComposerScaleBar::readXML( const QDomElement& itemElem, const QDomDocument& doc )
647 {
648  if ( itemElem.isNull() )
649  {
650  return false;
651  }
652 
653  mHeight = itemElem.attribute( "height", "5.0" ).toDouble();
654  mLabelBarSpace = itemElem.attribute( "labelBarSpace", "3.0" ).toDouble();
655  mBoxContentSpace = itemElem.attribute( "boxContentSpace", "1.0" ).toDouble();
656  mNumSegments = itemElem.attribute( "numSegments", "2" ).toInt();
657  mNumSegmentsLeft = itemElem.attribute( "numSegmentsLeft", "0" ).toInt();
658  mNumUnitsPerSegment = itemElem.attribute( "numUnitsPerSegment", "1.0" ).toDouble();
659  mSegmentMillimeters = itemElem.attribute( "segmentMillimeters", "0.0" ).toDouble();
660  mNumMapUnitsPerScaleBarUnit = itemElem.attribute( "numMapUnitsPerScaleBarUnit", "1.0" ).toDouble();
661  mPen.setWidthF( itemElem.attribute( "outlineWidth", "1.0" ).toDouble() );
662  mUnitLabeling = itemElem.attribute( "unitLabel" );
663  mLineJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( itemElem.attribute( "lineJoinStyle", "miter" ) );
664  mPen.setJoinStyle( mLineJoinStyle );
665  mLineCapStyle = QgsSymbolLayerV2Utils::decodePenCapStyle( itemElem.attribute( "lineCapStyle", "square" ) );
666  mPen.setCapStyle( mLineCapStyle );
667  QString fontString = itemElem.attribute( "font", "" );
668  if ( !fontString.isEmpty() )
669  {
670  mFont.fromString( fontString );
671  }
672 
673  //colors
674  //fill color
675  QDomNodeList fillColorList = itemElem.elementsByTagName( "fillColor" );
676  if ( fillColorList.size() > 0 )
677  {
678  QDomElement fillColorElem = fillColorList.at( 0 ).toElement();
679  bool redOk, greenOk, blueOk, alphaOk;
680  int fillRed, fillGreen, fillBlue, fillAlpha;
681 
682  fillRed = fillColorElem.attribute( "red" ).toDouble( &redOk );
683  fillGreen = fillColorElem.attribute( "green" ).toDouble( &greenOk );
684  fillBlue = fillColorElem.attribute( "blue" ).toDouble( &blueOk );
685  fillAlpha = fillColorElem.attribute( "alpha" ).toDouble( &alphaOk );
686 
687  if ( redOk && greenOk && blueOk && alphaOk )
688  {
689  mBrush.setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
690  }
691  }
692  else
693  {
694  mBrush.setColor( QColor( itemElem.attribute( "brushColor", "#000000" ) ) );
695  }
696 
697  //fill color 2
698  QDomNodeList fillColor2List = itemElem.elementsByTagName( "fillColor2" );
699  if ( fillColor2List.size() > 0 )
700  {
701  QDomElement fillColor2Elem = fillColor2List.at( 0 ).toElement();
702  bool redOk, greenOk, blueOk, alphaOk;
703  int fillRed, fillGreen, fillBlue, fillAlpha;
704 
705  fillRed = fillColor2Elem.attribute( "red" ).toDouble( &redOk );
706  fillGreen = fillColor2Elem.attribute( "green" ).toDouble( &greenOk );
707  fillBlue = fillColor2Elem.attribute( "blue" ).toDouble( &blueOk );
708  fillAlpha = fillColor2Elem.attribute( "alpha" ).toDouble( &alphaOk );
709 
710  if ( redOk && greenOk && blueOk && alphaOk )
711  {
712  mBrush2.setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
713  }
714  }
715  else
716  {
717  mBrush2.setColor( QColor( itemElem.attribute( "brush2Color", "#ffffff" ) ) );
718  }
719 
720  //stroke color
721  QDomNodeList strokeColorList = itemElem.elementsByTagName( "strokeColor" );
722  if ( strokeColorList.size() > 0 )
723  {
724  QDomElement strokeColorElem = strokeColorList.at( 0 ).toElement();
725  bool redOk, greenOk, blueOk, alphaOk;
726  int strokeRed, strokeGreen, strokeBlue, strokeAlpha;
727 
728  strokeRed = strokeColorElem.attribute( "red" ).toDouble( &redOk );
729  strokeGreen = strokeColorElem.attribute( "green" ).toDouble( &greenOk );
730  strokeBlue = strokeColorElem.attribute( "blue" ).toDouble( &blueOk );
731  strokeAlpha = strokeColorElem.attribute( "alpha" ).toDouble( &alphaOk );
732 
733  if ( redOk && greenOk && blueOk && alphaOk )
734  {
735  mPen.setColor( QColor( strokeRed, strokeGreen, strokeBlue, strokeAlpha ) );
736  }
737  }
738  else
739  {
740  mPen.setColor( QColor( itemElem.attribute( "penColor", "#000000" ) ) );
741  }
742 
743  //font color
744  QDomNodeList textColorList = itemElem.elementsByTagName( "textColor" );
745  if ( textColorList.size() > 0 )
746  {
747  QDomElement textColorElem = textColorList.at( 0 ).toElement();
748  bool redOk, greenOk, blueOk, alphaOk;
749  int textRed, textGreen, textBlue, textAlpha;
750 
751  textRed = textColorElem.attribute( "red" ).toDouble( &redOk );
752  textGreen = textColorElem.attribute( "green" ).toDouble( &greenOk );
753  textBlue = textColorElem.attribute( "blue" ).toDouble( &blueOk );
754  textAlpha = textColorElem.attribute( "alpha" ).toDouble( &alphaOk );
755 
756  if ( redOk && greenOk && blueOk && alphaOk )
757  {
758  mFontColor = QColor( textRed, textGreen, textBlue, textAlpha );
759  }
760  }
761  else
762  {
763  mFontColor.setNamedColor( itemElem.attribute( "fontColor", "#000000" ) );
764  }
765 
766  //style
767  delete mStyle;
768  mStyle = 0;
769  QString styleString = itemElem.attribute( "style", "" );
770  setStyle( tr( styleString.toLocal8Bit().data() ) );
771 
772  mUnits = ( ScaleBarUnits )itemElem.attribute( "units" ).toInt();
773  mAlignment = ( Alignment )( itemElem.attribute( "alignment", "0" ).toInt() );
774 
775  //map
776  int mapId = itemElem.attribute( "mapId", "-1" ).toInt();
777  if ( mapId >= 0 )
778  {
781  if ( mComposerMap )
782  {
783  connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
784  connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
785  }
786  }
787 
789 
790  //restore general composer item properties
791  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
792  if ( composerItemList.size() > 0 )
793  {
794  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
795  _readXML( composerItemElem, doc );
796  }
797 
798  return true;
799 }
800 
801 void QgsComposerScaleBar::correctXPositionAlignment( double width, double widthAfter )
802 {
803  //Don't adjust position for numeric scale bars:
804  if ( mStyle->name() == "Numeric" )
805  {
806  return;
807  }
808 
809  if ( mAlignment == Middle )
810  {
811  move( -( widthAfter - width ) / 2.0, 0 );
812  }
813  else if ( mAlignment == Right )
814  {
815  move( -( widthAfter - width ), 0 );
816  }
817 }
818 
Double box with alternating colors.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
double mLabelBarSpace
Space between bar and Text labels.
double mHeight
Height of bars/lines.
double mNumUnitsPerSegment
Size of a segment (in map units)
void setUnits(ScaleBarUnits u)
void setLineCapStyle(Qt::PenCapStyle style)
Sets cap style used when drawing the lines in the scalebar.
double mNumMapUnitsPerScaleBarUnit
Number of map units per scale bar units (e.g.
void setFont(const QFont &font)
A scale bar style that draws text in the form of &#39;1:XXXXX&#39;.
void itemChanged()
Emitted when the item changes.
Qt::PenJoinStyle mLineJoinStyle
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
void setUnitLabeling(const QString &label)
void applyDefaultSize(ScaleBarUnits u=Meters)
Apply default size (scale bar 1/5 of map item width)
void setAlignment(Alignment a)
void applyDefaultSettings()
Apply default settings.
A item that forms part of a map composition.
void setNumSegments(int nSegments)
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Reimplementation of QCanvasItem::paint.
void segmentPositions(QList< QPair< double, double > > &posWidthList) const
Returns the x - positions of the segment borders (in item coordinates) and the width of the segment...
virtual QRectF calculateBoxSize() const
void setNumSegmentsLeft(int nSegmentsLeft)
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
ScaleBarUnits units() const
virtual void drawFrame(QPainter *p)
Draw black frame around item.
QgsScaleBarStyle * mStyle
Scalebar style.
QBrush mBrush2
Secondary fill.
virtual QString name() const =0
bool setEllipsoid(const QString &ellipsoid)
sets ellipsoid by its acronym
void update()
Adjusts box size and calls QgsComposerItem::update()
A scale bar that draws segments using short ticks.
void setNumMapUnitsPerScaleBarUnit(double d)
void adjustBoxSize()
Sets box size suitable to content.
bool _readXML(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document.
double mSegmentMillimeters
Width of a segment (in mm)
void setLineJoinStyle(Qt::PenJoinStyle style)
Sets join style used when drawing the lines in the scalebar.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
static Qt::PenCapStyle decodePenCapStyle(QString str)
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
Qt::PenCapStyle mLineCapStyle
void setStyle(const QString &styleName)
Sets style by name.
virtual void draw(QPainter *p, double xOffset=0) const =0
Draws the style.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
QgsComposerScaleBar(QgsComposition *composition)
bool writeXML(QDomElement &elem, QDomDocument &doc) const override
stores state in Dom element
int mNumSegmentsLeft
Number of segments on left side.
bool readXML(const QDomElement &itemElem, const QDomDocument &doc) override
sets state from Dom document
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
void setBackgroundEnabled(const bool drawBackground)
Set whether this item has a Background drawn around it or not.
A class to represent a point.
Definition: qgspoint.h:63
const QgsComposerMap * composerMap() const
Graphics scene for map printing.
Object representing map window.
QString style() const
Returns style name.
QgsRectangle * currentMapExtent()
Returns a pointer to the current map extent, which is either the original user specified extent or th...
void setComposerMap(const QgsComposerMap *map)
void refreshSegmentMillimeters()
Calculates with of a segment in mm and stores it in mSegmentMillimeters.
void invalidateCurrentMap()
Sets mCompositionMap to 0 if the map is deleted.
void setBoxContentSpace(double space)
int id() const
Get identification number.
General purpose distance and area calculator.
static double textWidthMM(const QFont &font, const QString &text)
Calculate font width in millimeters for a string, including workarounds for QT font rendering issues...
QgsComposition * mComposition
int mNumSegments
Number of segments on right side.
QRectF evalItemRect(const QRectF &newRect, const bool resizeOnly=false)
Evaluates an item&#39;s bounding rect to consider data defined position and size of item and reference po...
bool _writeXML(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document.
virtual void drawBackground(QPainter *p)
Draw background.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
double measureLine(const QList< QgsPoint > &points)
measures line
double mBoxContentSpace
Space between content and item box.
static double fromUnitToUnitFactor(QGis::UnitType fromUnit, QGis::UnitType toUnit)
Returns the conversion factor between the specified units.
Definition: qgis.cpp:135
UnitType
Map units that qgis supports.
Definition: qgis.h:229
QString mUnitLabeling
Labeling of map units.
static Qt::PenJoinStyle decodePenJoinStyle(QString str)
void setSceneRect(const QRectF &rectangle) override
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
double mapWidth() const
Returns diagonal of composer map in selected units (map units / meters / feet / nautical miles) ...
const QgsComposerMap * mComposerMap
Reference to composer map object.
void setNumUnitsPerSegment(double units)
const QgsComposerMap * getComposerMapById(const int id) const
Returns the composer map with specified id.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
void move(double dx, double dy)
Moves item in canvas coordinates.
Scalebar style that draws a single box with alternating color for the segments.
void correctXPositionAlignment(double width, double widthAfter)
Moves scalebar position to the left / right depending on alignment and change in item width...
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:183
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
void setTickPosition(TickPosition p)
QString firstLabelString() const
Returns string of first label (important for drawing, labeling, size calculation. ...
static QString encodePenCapStyle(Qt::PenCapStyle style)
#define tr(sourceText)