00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "qgisinterface.h"
00026 #include "qgisgui.h"
00027 #include "qgsmapcanvas.h"
00028 #include "qgsmaplayer.h"
00029 #include "qgsmaptopixel.h"
00030 #include "qgspoint.h"
00031 #include "qgsproject.h"
00032
00033 #include "plugin.h"
00034
00035 #include <QPainter>
00036 #include <QAction>
00037 #include <QPen>
00038 #include <QPolygon>
00039 #include <QString>
00040 #include <QFontMetrics>
00041 #include <QFont>
00042 #include <QColor>
00043 #include <QMenu>
00044
00045
00046 #include <cmath>
00047
00048
00049 #include "plugingui.h"
00050 #include "qgslogger.h"
00051
00052
00053
00054 #ifdef _MSC_VER
00055 #define round(x) ((x) >= 0 ? floor((x)+0.5) : floor((x)-0.5))
00056 #endif
00057
00058 static const char * const ident_ = "$Id: plugin.cpp 9471 2008-10-10 20:02:22Z jef $";
00059
00060 static const QString name_ = QObject::tr( "ScaleBar" );
00061 static const QString description_ = QObject::tr( "Draws a scale bar" );
00062 static const QString version_ = QObject::tr( "Version 0.1" );
00063 static const QgisPlugin::PLUGINTYPE type_ = QgisPlugin::UI;
00064
00065
00072 QgsScaleBarPlugin::QgsScaleBarPlugin( QgisInterface * theQgisInterFace ):
00073 QgisPlugin( name_, description_, version_, type_ ),
00074 qGisInterface( theQgisInterFace )
00075 {
00076 mPlacementLabels << tr( "Bottom Left" ) << tr( "Top Left" )
00077 << tr( "Top Right" ) << tr( "Bottom Right" );
00078 mPlacementIndex = 1;
00079 mStyleLabels << tr( "Tick Down" ) << tr( "Tick Up" )
00080 << tr( "Bar" ) << tr( "Box" );
00081
00082 mPreferredSize = 30;
00083 mStyleIndex = 0;
00084 mEnabled = true;
00085 mSnapping = true;
00086 mColour = Qt::black;
00087 }
00088
00089 QgsScaleBarPlugin::~QgsScaleBarPlugin()
00090 {
00091
00092 }
00093
00094
00095
00096
00097 void QgsScaleBarPlugin::initGui()
00098 {
00099
00100 myQActionPointer = new QAction( QIcon( ":/scale_bar.png" ), tr( "&Scale Bar" ), this );
00101 myQActionPointer->setWhatsThis( tr( "Creates a scale bar that is displayed on the map canvas" ) );
00102
00103 connect( myQActionPointer, SIGNAL( activated() ), this, SLOT( run() ) );
00104
00105 connect( qGisInterface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( renderScaleBar( QPainter * ) ) );
00106
00107 connect( qGisInterface->mainWindow(), SIGNAL( projectRead() ), this, SLOT( projectRead() ) );
00108
00109 qGisInterface->addToolBarIcon( myQActionPointer );
00110 qGisInterface->addPluginToMenu( tr( "&Decorations" ), myQActionPointer );
00111 }
00112
00113 void QgsScaleBarPlugin::projectRead()
00114 {
00115 QgsDebugMsg( "+++++++++ scalebar plugin - project read slot called...." );
00116
00117
00118 mPreferredSize = QgsProject::instance()->readNumEntry( "ScaleBar", "/PreferredSize", 30 );
00119 mStyleIndex = QgsProject::instance()->readNumEntry( "ScaleBar", "/Style", 0 );
00120 mPlacementIndex = QgsProject::instance()->readNumEntry( "ScaleBar", "/Placement", 2 );
00121 mEnabled = QgsProject::instance()->readBoolEntry( "ScaleBar", "/Enabled", true );
00122 mSnapping = QgsProject::instance()->readBoolEntry( "ScaleBar", "/Snapping", true );
00123 int myRedInt = QgsProject::instance()->readNumEntry( "ScaleBar", "/ColorRedPart", 0 );
00124 int myGreenInt = QgsProject::instance()->readNumEntry( "ScaleBar", "/ColorGreenPart", 0 );
00125 int myBlueInt = QgsProject::instance()->readNumEntry( "ScaleBar", "/ColorBluePart", 0 );
00126 mColour = QColor( myRedInt, myGreenInt, myBlueInt );
00127 }
00128
00129 void QgsScaleBarPlugin::help()
00130 {
00131
00132 }
00133
00134
00135 void QgsScaleBarPlugin::run()
00136 {
00137 QgsScaleBarPluginGui *myPluginGui = new QgsScaleBarPluginGui( qGisInterface->mainWindow(), QgisGui::ModalDialogFlags );
00138 myPluginGui->setAttribute( Qt::WA_DeleteOnClose );
00139 myPluginGui->setPreferredSize( mPreferredSize );
00140 myPluginGui->setSnapping( mSnapping );
00141 myPluginGui->setPlacementLabels( mPlacementLabels );
00142 myPluginGui->setPlacement( mPlacementIndex );
00143 myPluginGui->setEnabled( mEnabled );
00144 myPluginGui->setStyleLabels( mStyleLabels );
00145 myPluginGui->setStyle( mStyleIndex );
00146 myPluginGui->setColour( mColour );
00147
00148 connect( myPluginGui, SIGNAL( changePreferredSize( int ) ), this, SLOT( setPreferredSize( int ) ) );
00149 connect( myPluginGui, SIGNAL( changeSnapping( bool ) ), this, SLOT( setSnapping( bool ) ) );
00150 connect( myPluginGui, SIGNAL( changePlacement( int ) ), this, SLOT( setPlacement( int ) ) );
00151 connect( myPluginGui, SIGNAL( changeEnabled( bool ) ), this, SLOT( setEnabled( bool ) ) );
00152 connect( myPluginGui, SIGNAL( changeStyle( int ) ), this, SLOT( setStyle( int ) ) );
00153 connect( myPluginGui, SIGNAL( changeColour( QColor ) ), this, SLOT( setColour( QColor ) ) );
00154 connect( myPluginGui, SIGNAL( refreshCanvas() ), this, SLOT( refreshCanvas() ) );
00155 myPluginGui->show();
00156
00157 int myUnits = qGisInterface->mapCanvas()->mapUnits();
00158 switch ( myUnits )
00159 {
00160 case 0: myPluginGui->getSpinSize()->setSuffix( tr( " metres/km" ) ); break;
00161 case 1: myPluginGui->getSpinSize()->setSuffix( tr( " feet/miles" ) ); break;
00162 case 2: myPluginGui->getSpinSize()->setSuffix( tr( " degrees" ) ); break;
00163 default:
00164 QgsDebugMsg( QString( "Error: not picked up map units - actual value = %1" ).arg( myUnits ) );
00165 };
00166 }
00167
00168
00169 void QgsScaleBarPlugin::refreshCanvas()
00170 {
00171 qGisInterface->mapCanvas()->refresh();
00172 }
00173
00174
00175
00176
00177 void QgsScaleBarPlugin::renderScaleBar( QPainter * theQPainter )
00178 {
00179 int myBufferSize = 1;
00180
00181
00182 int myCanvasHeight = theQPainter->device()->height();
00183 int myCanvasWidth = theQPainter->device()->width();
00184
00185
00186
00187
00188 double myMapUnitsPerPixelDouble = std::abs( qGisInterface->mapCanvas()->mapUnitsPerPixel() );
00189
00190
00191 int myLayerCount = qGisInterface->mapCanvas()->layerCount();
00192 if ( !myLayerCount || !myCanvasWidth || !myMapUnitsPerPixelDouble ) return;
00193
00194
00195 if ( mEnabled )
00196 {
00197
00198 int myMajorTickSize = 8;
00199 int myTextOffsetX = 3;
00200 double myActualSize = mPreferredSize;
00201 int myMargin = 20;
00202
00203
00204 double myScaleBarWidth = mPreferredSize / myMapUnitsPerPixelDouble;
00205
00206
00207 if ( myScaleBarWidth < 30 )
00208 {
00209 myScaleBarWidth = myCanvasWidth / 4;
00210 myActualSize = myScaleBarWidth * myMapUnitsPerPixelDouble;
00211 };
00212
00213
00214 while ( myScaleBarWidth > myCanvasWidth / 3 )
00215 {
00216 myScaleBarWidth = myScaleBarWidth / 3;
00217 };
00218 myActualSize = myScaleBarWidth * myMapUnitsPerPixelDouble;
00219
00220
00221
00222 double myPowerOf10 = floor( log10( myActualSize ) );
00223
00224
00225 if ( mSnapping )
00226 {
00227 double scaler = pow( 10.0, myPowerOf10 );
00228 myActualSize = round( myActualSize / scaler ) * scaler;
00229 myScaleBarWidth = myActualSize / myMapUnitsPerPixelDouble;
00230 }
00231
00232
00233 QGis::UnitType myMapUnits = qGisInterface->mapCanvas()->mapUnits();
00234 QString myScaleBarUnitLabel;
00235 switch ( myMapUnits )
00236 {
00237 case QGis::Meters:
00238 if ( myActualSize > 1000.0 )
00239 {
00240 myScaleBarUnitLabel = tr( " km" );
00241 myActualSize = myActualSize / 1000;
00242 }
00243 else if ( myActualSize < 0.01 )
00244 {
00245 myScaleBarUnitLabel = tr( " mm" );
00246 myActualSize = myActualSize * 1000;
00247 }
00248 else if ( myActualSize < 0.1 )
00249 {
00250 myScaleBarUnitLabel = tr( " cm" );
00251 myActualSize = myActualSize * 100;
00252 }
00253 else
00254 myScaleBarUnitLabel = tr( " m" );
00255 break;
00256 case QGis::Feet:
00257 if ( myActualSize > 5280.0 )
00258 {
00259 myScaleBarUnitLabel = tr( " miles" );
00260 myActualSize = myActualSize / 5280;
00261 }
00262 else if ( myActualSize == 5280.0 )
00263 {
00264 myScaleBarUnitLabel = tr( " mile" );
00265 myActualSize = myActualSize / 5280;
00266 }
00267 else if ( myActualSize < 1 )
00268 {
00269 myScaleBarUnitLabel = tr( " inches" );
00270 myActualSize = myActualSize * 12;
00271 }
00272 else if ( myActualSize == 1.0 )
00273 {
00274 myScaleBarUnitLabel = tr( " foot" );
00275 }
00276 else
00277 {
00278 myScaleBarUnitLabel = tr( " feet" );
00279 }
00280 break;
00281 case QGis::Degrees:
00282 if ( myActualSize == 1.0 )
00283 myScaleBarUnitLabel = tr( " degree" );
00284 else
00285 myScaleBarUnitLabel = tr( " degrees" );
00286 break;
00287 case QGis::UnknownUnit:
00288 myScaleBarUnitLabel = tr( " unknown" );
00289 default:
00290 QgsDebugMsg( QString( "Error: not picked up map units - actual value = %1" ).arg( myMapUnits ) );
00291 };
00292
00293
00294 int myFontSize = 10;
00295 QFont myFont( "helvetica", myFontSize );
00296 theQPainter->setFont( myFont );
00297 QFontMetrics myFontMetrics( myFont );
00298 double myFontWidth = myFontMetrics.width( myScaleBarUnitLabel );
00299 double myFontHeight = myFontMetrics.height();
00300
00301
00302 QString myScaleBarMaxLabel = QString::number( myActualSize );
00303
00304
00305 double myTotalScaleBarWidth = myScaleBarWidth + myFontWidth;
00306
00307
00308 int myOriginX = myMargin;
00309 int myOriginY = myMargin;
00310 switch ( mPlacementIndex )
00311 {
00312 case 0:
00313 myOriginX = myMargin;
00314 myOriginY = myCanvasHeight - myMargin;
00315 break;
00316 case 1:
00317 myOriginX = myMargin;
00318 myOriginY = myMargin;
00319 break;
00320 case 2:
00321 myOriginX = myCanvasWidth - (( int ) myTotalScaleBarWidth ) - myMargin;
00322 myOriginY = myMargin;
00323 break;
00324 case 3:
00325 myOriginX = myCanvasWidth - (( int ) myTotalScaleBarWidth ) - myMargin;
00326 myOriginY = myCanvasHeight - myMargin;
00327 break;
00328 default:
00329 QgsDebugMsg( "Unable to determine where to put scale bar so defaulting to top left" );
00330 }
00331
00332
00333 QPen myForegroundPen( mColour, 2 );
00334 QPen myBackgroundPen( Qt::white, 4 );
00335
00336
00337 int myScaleBarWidthInt = ( int ) myScaleBarWidth;
00338
00339
00340 switch ( mStyleIndex )
00341 {
00342 case 0:
00343 {
00344 QPolygon myTickDownArray( 4 );
00345
00346 theQPainter->setPen( myBackgroundPen );
00347 myTickDownArray.putPoints( 0, 4,
00348 myOriginX , ( myOriginY + myMajorTickSize ) ,
00349 myOriginX , myOriginY ,
00350 ( myScaleBarWidthInt + myOriginX ), myOriginY ,
00351 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize )
00352 );
00353 theQPainter->drawPolyline( myTickDownArray );
00354
00355 theQPainter->setPen( myForegroundPen );
00356 myTickDownArray.putPoints( 0, 4,
00357 myOriginX , ( myOriginY + myMajorTickSize ) ,
00358 myOriginX , myOriginY ,
00359 ( myScaleBarWidthInt + myOriginX ), myOriginY ,
00360 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize )
00361 );
00362 theQPainter->drawPolyline( myTickDownArray );
00363 break;
00364 }
00365 case 1:
00366 {
00367 QPolygon myTickUpArray( 4 );
00368
00369 theQPainter->setPen( myBackgroundPen );
00370 myTickUpArray.putPoints( 0, 4,
00371 myOriginX , myOriginY ,
00372 myOriginX , myOriginY + myMajorTickSize ,
00373 ( myScaleBarWidthInt + myOriginX ), myOriginY + myMajorTickSize ,
00374 ( myScaleBarWidthInt + myOriginX ), myOriginY
00375 );
00376 theQPainter->drawPolyline( myTickUpArray );
00377
00378 theQPainter->setPen( myForegroundPen );
00379 myTickUpArray.putPoints( 0, 4,
00380 myOriginX , myOriginY ,
00381 myOriginX , myOriginY + myMajorTickSize ,
00382 ( myScaleBarWidthInt + myOriginX ), myOriginY + myMajorTickSize ,
00383 ( myScaleBarWidthInt + myOriginX ), myOriginY
00384 );
00385 theQPainter->drawPolyline( myTickUpArray );
00386 break;
00387 }
00388 case 2:
00389 {
00390 QPolygon myBarArray( 2 );
00391
00392 theQPainter->setPen( myBackgroundPen );
00393 myBarArray.putPoints( 0, 2,
00394 myOriginX , ( myOriginY + ( myMajorTickSize / 2 ) ),
00395 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + ( myMajorTickSize / 2 ) )
00396 );
00397 theQPainter->drawPolyline( myBarArray );
00398
00399 theQPainter->setPen( myForegroundPen );
00400 myBarArray.putPoints( 0, 2,
00401 myOriginX , ( myOriginY + ( myMajorTickSize / 2 ) ),
00402 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + ( myMajorTickSize / 2 ) )
00403 );
00404 theQPainter->drawPolyline( myBarArray );
00405 break;
00406 }
00407 case 3:
00408 {
00409
00410 myBackgroundPen.setJoinStyle( Qt::MiterJoin );
00411 myForegroundPen.setJoinStyle( Qt::MiterJoin );
00412 QPolygon myBoxArray( 5 );
00413
00414 theQPainter->setPen( myBackgroundPen );
00415 myBoxArray.putPoints( 0, 5,
00416 myOriginX , myOriginY,
00417 ( myScaleBarWidthInt + myOriginX ), myOriginY,
00418 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ),
00419 myOriginX , ( myOriginY + myMajorTickSize ),
00420 myOriginX , myOriginY
00421 );
00422 theQPainter->drawPolyline( myBoxArray );
00423
00424 theQPainter->setPen( myForegroundPen );
00425 theQPainter->setBrush( QBrush( mColour, Qt::SolidPattern ) );
00426 int midPointX = myScaleBarWidthInt / 2 + myOriginX;
00427 myBoxArray.putPoints( 0, 5,
00428 myOriginX , myOriginY,
00429 midPointX, myOriginY,
00430 midPointX, ( myOriginY + myMajorTickSize ),
00431 myOriginX , ( myOriginY + myMajorTickSize ),
00432 myOriginX , myOriginY
00433 );
00434 theQPainter->drawPolygon( myBoxArray );
00435
00436 theQPainter->setBrush( Qt::NoBrush );
00437 myBoxArray.putPoints( 0, 5,
00438 midPointX , myOriginY,
00439 ( myScaleBarWidthInt + myOriginX ), myOriginY,
00440 ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ),
00441 midPointX , ( myOriginY + myMajorTickSize ),
00442 midPointX , myOriginY
00443 );
00444 theQPainter->drawPolygon( myBoxArray );
00445 break;
00446 }
00447 default:
00448 QgsDebugMsg( "Unknown style" );
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 QColor myBackColor = Qt::white;
00458 QColor myForeColor = Qt::black;
00459
00460
00461 theQPainter->setPen( myBackColor );
00462 myFontWidth = myFontMetrics.width( "0" );
00463 myFontHeight = myFontMetrics.height();
00464
00465 for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
00466 {
00467 for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
00468 {
00469 theQPainter->drawText( int( i + ( myOriginX - ( myFontWidth / 2 ) ) ),
00470 int( j + ( myOriginY - ( myFontHeight / 4 ) ) ),
00471 "0" );
00472 }
00473 }
00474
00475
00476 theQPainter->setPen( myForeColor );
00477
00478 theQPainter->drawText(
00479 int( myOriginX - ( myFontWidth / 2 ) ),
00480 int( myOriginY - ( myFontHeight / 4 ) ),
00481 "0"
00482 );
00483
00484
00485
00486
00487 theQPainter->setPen( myBackColor );
00488 myFontWidth = myFontMetrics.width( myScaleBarMaxLabel );
00489 myFontHeight = myFontMetrics.height();
00490
00491 for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
00492 {
00493 for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
00494 {
00495 theQPainter->drawText( int( i + ( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ) ),
00496 int( j + ( myOriginY - ( myFontHeight / 4 ) ) ),
00497 myScaleBarMaxLabel );
00498 }
00499 }
00500
00501 theQPainter->setPen( myForeColor );
00502 theQPainter->drawText(
00503 int( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ),
00504 int( myOriginY - ( myFontHeight / 4 ) ),
00505 myScaleBarMaxLabel
00506 );
00507
00508
00509
00510
00511 theQPainter->setPen( myBackColor );
00512 myFontWidth = myFontMetrics.width( myScaleBarUnitLabel );
00513 myFontHeight = myFontMetrics.height();
00514
00515 for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
00516 {
00517 for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
00518 {
00519 theQPainter->drawText( i + ( myOriginX + myScaleBarWidthInt + myTextOffsetX ),
00520 j + ( myOriginY + myMajorTickSize ),
00521 myScaleBarUnitLabel );
00522 }
00523 }
00524
00525 theQPainter->setPen( myForeColor );
00526 theQPainter->drawText(
00527 ( myOriginX + myScaleBarWidthInt + myTextOffsetX ), ( myOriginY + myMajorTickSize ),
00528 myScaleBarUnitLabel
00529 );
00530 }
00531 }
00532
00533
00534
00535
00536 void QgsScaleBarPlugin::unload()
00537 {
00538
00539 qGisInterface->removePluginMenu( tr( "&Decorations" ), myQActionPointer );
00540 qGisInterface->removeToolBarIcon( myQActionPointer );
00541
00542
00543 disconnect( qGisInterface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ),
00544 this, SLOT( renderScaleBar( QPainter * ) ) );
00545 refreshCanvas();
00546
00547 delete myQActionPointer;
00548 }
00549
00551 void QgsScaleBarPlugin::setPlacement( int placementIndex )
00552 {
00553 mPlacementIndex = placementIndex;
00554 QgsProject::instance()->writeEntry( "ScaleBar", "/Placement", mPlacementIndex );
00555 }
00556
00558 void QgsScaleBarPlugin::setPreferredSize( int thePreferredSize )
00559 {
00560 mPreferredSize = thePreferredSize;
00561 QgsProject::instance()->writeEntry( "ScaleBar", "/PreferredSize", mPreferredSize );
00562 }
00563
00565 void QgsScaleBarPlugin::setSnapping( bool theSnapping )
00566 {
00567 mSnapping = theSnapping;
00568 QgsProject::instance()->writeEntry( "ScaleBar", "/Snapping", mSnapping );
00569 }
00570
00572 void QgsScaleBarPlugin::setEnabled( bool theBool )
00573 {
00574 mEnabled = theBool;
00575 QgsProject::instance()->writeEntry( "ScaleBar", "/Enabled", mEnabled );
00576 }
00578 void QgsScaleBarPlugin::setStyle( int styleIndex )
00579 {
00580 mStyleIndex = styleIndex;
00581 QgsProject::instance()->writeEntry( "ScaleBar", "/Style", mStyleIndex );
00582 }
00584 void QgsScaleBarPlugin::setColour( QColor theQColor )
00585 {
00586 mColour = theQColor;
00587 QgsProject::instance()->writeEntry( "ScaleBar", "/ColorRedPart", mColour.red() );
00588 QgsProject::instance()->writeEntry( "ScaleBar", "/ColorGreenPart", mColour.green() );
00589 QgsProject::instance()->writeEntry( "ScaleBar", "/ColorBluePart", mColour.blue() );
00590 }
00591
00592
00598
00599 QGISEXTERN QgisPlugin * classFactory( QgisInterface * theQgisInterfacePointer )
00600 {
00601 return new QgsScaleBarPlugin( theQgisInterfacePointer );
00602 }
00603
00604
00605
00606 QGISEXTERN QString name()
00607 {
00608 return name_;
00609 }
00610
00611
00612 QGISEXTERN QString description()
00613 {
00614 return description_;
00615 }
00616
00617
00618 QGISEXTERN int type()
00619 {
00620 return type_;
00621 }
00622
00623
00624 QGISEXTERN QString version()
00625 {
00626 return version_;
00627 }
00628
00629
00630 QGISEXTERN void unload( QgisPlugin * thePluginPointer )
00631 {
00632 delete thePluginPointer;
00633 }