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