1
/***************************************************************************
2
qgscomposerscalebar.cpp
5
copyright : (C) 2005 by Radim Blazek
7
***************************************************************************/
8
/***************************************************************************
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. *
15
***************************************************************************/
17
#include "qgscomposerscalebar.h"
18
#include "qgscomposermap.h"
19
#include "qgsscalebarstyle.h"
20
#include "qgsdoubleboxscalebarstyle.h"
21
#include "qgsnumericscalebarstyle.h"
22
#include "qgssingleboxscalebarstyle.h"
23
#include "qgsticksscalebarstyle.h"
24
#include "qgsrectangle.h"
25
#include <QDomDocument>
26
#include <QDomElement>
27
#include <QFontMetricsF>
31
QgsComposerScaleBar::QgsComposerScaleBar( QgsComposition* composition ): QgsComposerItem( composition ), mComposerMap( 0 ), mStyle( 0 ), mSegmentMillimeters( 0.0 )
33
applyDefaultSettings();
36
QgsComposerScaleBar::~QgsComposerScaleBar()
41
void QgsComposerScaleBar::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
43
if ( !mStyle || !painter )
48
drawBackground( painter );
49
painter->setPen( QPen( QColor( 0, 0, 0 ) ) ); //draw all text black
51
//x-offset is half of first label width because labels are drawn centered
52
QString firstLabel = firstLabelString();
53
double firstLabelWidth = textWidthMillimeters( mFont, firstLabel );
55
mStyle->draw( painter, firstLabelWidth / 2 );
57
//draw frame and selection boxes if necessary
61
drawSelectionBoxes( painter );
65
void QgsComposerScaleBar::setNumUnitsPerSegment( double units )
67
mNumUnitsPerSegment = units;
68
refreshSegmentMillimeters();
71
void QgsComposerScaleBar::setComposerMap( const QgsComposerMap* map )
73
disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
74
disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
82
connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
83
connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
85
refreshSegmentMillimeters();
88
void QgsComposerScaleBar::invalidateCurrentMap()
90
disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
91
disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
95
void QgsComposerScaleBar::refreshSegmentMillimeters()
99
//get extent of composer map
100
QgsRectangle composerMapRect = mComposerMap->extent();
102
//get mm dimension of composer map
103
QRectF composerItemRect = mComposerMap->rect();
105
//calculate size depending on mNumUnitsPerSegment
106
mSegmentMillimeters = composerItemRect.width() / composerMapRect.width() * mNumUnitsPerSegment;
110
void QgsComposerScaleBar::applyDefaultSettings()
113
mNumSegmentsLeft = 0;
115
mNumMapUnitsPerScaleBarUnit = 1.0;
119
mStyle = new QgsSingleBoxScaleBarStyle( this );
123
mPen = QPen( QColor( 0, 0, 0 ) );
124
mPen.setWidthF( 1.0 );
126
mBrush.setColor( QColor( 0, 0, 0 ) );
127
mBrush.setStyle( Qt::SolidPattern );
129
mFont.setPointSizeF( 12.0 );
131
mLabelBarSpace = 3.0;
132
mBoxContentSpace = 1.0;
136
//calculate mNumUnitsPerSegment
137
QRectF composerItemRect = mComposerMap->rect();
138
QgsRectangle composerMapRect = mComposerMap->extent();
140
double proposedScaleBarLength = composerMapRect.width() / 4;
141
int powerOf10 = int ( pow( 10.0, int ( log( proposedScaleBarLength ) / log( 10.0 ) ) ) ); // from scalebar plugin
142
int nPow10 = proposedScaleBarLength / powerOf10;
144
mNumUnitsPerSegment = ( nPow10 / 2 ) * powerOf10;
147
refreshSegmentMillimeters();
151
void QgsComposerScaleBar::adjustBoxSize()
158
QRectF box = mStyle->calculateBoxSize();
162
void QgsComposerScaleBar::update()
165
QgsComposerItem::update();
168
void QgsComposerScaleBar::updateSegmentSize()
170
refreshSegmentMillimeters();
174
void QgsComposerScaleBar::segmentPositions( QList<QPair<double, double> >& posWidthList ) const
176
posWidthList.clear();
177
double mCurrentXCoord = mPen.widthF() + mBoxContentSpace;
180
for ( int i = 0; i < mNumSegmentsLeft; ++i )
182
posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters / mNumSegmentsLeft ) );
183
mCurrentXCoord += mSegmentMillimeters / mNumSegmentsLeft;
187
for ( int i = 0; i < mNumSegments; ++i )
189
posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters ) );
190
mCurrentXCoord += mSegmentMillimeters;
194
void QgsComposerScaleBar::setStyle( const QString& styleName )
199
//switch depending on style name
200
if ( styleName == "Single Box" )
202
mStyle = new QgsSingleBoxScaleBarStyle( this );
204
else if ( styleName == "Double Box" )
206
mStyle = new QgsDoubleBoxScaleBarStyle( this );
208
else if ( styleName == "Line Ticks Middle" || styleName == "Line Ticks Down" || styleName == "Line Ticks Up" )
210
QgsTicksScaleBarStyle* tickStyle = new QgsTicksScaleBarStyle( this );
211
if ( styleName == "Line Ticks Middle" )
213
tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksMiddle );
215
else if ( styleName == "Line Ticks Down" )
217
tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksDown );
219
else if ( styleName == "Line Ticks Up" )
221
tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksUp );
225
else if ( styleName == "Numeric" )
227
mStyle = new QgsNumericScaleBarStyle( this );
231
QString QgsComposerScaleBar::style() const
235
return mStyle->name();
243
QString QgsComposerScaleBar::firstLabelString() const
245
if ( mNumSegmentsLeft > 0 )
247
return QString::number( mNumUnitsPerSegment / mNumMapUnitsPerScaleBarUnit );
255
QFont QgsComposerScaleBar::font() const
260
void QgsComposerScaleBar::setFont( const QFont& font )
267
bool QgsComposerScaleBar::writeXML( QDomElement& elem, QDomDocument & doc ) const
274
QDomElement composerScaleBarElem = doc.createElement( "ComposerScaleBar" );
275
composerScaleBarElem.setAttribute( "height", mHeight );
276
composerScaleBarElem.setAttribute( "labelBarSpace", mLabelBarSpace );
277
composerScaleBarElem.setAttribute( "boxContentSpace", mBoxContentSpace );
278
composerScaleBarElem.setAttribute( "numSegments", mNumSegments );
279
composerScaleBarElem.setAttribute( "numSegmentsLeft", mNumSegmentsLeft );
280
composerScaleBarElem.setAttribute( "numUnitsPerSegment", mNumUnitsPerSegment );
281
composerScaleBarElem.setAttribute( "segmentMillimeters", mSegmentMillimeters );
282
composerScaleBarElem.setAttribute( "numMapUnitsPerScaleBarUnit", mNumMapUnitsPerScaleBarUnit );
283
composerScaleBarElem.setAttribute( "font", mFont.toString() );
284
composerScaleBarElem.setAttribute( "outlineWidth", mPen.widthF() );
285
composerScaleBarElem.setAttribute( "unitLabel", mUnitLabeling );
290
composerScaleBarElem.setAttribute( "style", mStyle->name() );
296
composerScaleBarElem.setAttribute( "mapId", mComposerMap->id() );
300
QColor brushColor = mBrush.color();
301
QDomElement colorElem = doc.createElement( "BrushColor" );
302
colorElem.setAttribute( "red", brushColor.red() );
303
colorElem.setAttribute( "green", brushColor.green() );
304
colorElem.setAttribute( "blue", brushColor.blue() );
305
composerScaleBarElem.appendChild( colorElem );
307
elem.appendChild( composerScaleBarElem );
308
return _writeXML( composerScaleBarElem, doc );
311
bool QgsComposerScaleBar::readXML( const QDomElement& itemElem, const QDomDocument& doc )
313
if ( itemElem.isNull() )
318
mHeight = itemElem.attribute( "height", "5.0" ).toDouble();
319
mLabelBarSpace = itemElem.attribute( "labelBarSpace", "3.0" ).toDouble();
320
mBoxContentSpace = itemElem.attribute( "boxContentSpace", "1.0" ).toDouble();
321
mNumSegments = itemElem.attribute( "numSegments", "2" ).toInt();
322
mNumSegmentsLeft = itemElem.attribute( "numSegmentsLeft", "0" ).toInt();
323
mNumUnitsPerSegment = itemElem.attribute( "numUnitsPerSegment", "1.0" ).toDouble();
324
mSegmentMillimeters = itemElem.attribute( "segmentMillimeters", "0.0" ).toDouble();
325
mNumMapUnitsPerScaleBarUnit = itemElem.attribute( "numMapUnitsPerScaleBarUnit", "1.0" ).toDouble();
326
mPen.setWidthF( itemElem.attribute( "outlineWidth", "1.0" ).toDouble() );
327
mUnitLabeling = itemElem.attribute( "unitLabel" );
328
QString fontString = itemElem.attribute( "font", "" );
329
if ( !fontString.isEmpty() )
331
mFont.fromString( fontString );
337
QString styleString = itemElem.attribute( "style", "" );
338
setStyle( tr( styleString.toLocal8Bit().data() ) );
341
int mapId = itemElem.attribute( "mapId", "-1" ).toInt();
344
const QgsComposerMap* composerMap = mComposition->getComposerMapById( mapId );
345
mComposerMap = composerMap;
348
connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
349
connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
353
refreshSegmentMillimeters();
355
//restore general composer item properties
356
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
357
if ( composerItemList.size() > 0 )
359
QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
360
_readXML( composerItemElem, doc );