00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "qgscomposerscalebar.h"
00018 #include "qgscomposermap.h"
00019 #include "qgsscalebarstyle.h"
00020 #include "qgsdoubleboxscalebarstyle.h"
00021 #include "qgsnumericscalebarstyle.h"
00022 #include "qgssingleboxscalebarstyle.h"
00023 #include "qgsticksscalebarstyle.h"
00024 #include "qgsrectangle.h"
00025 #include <QDomDocument>
00026 #include <QDomElement>
00027 #include <QFontMetricsF>
00028 #include <QPainter>
00029 #include <cmath>
00030
00031 QgsComposerScaleBar::QgsComposerScaleBar( QgsComposition* composition ): QgsComposerItem( composition ), mComposerMap( 0 ), mStyle( 0 ), mSegmentMillimeters( 0.0 )
00032 {
00033 applyDefaultSettings();
00034 }
00035
00036 QgsComposerScaleBar::~QgsComposerScaleBar()
00037 {
00038 delete mStyle;
00039 }
00040
00041 void QgsComposerScaleBar::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
00042 {
00043 if ( !mStyle || !painter )
00044 {
00045 return;
00046 }
00047
00048 drawBackground( painter );
00049 painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
00050
00051
00052 QString firstLabel = firstLabelString();
00053 double firstLabelWidth = textWidthMillimeters( mFont, firstLabel );
00054
00055 mStyle->draw( painter, firstLabelWidth / 2 );
00056
00057
00058 drawFrame( painter );
00059 if ( isSelected() )
00060 {
00061 drawSelectionBoxes( painter );
00062 }
00063 }
00064
00065 void QgsComposerScaleBar::setNumUnitsPerSegment( double units )
00066 {
00067 mNumUnitsPerSegment = units;
00068 refreshSegmentMillimeters();
00069 }
00070
00071 void QgsComposerScaleBar::setComposerMap( const QgsComposerMap* map )
00072 {
00073 disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
00074 disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
00075 mComposerMap = map;
00076
00077 if ( !map )
00078 {
00079 return;
00080 }
00081
00082 connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
00083 connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
00084
00085 refreshSegmentMillimeters();
00086 }
00087
00088 void QgsComposerScaleBar::invalidateCurrentMap()
00089 {
00090 disconnect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
00091 disconnect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
00092 mComposerMap = 0;
00093 }
00094
00095 void QgsComposerScaleBar::refreshSegmentMillimeters()
00096 {
00097 if ( mComposerMap )
00098 {
00099
00100 QgsRectangle composerMapRect = mComposerMap->extent();
00101
00102
00103 QRectF composerItemRect = mComposerMap->rect();
00104
00105
00106 mSegmentMillimeters = composerItemRect.width() / composerMapRect.width() * mNumUnitsPerSegment;
00107 }
00108 }
00109
00110 void QgsComposerScaleBar::applyDefaultSettings()
00111 {
00112 mNumSegments = 2;
00113 mNumSegmentsLeft = 0;
00114
00115 mNumMapUnitsPerScaleBarUnit = 1.0;
00116
00117
00118 delete mStyle;
00119 mStyle = new QgsSingleBoxScaleBarStyle( this );
00120
00121 mHeight = 5;
00122
00123 mPen = QPen( QColor( 0, 0, 0 ) );
00124 mPen.setWidthF( 1.0 );
00125
00126 mBrush.setColor( QColor( 0, 0, 0 ) );
00127 mBrush.setStyle( Qt::SolidPattern );
00128
00129 mFont.setPointSizeF( 12.0 );
00130
00131 mLabelBarSpace = 3.0;
00132 mBoxContentSpace = 1.0;
00133
00134 if ( mComposerMap )
00135 {
00136
00137 QRectF composerItemRect = mComposerMap->rect();
00138 QgsRectangle composerMapRect = mComposerMap->extent();
00139
00140 double proposedScaleBarLength = composerMapRect.width() / 4;
00141 int powerOf10 = int ( pow( 10.0, int ( log( proposedScaleBarLength ) / log( 10.0 ) ) ) );
00142 int nPow10 = proposedScaleBarLength / powerOf10;
00143 mNumSegments = 2;
00144 mNumUnitsPerSegment = ( nPow10 / 2 ) * powerOf10;
00145 }
00146
00147 refreshSegmentMillimeters();
00148 adjustBoxSize();
00149 }
00150
00151 void QgsComposerScaleBar::adjustBoxSize()
00152 {
00153 if ( !mStyle )
00154 {
00155 return;
00156 }
00157
00158 QRectF box = mStyle->calculateBoxSize();
00159 setSceneRect( box );
00160 }
00161
00162 void QgsComposerScaleBar::update()
00163 {
00164 adjustBoxSize();
00165 QgsComposerItem::update();
00166 }
00167
00168 void QgsComposerScaleBar::updateSegmentSize()
00169 {
00170 refreshSegmentMillimeters();
00171 update();
00172 }
00173
00174 void QgsComposerScaleBar::segmentPositions( QList<QPair<double, double> >& posWidthList ) const
00175 {
00176 posWidthList.clear();
00177 double mCurrentXCoord = mPen.widthF() + mBoxContentSpace;
00178
00179
00180 for ( int i = 0; i < mNumSegmentsLeft; ++i )
00181 {
00182 posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters / mNumSegmentsLeft ) );
00183 mCurrentXCoord += mSegmentMillimeters / mNumSegmentsLeft;
00184 }
00185
00186
00187 for ( int i = 0; i < mNumSegments; ++i )
00188 {
00189 posWidthList.push_back( qMakePair( mCurrentXCoord, mSegmentMillimeters ) );
00190 mCurrentXCoord += mSegmentMillimeters;
00191 }
00192 }
00193
00194 void QgsComposerScaleBar::setStyle( const QString& styleName )
00195 {
00196 delete mStyle;
00197 mStyle = 0;
00198
00199
00200 if ( styleName == "Single Box" )
00201 {
00202 mStyle = new QgsSingleBoxScaleBarStyle( this );
00203 }
00204 else if ( styleName == "Double Box" )
00205 {
00206 mStyle = new QgsDoubleBoxScaleBarStyle( this );
00207 }
00208 else if ( styleName == "Line Ticks Middle" || styleName == "Line Ticks Down" || styleName == "Line Ticks Up" )
00209 {
00210 QgsTicksScaleBarStyle* tickStyle = new QgsTicksScaleBarStyle( this );
00211 if ( styleName == "Line Ticks Middle" )
00212 {
00213 tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksMiddle );
00214 }
00215 else if ( styleName == "Line Ticks Down" )
00216 {
00217 tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksDown );
00218 }
00219 else if ( styleName == "Line Ticks Up" )
00220 {
00221 tickStyle->setTickPosition( QgsTicksScaleBarStyle::TicksUp );
00222 }
00223 mStyle = tickStyle;
00224 }
00225 else if ( styleName == "Numeric" )
00226 {
00227 mStyle = new QgsNumericScaleBarStyle( this );
00228 }
00229 }
00230
00231 QString QgsComposerScaleBar::style() const
00232 {
00233 if ( mStyle )
00234 {
00235 return mStyle->name();
00236 }
00237 else
00238 {
00239 return "";
00240 }
00241 }
00242
00243 QString QgsComposerScaleBar::firstLabelString() const
00244 {
00245 if ( mNumSegmentsLeft > 0 )
00246 {
00247 return QString::number( mNumUnitsPerSegment / mNumMapUnitsPerScaleBarUnit );
00248 }
00249 else
00250 {
00251 return "0";
00252 }
00253 }
00254
00255 QFont QgsComposerScaleBar::font() const
00256 {
00257 return mFont;
00258 }
00259
00260 void QgsComposerScaleBar::setFont( const QFont& font )
00261 {
00262 mFont = font;
00263 adjustBoxSize();
00264 update();
00265 }
00266
00267 bool QgsComposerScaleBar::writeXML( QDomElement& elem, QDomDocument & doc ) const
00268 {
00269 if ( elem.isNull() )
00270 {
00271 return false;
00272 }
00273
00274 QDomElement composerScaleBarElem = doc.createElement( "ComposerScaleBar" );
00275 composerScaleBarElem.setAttribute( "height", mHeight );
00276 composerScaleBarElem.setAttribute( "labelBarSpace", mLabelBarSpace );
00277 composerScaleBarElem.setAttribute( "boxContentSpace", mBoxContentSpace );
00278 composerScaleBarElem.setAttribute( "numSegments", mNumSegments );
00279 composerScaleBarElem.setAttribute( "numSegmentsLeft", mNumSegmentsLeft );
00280 composerScaleBarElem.setAttribute( "numUnitsPerSegment", mNumUnitsPerSegment );
00281 composerScaleBarElem.setAttribute( "segmentMillimeters", mSegmentMillimeters );
00282 composerScaleBarElem.setAttribute( "numMapUnitsPerScaleBarUnit", mNumMapUnitsPerScaleBarUnit );
00283 composerScaleBarElem.setAttribute( "font", mFont.toString() );
00284 composerScaleBarElem.setAttribute( "outlineWidth", mPen.widthF() );
00285 composerScaleBarElem.setAttribute( "unitLabel", mUnitLabeling );
00286
00287
00288 if ( mStyle )
00289 {
00290 composerScaleBarElem.setAttribute( "style", mStyle->name() );
00291 }
00292
00293
00294 if ( mComposerMap )
00295 {
00296 composerScaleBarElem.setAttribute( "mapId", mComposerMap->id() );
00297 }
00298
00299
00300 QColor brushColor = mBrush.color();
00301 QDomElement colorElem = doc.createElement( "BrushColor" );
00302 colorElem.setAttribute( "red", brushColor.red() );
00303 colorElem.setAttribute( "green", brushColor.green() );
00304 colorElem.setAttribute( "blue", brushColor.blue() );
00305 composerScaleBarElem.appendChild( colorElem );
00306
00307 elem.appendChild( composerScaleBarElem );
00308 return _writeXML( composerScaleBarElem, doc );
00309 }
00310
00311 bool QgsComposerScaleBar::readXML( const QDomElement& itemElem, const QDomDocument& doc )
00312 {
00313 if ( itemElem.isNull() )
00314 {
00315 return false;
00316 }
00317
00318 mHeight = itemElem.attribute( "height", "5.0" ).toDouble();
00319 mLabelBarSpace = itemElem.attribute( "labelBarSpace", "3.0" ).toDouble();
00320 mBoxContentSpace = itemElem.attribute( "boxContentSpace", "1.0" ).toDouble();
00321 mNumSegments = itemElem.attribute( "numSegments", "2" ).toInt();
00322 mNumSegmentsLeft = itemElem.attribute( "numSegmentsLeft", "0" ).toInt();
00323 mNumUnitsPerSegment = itemElem.attribute( "numUnitsPerSegment", "1.0" ).toDouble();
00324 mSegmentMillimeters = itemElem.attribute( "segmentMillimeters", "0.0" ).toDouble();
00325 mNumMapUnitsPerScaleBarUnit = itemElem.attribute( "numMapUnitsPerScaleBarUnit", "1.0" ).toDouble();
00326 mPen.setWidthF( itemElem.attribute( "outlineWidth", "1.0" ).toDouble() );
00327 mUnitLabeling = itemElem.attribute( "unitLabel" );
00328 QString fontString = itemElem.attribute( "font", "" );
00329 if ( !fontString.isEmpty() )
00330 {
00331 mFont.fromString( fontString );
00332 }
00333
00334
00335 delete mStyle;
00336 mStyle = 0;
00337 QString styleString = itemElem.attribute( "style", "" );
00338 setStyle( tr( styleString.toLocal8Bit().data() ) );
00339
00340
00341 int mapId = itemElem.attribute( "mapId", "-1" ).toInt();
00342 if ( mapId >= 0 )
00343 {
00344 const QgsComposerMap* composerMap = mComposition->getComposerMapById( mapId );
00345 mComposerMap = composerMap;
00346 if ( mComposerMap )
00347 {
00348 connect( mComposerMap, SIGNAL( extentChanged() ), this, SLOT( updateSegmentSize() ) );
00349 connect( mComposerMap, SIGNAL( destroyed( QObject* ) ), this, SLOT( invalidateCurrentMap() ) );
00350 }
00351 }
00352
00353 refreshSegmentMillimeters();
00354
00355
00356 QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
00357 if ( composerItemList.size() > 0 )
00358 {
00359 QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
00360 _readXML( composerItemElem, doc );
00361 }
00362
00363 return true;
00364 }
00365
00366