00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <QtGlobal>
00021 #include <QApplication>
00022 #include <QCursor>
00023 #include <QDir>
00024 #include <QFile>
00025 #include <QGraphicsItem>
00026 #include <QGraphicsScene>
00027 #include <QGraphicsView>
00028 #include <QKeyEvent>
00029 #include <QMouseEvent>
00030 #include <QPainter>
00031 #include <QPaintEvent>
00032 #include <QPixmap>
00033 #include <QRect>
00034 #include <QTextStream>
00035 #include <QResizeEvent>
00036 #include <QString>
00037 #include <QStringList>
00038 #include <QWheelEvent>
00039
00040 #include "qgis.h"
00041 #include "qgslogger.h"
00042 #include "qgsmapcanvas.h"
00043 #include "qgsmapcanvasmap.h"
00044 #include "qgsmaplayer.h"
00045 #include "qgsmaplayerregistry.h"
00046 #include "qgsmaptoolpan.h"
00047 #include "qgsmaptoolzoom.h"
00048 #include "qgsmaptopixel.h"
00049 #include "qgsmapoverviewcanvas.h"
00050 #include "qgsmaprenderer.h"
00051 #include "qgsmessageviewer.h"
00052 #include "qgsproject.h"
00053 #include "qgsrubberband.h"
00054 #include "qgsvectorlayer.h"
00055 #include <math.h>
00056
00058 class QgsMapCanvas::CanvasProperties
00059 {
00060 public:
00061
00062 CanvasProperties() : panSelectorDown( false ) { }
00063
00065 bool mouseButtonDown;
00066
00068 QPoint mouseLastXY;
00069
00071 QPoint rubberStartPoint;
00072
00074 bool panSelectorDown;
00075
00076 };
00077
00078
00079
00080 QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
00081 : QGraphicsView( parent ),
00082 mCanvasProperties( new CanvasProperties )
00083 {
00084 mScene = new QGraphicsScene();
00085 setScene( mScene );
00086 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00087 setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00088 mLastExtentIndex = -1;
00089 mCurrentLayer = NULL;
00090 mMapOverview = NULL;
00091 mMapTool = NULL;
00092 mLastNonZoomMapTool = NULL;
00093
00094 mDrawing = false;
00095 mFrozen = false;
00096 mDirty = true;
00097
00098 setWheelAction( WheelZoom );
00099
00100
00101 mRenderFlag = true;
00102
00103 setMouseTracking( true );
00104 setFocusPolicy( Qt::StrongFocus );
00105
00106 mMapRenderer = new QgsMapRenderer;
00107
00108
00109 mMap = new QgsMapCanvasMap( this );
00110 mScene->addItem( mMap );
00111 mScene->update();
00112
00113 moveCanvasContents( true );
00114
00115
00116 connect( mMapRenderer, SIGNAL( drawError( QgsMapLayer* ) ), this, SLOT( showError( QgsMapLayer* ) ) );
00117
00118
00119 connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
00120 this, SLOT( readProject( const QDomDocument & ) ) );
00121 connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
00122 this, SLOT( writeProject( QDomDocument & ) ) );
00123
00124 }
00125
00126
00127 QgsMapCanvas::~QgsMapCanvas()
00128 {
00129 if ( mMapTool )
00130 {
00131 mMapTool->deactivate();
00132 mMapTool = NULL;
00133 }
00134 mLastNonZoomMapTool = NULL;
00135
00136
00137
00138
00139 QList<QGraphicsItem*> list = mScene->items();
00140 QList<QGraphicsItem*>::iterator it = list.begin();
00141 while ( it != list.end() )
00142 {
00143 QGraphicsItem* item = *it;
00144 delete item;
00145 it++;
00146 }
00147
00148 delete mScene;
00149
00150 delete mMapRenderer;
00151
00152
00153
00154 }
00155
00156 void QgsMapCanvas::enableAntiAliasing( bool theFlag )
00157 {
00158 mMap->enableAntiAliasing( theFlag );
00159 if ( mMapOverview )
00160 mMapOverview->enableAntiAliasing( theFlag );
00161 }
00162
00163 void QgsMapCanvas::useImageToRender( bool theFlag )
00164 {
00165 mMap->useImageToRender( theFlag );
00166 refresh();
00167 }
00168
00169 QgsMapCanvasMap* QgsMapCanvas::map()
00170 {
00171 return mMap;
00172 }
00173
00174 QgsMapRenderer* QgsMapCanvas::mapRenderer()
00175 {
00176 return mMapRenderer;
00177 }
00178
00179
00180 QgsMapLayer* QgsMapCanvas::layer( int index )
00181 {
00182 QStringList& layers = mMapRenderer->layerSet();
00183 if ( index >= 0 && index < ( int ) layers.size() )
00184 return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
00185 else
00186 return NULL;
00187 }
00188
00189
00190 void QgsMapCanvas::setCurrentLayer( QgsMapLayer* layer )
00191 {
00192 mCurrentLayer = layer;
00193 }
00194
00195 double QgsMapCanvas::scale()
00196 {
00197 return mMapRenderer->scale();
00198 }
00199
00200 void QgsMapCanvas::setDirty( bool dirty )
00201 {
00202 mDirty = dirty;
00203 }
00204
00205 bool QgsMapCanvas::isDirty() const
00206 {
00207 return mDirty;
00208 }
00209
00210
00211
00212 bool QgsMapCanvas::isDrawing()
00213 {
00214 return mDrawing;
00215 }
00216
00217
00218
00219
00220 const QgsMapToPixel * QgsMapCanvas::getCoordinateTransform()
00221 {
00222 return mMapRenderer->coordinateTransform();
00223 }
00224
00225 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
00226 {
00227 if ( mDrawing )
00228 {
00229 return;
00230 }
00231
00232
00233 QStringList layerSet, layerSetOverview;
00234
00235 int i;
00236 for ( i = 0; i < layers.size(); i++ )
00237 {
00238 QgsMapCanvasLayer &lyr = layers[i];
00239 if ( !lyr.layer() )
00240 {
00241 continue;
00242 }
00243
00244 if ( lyr.isVisible() )
00245 {
00246 layerSet.push_back( lyr.layer()->getLayerID() );
00247 }
00248 if ( lyr.isInOverview() )
00249 {
00250 layerSetOverview.push_back( lyr.layer()->getLayerID() );
00251 }
00252 }
00253
00254 QStringList& layerSetOld = mMapRenderer->layerSet();
00255
00256 bool layerSetChanged = layerSetOld != layerSet;
00257
00258
00259 if ( layerSetChanged )
00260 {
00261 for ( i = 0; i < layerCount(); i++ )
00262 {
00263
00264
00265 QgsMapLayer *currentLayer = layer( i );
00266 disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
00267 disconnect( currentLayer, SIGNAL( screenUpdateRequested() ), this, SLOT( updateMap() ) );
00268 QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
00269 if ( isVectLyr )
00270 {
00271 disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
00272 }
00273 }
00274
00275 mMapRenderer->setLayerSet( layerSet );
00276
00277 for ( i = 0; i < layerCount(); i++ )
00278 {
00279
00280
00281 QgsMapLayer *currentLayer = layer( i );
00282 connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
00283 connect( currentLayer, SIGNAL( screenUpdateRequested() ), this, SLOT( updateMap() ) );
00284 QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
00285 if ( isVectLyr )
00286 {
00287 connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
00288 }
00289 }
00290 }
00291
00292
00293 if ( mMapOverview )
00294 {
00295 mMapOverview->updateFullExtent( fullExtent() );
00296
00297 QStringList& layerSetOvOld = mMapOverview->layerSet();
00298 if ( layerSetOvOld != layerSetOverview )
00299 {
00300 mMapOverview->setLayerSet( layerSetOverview );
00301 }
00302
00303
00304
00305 updateOverview();
00306 }
00307
00308 if ( layerSetChanged )
00309 {
00310 QgsDebugMsg( "Layers have changed, refreshing" );
00311 emit layersChanged();
00312
00313 refresh();
00314 }
00315
00316 }
00317
00318 void QgsMapCanvas::enableOverviewMode( QgsMapOverviewCanvas* overview )
00319 {
00320 if ( mMapOverview )
00321 {
00322
00323 disconnect( mMapRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ),
00324 mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
00325 disconnect( mMapRenderer, SIGNAL( destinationSrsChanged() ),
00326 mMapOverview, SLOT( destinationSrsChanged() ) );
00327
00328
00329 }
00330
00331 mMapOverview = overview;
00332
00333 if ( overview )
00334 {
00335
00336 connect( mMapRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ),
00337 overview, SLOT( hasCrsTransformEnabled( bool ) ) );
00338 connect( mMapRenderer, SIGNAL( destinationSrsChanged() ),
00339 overview, SLOT( destinationSrsChanged() ) );
00340 }
00341 }
00342
00343
00344 void QgsMapCanvas::updateOverview()
00345 {
00346
00347 if ( mMapOverview )
00348 {
00349 mMapOverview->refresh();
00350 }
00351 }
00352
00353
00354 QgsMapLayer* QgsMapCanvas::currentLayer()
00355 {
00356 return mCurrentLayer;
00357 }
00358
00359
00360 void QgsMapCanvas::refresh()
00361 {
00362
00363 if ( mDrawing )
00364 return;
00365
00366 mDrawing = true;
00367
00368 if ( mRenderFlag && !mFrozen )
00369 {
00370 clear();
00371
00372
00373 QApplication::setOverrideCursor( Qt::WaitCursor );
00374
00375 emit renderStarting();
00376
00377 mMap->render();
00378
00379 mDirty = false;
00380
00381
00382 QPainter p;
00383 p.begin( &mMap->paintDevice() );
00384 emit renderComplete( &p );
00385 p.end();
00386
00387
00388 if ( mMapTool )
00389 mMapTool->renderComplete();
00390
00391
00392 QApplication::restoreOverrideCursor();
00393 }
00394
00395 mDrawing = false;
00396 }
00397
00398 void QgsMapCanvas::updateMap()
00399 {
00400 if ( mMap )
00401 {
00402 mMap->updateContents();
00403 }
00404 }
00405
00406
00407 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
00408 {
00409
00410
00411
00412 if ( theQPixmap != NULL )
00413 {
00414
00415 QPainter painter;
00416 painter.begin( theQPixmap );
00417 mMapRenderer->render( &painter );
00418 emit renderComplete( &painter );
00419 painter.end();
00420
00421 theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
00422 }
00423 else
00424 {
00425 mMap->pixmap().save( theFileName, theFormat.toLocal8Bit().data() );
00426 }
00427
00428 QgsRectangle myRect = mMapRenderer->extent();
00429 QString myHeader;
00430
00431
00432 myHeader += QString::number( mapUnitsPerPixel(), 'g', 17 ) + "\r\n";
00433
00434 myHeader += "0 \r\n";
00435
00436 myHeader += "0 \r\n";
00437
00438
00439 myHeader += "-" + QString::number( mapUnitsPerPixel(), 'g', 17 ) + "\r\n";
00440
00441 myHeader += QString::number( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ), 'g', 17 ) + "\r\n";
00442
00443 myHeader += QString::number( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ), 'g', 17 ) + "\r\n";
00444 QFileInfo myInfo = QFileInfo( theFileName );
00445
00446 QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
00447 QFile myWorldFile( myWorldFileName );
00448 if ( !myWorldFile.open( QIODevice::WriteOnly ) )
00449 {
00450 return;
00451 }
00452 QTextStream myStream( &myWorldFile );
00453 myStream << myHeader;
00454 }
00455
00456
00457
00458 QgsRectangle QgsMapCanvas::extent() const
00459 {
00460 return mMapRenderer->extent();
00461 }
00462
00463 QgsRectangle QgsMapCanvas::fullExtent() const
00464 {
00465 return mMapRenderer->fullExtent();
00466 }
00467
00468 void QgsMapCanvas::updateFullExtent()
00469 {
00470
00471
00472 QgsDebugMsg( "updating full extent" );
00473
00474 mMapRenderer->updateFullExtent();
00475 if ( mMapOverview )
00476 {
00477 mMapOverview->updateFullExtent( fullExtent() );
00478 updateOverview();
00479 }
00480 refresh();
00481 }
00482
00483 void QgsMapCanvas::setExtent( QgsRectangle const & r )
00484 {
00485 if ( mDrawing )
00486 {
00487 return;
00488 }
00489
00490 QgsRectangle current = extent();
00491
00492 if ( r.isEmpty() )
00493 {
00494 QgsDebugMsg( "Empty extent - keeping old extent with new center!" );
00495 QgsRectangle e( QgsPoint( r.center().x() - current.width() / 2.0, r.center().y() - current.height() / 2.0 ),
00496 QgsPoint( r.center().x() + current.width() / 2.0, r.center().y() + current.height() / 2.0 ) );
00497 mMapRenderer->setExtent( e );
00498 }
00499 else
00500 {
00501 mMapRenderer->setExtent( r );
00502 }
00503 emit extentsChanged();
00504 updateScale();
00505 if ( mMapOverview )
00506 mMapOverview->drawExtentRect();
00507 if ( mLastExtent.size() > 20 ) mLastExtent.removeAt( 0 );
00508
00509
00510 for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
00511 {
00512 mLastExtent.removeAt( i );
00513 }
00514
00515 mLastExtent.append( extent() ) ;
00516
00517
00518 if ( mLastExtent.size() > 20 )
00519 {
00520 mLastExtent.removeAt( 0 );
00521 }
00522
00523
00524 mLastExtentIndex = mLastExtent.size() - 1;
00525
00526
00527 emit zoomLastStatusChanged( mLastExtentIndex > 0 );
00528 emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
00529
00530 updateCanvasItemPositions();
00531
00532 }
00533
00534
00535 void QgsMapCanvas::updateScale()
00536 {
00537 double scale = mMapRenderer->scale();
00538
00539 emit scaleChanged( scale );
00540 }
00541
00542
00543 void QgsMapCanvas::clear()
00544 {
00545
00546 setDirty( true );
00547
00548 }
00549
00550
00551
00552 void QgsMapCanvas::zoomToFullExtent()
00553 {
00554 if ( mDrawing )
00555 {
00556 return;
00557 }
00558
00559 QgsRectangle extent = fullExtent();
00560
00561 if ( !extent.isEmpty() )
00562 {
00563
00564 extent.scale( 1.05 );
00565 setExtent( extent );
00566 }
00567 refresh();
00568
00569 }
00570
00571
00572
00573 void QgsMapCanvas::zoomToPreviousExtent()
00574 {
00575 if ( mDrawing )
00576 {
00577 return;
00578 }
00579
00580 if ( mLastExtentIndex > 0 )
00581 {
00582 mLastExtentIndex--;
00583 mMapRenderer->setExtent( mLastExtent[mLastExtentIndex] );
00584 emit extentsChanged();
00585 updateScale();
00586 if ( mMapOverview )
00587 mMapOverview->drawExtentRect();
00588 refresh();
00589
00590 emit zoomLastStatusChanged( mLastExtentIndex > 0 );
00591 emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
00592 }
00593
00594 }
00595
00596 void QgsMapCanvas::zoomToNextExtent()
00597 {
00598 if ( mDrawing )
00599 {
00600 return;
00601 }
00602 if ( mLastExtentIndex < mLastExtent.size() - 1 )
00603 {
00604 mLastExtentIndex++;
00605 mMapRenderer->setExtent( mLastExtent[mLastExtentIndex] );
00606 emit extentsChanged();
00607 updateScale();
00608 if ( mMapOverview )
00609 mMapOverview->drawExtentRect();
00610 refresh();
00611
00612 emit zoomLastStatusChanged( mLastExtentIndex > 0 );
00613 emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
00614 }
00615 }
00616
00617 void QgsMapCanvas::clearExtentHistory()
00618 {
00619 mLastExtent.clear();
00620 mLastExtent.append( extent() ) ;
00621 mLastExtentIndex = mLastExtent.size() - 1;
00622
00623 emit zoomLastStatusChanged( mLastExtentIndex > 0 );
00624 emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
00625 }
00626
00627
00628 bool QgsMapCanvas::hasCrsTransformEnabled()
00629 {
00630 return mMapRenderer->hasCrsTransformEnabled();
00631 }
00632
00633 void QgsMapCanvas::mapUnitsChanged()
00634 {
00635
00636
00637
00638
00639 updateScale();
00640
00641
00642
00643
00644
00645
00646
00647
00648 refresh();
00649 }
00650
00651 void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer )
00652 {
00653 if ( mDrawing )
00654 {
00655 return;
00656 }
00657
00658 if ( layer == NULL )
00659 {
00660
00661 layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
00662 }
00663
00664 if ( layer == NULL )
00665 {
00666 return;
00667 }
00668
00669 if ( layer->selectedFeatureCount() == 0 )
00670 {
00671 return;
00672 }
00673
00674 QgsRectangle rect = mMapRenderer->layerExtentToOutputExtent( layer, layer->boundingBoxOfSelected() );
00675
00676
00677
00678 if ( rect.isEmpty() )
00679 {
00680
00681 QgsPoint c = rect.center();
00682 rect = extent();
00683 rect.expand( 0.25, &c );
00684 }
00685
00686 else
00687 {
00688
00689
00690
00691 rect.scale( 1.05 );
00692 }
00693
00694 setExtent( rect );
00695 refresh();
00696 }
00697
00698 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
00699 {
00700
00701 if ( mDrawing )
00702 {
00703 e->ignore();
00704 }
00705
00706 emit keyPressed( e );
00707
00708 if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
00709 return;
00710
00711 QPainter paint;
00712 QPen pen( Qt::gray );
00713 QgsPoint ll, ur;
00714
00715 if ( ! mCanvasProperties->mouseButtonDown )
00716 {
00717
00718
00719 QgsRectangle currentExtent = mMapRenderer->extent();
00720 double dx = fabs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
00721 double dy = fabs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
00722
00723 switch ( e->key() )
00724 {
00725 case Qt::Key_Left:
00726 QgsDebugMsg( "Pan left" );
00727
00728 currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
00729 currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
00730 setExtent( currentExtent );
00731 refresh();
00732 break;
00733
00734 case Qt::Key_Right:
00735 QgsDebugMsg( "Pan right" );
00736
00737 currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
00738 currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
00739 setExtent( currentExtent );
00740 refresh();
00741 break;
00742
00743 case Qt::Key_Up:
00744 QgsDebugMsg( "Pan up" );
00745
00746 currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
00747 currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
00748 setExtent( currentExtent );
00749 refresh();
00750 break;
00751
00752 case Qt::Key_Down:
00753 QgsDebugMsg( "Pan down" );
00754
00755 currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
00756 currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
00757 setExtent( currentExtent );
00758 refresh();
00759 break;
00760
00761
00762
00763 case Qt::Key_Space:
00764 QgsDebugMsg( "Pressing pan selector" );
00765
00766
00767 if ( ! e->isAutoRepeat() )
00768 {
00769 mCanvasProperties->panSelectorDown = true;
00770 mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
00771 }
00772 break;
00773
00774 case Qt::Key_PageUp:
00775 QgsDebugMsg( "Zoom in" );
00776 zoomIn();
00777 break;
00778
00779 case Qt::Key_PageDown:
00780 QgsDebugMsg( "Zoom out" );
00781 zoomOut();
00782 break;
00783
00784 default:
00785
00786 if ( mMapTool )
00787 {
00788 mMapTool->keyPressEvent( e );
00789 }
00790 e->ignore();
00791
00792 QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
00793
00794 }
00795 }
00796 }
00797
00798 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
00799 {
00800 QgsDebugMsg( "keyRelease event" );
00801
00802 if ( mDrawing )
00803 {
00804 return;
00805 }
00806
00807 switch ( e->key() )
00808 {
00809 case Qt::Key_Space:
00810 if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
00811 {
00812 QgsDebugMsg( "Releasing pan selector" );
00813
00814 mCanvasProperties->panSelectorDown = false;
00815 panActionEnd( mCanvasProperties->mouseLastXY );
00816 }
00817 break;
00818
00819 default:
00820
00821 if ( mMapTool )
00822 {
00823 mMapTool->keyReleaseEvent( e );
00824 }
00825
00826 e->ignore();
00827
00828 QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
00829 }
00830
00831 emit keyReleased( e );
00832
00833 }
00834
00835
00836 void QgsMapCanvas::mouseDoubleClickEvent( QMouseEvent * e )
00837 {
00838 if ( mDrawing )
00839 {
00840 return;
00841 }
00842
00843
00844 if ( mMapTool )
00845 mMapTool->canvasDoubleClickEvent( e );
00846 }
00847
00848
00849 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
00850 {
00851 if ( mDrawing )
00852 {
00853 return;
00854 }
00855
00856
00857 if ( e->button() == Qt::MidButton )
00858 {
00859 mCanvasProperties->panSelectorDown = true;
00860 mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
00861 }
00862 else
00863 {
00864
00865
00866 if ( mMapTool )
00867 mMapTool->canvasPressEvent( e );
00868 }
00869
00870 if ( mCanvasProperties->panSelectorDown )
00871 {
00872 return;
00873 }
00874
00875 mCanvasProperties->mouseButtonDown = true;
00876 mCanvasProperties->rubberStartPoint = e->pos();
00877
00878 }
00879
00880
00881 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
00882 {
00883 if ( mDrawing )
00884 {
00885 return;
00886 }
00887
00888
00889 if ( e->button() == Qt::MidButton )
00890 {
00891 mCanvasProperties->panSelectorDown = false;
00892 panActionEnd( mCanvasProperties->mouseLastXY );
00893 }
00894 else
00895 {
00896
00897 if ( mMapTool )
00898 {
00899
00900 if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
00901 {
00902 QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
00903 QString( mLastNonZoomMapTool ? "not null." : "null." ) );
00904
00905 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
00906
00907
00908 if ( mLastNonZoomMapTool
00909 && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
00910 {
00911 QgsMapTool* t = mLastNonZoomMapTool;
00912 mLastNonZoomMapTool = NULL;
00913 setMapTool( t );
00914 }
00915 return;
00916 }
00917 mMapTool->canvasReleaseEvent( e );
00918 }
00919 }
00920
00921
00922 mCanvasProperties->mouseButtonDown = false;
00923
00924 if ( mCanvasProperties->panSelectorDown )
00925 return;
00926
00927 }
00928
00929 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
00930 {
00931 static bool isAlreadyIn = false;
00932 static QSize lastSize = QSize( -1, -1 );
00933
00934 lastSize = e->size();
00935
00936 if ( isAlreadyIn || mDrawing )
00937 {
00938
00939 if ( mMapRenderer )
00940 {
00941 QgsRenderContext* theRenderContext = mMapRenderer->rendererContext();
00942 if ( theRenderContext )
00943 {
00944 theRenderContext->setRenderingStopped( true );
00945 }
00946 }
00947 return;
00948 }
00949 isAlreadyIn = true;
00950
00951 while ( lastSize != QSize( -1, -1 ) )
00952 {
00953 int width = lastSize.width();
00954 int height = lastSize.height();
00955 lastSize = QSize( -1, -1 );
00956
00957
00958
00959 mMap->resize( QSize( width, height ) );
00960 mScene->setSceneRect( QRectF( 0, 0, width, height ) );
00961
00962
00963 updateCanvasItemPositions();
00964
00965 updateScale();
00966 #if QT_VERSION >= 0x40600
00967
00968 QTimer::singleShot( 1, this, SLOT( refresh() ) );
00969 #else
00970 refresh();
00971 #endif
00972 emit extentsChanged();
00973 }
00974 isAlreadyIn = false;
00975 }
00976
00977
00978 void QgsMapCanvas::updateCanvasItemPositions()
00979 {
00980 QList<QGraphicsItem*> list = mScene->items();
00981 QList<QGraphicsItem*>::iterator it = list.begin();
00982 while ( it != list.end() )
00983 {
00984 QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
00985
00986 if ( item )
00987 {
00988 item->updatePosition();
00989 }
00990
00991 it++;
00992 }
00993 }
00994
00995
00996 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
00997 {
00998
00999
01000
01001 QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
01002
01003 if ( mDrawing )
01004 {
01005 return;
01006 }
01007
01008 switch ( mWheelAction )
01009 {
01010 case WheelZoom:
01011
01012 if ( e->delta() > 0 )
01013 zoomIn();
01014 else
01015 zoomOut();
01016 break;
01017
01018 case WheelZoomAndRecenter:
01019
01020 zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
01021 break;
01022
01023 case WheelZoomToMouseCursor:
01024 {
01025
01026 double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
01027
01028 QgsPoint oldCenter( mMapRenderer->extent().center() );
01029 QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
01030 QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
01031 mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
01032
01033
01034 QgsRectangle extent = mMapRenderer->extent();
01035 extent.scale( scaleFactor, &newCenter );
01036 setExtent( extent );
01037 refresh();
01038 break;
01039 }
01040
01041 case WheelNothing:
01042
01043 break;
01044 }
01045 }
01046
01047 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
01048 {
01049 mWheelAction = action;
01050 mWheelZoomFactor = factor;
01051 }
01052
01053 void QgsMapCanvas::zoomIn()
01054 {
01055 zoomByFactor( 1 / mWheelZoomFactor );
01056 }
01057
01058 void QgsMapCanvas::zoomOut()
01059 {
01060 zoomByFactor( mWheelZoomFactor );
01061 }
01062
01063 void QgsMapCanvas::zoomScale( double newScale )
01064 {
01065 zoomByFactor( newScale / scale() );
01066 }
01067
01068 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
01069 {
01070 if ( mDrawing )
01071 {
01072 return;
01073 }
01074
01075 double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
01076
01077
01078 QgsPoint center = getCoordinateTransform()->toMapPoint( x, y );
01079 QgsRectangle r = mMapRenderer->extent();
01080 r.scale( scaleFactor, ¢er );
01081 setExtent( r );
01082 refresh();
01083 }
01084
01085 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
01086 {
01087 if ( mDrawing )
01088 {
01089 return;
01090 }
01091
01092 mCanvasProperties->mouseLastXY = e->pos();
01093
01094 if ( mCanvasProperties->panSelectorDown )
01095 {
01096 panAction( e );
01097 }
01098 else
01099 {
01100
01101 if ( mMapTool )
01102 mMapTool->canvasMoveEvent( e );
01103 }
01104
01105
01106 QPoint xy = e->pos();
01107 QgsPoint coord = getCoordinateTransform()->toMapCoordinates( xy );
01108 emit xyCoordinates( coord );
01109 }
01110
01111
01112
01114 void QgsMapCanvas::setMapTool( QgsMapTool* tool )
01115 {
01116 if ( !tool )
01117 return;
01118
01119 if ( mMapTool )
01120 mMapTool->deactivate();
01121
01122 if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
01123 {
01124
01125
01126
01127 mLastNonZoomMapTool = mMapTool;
01128 }
01129 else
01130 {
01131 mLastNonZoomMapTool = NULL;
01132 }
01133
01134
01135 mMapTool = tool;
01136 if ( mMapTool )
01137 mMapTool->activate();
01138
01139 emit mapToolSet( mMapTool );
01140 }
01141
01142 void QgsMapCanvas::unsetMapTool( QgsMapTool* tool )
01143 {
01144 if ( mMapTool && mMapTool == tool )
01145 {
01146 mMapTool->deactivate();
01147 mMapTool = NULL;
01148 emit mapToolSet( NULL );
01149 setCursor( Qt::ArrowCursor );
01150 }
01151
01152 if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
01153 {
01154 mLastNonZoomMapTool = NULL;
01155 }
01156 }
01157
01159 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
01160 {
01161
01162 mMap->setBackgroundColor( theColor );
01163
01164
01165 QBrush bgBrush( theColor );
01166 setBackgroundBrush( bgBrush );
01167 #if 0
01168 QPalette palette;
01169 palette.setColor( backgroundRole(), theColor );
01170 setPalette( palette );
01171 #endif
01172
01173
01174 mScene->setBackgroundBrush( bgBrush );
01175 }
01176
01177 QColor QgsMapCanvas::canvasColor() const
01178 {
01179 return mScene->backgroundBrush().color();
01180 }
01181
01182 int QgsMapCanvas::layerCount() const
01183 {
01184 return mMapRenderer->layerSet().size();
01185 }
01186
01187
01188 QList<QgsMapLayer*> QgsMapCanvas::layers() const
01189 {
01190 QList<QgsMapLayer*> lst;
01191 foreach( QString layerID, mMapRenderer->layerSet() )
01192 {
01193 QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
01194 if ( layer )
01195 lst.append( layer );
01196 }
01197 return lst;
01198 }
01199
01200
01201 void QgsMapCanvas::layerStateChange()
01202 {
01203
01204
01205 refresh();
01206
01207 }
01208
01209
01210
01211 void QgsMapCanvas::freeze( bool frz )
01212 {
01213 mFrozen = frz;
01214 }
01215
01216 bool QgsMapCanvas::isFrozen()
01217 {
01218 return mFrozen;
01219 }
01220
01221
01222 QPixmap& QgsMapCanvas::canvasPixmap()
01223 {
01224 return mMap->pixmap();
01225 }
01226
01227
01228
01229 double QgsMapCanvas::mapUnitsPerPixel() const
01230 {
01231 return mMapRenderer->mapUnitsPerPixel();
01232 }
01233
01234
01235 void QgsMapCanvas::setMapUnits( QGis::UnitType u )
01236 {
01237 QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
01238 mMapRenderer->setMapUnits( u );
01239 }
01240
01241
01242 QGis::UnitType QgsMapCanvas::mapUnits() const
01243 {
01244 return mMapRenderer->mapUnits();
01245 }
01246
01247
01248 void QgsMapCanvas::setRenderFlag( bool theFlag )
01249 {
01250 mRenderFlag = theFlag;
01251 if ( mMapRenderer )
01252 {
01253 QgsRenderContext* rc = mMapRenderer->rendererContext();
01254 if ( rc )
01255 {
01256 rc->setRenderingStopped( !theFlag );
01257 }
01258 }
01259
01260 if ( mRenderFlag )
01261 {
01262 refresh();
01263 }
01264 }
01265
01266 void QgsMapCanvas::connectNotify( const char * signal )
01267 {
01268 QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
01269 }
01270
01271
01272
01273 QgsMapTool* QgsMapCanvas::mapTool()
01274 {
01275 return mMapTool;
01276 }
01277
01278 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
01279 {
01280 if ( mDrawing )
01281 {
01282 return;
01283 }
01284
01285
01286 moveCanvasContents( true );
01287
01288
01289 QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
01290 QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
01291
01292 double dx = fabs( end.x() - start.x() );
01293 double dy = fabs( end.y() - start.y() );
01294
01295
01296 QgsRectangle r = mMapRenderer->extent();
01297
01298 if ( end.x() < start.x() )
01299 {
01300 r.setXMinimum( r.xMinimum() + dx );
01301 r.setXMaximum( r.xMaximum() + dx );
01302 }
01303 else
01304 {
01305 r.setXMinimum( r.xMinimum() - dx );
01306 r.setXMaximum( r.xMaximum() - dx );
01307 }
01308
01309 if ( end.y() < start.y() )
01310 {
01311 r.setYMaximum( r.yMaximum() + dy );
01312 r.setYMinimum( r.yMinimum() + dy );
01313
01314 }
01315 else
01316 {
01317 r.setYMaximum( r.yMaximum() - dy );
01318 r.setYMinimum( r.yMinimum() - dy );
01319
01320 }
01321
01322 setExtent( r );
01323 refresh();
01324 }
01325
01326 void QgsMapCanvas::panAction( QMouseEvent * e )
01327 {
01328 if ( mDrawing )
01329 {
01330 return;
01331 }
01332
01333
01334 moveCanvasContents();
01335
01336
01337
01338 }
01339
01340 void QgsMapCanvas::moveCanvasContents( bool reset )
01341 {
01342 if ( mDrawing )
01343 {
01344 return;
01345 }
01346
01347 QPoint pnt( 0, 0 );
01348 if ( !reset )
01349 pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
01350
01351 mMap->setPanningOffset( pnt );
01352
01353 QList<QGraphicsItem*> list = mScene->items();
01354 QList<QGraphicsItem*>::iterator it = list.begin();
01355 while ( it != list.end() )
01356 {
01357 QGraphicsItem* item = *it;
01358
01359 if ( item != mMap )
01360 {
01361
01362 QgsMapCanvasItem* canvasItem = dynamic_cast<QgsMapCanvasItem *>( item );
01363 if ( canvasItem )
01364 canvasItem->setPanningOffset( pnt );
01365 }
01366
01367 it++;
01368 }
01369
01370
01371 updateCanvasItemPositions();
01372
01373 }
01374
01375 void QgsMapCanvas::showError( QgsMapLayer * mapLayer )
01376 {
01377 #if 0
01378 QMessageBox::warning(
01379 this,
01380 mapLayer->lastErrorTitle(),
01381 tr( "Could not draw %1 because:\n%2", "COMMENTED OUT" ).arg( mapLayer->name() ).arg( mapLayer->lastError() )
01382 );
01383 #endif
01384
01385 QgsMessageViewer * mv = new QgsMessageViewer( this );
01386 mv->setWindowTitle( mapLayer->lastErrorTitle() );
01387 mv->setMessageAsPlainText( tr( "Could not draw %1 because:\n%2" )
01388 .arg( mapLayer->name() ).arg( mapLayer->lastError() ) );
01389 mv->exec();
01390
01391
01392
01393 }
01394
01395 QPoint QgsMapCanvas::mouseLastXY()
01396 {
01397 return mCanvasProperties->mouseLastXY;
01398 }
01399
01400 void QgsMapCanvas::readProject( const QDomDocument & doc )
01401 {
01402 QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
01403 if ( nodes.count() )
01404 {
01405 QDomNode node = nodes.item( 0 );
01406 mMapRenderer->readXML( node );
01407 clearExtentHistory();
01408 }
01409 else
01410 {
01411 QgsDebugMsg( "Couldn't read mapcanvas information from project" );
01412 }
01413
01414 }
01415
01416 void QgsMapCanvas::writeProject( QDomDocument & doc )
01417 {
01418
01419
01420 QDomNodeList nl = doc.elementsByTagName( "qgis" );
01421 if ( !nl.count() )
01422 {
01423 QgsDebugMsg( "Unable to find qgis element in project file" );
01424 return;
01425 }
01426 QDomNode qgisNode = nl.item( 0 );
01427
01428 QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
01429 qgisNode.appendChild( mapcanvasNode );
01430 mMapRenderer->writeXML( mapcanvasNode, doc );
01431
01432
01433 }
01434
01435 void QgsMapCanvas::zoomByFactor( double scaleFactor )
01436 {
01437 if ( mDrawing )
01438 {
01439 return;
01440 }
01441
01442 QgsRectangle r = mMapRenderer->extent();
01443 r.scale( scaleFactor );
01444 setExtent( r );
01445 refresh();
01446 }
01447
01448 void QgsMapCanvas::selectionChangedSlot()
01449 {
01450
01451 QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
01452 emit selectionChanged( layer );
01453 refresh();
01454 }