QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsmapcanvas.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmapcanvas.cpp - description
3  -------------------
4 begin : Sun Jun 30 2002
5 copyright : (C) 2002 by Gary E.Sherman
6 email : sherman at mrcc.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
19 #include <QtGlobal>
20 #include <QApplication>
21 #include <QCursor>
22 #include <QDir>
23 #include <QFile>
24 #include <QGraphicsItem>
25 #include <QGraphicsScene>
26 #include <QGraphicsView>
27 #include <QKeyEvent>
28 #include <QMouseEvent>
29 #include <QPainter>
30 #include <QPaintEvent>
31 #include <QPixmap>
32 #include <QRect>
33 #include <QSettings>
34 #include <QTextStream>
35 #include <QResizeEvent>
36 #include <QString>
37 #include <QStringList>
38 #include <QWheelEvent>
39 
40 #include "qgis.h"
41 #include "qgsapplication.h"
42 #include "qgscrscache.h"
44 #include "qgslogger.h"
45 #include "qgsmapcanvas.h"
46 #include "qgsmapcanvasmap.h"
47 #include "qgsmaplayer.h"
48 #include "qgsmaplayerregistry.h"
49 #include "qgsmaptoolpan.h"
50 #include "qgsmaptoolzoom.h"
51 #include "qgsmaptopixel.h"
52 #include "qgsmapoverviewcanvas.h"
53 #include "qgsmaprenderer.h"
54 #include "qgsmaprenderercache.h"
58 #include "qgsmessagelog.h"
59 #include "qgsmessageviewer.h"
60 #include "qgspallabeling.h"
61 #include "qgsproject.h"
62 #include "qgsrubberband.h"
63 #include "qgsvectorlayer.h"
64 #include <math.h>
65 
66 
69 {
70  public:
71 
73 
76 
78  QPoint mouseLastXY;
79 
82 
85 
86 };
87 
88 
89 
91  : QObject( canvas )
92  , mCanvas( canvas )
93  , mRenderer( renderer )
94  , mSyncingExtent( false )
95 {
96  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( onExtentC2R() ) );
97  connect( mRenderer, SIGNAL( extentsChanged() ), this, SLOT( onExtentR2C() ) );
98 
99  connect( mCanvas, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsC2R() ) );
100  connect( mRenderer, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsR2C() ) );
101 
102  connect( mCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ), this, SLOT( onCrsTransformC2R() ) );
103  connect( mRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( onCrsTransformR2C() ) );
104 
105  connect( mCanvas, SIGNAL( destinationCrsChanged() ), this, SLOT( onDestCrsC2R() ) );
106  connect( mRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( onDestCrsR2C() ) );
107 
108  connect( mCanvas, SIGNAL( layersChanged() ), this, SLOT( onLayersC2R() ) );
109  // TODO: layers R2C ? (should not happen!)
110 
111 }
112 
114 {
115  // protection against possible bounce back
116  if ( mSyncingExtent )
117  return;
118 
119  mSyncingExtent = true;
121  mSyncingExtent = false;
122 }
123 
125 {
126  // protection against possible bounce back
127  if ( mSyncingExtent )
128  return;
129 
130  mSyncingExtent = true;
132  mSyncingExtent = false;
133 }
134 
136 {
138 }
139 
141 {
143 }
144 
146 {
148 }
149 
151 {
153 }
154 
156 {
158 }
159 
161 {
163 }
164 
166 {
168 }
169 
170 
171 
172 QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
173  : QGraphicsView( parent )
174  , mCanvasProperties( new CanvasProperties )
175  , mJob( 0 )
176  , mJobCancelled( false )
177  , mLabelingResults( 0 )
178  , mUseParallelRendering( false )
179  , mDrawRenderingStats( false )
180  , mCache( 0 )
181  , mPreviewEffect( 0 )
182 {
183  setObjectName( name );
184  mScene = new QGraphicsScene();
185  setScene( mScene );
186  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
187  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
188  mLastExtentIndex = -1;
189  mCurrentLayer = NULL;
190  mMapOverview = NULL;
191  mMapTool = NULL;
192  mLastNonZoomMapTool = NULL;
193 
194  mFrozen = false;
195  mRefreshScheduled = false;
196 
198 
199  // by default, the canvas is rendered
200  mRenderFlag = true;
201 
202  setMouseTracking( true );
203  setFocusPolicy( Qt::StrongFocus );
204 
206 
207  mResizeTimer = new QTimer( this );
208  mResizeTimer->setSingleShot( true );
209  connect( mResizeTimer, SIGNAL( timeout() ), this, SLOT( refresh() ) );
210 
211  // create map canvas item which will show the map
212  mMap = new QgsMapCanvasMap( this );
213  mScene->addItem( mMap );
214 
215  // project handling
216  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
217  this, SLOT( readProject( const QDomDocument & ) ) );
218  connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
219  this, SLOT( writeProject( QDomDocument & ) ) );
220 
223 
224  // class that will sync most of the changes between canvas and (legacy) map renderer
225  // it is parented to map canvas, will be deleted automatically
227 
228  QSize s = viewport()->size();
231  setSceneRect( 0, 0, s.width(), s.height() );
232  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
233 
234  moveCanvasContents( true );
235 
236  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
237  mMapUpdateTimer.setInterval( 250 );
238 
239 #ifdef Q_OS_WIN
240  // Enable touch event on Windows.
241  // Qt on Windows needs to be told it can take touch events or else it ignores them.
242  grabGesture( Qt::PinchGesture );
243  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
244 #endif
245 
246  mPreviewEffect = new QgsPreviewEffect( this );
247  viewport()->setGraphicsEffect( mPreviewEffect );
248 
249  refresh();
250 
251 } // QgsMapCanvas ctor
252 
253 
255 {
256  if ( mMapTool )
257  {
258  mMapTool->deactivate();
259  mMapTool = NULL;
260  }
261  mLastNonZoomMapTool = NULL;
262 
263  // delete canvas items prior to deleteing the canvas
264  // because they might try to update canvas when it's
265  // already being destructed, ends with segfault
266  QList<QGraphicsItem*> list = mScene->items();
267  QList<QGraphicsItem*>::iterator it = list.begin();
268  while ( it != list.end() )
269  {
270  QGraphicsItem* item = *it;
271  delete item;
272  ++it;
273  }
274 
275  mScene->deleteLater(); // crashes in python tests on windows
276 
277  delete mMapRenderer;
278  // mCanvasProperties auto-deleted via std::auto_ptr
279  // CanvasProperties struct has its own dtor for freeing resources
280 
281  if ( mJob )
282  {
283  mJob->cancel();
284  Q_ASSERT( mJob == 0 );
285  }
286 
287  delete mCache;
288 
289  delete mLabelingResults;
290 
291 } // dtor
292 
294 {
296 
297  if ( mMapOverview )
298  mMapOverview->enableAntiAliasing( theFlag );
299 } // anti aliasing
300 
301 void QgsMapCanvas::useImageToRender( bool theFlag )
302 {
303  Q_UNUSED( theFlag );
304 }
305 
307 {
308  return mMap;
309 }
310 
312 {
313  return mMapRenderer;
314 }
315 
316 
318 {
319  const QStringList& layers = mapSettings().layers();
320  if ( index >= 0 && index < ( int ) layers.size() )
321  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
322  else
323  return NULL;
324 }
325 
326 
328 {
330 }
331 
333 {
334  return mapSettings().scale();
335 } // scale
336 
337 void QgsMapCanvas::setDirty( bool dirty )
338 {
339  if ( dirty )
340  refresh();
341 }
342 
344 {
345  return false;
346 }
347 
348 
349 
351 {
352  return mJob != 0;
353 } // isDrawing
354 
355 
356 // return the current coordinate transform based on the extents and
357 // device size
359 {
360  return &mapSettings().mapToPixel();
361 }
362 
363 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
364 {
365  // create layer set
366  QStringList layerSet, layerSetOverview;
367 
368  int i;
369  for ( i = 0; i < layers.size(); i++ )
370  {
371  QgsMapCanvasLayer &lyr = layers[i];
372  if ( !lyr.layer() )
373  {
374  continue;
375  }
376 
377  if ( lyr.isVisible() )
378  {
379  layerSet.push_back( lyr.layer()->id() );
380  }
381 
382  if ( lyr.isInOverview() )
383  {
384  layerSetOverview.push_back( lyr.layer()->id() );
385  }
386  }
387 
388  const QStringList& layerSetOld = mapSettings().layers();
389 
390  bool layerSetChanged = layerSetOld != layerSet;
391 
392  // update only if needed
393  if ( layerSetChanged )
394  {
395  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
396 
397  for ( i = 0; i < layerCount(); i++ )
398  {
399  // Add check if vector layer when disconnecting from selectionChanged slot
400  // Ticket #811 - racicot
402  if ( !currentLayer )
403  continue;
404  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
405  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
406  if ( isVectLyr )
407  {
408  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
409  }
410  }
411 
412  mSettings.setLayers( layerSet );
413 
414  for ( i = 0; i < layerCount(); i++ )
415  {
416  // Add check if vector layer when connecting to selectionChanged slot
417  // Ticket #811 - racicot
419  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
420  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
421  if ( isVectLyr )
422  {
423  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
424  }
425  }
426 
428 
429  QgsDebugMsg( "Layers have changed, refreshing" );
430  emit layersChanged();
431 
432  refresh();
433  }
434 
435  if ( mMapOverview )
436  {
437  const QStringList& layerSetOvOld = mMapOverview->layerSet();
438  if ( layerSetOvOld != layerSetOverview )
439  {
440  mMapOverview->setLayerSet( layerSetOverview );
441  }
442 
443  // refresh overview maplayers even if layer set is the same
444  // because full extent might have changed
445  updateOverview();
446  }
447 } // setLayerSet
448 
450 {
451  if ( mMapOverview )
452  {
453  // disconnect old map overview if exists
454  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
455  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
456  disconnect( this, SIGNAL( destinationCrsChanged() ),
457  mMapOverview, SLOT( destinationSrsChanged() ) );
458 
459  // map overview is not owned by map canvas so don't delete it...
460  }
461 
462  mMapOverview = overview;
463 
464  if ( overview )
465  {
466  // connect to the map render to copy its projection settings
467  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
468  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
469  connect( this, SIGNAL( destinationCrsChanged() ),
470  overview, SLOT( destinationSrsChanged() ) );
471  }
472 }
473 
475 {
476  return mSettings;
477 }
478 
480 {
481  if ( mSettings.hasCrsTransformEnabled() == enabled )
482  return;
483 
485 
487 
488  refresh();
489 
490  emit hasCrsTransformEnabledChanged( enabled );
491 }
492 
494 {
495  if ( mSettings.destinationCrs() == crs )
496  return;
497 
499  {
500  // try to reproject current extent to the new one
501  QgsRectangle rect;
502  if ( !mSettings.visibleExtent().isEmpty() )
503  {
504  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
505  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
506  }
507  if ( !rect.isEmpty() )
508  {
509  setExtent( rect );
510  }
511 
512  QgsDebugMsg( "refreshing after destination CRS changed" );
513  refresh();
514  }
515 
517 
519 
520  emit destinationCrsChanged();
521 }
522 
524 {
525  return mLabelingResults;
526 }
527 
529 {
530  if ( enabled == isCachingEnabled() )
531  return;
532 
533  if ( enabled )
534  {
536  }
537  else
538  {
539  delete mCache;
540  mCache = 0;
541  }
542 }
543 
545 {
546  return mCache != 0;
547 }
548 
550 {
551  if ( mCache )
552  mCache->clear();
553 }
554 
556 {
557  mUseParallelRendering = enabled;
558 }
559 
561 {
562  return mUseParallelRendering;
563 }
564 
565 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
566 {
567  mMapUpdateTimer.setInterval( timeMiliseconds );
568 }
569 
571 {
572  return mMapUpdateTimer.interval();
573 }
574 
575 
577 {
578  // redraw overview
579  if ( mMapOverview )
580  {
582  }
583 }
584 
585 
587 {
588  return mCurrentLayer;
589 }
590 
591 
593 {
594  if ( !mSettings.hasValidSettings() )
595  {
596  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
597  return;
598  }
599 
600  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
601  {
602  QgsDebugMsg( "CANVAS render flag off" );
603  return;
604  }
605 
606  if ( mRefreshScheduled )
607  {
608  QgsDebugMsg( "CANVAS refresh already scheduled" );
609  return;
610  }
611 
612  mRefreshScheduled = true;
613 
614  QgsDebugMsg( "CANVAS refresh scheduling" );
615 
616  // schedule a refresh
617  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
618 } // refresh
619 
621 {
622  Q_ASSERT( mRefreshScheduled );
623 
624  QgsDebugMsg( "CANVAS refresh!" );
625 
626  stopRendering(); // if any...
627 
628  // from now on we can accept refresh requests again
629  mRefreshScheduled = false;
630 
631  //update $map variable to canvas
632  QgsExpression::setSpecialColumn( "$map", tr( "canvas" ) );
633 
634  // create the renderer job
635  Q_ASSERT( mJob == 0 );
636  mJobCancelled = false;
637  if ( mUseParallelRendering )
639  else
641  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
642  mJob->setCache( mCache );
643 
644  QStringList layersForGeometryCache;
645  foreach ( QString id, mSettings.layers() )
646  {
647  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
648  {
649  if ( vl->isEditable() )
650  layersForGeometryCache << id;
651  }
652  }
653  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
654 
655  mJob->start();
656 
657  mMapUpdateTimer.start();
658 
659  emit renderStarting();
660 }
661 
662 
664 {
665  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
666 
667  mMapUpdateTimer.stop();
668 
669  // TODO: would be better to show the errors in message bar
670  foreach ( const QgsMapRendererJob::Error& error, mJob->errors() )
671  {
672  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
673  }
674 
675  if ( !mJobCancelled )
676  {
677  // take labeling results before emitting renderComplete, so labeling map tools
678  // connected to signal work with correct results
679  delete mLabelingResults;
681 
682  QImage img = mJob->renderedImage();
683 
684  // emit renderComplete to get our decorations drawn
685  QPainter p( &img );
686  emit renderComplete( &p );
687 
688  QSettings settings;
689  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
690  {
691  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
692  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
693  }
694 
695  if ( mDrawRenderingStats )
696  {
697  int w = img.width(), h = img.height();
698  QFont fnt = p.font();
699  fnt.setBold( true );
700  p.setFont( fnt );
701  int lh = p.fontMetrics().height() * 2;
702  QRect r( 0, h - lh, w, lh );
703  p.setPen( Qt::NoPen );
704  p.setBrush( QColor( 0, 0, 0, 110 ) );
705  p.drawRect( r );
706  p.setPen( Qt::white );
707  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
708  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
709  }
710 
711  p.end();
712 
714  }
715 
716  // now we are in a slot called from mJob - do not delete it immediately
717  // so the class is still valid when the execution returns to the class
718  mJob->deleteLater();
719  mJob = 0;
720 
721  emit mapCanvasRefreshed();
722 }
723 
725 {
727 }
728 
729 
731 {
732  if ( mJob )
733  {
734  QgsDebugMsg( "CANVAS stop rendering!" );
735  mJobCancelled = true;
736  mJob->cancel();
737  Q_ASSERT( mJob == 0 ); // no need to delete here: already deleted in finished()
738  }
739 }
740 
742 {
743 }
744 
745 //the format defaults to "PNG" if not specified
746 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
747 {
748  //
749  //check if the optional QPaintDevice was supplied
750  //
751  if ( theQPixmap != NULL )
752  {
753  // render
754  QPainter painter;
755  painter.begin( theQPixmap );
756  QgsMapRendererCustomPainterJob job( mSettings, &painter );
757  job.start();
758  job.waitForFinished();
759  emit renderComplete( &painter );
760  painter.end();
761 
762  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
763  }
764  else //use the map view
765  {
766  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
767  }
768  //create a world file to go with the image...
770  QString myHeader;
771  // note: use 17 places of precision for all numbers output
772  //Pixel XDim
773  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
774  //Rotation on y axis - hard coded
775  myHeader += "0 \r\n";
776  //Rotation on x axis - hard coded
777  myHeader += "0 \r\n";
778  //Pixel YDim - almost always negative - see
779  //http://en.wikipedia.org/wiki/World_file#cite_note-2
780  myHeader += "-" + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
781  //Origin X (center of top left cell)
782  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
783  //Origin Y (center of top left cell)
784  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
785  QFileInfo myInfo = QFileInfo( theFileName );
786  // allow dotted names
787  QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
788  QFile myWorldFile( myWorldFileName );
789  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
790  {
791  return;
792  }
793  QTextStream myStream( &myWorldFile );
794  myStream << myHeader;
795 } // saveAsImage
796 
797 
798 
800 {
801  return mapSettings().visibleExtent();
802 } // extent
803 
805 {
806  return mapSettings().fullExtent();
807 } // extent
808 
809 
811 {
812  QgsRectangle current = extent();
813 
814  if ( r == current )
815  return;
816 
817  if ( r.isEmpty() )
818  {
819  QgsDebugMsg( "Empty extent - keeping old extent with new center!" );
820  QgsRectangle e( QgsPoint( r.center().x() - current.width() / 2.0, r.center().y() - current.height() / 2.0 ),
821  QgsPoint( r.center().x() + current.width() / 2.0, r.center().y() + current.height() / 2.0 ) );
822  mSettings.setExtent( e );
823  }
824  else
825  {
826  mSettings.setExtent( r );
827  }
828  emit extentsChanged();
829  updateScale();
830  if ( mLastExtent.size() > 20 )
831  mLastExtent.removeAt( 0 );
832 
833  //clear all extent items after current index
834  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
835  {
836  mLastExtent.removeAt( i );
837  }
838 
839  mLastExtent.append( extent() ) ;
840 
841  // adjust history to no more than 20
842  if ( mLastExtent.size() > 20 )
843  {
844  mLastExtent.removeAt( 0 );
845  }
846 
847  // the last item is the current extent
848  mLastExtentIndex = mLastExtent.size() - 1;
849 
850  // update controls' enabled state
851  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
852  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
853  // notify canvas items of change
855 
856 } // setExtent
857 
858 
860 {
861  emit scaleChanged( mapSettings().scale() );
862 }
863 
864 
866 {
867  refresh();
868 } // clear
869 
870 
871 
873 {
875  // If the full extent is an empty set, don't do the zoom
876  if ( !extent.isEmpty() )
877  {
878  // Add a 5% margin around the full extent
879  extent.scale( 1.05 );
880  setExtent( extent );
881  }
882  refresh();
883 
884 } // zoomToFullExtent
885 
886 
887 
889 {
890  if ( mLastExtentIndex > 0 )
891  {
894  emit extentsChanged();
895  updateScale();
896  refresh();
897  // update controls' enabled state
898  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
899  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
900  // notify canvas items of change
902  }
903 
904 } // zoomToPreviousExtent
905 
907 {
908  if ( mLastExtentIndex < mLastExtent.size() - 1 )
909  {
912  emit extentsChanged();
913  updateScale();
914  refresh();
915  // update controls' enabled state
916  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
917  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
918  // notify canvas items of change
920  }
921 }// zoomToNextExtent
922 
924 {
925  mLastExtent.clear(); // clear the zoom history list
926  mLastExtent.append( extent() ) ; // set the current extent in the list
927  mLastExtentIndex = mLastExtent.size() - 1;
928  // update controls' enabled state
931 }// clearExtentHistory
932 
933 
935 {
937 }
938 
940 {
941  if ( layer == NULL )
942  {
943  // use current layer by default
944  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
945  }
946 
947  if ( layer == NULL )
948  {
949  return;
950  }
951 
952  if ( layer->selectedFeatureCount() == 0 )
953  {
954  return;
955  }
956 
958 
959  // no selected features, only one selected point feature
960  //or two point features with the same x- or y-coordinates
961  if ( rect.isEmpty() )
962  {
963  // zoom in
964  QgsPoint c = rect.center();
965  rect = extent();
966  rect.scale( 1.0, &c );
967  }
968  //zoom to an area
969  else
970  {
971  // Expand rect to give a bit of space around the selected
972  // objects so as to keep them clear of the map boundaries
973  // The same 5% should apply to all margins.
974  rect.scale( 1.05 );
975  }
976 
977  setExtent( rect );
978  refresh();
979 } // zoomToSelected
980 
982 {
983  if ( layer == NULL )
984  {
985  // use current layer by default
986  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
987  }
988 
989  if ( layer == NULL )
990  {
991  return;
992  }
993 
994  if ( layer->selectedFeatureCount() == 0 )
995  {
996  return;
997  }
998 
1000  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1001  refresh();
1002 } // panToSelected
1003 
1004 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
1005 {
1006  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1007  {
1008  emit keyPressed( e );
1009  return;
1010  }
1011 
1012  QPainter paint;
1013  QPen pen( Qt::gray );
1014  QgsPoint ll, ur;
1015 
1016  if ( ! mCanvasProperties->mouseButtonDown )
1017  {
1018  // Don't want to interfer with mouse events
1019 
1020  QgsRectangle currentExtent = mapSettings().visibleExtent();
1021  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
1022  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
1023 
1024  switch ( e->key() )
1025  {
1026  case Qt::Key_Left:
1027  QgsDebugMsg( "Pan left" );
1028 
1029  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
1030  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
1031  setExtent( currentExtent );
1032  refresh();
1033  break;
1034 
1035  case Qt::Key_Right:
1036  QgsDebugMsg( "Pan right" );
1037 
1038  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
1039  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
1040  setExtent( currentExtent );
1041  refresh();
1042  break;
1043 
1044  case Qt::Key_Up:
1045  QgsDebugMsg( "Pan up" );
1046 
1047  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
1048  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
1049  setExtent( currentExtent );
1050  refresh();
1051  break;
1052 
1053  case Qt::Key_Down:
1054  QgsDebugMsg( "Pan down" );
1055 
1056  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
1057  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
1058  setExtent( currentExtent );
1059  refresh();
1060  break;
1061 
1062 
1063 
1064  case Qt::Key_Space:
1065  QgsDebugMsg( "Pressing pan selector" );
1066 
1067  //mCanvasProperties->dragging = true;
1068  if ( ! e->isAutoRepeat() )
1069  {
1070  mCanvasProperties->panSelectorDown = true;
1071  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1072  }
1073  break;
1074 
1075  case Qt::Key_PageUp:
1076  QgsDebugMsg( "Zoom in" );
1077  zoomIn();
1078  break;
1079 
1080  case Qt::Key_PageDown:
1081  QgsDebugMsg( "Zoom out" );
1082  zoomOut();
1083  break;
1084 
1085  case Qt::Key_P:
1087  refresh();
1088  break;
1089 
1090  case Qt::Key_S:
1092  refresh();
1093  break;
1094 
1095  default:
1096  // Pass it on
1097  if ( mMapTool )
1098  {
1099  mMapTool->keyPressEvent( e );
1100  }
1101  else e->ignore();
1102 
1103  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1104  }
1105  }
1106 
1107  emit keyPressed( e );
1108 
1109 } //keyPressEvent()
1110 
1111 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
1112 {
1113  QgsDebugMsg( "keyRelease event" );
1114 
1115  switch ( e->key() )
1116  {
1117  case Qt::Key_Space:
1118  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1119  {
1120  QgsDebugMsg( "Releasing pan selector" );
1121 
1122  mCanvasProperties->panSelectorDown = false;
1123  panActionEnd( mCanvasProperties->mouseLastXY );
1124  }
1125  break;
1126 
1127  default:
1128  // Pass it on
1129  if ( mMapTool )
1130  {
1131  mMapTool->keyReleaseEvent( e );
1132  }
1133  else e->ignore();
1134 
1135  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1136  }
1137 
1138  emit keyReleased( e );
1139 
1140 } //keyReleaseEvent()
1141 
1142 
1144 {
1145  // call handler of current map tool
1146  if ( mMapTool )
1148 } // mouseDoubleClickEvent
1149 
1150 
1151 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
1152 {
1153  //use middle mouse button for panning, map tools won't receive any events in that case
1154  if ( e->button() == Qt::MidButton )
1155  {
1156  mCanvasProperties->panSelectorDown = true;
1157  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1158  }
1159  else
1160  {
1161 
1162  // call handler of current map tool
1163  if ( mMapTool )
1164  mMapTool->canvasPressEvent( e );
1165  }
1166 
1167  if ( mCanvasProperties->panSelectorDown )
1168  {
1169  return;
1170  }
1171 
1172  mCanvasProperties->mouseButtonDown = true;
1173  mCanvasProperties->rubberStartPoint = e->pos();
1174 
1175 } // mousePressEvent
1176 
1177 
1178 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
1179 {
1180  //use middle mouse button for panning, map tools won't receive any events in that case
1181  if ( e->button() == Qt::MidButton )
1182  {
1183  mCanvasProperties->panSelectorDown = false;
1184  panActionEnd( mCanvasProperties->mouseLastXY );
1185  }
1186  else
1187  {
1188  // call handler of current map tool
1189  if ( mMapTool )
1190  {
1191  // right button was pressed in zoom tool? return to previous non zoom tool
1192  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1193  {
1194  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1195  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1196 
1197  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1198 
1199  // change to older non-zoom tool
1200  if ( mLastNonZoomMapTool
1201  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1202  {
1204  mLastNonZoomMapTool = NULL;
1205  setMapTool( t );
1206  }
1207  return;
1208  }
1210  }
1211  }
1212 
1213 
1214  mCanvasProperties->mouseButtonDown = false;
1215 
1216  if ( mCanvasProperties->panSelectorDown )
1217  return;
1218 
1219 } // mouseReleaseEvent
1220 
1221 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
1222 {
1223  QGraphicsView::resizeEvent( e );
1224  mResizeTimer->start( 500 );
1225 
1226  QSize lastSize = viewport()->size();
1227 
1228  mSettings.setOutputSize( lastSize );
1230 
1231  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1232 
1233  moveCanvasContents( true );
1234 
1235  // notify canvas items of change
1237 
1238  updateScale();
1239 
1240  //refresh();
1241 
1242  emit extentsChanged();
1243 }
1244 
1245 void QgsMapCanvas::paintEvent( QPaintEvent *e )
1246 {
1247  // no custom event handling anymore
1248 
1249  QGraphicsView::paintEvent( e );
1250 } // paintEvent
1251 
1253 {
1254  QList<QGraphicsItem*> list = mScene->items();
1255  QList<QGraphicsItem*>::iterator it = list.begin();
1256  while ( it != list.end() )
1257  {
1258  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1259 
1260  if ( item )
1261  {
1262  item->updatePosition();
1263  }
1264 
1265  ++it;
1266  }
1267 }
1268 
1269 
1270 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
1271 {
1272  // Zoom the map canvas in response to a mouse wheel event. Moving the
1273  // wheel forward (away) from the user zooms in
1274 
1275  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1276 
1277  if ( mMapTool )
1278  {
1279  mMapTool->wheelEvent( e );
1280  }
1281 
1282  if ( QgsApplication::keyboardModifiers() )
1283  {
1284  // leave the wheel for map tools if any modifier pressed
1285  return;
1286  }
1287 
1288  switch ( mWheelAction )
1289  {
1290  case WheelZoom:
1291  // zoom without changing extent
1292  if ( e->delta() > 0 )
1293  zoomIn();
1294  else
1295  zoomOut();
1296  break;
1297 
1298  case WheelZoomAndRecenter:
1299  // zoom and don't change extent
1300  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1301  break;
1302 
1304  {
1305  // zoom map to mouse cursor
1306  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1307 
1308  QgsPoint oldCenter( mapSettings().visibleExtent().center() );
1309  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1310  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1311  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1312 
1313  // same as zoomWithCenter (no coordinate transformations are needed)
1315  extent.scale( scaleFactor, &newCenter );
1316  setExtent( extent );
1317  refresh();
1318  break;
1319  }
1320 
1321  case WheelNothing:
1322  // well, nothing!
1323  break;
1324  }
1325 }
1326 
1327 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1328 {
1329  mWheelAction = action;
1330  mWheelZoomFactor = factor;
1331 }
1332 
1334 {
1336 }
1337 
1339 {
1341 }
1342 
1343 void QgsMapCanvas::zoomScale( double newScale )
1344 {
1345  zoomByFactor( newScale / scale() );
1346 }
1347 
1348 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1349 {
1350  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1351 
1352  // transform the mouse pos to map coordinates
1353  QgsPoint center = getCoordinateTransform()->toMapPoint( x, y );
1355  r.scale( scaleFactor, &center );
1356  setExtent( r );
1357  refresh();
1358 }
1359 
1360 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
1361 {
1362  mCanvasProperties->mouseLastXY = e->pos();
1363 
1364  if ( mCanvasProperties->panSelectorDown )
1365  {
1366  panAction( e );
1367  }
1368  else
1369  {
1370  // call handler of current map tool
1371  if ( mMapTool )
1372  mMapTool->canvasMoveEvent( e );
1373  }
1374 
1375  // show x y on status bar
1376  QPoint xy = e->pos();
1378  emit xyCoordinates( coord );
1379 } // mouseMoveEvent
1380 
1381 
1382 
1385 {
1386  if ( !tool )
1387  return;
1388 
1389  if ( mMapTool )
1390  {
1391  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1392  mMapTool->deactivate();
1393  }
1394 
1395  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1396  {
1397  // if zoom or pan tool will be active, save old tool
1398  // to bring it back on right click
1399  // (but only if it wasn't also zoom or pan tool)
1401  }
1402  else
1403  {
1404  mLastNonZoomMapTool = NULL;
1405  }
1406 
1407  QgsMapTool* oldTool = mMapTool;
1408 
1409  // set new map tool and activate it
1410  mMapTool = tool;
1411  if ( mMapTool )
1412  {
1413  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1414  mMapTool->activate();
1415  }
1416 
1417  emit mapToolSet( mMapTool );
1418  emit mapToolSet( mMapTool, oldTool );
1419 } // setMapTool
1420 
1422 {
1423  if ( mMapTool && mMapTool == tool )
1424  {
1425  mMapTool->deactivate();
1426  mMapTool = NULL;
1427  emit mapToolSet( NULL );
1428  emit mapToolSet( NULL, mMapTool );
1429  setCursor( Qt::ArrowCursor );
1430  }
1431 
1432  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1433  {
1434  mLastNonZoomMapTool = NULL;
1435  }
1436 }
1437 
1439 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1440 {
1441  // background of map's pixmap
1442  mSettings.setBackgroundColor( theColor );
1443 
1444  // background of the QGraphicsView
1445  QBrush bgBrush( theColor );
1446  setBackgroundBrush( bgBrush );
1447 #if 0
1448  QPalette palette;
1449  palette.setColor( backgroundRole(), theColor );
1450  setPalette( palette );
1451 #endif
1452 
1453  // background of QGraphicsScene
1454  mScene->setBackgroundBrush( bgBrush );
1455 } // setBackgroundColor
1456 
1458 {
1459  return mScene->backgroundBrush().color();
1460 }
1461 
1462 void QgsMapCanvas::setSelectionColor( const QColor& color )
1463 {
1464  mSettings.setSelectionColor( color );
1465 }
1466 
1468 {
1469  return mapSettings().layers().size();
1470 } // layerCount
1471 
1472 
1473 QList<QgsMapLayer*> QgsMapCanvas::layers() const
1474 {
1475  QList<QgsMapLayer*> lst;
1476  foreach ( QString layerID, mapSettings().layers() )
1477  {
1479  if ( layer )
1480  lst.append( layer );
1481  }
1482  return lst;
1483 }
1484 
1485 
1487 {
1488  // called when a layer has changed visibility setting
1489 
1490  refresh();
1491 
1492 } // layerStateChange
1493 
1494 
1495 
1496 void QgsMapCanvas::freeze( bool frz )
1497 {
1498  mFrozen = frz;
1499 } // freeze
1500 
1502 {
1503  return mFrozen;
1504 } // freeze
1505 
1506 
1508 {
1510  return mMap->paintDevice();
1512 }
1513 
1515 {
1516  return mapSettings().mapUnitsPerPixel();
1517 } // mapUnitsPerPixel
1518 
1519 
1521 {
1522  if ( mSettings.mapUnits() == u )
1523  return;
1524 
1525  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1526  mSettings.setMapUnits( u );
1527 
1528  updateScale();
1529 
1530  refresh(); // this will force the scale bar to be updated
1531 
1532  emit mapUnitsChanged();
1533 }
1534 
1535 
1537 {
1538  return mapSettings().mapUnits();
1539 }
1540 
1541 
1542 void QgsMapCanvas::setRenderFlag( bool theFlag )
1543 {
1544  mRenderFlag = theFlag;
1545 
1546  if ( mRenderFlag )
1547  {
1548  refresh();
1549  }
1550  else
1551  stopRendering();
1552 }
1553 
1554 void QgsMapCanvas::connectNotify( const char * signal )
1555 {
1556  Q_UNUSED( signal );
1557  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1558 } //connectNotify
1559 
1560 
1562 {
1564  return;
1565 
1566  QString destAuthId = mSettings.destinationCrs().authid();
1567  foreach ( QString layerID, mSettings.layers() )
1568  {
1570  if ( !layer )
1571  continue;
1572 
1573  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1574  if ( vl && vl->geometryType() == QGis::NoGeometry )
1575  continue;
1576 
1577  // if there are more options, ask the user which datum transform to use
1579  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1580  }
1581 }
1582 
1583 
1584 
1586 {
1587  return mMapTool;
1588 }
1589 
1590 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
1591 {
1592  // move map image and other items to standard position
1593  moveCanvasContents( true ); // true means reset
1594 
1595  // use start and end box points to calculate the extent
1596  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1597  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1598 
1599  double dx = qAbs( end.x() - start.x() );
1600  double dy = qAbs( end.y() - start.y() );
1601 
1602  // modify the extent
1604 
1605  if ( end.x() < start.x() )
1606  {
1607  r.setXMinimum( r.xMinimum() + dx );
1608  r.setXMaximum( r.xMaximum() + dx );
1609  }
1610  else
1611  {
1612  r.setXMinimum( r.xMinimum() - dx );
1613  r.setXMaximum( r.xMaximum() - dx );
1614  }
1615 
1616  if ( end.y() < start.y() )
1617  {
1618  r.setYMaximum( r.yMaximum() + dy );
1619  r.setYMinimum( r.yMinimum() + dy );
1620 
1621  }
1622  else
1623  {
1624  r.setYMaximum( r.yMaximum() - dy );
1625  r.setYMinimum( r.yMinimum() - dy );
1626 
1627  }
1628 
1629  setExtent( r );
1630 
1631  r = mapSettings().visibleExtent();
1632 
1633  refresh();
1634 }
1635 
1636 void QgsMapCanvas::panAction( QMouseEvent * e )
1637 {
1638  Q_UNUSED( e );
1639 
1640  // move all map canvas items
1642 }
1643 
1645 {
1646  QPoint pnt( 0, 0 );
1647  if ( !reset )
1648  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1649 
1650  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1651 }
1652 
1654 {
1655  Q_UNUSED( mapLayer );
1656 }
1657 
1659 {
1660  return mCanvasProperties->mouseLastXY;
1661 }
1662 
1663 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1664 {
1665  if ( !mPreviewEffect )
1666  {
1667  return;
1668  }
1669 
1670  mPreviewEffect->setEnabled( previewEnabled );
1671 }
1672 
1674 {
1675  if ( !mPreviewEffect )
1676  {
1677  return false;
1678  }
1679 
1680  return mPreviewEffect->isEnabled();
1681 }
1682 
1684 {
1685  if ( !mPreviewEffect )
1686  {
1687  return;
1688  }
1689 
1690  mPreviewEffect->setMode( mode );
1691 }
1692 
1694 {
1695  if ( !mPreviewEffect )
1696  {
1698  }
1699 
1700  return mPreviewEffect->mode();
1701 }
1702 
1703 void QgsMapCanvas::readProject( const QDomDocument & doc )
1704 {
1705  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1706  if ( nodes.count() )
1707  {
1708  QDomNode node = nodes.item( 0 );
1709 
1710  QgsMapSettings tmpSettings;
1711  tmpSettings.readXML( node );
1712  setMapUnits( tmpSettings.mapUnits() );
1714  setDestinationCrs( tmpSettings.destinationCrs() );
1715  setExtent( tmpSettings.extent() );
1717 
1718  clearExtentHistory(); // clear the extent history on project load
1719  }
1720  else
1721  {
1722  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1723  }
1724 }
1725 
1726 void QgsMapCanvas::writeProject( QDomDocument & doc )
1727 {
1728  // create node "mapcanvas" and call mMapRenderer->writeXML()
1729 
1730  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1731  if ( !nl.count() )
1732  {
1733  QgsDebugMsg( "Unable to find qgis element in project file" );
1734  return;
1735  }
1736  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1737 
1738  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1739  qgisNode.appendChild( mapcanvasNode );
1740 
1741  mSettings.writeXML( mapcanvasNode, doc );
1742  // TODO: store only units, extent, projections, dest CRS
1743 }
1744 
1746 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1747 {
1748  if ( !ml )
1749  {
1750  return;
1751  }
1752 
1753  //check if default datum transformation available
1754  QSettings s;
1755  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1756  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1757  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1758  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1759  {
1760  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1761  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1762  return;
1763  }
1764 
1765  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1766  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1767 
1768  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1769  {
1770  // just use the default transform
1771  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1772  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1773  return;
1774  }
1775 
1776  //get list of datum transforms
1777  QList< QList< int > > dt = QgsCoordinateTransform::datumTransformations( srcCRS, destCRS );
1778  if ( dt.size() < 2 )
1779  {
1780  return;
1781  }
1782 
1783  //if several possibilities: present dialog
1784  QgsDatumTransformDialog d( ml->name(), dt );
1785  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1786  if ( d.exec() == QDialog::Accepted )
1787  {
1788  int srcTransform = -1;
1789  int destTransform = -1;
1790  QList<int> t = d.selectedDatumTransform();
1791  if ( t.size() > 0 )
1792  {
1793  srcTransform = t.at( 0 );
1794  }
1795  if ( t.size() > 1 )
1796  {
1797  destTransform = t.at( 1 );
1798  }
1799  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1800  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1801  if ( d.rememberSelection() )
1802  {
1803  s.setValue( settingsString + "_srcTransform", srcTransform );
1804  s.setValue( settingsString + "_destTransform", destTransform );
1805  }
1806  }
1807  else
1808  {
1809  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1810  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1811  }
1812 }
1813 
1814 void QgsMapCanvas::zoomByFactor( double scaleFactor )
1815 {
1817  r.scale( scaleFactor );
1818  setExtent( r );
1819  refresh();
1820 }
1821 
1823 {
1824  // Find out which layer it was that sent the signal.
1825  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1826  emit selectionChanged( layer );
1827  refresh();
1828 }
1829 
1830 void QgsMapCanvas::dragEnterEvent( QDragEnterEvent * e )
1831 {
1832  // By default graphics view delegates the drag events to graphics items.
1833  // But we do not want that and by ignoring the drag enter we let the
1834  // parent (e.g. QgisApp) to handle drops of map layers etc.
1835  e->ignore();
1836 }
1837 
1839 {
1840  QgsDebugMsg( "maptool destroyed" );
1841  mMapTool = 0;
1842 }
1843 
1844 #ifdef HAVE_TOUCH
1845 bool QgsMapCanvas::event( QEvent * e )
1846 {
1847  bool done = false;
1848  if ( e->type() == QEvent::Gesture )
1849  {
1850  // call handler of current map tool
1851  if ( mMapTool )
1852  {
1853  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
1854  }
1855  }
1856  else
1857  {
1858  // pass other events to base class
1859  done = QGraphicsView::event( e );
1860  }
1861  return done;
1862 }
1863 #endif
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
QgsMapCanvasMap * mMap
owns pixmap with rendered map and controls rendering
Definition: qgsmapcanvas.h:570
void zoomToSelected(QgsVectorLayer *layer=NULL)
Zoom to the extent of the selected features of current (vector) layer.
void setRequestedGeometryCacheForLayers(const QStringList &layerIds)
Set which vector layers should be cached while rendering.
void updateCanvasItemPositions()
called on resize or changed extent to notify canvas items to change their rectangle ...
QgsMapSettings mSettings
encompases all map settings necessary for map rendering
Definition: qgsmapcanvas.h:564
bool mDrawRenderingStats
Whether to add rendering stats to the rendered image.
Definition: qgsmapcanvas.h:622
void setParallelRenderingEnabled(bool enabled)
Set whether the layers are rendered in parallel or sequentially.
const QgsDatumTransformStore & datumTransformStore() const
static unsigned index
void mapUpdateTimeout()
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
QPoint mouseLastXY
Last seen point of the mouse.
virtual QColor canvasColor() const
Read property of QColor bgColor.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:47
Job implementation that renders everything sequentially using a custom painter.
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
bool isEmpty() const
test if rectangle is empty.
void zoomToNextExtent()
Zoom to the next extent (view)
QGraphicsScene * mScene
graphics scene manages canvas items
Definition: qgsmapcanvas.h:588
void zoomWithCenter(int x, int y, bool zoomIn)
Zooms in/out with a given center.
Q_DECL_DEPRECATED bool isDirty() const
Return the state of the canvas (dirty or not)
void freeze(bool frz=true)
virtual void setCanvasColor(const QColor &_newVal)
Write property of QColor bgColor.
void enableOverviewMode(QgsMapOverviewCanvas *overview)
QTimer * mResizeTimer
Definition: qgsmapcanvas.h:627
double scale() const
Return the calculated scale of the map.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
bool hasEntryForLayer(QgsMapLayer *layer) const
int layerCount() const
return number of layers on the map
bool mUseParallelRendering
Whether layers are rendered sequentially or in parallel.
Definition: qgsmapcanvas.h:619
A widget that displays an overview map.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:169
void clearExtentHistory()
void readXML(QDomNode &theNode)
QgsRectangle fullExtent() const
returns current extent of layer set
QgsMapRenderer * mMapRenderer
all map rendering is done in this class
Definition: qgsmapcanvas.h:567
bool mouseButtonDown
Flag to indicate status of mouse button.
static QList< QList< int > > datumTransformations(const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS)
Returns list of datum transformations for the given src and dest CRS.
bool mRefreshScheduled
Flag that allows squashing multiple refresh() calls into just one delayed rendering job...
Definition: qgsmapcanvas.h:579
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:194
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void stopRendering()
stop rendering (if there is any right now)
virtual void canvasMoveEvent(QMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:134
void zoomByFactor(double scaleFactor)
Zoom with the factor supplied. Factor > 1 zooms out, interval (0,1) zooms in.
void mouseReleaseEvent(QMouseEvent *e)
Overridden mouse release event.
QgsRectangle extent() const
returns current extent
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
QString qgsDoubleToString(const double &a)
Definition: qgis.h:316
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:439
An abstract class for items that can be placed on the map canvas.
A class that stores visibility and presence in overview flags together with pointer to the layer...
Definition: qgsmapcanvas.h:74
bool hasCrsTransformEnabled()
A simple helper method to find out if on the fly projections are enabled or not.
void setCurrentLayer(QgsMapLayer *layer)
bool previewModeEnabled() const
Returns whether a preview mode is enabled for the map canvas.
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
QList< QgsMapLayer * > layers() const
return list of layers within map canvas. Added in v1.5
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
WheelAction mWheelAction
Mouse wheel action.
Definition: qgsmapcanvas.h:604
bool isVisible() const
Definition: qgsmapcanvas.h:83
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from layer's CRS to output CRS
void readProject(const QDomDocument &)
called to read map canvas settings from project
bool panSelectorDown
Flag to indicate the pan selector key is held down by user.
QgsMapOverviewCanvas * mMapOverview
map overview widget - it's controlled by QgsMapCanvas
Definition: qgsmapcanvas.h:573
void refresh()
Repaints the canvas map.
void renderComplete(QPainter *)
Emitted when the canvas has rendered.
void setProjectionsEnabled(bool enabled)
sets whether to use projections for this layer set
~QgsMapCanvas()
Destructor.
const QgsMapToPixel & mapToPixel() const
void keyReleaseEvent(QKeyEvent *e)
Overridden key release event.
QgsMapTool * mapTool()
Returns the currently active tool.
void setLayerSet(const QStringList &layers)
change current layer set
virtual void canvasDoubleClickEvent(QMouseEvent *e)
Mouse double click event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:139
const QgsLabelingResults * labelingResults() const
Get access to the labeling results (may be null)
A non GUI class for rendering a map layer set onto a QPainter.
virtual void canvasPressEvent(QMouseEvent *e)
Mouse press event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:144
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
void resizeEvent(QResizeEvent *e)
Overridden resize event.
QgsMapTool * mMapTool
pointer to current map tool
Definition: qgsmapcanvas.h:591
virtual QImage renderedImage()=0
Get a preview/resulting image.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:104
double x() const
Definition: qgspoint.h:110
void zoomLastStatusChanged(bool)
Emitted when zoom last status changed.
A graphics effect which can be applied to a widget to simulate various printing and color blindness m...
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void updateScale()
Emits signal scaleChanged to update scale in main window.
void mouseDoubleClickEvent(QMouseEvent *e)
Overridden mouse double click event.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
The QgsMapSettings class contains configuration for rendering of the map.
QgsMapLayer * mCurrentLayer
current layer in legend
Definition: qgsmapcanvas.h:585
void setDatumTransformInfo(const QString &srcCRSauthId, const QString &destCRSauthId)
void hasCrsTransformEnabledChanged(bool flag)
Emitted when on-the-fly projection has been turned on/off.
void setMapTool(QgsMapTool *mapTool)
Sets the map tool currently being used on the canvas.
void enableAntiAliasing(bool flag)
const QString & name() const
Get the display name of the layer.
virtual void activate()
called when set as currently active map tool
Definition: qgsmaptool.cpp:77
void paintEvent(QPaintEvent *e)
Overridden paint event.
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QgsMapRenderer * mRenderer
Definition: qgsmapcanvas.h:666
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
virtual void keyReleaseEvent(QKeyEvent *e)
Key event for overriding.
Definition: qgsmaptool.cpp:164
int outputDpi() const
Return DPI used for conversion between real world units (e.g.
Q_DECL_DEPRECATED void showError(QgsMapLayer *mapLayer)
A rectangular graphics item representing the map on the canvas.
Q_DECL_DEPRECATED void clear()
Clear the map canvas.
void addEntry(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform, int destDatumTransform)
int mLastExtentIndex
Definition: qgsmapcanvas.h:598
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
double scale()
Get the last reported scale of the canvas.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
void zoomNextStatusChanged(bool)
Emitted when zoom next status changed.
QgsMapTool * mLastNonZoomMapTool
previous tool if current is for zooming/panning
Definition: qgsmapcanvas.h:594
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
void clearCache()
Make sure to remove any rendered images from cache (does nothing if cache is not enabled) ...
void mousePressEvent(QMouseEvent *e)
Overridden mouse press event.
void setMapUnits(QGis::UnitType u)
Set units of map's geographical coordinates - used for scale calculation.
virtual void waitForFinished()
Block until the job has finished.
Job implementation that renders all layers in parallel.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void panToSelected(QgsVectorLayer *layer=NULL)
Pan to the selected features of current (vector) layer keeping same extent.
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:174
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:665
void keyReleased(QKeyEvent *e)
Emit key release event.
Q_DECL_DEPRECATED QPaintDevice & paintDevice()
void mapToolDestroyed()
called when current maptool is destroyed
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Enable anti-aliasin for map rendering.
void setMapUnits(QGis::UnitType u)
void getDatumTransformInfo(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId)
ask user about datum transformation
Q_DECL_DEPRECATED QPaintDevice & canvasPaintDevice()
Accessor for the canvas paint device.
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:92
void wheelEvent(QWheelEvent *e)
Overridden mouse wheel event.
void destinationCrsChanged()
Emitted when map CRS has changed.
int mapUpdateInterval() const
Find out how often map preview should be updated while it is being rendered (in milliseconds) ...
void updateDatumTransformEntries()
Make sure the datum transform store is properly populated.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
void setRenderFlag(bool theFlag)
Whether to suppress rendering or not.
QGis::UnitType mapUnits() const
Get units of map's geographical coordinates - used for scale calculation.
QGis::UnitType mapUnits() const
Get the current canvas map units.
virtual void start()
Start the rendering job and immediately return.
void setOutputSize(QSize size, int dpi)
void setCachingEnabled(bool enabled)
Set whether to cache images of rendered layers.
virtual void deactivate()
called when map tool is being deactivated
Definition: qgsmaptool.cpp:91
virtual bool isEditTool()
Check whether this MapTool performs an edit operation.
Definition: qgsmaptool.cpp:186
QgsMapCanvasMap * map()
void setPreviewMode(QgsPreviewEffect::PreviewMode mode)
Sets a preview mode for the map canvas.
virtual void wheelEvent(QWheelEvent *e)
Mouse wheel event for overriding.
Definition: qgsmaptool.cpp:154
void refresh()
renders overview and updates panning widget
void setMode(PreviewMode mode)
Sets the mode for the preview effect, which controls how the effect modifies a widgets appearance...
void renderStarting()
Emitted when the canvas is about to be rendered.
A class to represent a point geometry.
Definition: qgspoint.h:63
void saveAsImage(QString theFileName, QPixmap *QPixmap=0, QString="PNG")
Save the convtents of the map canvas to disk as an image.
void keyPressed(QKeyEvent *e)
Emit key press event.
QgsMapRendererQImageJob * mJob
Job that takes care of map rendering in background.
Definition: qgsmapcanvas.h:610
void zoomOut()
Zoom out with fixed factor.
QgsPreviewEffect::PreviewMode previewMode() const
Returns the current preview mode for the map canvas.
Enable drawing of vertex markers for layers in editing mode.
void zoomToPreviousExtent()
Zoom to the previous extent (view)
void xyCoordinates(const QgsPoint &p)
emits current mouse position
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs, bool refreshCoordinateTransformInfo=true, bool transformExtent=true)
sets destination coordinate reference system
bool isDrawing()
Find out whether rendering is in progress.
QgsLabelingResults * mLabelingResults
Labeling results from the recently rendered map.
Definition: qgsmapcanvas.h:616
void setPreviewModeEnabled(bool previewEnabled)
Enables a preview mode for the map canvas.
virtual void start()=0
Start the rendering job and immediately return.
QPoint mouseLastXY()
returns last position of mouse cursor
QgsMapLayer * currentLayer()
returns current layer (set by legend widget)
void setWheelAction(WheelAction action, double factor=2)
set wheel action and zoom factor (should be greater than 1)
void selectionChanged(QgsMapLayer *layer)
Emitted when selection in any layer gets changed.
virtual void keyPressEvent(QKeyEvent *e)
Key event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:159
bool isCachingEnabled() const
Check whether images of rendered layers are curerently being cached.
QgsPoint toMapCoordinates(int x, int y) const
void clear()
invalidate the cache contents
Abstract base class for all map tools.
Definition: qgsmaptool.h:48
void selectionChangedSlot()
Receives signal about selection change, and pass it on with layer info.
Job implementation that renders everything sequentially in one thread.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
QTimer mMapUpdateTimer
Timer that periodically fires while map rendering is in progress to update the visible map...
Definition: qgsmapcanvas.h:607
double mWheelZoomFactor
Scale factor multiple for default zoom in/out.
Definition: qgsmapcanvas.h:601
bool mFrozen
Flag indicating if the map canvas is frozen.
Definition: qgsmapcanvas.h:576
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QImage contentImage() const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
bool isInOverview() const
Definition: qgsmapcanvas.h:84
QgsMapRendererCache * mCache
Optionally use cache with rendered map layers for the current map settings.
Definition: qgsmapcanvas.h:625
virtual void canvasReleaseEvent(QMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:149
void setSelectionColor(const QColor &color)
Set color that is used for drawing of selected vector features.
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
void setOutputSize(const QSize &size)
Set the size of the resulting map image.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:179
void writeProject(QDomDocument &)
called to write map canvas settings to project
void panAction(QMouseEvent *event)
Called when mouse is moving and pan is activated.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
QgsPreviewEffect * mPreviewEffect
Definition: qgsmapcanvas.h:629
bool mRenderFlag
determines whether user has requested to suppress rendering
Definition: qgsmapcanvas.h:582
Class for storing a coordinate reference system (CRS)
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
QgsMapCanvasRendererSync(QgsMapCanvas *canvas, QgsMapRenderer *renderer)
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
void zoomScale(double scale)
Zoom to a specific scale.
Class for doing transforms between two map coordinate systems.
UnitType
Map units that qgis supports.
Definition: qgis.h:229
const QgsMapToPixel * getCoordinateTransform()
Get the current coordinate transform.
void scaleChanged(double)
Emitted when the scale of the map changes.
virtual bool isTransient()
Check whether this MapTool performs a zoom or pan operation.
Definition: qgsmaptool.cpp:181
double y() const
Definition: qgspoint.h:118
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
void enableAntiAliasing(bool theFlag)
used to determine if anti-aliasing is enabled or not
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
void setSelectionColor(const QColor &color)
Set color of selected vector features.
void setMapUpdateInterval(int timeMiliseconds)
Set how often map preview should be updated while it is being rendered (in milliseconds) ...
void layerStateChange()
This slot is connected to the visibility change of one or more layers.
void rendererJobFinished()
called when a renderer job has finished successfully or when it was cancelled
Enable vector simplification and other rendering optimizations.
Class that stores computed placement from labeling engine.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
This class is responsible for keeping cache of rendered images of individual layers.
QgsMapCanvas(QWidget *parent=0, const char *name=0)
Constructor.
void setMapUnits(QGis::UnitType mapUnits)
Set map units (needed by project properties dialog)
void updateOverview()
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
void connectNotify(const char *signal)
debugging member invoked when a connect() is made to this object
PreviewMode mode() const
Returns the mode used for the preview effect.
Q_DECL_DEPRECATED void setDirty(bool _dirty)
Flag the canvas as dirty and needed a refresh.
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
QPoint rubberStartPoint
Beginning point of a rubber band.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
Class that does synchronization between QgsMapCanvas and its associated QgsMapRenderer: ...
Definition: qgsmapcanvas.h:643
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:204
virtual QgsLabelingResults * takeLabelingResults()=0
Get pointer to internal labeling engine (in order to get access to the results)
void zoomIn()
Zoom in with fixed factor.
virtual bool isEditable() const
Returns true if the provider is in editing mode.
QGis::UnitType mapUnits() const
Represents a vector layer which manages a vector based data sets.
virtual void updatePosition()
called on changed extent or resize event to update position of the item
int selectedFeatureCount()
The number of features that are selected in this layer.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
QList< QgsRectangle > mLastExtent
recently used extent
Definition: qgsmapcanvas.h:597
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:85
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:214
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:86
void extentsChanged()
Emitted when the extents of the map change.
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
std::auto_ptr< CanvasProperties > mCanvasProperties
Handle pattern for implementation object.
Definition: qgsmapcanvas.h:540
void mouseMoveEvent(QMouseEvent *e)
Overridden mouse move event.
bool mJobCancelled
Flag determining whether the active job has been cancelled.
Definition: qgsmapcanvas.h:613
QgsMapLayer * layer(int index)
return the map layer at position index in the layer stack
Q_DECL_DEPRECATED void updateMap()
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:164
void keyPressEvent(QKeyEvent *e)
Overridden key press event.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:209
void dragEnterEvent(QDragEnterEvent *e)
Overridden drag enter event.
QgsPoint toMapPoint(double x, double y) const
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
void panActionEnd(QPoint releasePoint)
Ends pan action and redraws the canvas.
void mapUnitsChanged()
Emmitted when map units are changed.
QStringList layerSet() const
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
void layersChanged()
Emitted when a new set of layers has been received.
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
#define tr(sourceText)
void writeXML(QDomNode &theNode, QDomDocument &theDoc)
void mapToolSet(QgsMapTool *tool)
Emit map tool changed event.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.