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