QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
212  double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
214  {
216  }
218  {
220  }
221  return measure;
222  }
223 }
224 
226 {
227  mAlignment = a;
228  update();
229  emit itemChanged();
230 }
231 
233 {
234  mUnits = u;
236  emit itemChanged();
237 }
238 
239 void QgsComposerScaleBar::setLineJoinStyle( Qt::PenJoinStyle style )
240 {
241  if ( mLineJoinStyle == style )
242  {
243  //no change
244  return;
245  }
247  mPen.setJoinStyle( mLineJoinStyle );
248  update();
249  emit itemChanged();
250 }
251 
252 void QgsComposerScaleBar::setLineCapStyle( Qt::PenCapStyle style )
253 {
254  if ( mLineCapStyle == style )
255  {
256  //no change
257  return;
258  }
260  mPen.setCapStyle( mLineCapStyle );
261  update();
262  emit itemChanged();
263 }
264 
266 {
267  mNumSegments = 2;
268  mNumSegmentsLeft = 0;
269 
271 
272  //style
273  delete mStyle;
274  mStyle = new QgsSingleBoxScaleBarStyle( this );
275 
276  mHeight = 3;
277 
278  //default to no background
279  setBackgroundEnabled( false );
280 
281  mPen = QPen( Qt::black );
282  mPen.setJoinStyle( mLineJoinStyle );
283  mPen.setCapStyle( mLineCapStyle );
284  mPen.setWidthF( 1.0 );
285 
286  mBrush.setColor( Qt::black );
287  mBrush.setStyle( Qt::SolidPattern );
288 
289  mBrush2.setColor( Qt::white );
290  mBrush2.setStyle( Qt::SolidPattern );
291 
292  //get default composer font from settings
293  QSettings settings;
294  QString defaultFontString = settings.value( "/Composer/defaultFont" ).toString();
295  if ( !defaultFontString.isEmpty() )
296  {
297  mFont.setFamily( defaultFontString );
298  }
299  mFont.setPointSizeF( 12.0 );
300  mFontColor = QColor( 0, 0, 0 );
301 
302  mLabelBarSpace = 3.0;
303  mBoxContentSpace = 1.0;
304  emit itemChanged();
305 }
306 
308 {
309  if ( mComposerMap )
310  {
311  setUnits( u );
312  double upperMagnitudeMultiplier = 1.0;
313  double widthInSelectedUnits = mapWidth();
314  double initialUnitsPerSegment = widthInSelectedUnits / 10.0; //default scalebar width equals half the map width
315  setNumUnitsPerSegment( initialUnitsPerSegment );
316 
317  switch ( mUnits )
318  {
319  case MapUnits:
320  {
321  upperMagnitudeMultiplier = 1.0;
322  setUnitLabeling( tr( "units" ) );
323  break;
324  }
325  case Meters:
326  {
327  if ( initialUnitsPerSegment > 1000.0 )
328  {
329  upperMagnitudeMultiplier = 1000.0;
330  setUnitLabeling( tr( "km" ) );
331  }
332  else
333  {
334  upperMagnitudeMultiplier = 1.0;
335  setUnitLabeling( tr( "m" ) );
336  }
337  break;
338  }
339  case Feet:
340  {
341  if ( initialUnitsPerSegment > 5419.95 )
342  {
343  upperMagnitudeMultiplier = 5419.95;
344  setUnitLabeling( tr( "miles" ) );
345  }
346  else
347  {
348  upperMagnitudeMultiplier = 1.0;
349  setUnitLabeling( tr( "ft" ) );
350  }
351  break;
352  }
353  case NauticalMiles:
354  {
355  upperMagnitudeMultiplier = 1;
356  setUnitLabeling( tr( "Nm" ) );
357  break;
358  }
359  }
360 
361  double segmentWidth = initialUnitsPerSegment / upperMagnitudeMultiplier;
362  int segmentMagnitude = floor( log10( segmentWidth ) );
363  double unitsPerSegment = upperMagnitudeMultiplier * ( pow( 10.0, segmentMagnitude ) );
364  double multiplier = floor(( widthInSelectedUnits / ( unitsPerSegment * 10.0 ) ) / 2.5 ) * 2.5;
365 
366  if ( multiplier > 0 )
367  {
368  unitsPerSegment = unitsPerSegment * multiplier;
369  }
370  setNumUnitsPerSegment( unitsPerSegment );
371  setNumMapUnitsPerScaleBarUnit( upperMagnitudeMultiplier );
372 
373  setNumSegments( 4 );
374  setNumSegmentsLeft( 2 );
375  }
376 
378  adjustBoxSize();
379  emit itemChanged();
380 }
381 
383 {
384  if ( !mStyle )
385  {
386  return;
387  }
388 
389  QRectF box = mStyle->calculateBoxSize();
390  if ( rect().height() > box.height() )
391  {
392  //keep user specified item height if higher than minimum scale bar height
393  box.setHeight( rect().height() );
394  }
395 
396  //update rect for data defined size and position
397  QRectF newRect = evalItemRect( box, true );
398 
399  //scale bars have a minimum size, respect that regardless of data defined settings
400  if ( newRect.width() < box.width() )
401  {
402  newRect.setWidth( box.width() );
403  }
404  if ( newRect.height() < box.height() )
405  {
406  newRect.setHeight( box.height() );
407  }
408 
410 }
411 
412 void QgsComposerScaleBar::setSceneRect( const QRectF& rectangle )
413 {
414  QRectF box = mStyle->calculateBoxSize();
415  if ( rectangle.height() > box.height() )
416  {
417  //keep user specified item height if higher than minimum scale bar height
418  box.setHeight( rectangle.height() );
419  }
420  box.moveTopLeft( rectangle.topLeft() );
421 
422  //update rect for data defined size and position
423  QRectF newRect = evalItemRect( rectangle );
424 
425  //scale bars have a minimum size, respect that regardless of data defined settings
426  if ( newRect.width() < box.width() )
427  {
428  newRect.setWidth( box.width() );
429  }
430  if ( newRect.height() < box.height() )
431  {
432  newRect.setHeight( box.height() );
433  }
434 
436 }
437 
439 {
440  //Don't adjust box size for numeric scale bars:
441  if ( mStyle && mStyle->name() != "Numeric" )
442  {
443  adjustBoxSize();
444  }
445  QgsComposerItem::update();
446 }
447 
449 {
450  if ( !mStyle )
451  {
452  return;
453  }
454  double width = mStyle->calculateBoxSize().width();
456  double widthAfter = mStyle->calculateBoxSize().width();
457  correctXPositionAlignment( width, widthAfter );
458  update();
459  emit itemChanged();
460 }
461 
462 void QgsComposerScaleBar::segmentPositions( QList<QPair<double, double> >& posWidthList ) const
463 {
464  posWidthList.clear();
465  double mCurrentXCoord = mPen.widthF() + mBoxContentSpace;
466 
467  //left segments
468  double leftSegmentSize = mSegmentMillimeters / mNumSegmentsLeft;
469  for ( int i = 0; i < mNumSegmentsLeft; ++i )
470  {
471  posWidthList.push_back( qMakePair( mCurrentXCoord, leftSegmentSize ) );
472  mCurrentXCoord += leftSegmentSize;
473  }
474 
475  //right segments
476  for ( int i = 0; i < mNumSegments; ++i )
477  {
478  posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters ) );
479  mCurrentXCoord += mSegmentMillimeters;
480  }
481 }
482 
483 void QgsComposerScaleBar::setStyle( const QString& styleName )
484 {
485  delete mStyle;
486  mStyle = 0;
487 
488  //switch depending on style name
489  if ( styleName == "Single Box" )
490  {
491  mStyle = new QgsSingleBoxScaleBarStyle( this );
492  }
493  else if ( styleName == "Double Box" )
494  {
495  mStyle = new QgsDoubleBoxScaleBarStyle( this );
496  }
497  else if ( styleName == "Line Ticks Middle" || styleName == "Line Ticks Down" || styleName == "Line Ticks Up" )
498  {
499  QgsTicksScaleBarStyle* tickStyle = new QgsTicksScaleBarStyle( this );
500  if ( styleName == "Line Ticks Middle" )
501  {
503  }
504  else if ( styleName == "Line Ticks Down" )
505  {
507  }
508  else if ( styleName == "Line Ticks Up" )
509  {
511  }
512  mStyle = tickStyle;
513  }
514  else if ( styleName == "Numeric" )
515  {
516  mStyle = new QgsNumericScaleBarStyle( this );
517  }
518  emit itemChanged();
519 }
520 
522 {
523  if ( mStyle )
524  {
525  return mStyle->name();
526  }
527  else
528  {
529  return "";
530  }
531 }
532 
534 {
535  if ( mNumSegmentsLeft > 0 )
536  {
537  return QString::number( mNumUnitsPerSegment / mNumMapUnitsPerScaleBarUnit );
538  }
539  else
540  {
541  return "0";
542  }
543 }
544 
546 {
547  return mFont;
548 }
549 
550 void QgsComposerScaleBar::setFont( const QFont& font )
551 {
552  mFont = font;
553  update();
554  emit itemChanged();
555 }
556 
557 bool QgsComposerScaleBar::writeXML( QDomElement& elem, QDomDocument & doc ) const
558 {
559  if ( elem.isNull() )
560  {
561  return false;
562  }
563 
564  QDomElement composerScaleBarElem = doc.createElement( "ComposerScaleBar" );
565  composerScaleBarElem.setAttribute( "height", QString::number( mHeight ) );
566  composerScaleBarElem.setAttribute( "labelBarSpace", QString::number( mLabelBarSpace ) );
567  composerScaleBarElem.setAttribute( "boxContentSpace", QString::number( mBoxContentSpace ) );
568  composerScaleBarElem.setAttribute( "numSegments", mNumSegments );
569  composerScaleBarElem.setAttribute( "numSegmentsLeft", mNumSegmentsLeft );
570  composerScaleBarElem.setAttribute( "numUnitsPerSegment", QString::number( mNumUnitsPerSegment ) );
571  composerScaleBarElem.setAttribute( "segmentMillimeters", QString::number( mSegmentMillimeters ) );
572  composerScaleBarElem.setAttribute( "numMapUnitsPerScaleBarUnit", QString::number( mNumMapUnitsPerScaleBarUnit ) );
573  composerScaleBarElem.setAttribute( "font", mFont.toString() );
574  composerScaleBarElem.setAttribute( "outlineWidth", QString::number( mPen.widthF() ) );
575  composerScaleBarElem.setAttribute( "unitLabel", mUnitLabeling );
576  composerScaleBarElem.setAttribute( "units", mUnits );
577  composerScaleBarElem.setAttribute( "lineJoinStyle", QgsSymbolLayerV2Utils::encodePenJoinStyle( mLineJoinStyle ) );
578  composerScaleBarElem.setAttribute( "lineCapStyle", QgsSymbolLayerV2Utils::encodePenCapStyle( mLineCapStyle ) );
579 
580  //style
581  if ( mStyle )
582  {
583  composerScaleBarElem.setAttribute( "style", mStyle->name() );
584  }
585 
586  //map id
587  if ( mComposerMap )
588  {
589  composerScaleBarElem.setAttribute( "mapId", mComposerMap->id() );
590  }
591 
592  //colors
593 
594  //fill color
595  QDomElement fillColorElem = doc.createElement( "fillColor" );
596  QColor fillColor = mBrush.color();
597  fillColorElem.setAttribute( "red", QString::number( fillColor.red() ) );
598  fillColorElem.setAttribute( "green", QString::number( fillColor.green() ) );
599  fillColorElem.setAttribute( "blue", QString::number( fillColor.blue() ) );
600  fillColorElem.setAttribute( "alpha", QString::number( fillColor.alpha() ) );
601  composerScaleBarElem.appendChild( fillColorElem );
602 
603  //fill color 2
604  QDomElement fillColor2Elem = doc.createElement( "fillColor2" );
605  QColor fillColor2 = mBrush2.color();
606  fillColor2Elem.setAttribute( "red", QString::number( fillColor2.red() ) );
607  fillColor2Elem.setAttribute( "green", QString::number( fillColor2.green() ) );
608  fillColor2Elem.setAttribute( "blue", QString::number( fillColor2.blue() ) );
609  fillColor2Elem.setAttribute( "alpha", QString::number( fillColor2.alpha() ) );
610  composerScaleBarElem.appendChild( fillColor2Elem );
611 
612  //pen color
613  QDomElement strokeColorElem = doc.createElement( "strokeColor" );
614  QColor strokeColor = mPen.color();
615  strokeColorElem.setAttribute( "red", QString::number( strokeColor.red() ) );
616  strokeColorElem.setAttribute( "green", QString::number( strokeColor.green() ) );
617  strokeColorElem.setAttribute( "blue", QString::number( strokeColor.blue() ) );
618  strokeColorElem.setAttribute( "alpha", QString::number( strokeColor.alpha() ) );
619  composerScaleBarElem.appendChild( strokeColorElem );
620 
621  //font color
622  QDomElement fontColorElem = doc.createElement( "textColor" );
623  fontColorElem.setAttribute( "red", QString::number( mFontColor.red() ) );
624  fontColorElem.setAttribute( "green", QString::number( mFontColor.green() ) );
625  fontColorElem.setAttribute( "blue", QString::number( mFontColor.blue() ) );
626  fontColorElem.setAttribute( "alpha", QString::number( mFontColor.alpha() ) );
627  composerScaleBarElem.appendChild( fontColorElem );
628 
629  //alignment
630  composerScaleBarElem.setAttribute( "alignment", QString::number(( int ) mAlignment ) );
631 
632  elem.appendChild( composerScaleBarElem );
633  return _writeXML( composerScaleBarElem, doc );
634 }
635 
636 bool QgsComposerScaleBar::readXML( const QDomElement& itemElem, const QDomDocument& doc )
637 {
638  if ( itemElem.isNull() )
639  {
640  return false;
641  }
642 
643  mHeight = itemElem.attribute( "height", "5.0" ).toDouble();
644  mLabelBarSpace = itemElem.attribute( "labelBarSpace", "3.0" ).toDouble();
645  mBoxContentSpace = itemElem.attribute( "boxContentSpace", "1.0" ).toDouble();
646  mNumSegments = itemElem.attribute( "numSegments", "2" ).toInt();
647  mNumSegmentsLeft = itemElem.attribute( "numSegmentsLeft", "0" ).toInt();
648  mNumUnitsPerSegment = itemElem.attribute( "numUnitsPerSegment", "1.0" ).toDouble();
649  mSegmentMillimeters = itemElem.attribute( "segmentMillimeters", "0.0" ).toDouble();
650  mNumMapUnitsPerScaleBarUnit = itemElem.attribute( "numMapUnitsPerScaleBarUnit", "1.0" ).toDouble();
651  mPen.setWidthF( itemElem.attribute( "outlineWidth", "1.0" ).toDouble() );
652  mUnitLabeling = itemElem.attribute( "unitLabel" );
653  mLineJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( itemElem.attribute( "lineJoinStyle", "miter" ) );
654  mPen.setJoinStyle( mLineJoinStyle );
655  mLineCapStyle = QgsSymbolLayerV2Utils::decodePenCapStyle( itemElem.attribute( "lineCapStyle", "square" ) );
656  mPen.setCapStyle( mLineCapStyle );
657  QString fontString = itemElem.attribute( "font", "" );
658  if ( !fontString.isEmpty() )
659  {
660  mFont.fromString( fontString );
661  }
662 
663  //colors
664  //fill color
665  QDomNodeList fillColorList = itemElem.elementsByTagName( "fillColor" );
666  if ( fillColorList.size() > 0 )
667  {
668  QDomElement fillColorElem = fillColorList.at( 0 ).toElement();
669  bool redOk, greenOk, blueOk, alphaOk;
670  int fillRed, fillGreen, fillBlue, fillAlpha;
671 
672  fillRed = fillColorElem.attribute( "red" ).toDouble( &redOk );
673  fillGreen = fillColorElem.attribute( "green" ).toDouble( &greenOk );
674  fillBlue = fillColorElem.attribute( "blue" ).toDouble( &blueOk );
675  fillAlpha = fillColorElem.attribute( "alpha" ).toDouble( &alphaOk );
676 
677  if ( redOk && greenOk && blueOk && alphaOk )
678  {
679  mBrush.setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
680  }
681  }
682  else
683  {
684  mBrush.setColor( QColor( itemElem.attribute( "brushColor", "#000000" ) ) );
685  }
686 
687  //fill color 2
688  QDomNodeList fillColor2List = itemElem.elementsByTagName( "fillColor2" );
689  if ( fillColor2List.size() > 0 )
690  {
691  QDomElement fillColor2Elem = fillColor2List.at( 0 ).toElement();
692  bool redOk, greenOk, blueOk, alphaOk;
693  int fillRed, fillGreen, fillBlue, fillAlpha;
694 
695  fillRed = fillColor2Elem.attribute( "red" ).toDouble( &redOk );
696  fillGreen = fillColor2Elem.attribute( "green" ).toDouble( &greenOk );
697  fillBlue = fillColor2Elem.attribute( "blue" ).toDouble( &blueOk );
698  fillAlpha = fillColor2Elem.attribute( "alpha" ).toDouble( &alphaOk );
699 
700  if ( redOk && greenOk && blueOk && alphaOk )
701  {
702  mBrush2.setColor( QColor( fillRed, fillGreen, fillBlue, fillAlpha ) );
703  }
704  }
705  else
706  {
707  mBrush2.setColor( QColor( itemElem.attribute( "brush2Color", "#ffffff" ) ) );
708  }
709 
710  //stroke color
711  QDomNodeList strokeColorList = itemElem.elementsByTagName( "strokeColor" );
712  if ( strokeColorList.size() > 0 )
713  {
714  QDomElement strokeColorElem = strokeColorList.at( 0 ).toElement();
715  bool redOk, greenOk, blueOk, alphaOk;
716  int strokeRed, strokeGreen, strokeBlue, strokeAlpha;
717 
718  strokeRed = strokeColorElem.attribute( "red" ).toDouble( &redOk );
719  strokeGreen = strokeColorElem.attribute( "green" ).toDouble( &greenOk );
720  strokeBlue = strokeColorElem.attribute( "blue" ).toDouble( &blueOk );
721  strokeAlpha = strokeColorElem.attribute( "alpha" ).toDouble( &alphaOk );
722 
723  if ( redOk && greenOk && blueOk && alphaOk )
724  {
725  mPen.setColor( QColor( strokeRed, strokeGreen, strokeBlue, strokeAlpha ) );
726  }
727  }
728  else
729  {
730  mPen.setColor( QColor( itemElem.attribute( "penColor", "#000000" ) ) );
731  }
732 
733  //font color
734  QDomNodeList textColorList = itemElem.elementsByTagName( "textColor" );
735  if ( textColorList.size() > 0 )
736  {
737  QDomElement textColorElem = textColorList.at( 0 ).toElement();
738  bool redOk, greenOk, blueOk, alphaOk;
739  int textRed, textGreen, textBlue, textAlpha;
740 
741  textRed = textColorElem.attribute( "red" ).toDouble( &redOk );
742  textGreen = textColorElem.attribute( "green" ).toDouble( &greenOk );
743  textBlue = textColorElem.attribute( "blue" ).toDouble( &blueOk );
744  textAlpha = textColorElem.attribute( "alpha" ).toDouble( &alphaOk );
745 
746  if ( redOk && greenOk && blueOk && alphaOk )
747  {
748  mFontColor = QColor( textRed, textGreen, textBlue, textAlpha );
749  }
750  }
751  else
752  {
753  mFontColor.setNamedColor( itemElem.attribute( "fontColor", "#000000" ) );
754  }
755 
756  //style
757  delete mStyle;
758  mStyle = 0;
759  QString styleString = itemElem.attribute( "style", "" );
760  setStyle( tr( styleString.toLocal8Bit().data() ) );
761 
762  mUnits = ( ScaleBarUnits )itemElem.attribute( "units" ).toInt();
763  mAlignment = ( Alignment )( itemElem.attribute( "alignment", "0" ).toInt() );
764 
765  //map
766  int mapId = itemElem.attribute( "mapId", "-1" ).toInt();
767  if ( mapId >= 0 )
768  {
771  if ( mComposerMap )
772  {
773  connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
774  connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
775  }
776  }
777 
779 
780  //restore general composer item properties
781  QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
782  if ( composerItemList.size() > 0 )
783  {
784  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
785  _readXML( composerItemElem, doc );
786  }
787 
788  return true;
789 }
790 
791 void QgsComposerScaleBar::correctXPositionAlignment( double width, double widthAfter )
792 {
793  //Don't adjust position for numeric scale bars:
794  if ( mStyle->name() == "Numeric" )
795  {
796  return;
797  }
798 
799  if ( mAlignment == Middle )
800  {
801  move( -( widthAfter - width ) / 2.0, 0 );
802  }
803  else if ( mAlignment == Right )
804  {
805  move( -( widthAfter - width ), 0 );
806  }
807 }
808 
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)
bool writeXML(QDomElement &elem, QDomDocument &doc) const
stores state in Dom element
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.
bool readXML(const QDomElement &itemElem, const QDomDocument &doc)
sets state from Dom document
void setFont(const QFont &font)
A scale bar style that draws text in the form of '1:XXXXX'.
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 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.
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 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)
int mNumSegmentsLeft
Number of segments on left side.
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's bounding rect to consider data defined position and size of item and reference po...
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget)
Reimplementation of QCanvasItem::paint.
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:362
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:123
QString mUnitLabeling
Labeling of map units.
static Qt::PenJoinStyle decodePenJoinStyle(QString str)
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)