QGIS API Documentation  2.8.6-Wien
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"
48 #include "qgsmaplayer.h"
49 #include "qgsmaplayerregistry.h"
50 #include "qgsmaptoolpan.h"
51 #include "qgsmaptoolzoom.h"
52 #include "qgsmaptopixel.h"
53 #include "qgsmapoverviewcanvas.h"
54 #include "qgsmaprenderer.h"
55 #include "qgsmaprenderercache.h"
59 #include "qgsmessagelog.h"
60 #include "qgsmessageviewer.h"
61 #include "qgspallabeling.h"
62 #include "qgsproject.h"
63 #include "qgsrubberband.h"
64 #include "qgsvectorlayer.h"
65 #include <math.h>
66 
67 
70 {
71  public:
72 
74 
77 
79  QPoint mouseLastXY;
80 
83 
86 };
87 
88 
90  : QObject( canvas )
91  , mCanvas( canvas )
92  , mRenderer( renderer )
93  , mSyncingExtent( false )
94 {
95  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( onExtentC2R() ) );
96  connect( mRenderer, SIGNAL( extentsChanged() ), this, SLOT( onExtentR2C() ) );
97 
98  connect( mCanvas, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsC2R() ) );
99  connect( mRenderer, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsR2C() ) );
100 
101  connect( mCanvas, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationC2R() ) );
102  connect( mRenderer, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationR2C() ) );
103 
104  connect( mCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ), this, SLOT( onCrsTransformC2R() ) );
105  connect( mRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( onCrsTransformR2C() ) );
106 
107  connect( mCanvas, SIGNAL( destinationCrsChanged() ), this, SLOT( onDestCrsC2R() ) );
108  connect( mRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( onDestCrsR2C() ) );
109 
110  connect( mCanvas, SIGNAL( layersChanged() ), this, SLOT( onLayersC2R() ) );
111  // TODO: layers R2C ? (should not happen!)
112 
113 }
114 
116 {
117  // protection against possible bounce back
118  if ( mSyncingExtent )
119  return;
120 
121  mSyncingExtent = true;
123  mSyncingExtent = false;
124 }
125 
127 {
128  // protection against possible bounce back
129  if ( mSyncingExtent )
130  return;
131 
132  mSyncingExtent = true;
134  mSyncingExtent = false;
135 }
136 
138 {
140 }
141 
143 {
145 }
146 
148 {
150 }
151 
153 {
155 }
156 
158 {
160 }
161 
163 {
165 }
166 
168 {
170 }
171 
173 {
175 }
176 
178 {
180 }
181 
182 
183 
184 QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
185  : QGraphicsView( parent )
186  , mCanvasProperties( new CanvasProperties )
187  , mJob( 0 )
188  , mJobCancelled( false )
189  , mLabelingResults( 0 )
190  , mUseParallelRendering( false )
191  , mDrawRenderingStats( false )
192  , mCache( 0 )
193  , mPreviewEffect( 0 )
194  , mSnappingUtils( 0 )
195 {
196  setObjectName( name );
197  mScene = new QGraphicsScene();
198  setScene( mScene );
199  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
200  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
201  mLastExtentIndex = -1;
202  mCurrentLayer = NULL;
203  mMapOverview = NULL;
204  mMapTool = NULL;
205  mLastNonZoomMapTool = NULL;
206 
207  mFrozen = false;
208  mRefreshScheduled = false;
209 
211 
212  // by default, the canvas is rendered
213  mRenderFlag = true;
214 
215  setMouseTracking( true );
216  setFocusPolicy( Qt::StrongFocus );
217 
218  mMapRenderer = new QgsMapRenderer;
219 
220  mResizeTimer = new QTimer( this );
221  mResizeTimer->setSingleShot( true );
222  connect( mResizeTimer, SIGNAL( timeout() ), this, SLOT( refresh() ) );
223 
224  // create map canvas item which will show the map
225  mMap = new QgsMapCanvasMap( this );
226  mScene->addItem( mMap );
227 
228  // project handling
229  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
230  this, SLOT( readProject( const QDomDocument & ) ) );
231  connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
232  this, SLOT( writeProject( QDomDocument & ) ) );
233 
236 
237  // class that will sync most of the changes between canvas and (legacy) map renderer
238  // it is parented to map canvas, will be deleted automatically
239  new QgsMapCanvasRendererSync( this, mMapRenderer );
240 
241  QSize s = viewport()->size();
242  mSettings.setOutputSize( s );
243  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
244  setSceneRect( 0, 0, s.width(), s.height() );
245  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
246 
247  moveCanvasContents( true );
248 
249  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
250  mMapUpdateTimer.setInterval( 250 );
251 
252 #ifdef Q_OS_WIN
253  // Enable touch event on Windows.
254  // Qt on Windows needs to be told it can take touch events or else it ignores them.
255  grabGesture( Qt::PinchGesture );
256  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
257 #endif
258 
259  mPreviewEffect = new QgsPreviewEffect( this );
260  viewport()->setGraphicsEffect( mPreviewEffect );
261 
262  setInteractive( false );
263 
264  refresh();
265 
266 } // QgsMapCanvas ctor
267 
268 
270 {
271  if ( mMapTool )
272  {
273  mMapTool->deactivate();
274  mMapTool = NULL;
275  }
276  mLastNonZoomMapTool = NULL;
277 
278  // delete canvas items prior to deleteing the canvas
279  // because they might try to update canvas when it's
280  // already being destructed, ends with segfault
281  QList<QGraphicsItem*> list = mScene->items();
282  QList<QGraphicsItem*>::iterator it = list.begin();
283  while ( it != list.end() )
284  {
285  QGraphicsItem* item = *it;
286  delete item;
287  ++it;
288  }
289 
290  mScene->deleteLater(); // crashes in python tests on windows
291 
292  delete mMapRenderer;
293  // mCanvasProperties auto-deleted via QScopedPointer
294  // CanvasProperties struct has its own dtor for freeing resources
295 
296  if ( mJob )
297  {
298  mJob->cancel();
299  Q_ASSERT( mJob == 0 );
300  }
301 
302  delete mCache;
303 
304  delete mLabelingResults;
305 
306 } // dtor
307 
309 {
310  mSettings.setFlag( QgsMapSettings::Antialiasing, theFlag );
311 
312  if ( mMapOverview )
313  mMapOverview->enableAntiAliasing( theFlag );
314 } // anti aliasing
315 
316 void QgsMapCanvas::useImageToRender( bool theFlag )
317 {
318  Q_UNUSED( theFlag );
319 }
320 
322 {
323  return mMap;
324 }
325 
327 {
328  return mMapRenderer;
329 }
330 
331 
333 {
334  const QStringList& layers = mapSettings().layers();
335  if ( index >= 0 && index < ( int ) layers.size() )
336  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
337  else
338  return NULL;
339 }
340 
341 
343 {
344  mCurrentLayer = layer;
345  emit currentLayerChanged( layer );
346 }
347 
349 {
350  return mapSettings().scale();
351 } // scale
352 
353 void QgsMapCanvas::setDirty( bool dirty )
354 {
355  if ( dirty )
356  refresh();
357 }
358 
360 {
361  return false;
362 }
363 
364 
365 
367 {
368  return mJob != 0;
369 } // isDrawing
370 
371 
372 // return the current coordinate transform based on the extents and
373 // device size
375 {
376  return &mapSettings().mapToPixel();
377 }
378 
379 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
380 {
381  // create layer set
382  QStringList layerSet, layerSetOverview;
383 
384  int i;
385  for ( i = 0; i < layers.size(); i++ )
386  {
387  QgsMapCanvasLayer &lyr = layers[i];
388  if ( !lyr.layer() )
389  {
390  continue;
391  }
392 
393  if ( lyr.isVisible() )
394  {
395  layerSet.push_back( lyr.layer()->id() );
396  }
397 
398  if ( lyr.isInOverview() )
399  {
400  layerSetOverview.push_back( lyr.layer()->id() );
401  }
402  }
403 
404  const QStringList& layerSetOld = mapSettings().layers();
405 
406  bool layerSetChanged = layerSetOld != layerSet;
407 
408  // update only if needed
409  if ( layerSetChanged )
410  {
411  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
412 
413  for ( i = 0; i < layerCount(); i++ )
414  {
415  // Add check if vector layer when disconnecting from selectionChanged slot
416  // Ticket #811 - racicot
418  if ( !currentLayer )
419  continue;
420  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
421  disconnect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
422  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
423  if ( isVectLyr )
424  {
425  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
426  }
427  }
428 
429  mSettings.setLayers( layerSet );
430 
431  for ( i = 0; i < layerCount(); i++ )
432  {
433  // Add check if vector layer when connecting to selectionChanged slot
434  // Ticket #811 - racicot
436  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
437  connect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
438  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
439  if ( isVectLyr )
440  {
441  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
442  }
443  }
444 
446 
447  QgsDebugMsg( "Layers have changed, refreshing" );
448  emit layersChanged();
449 
450  refresh();
451  }
452 
453  if ( mMapOverview )
454  {
455  const QStringList& layerSetOvOld = mMapOverview->layerSet();
456  if ( layerSetOvOld != layerSetOverview )
457  {
458  mMapOverview->setLayerSet( layerSetOverview );
459  }
460 
461  // refresh overview maplayers even if layer set is the same
462  // because full extent might have changed
463  updateOverview();
464  }
465 } // setLayerSet
466 
468 {
469  if ( mMapOverview )
470  {
471  // disconnect old map overview if exists
472  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
473  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
474  disconnect( this, SIGNAL( destinationCrsChanged() ),
475  mMapOverview, SLOT( destinationSrsChanged() ) );
476 
477  // map overview is not owned by map canvas so don't delete it...
478  }
479 
480  mMapOverview = overview;
481 
482  if ( overview )
483  {
484  // connect to the map render to copy its projection settings
485  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
486  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
487  connect( this, SIGNAL( destinationCrsChanged() ),
488  overview, SLOT( destinationSrsChanged() ) );
489  }
490 }
491 
493 {
494  return mSettings;
495 }
496 
498 {
499  if ( mSettings.hasCrsTransformEnabled() == enabled )
500  return;
501 
502  mSettings.setCrsTransformEnabled( enabled );
503 
505 
506  refresh();
507 
508  emit hasCrsTransformEnabledChanged( enabled );
509 }
510 
512 {
513  if ( mSettings.destinationCrs() == crs )
514  return;
515 
516  if ( mSettings.hasCrsTransformEnabled() )
517  {
518  // try to reproject current extent to the new one
519  QgsRectangle rect;
520  if ( !mSettings.visibleExtent().isEmpty() )
521  {
522  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
523  try
524  {
525  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
526  }
527  catch ( QgsCsException &e )
528  {
529  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
530  }
531  }
532  if ( !rect.isEmpty() )
533  {
534  setExtent( rect );
535  }
536 
537  QgsDebugMsg( "refreshing after destination CRS changed" );
538  refresh();
539  }
540 
541  mSettings.setDestinationCrs( crs );
542 
544 
545  emit destinationCrsChanged();
546 }
547 
549 {
550  return mLabelingResults;
551 }
552 
554 {
555  if ( enabled == isCachingEnabled() )
556  return;
557 
558  if ( mJob && mJob->isActive() )
559  {
560  // wait for the current rendering to finish, before touching the cache
561  mJob->waitForFinished();
562  }
563 
564  if ( enabled )
565  {
566  mCache = new QgsMapRendererCache;
567  }
568  else
569  {
570  delete mCache;
571  mCache = 0;
572  }
573 }
574 
576 {
577  return mCache != 0;
578 }
579 
581 {
582  if ( mCache )
583  mCache->clear();
584 }
585 
587 {
588  mUseParallelRendering = enabled;
589 }
590 
592 {
593  return mUseParallelRendering;
594 }
595 
596 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
597 {
598  mMapUpdateTimer.setInterval( timeMiliseconds );
599 }
600 
602 {
603  return mMapUpdateTimer.interval();
604 }
605 
606 
608 {
609  // redraw overview
610  if ( mMapOverview )
611  {
612  mMapOverview->refresh();
613  }
614 }
615 
616 
618 {
619  return mCurrentLayer;
620 }
621 
622 
624 {
625  if ( !mSettings.hasValidSettings() )
626  {
627  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
628  return;
629  }
630 
631  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
632  {
633  QgsDebugMsg( "CANVAS render flag off" );
634  return;
635  }
636 
637  if ( mRefreshScheduled )
638  {
639  QgsDebugMsg( "CANVAS refresh already scheduled" );
640  return;
641  }
642 
643  mRefreshScheduled = true;
644 
645  QgsDebugMsg( "CANVAS refresh scheduling" );
646 
647  // schedule a refresh
648  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
649 } // refresh
650 
651 void QgsMapCanvas::refreshMap()
652 {
653  Q_ASSERT( mRefreshScheduled );
654 
655  QgsDebugMsg( "CANVAS refresh!" );
656 
657  stopRendering(); // if any...
658 
659  // from now on we can accept refresh requests again
660  mRefreshScheduled = false;
661 
662  //update $map variable to canvas
663  QgsExpression::setSpecialColumn( "$map", tr( "canvas" ) );
664 
665  // create the renderer job
666  Q_ASSERT( mJob == 0 );
667  mJobCancelled = false;
668  if ( mUseParallelRendering )
669  mJob = new QgsMapRendererParallelJob( mSettings );
670  else
671  mJob = new QgsMapRendererSequentialJob( mSettings );
672  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
673  mJob->setCache( mCache );
674 
675  QStringList layersForGeometryCache;
676  foreach ( QString id, mSettings.layers() )
677  {
678  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
679  {
680  if ( vl->isEditable() )
681  layersForGeometryCache << id;
682  }
683  }
684  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
685 
686  mJob->start();
687 
688  mMapUpdateTimer.start();
689 
690  emit renderStarting();
691 }
692 
693 
694 void QgsMapCanvas::rendererJobFinished()
695 {
696  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
697 
698  mMapUpdateTimer.stop();
699 
700  // TODO: would be better to show the errors in message bar
701  foreach ( const QgsMapRendererJob::Error& error, mJob->errors() )
702  {
703  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
704  }
705 
706  if ( !mJobCancelled )
707  {
708  // take labeling results before emitting renderComplete, so labeling map tools
709  // connected to signal work with correct results
710  delete mLabelingResults;
711  mLabelingResults = mJob->takeLabelingResults();
712 
713  QImage img = mJob->renderedImage();
714 
715  // emit renderComplete to get our decorations drawn
716  QPainter p( &img );
717  emit renderComplete( &p );
718 
719  QSettings settings;
720  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
721  {
722  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
723  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
724  }
725 
726  if ( mDrawRenderingStats )
727  {
728  int w = img.width(), h = img.height();
729  QFont fnt = p.font();
730  fnt.setBold( true );
731  p.setFont( fnt );
732  int lh = p.fontMetrics().height() * 2;
733  QRect r( 0, h - lh, w, lh );
734  p.setPen( Qt::NoPen );
735  p.setBrush( QColor( 0, 0, 0, 110 ) );
736  p.drawRect( r );
737  p.setPen( Qt::white );
738  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
739  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
740  }
741 
742  p.end();
743 
744  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
745  }
746 
747  // now we are in a slot called from mJob - do not delete it immediately
748  // so the class is still valid when the execution returns to the class
749  mJob->deleteLater();
750  mJob = 0;
751 
752  emit mapCanvasRefreshed();
753 }
754 
755 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
756 {
757  // This is a hack to pass QgsMapCanvasItem::setRect what it
758  // expects (encoding of position and size of the item)
759  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
760  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
761  double res = m2p.mapUnitsPerPixel();
762  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
763  return rect;
764 }
765 
766 void QgsMapCanvas::mapUpdateTimeout()
767 {
768  const QImage& img = mJob->renderedImage();
769  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
770 }
771 
773 {
774  if ( mJob )
775  {
776  QgsDebugMsg( "CANVAS stop rendering!" );
777  mJobCancelled = true;
778  mJob->cancel();
779  Q_ASSERT( mJob == 0 ); // no need to delete here: already deleted in finished()
780  }
781 }
782 
784 {
785 }
786 
787 //the format defaults to "PNG" if not specified
788 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
789 {
790  //
791  //check if the optional QPaintDevice was supplied
792  //
793  if ( theQPixmap != NULL )
794  {
795  // render
796  QPainter painter;
797  painter.begin( theQPixmap );
798  QgsMapRendererCustomPainterJob job( mSettings, &painter );
799  job.start();
800  job.waitForFinished();
801  emit renderComplete( &painter );
802  painter.end();
803 
804  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
805  }
806  else //use the map view
807  {
808  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
809  }
810  //create a world file to go with the image...
812  QString myHeader;
813  // note: use 17 places of precision for all numbers output
814  //Pixel XDim
815  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
816  //Rotation on y axis - hard coded
817  myHeader += "0 \r\n";
818  //Rotation on x axis - hard coded
819  myHeader += "0 \r\n";
820  //Pixel YDim - almost always negative - see
821  //http://en.wikipedia.org/wiki/World_file#cite_note-2
822  myHeader += "-" + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
823  //Origin X (center of top left cell)
824  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
825  //Origin Y (center of top left cell)
826  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
827  QFileInfo myInfo = QFileInfo( theFileName );
828  // allow dotted names
829  QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
830  QFile myWorldFile( myWorldFileName );
831  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
832  {
833  return;
834  }
835  QTextStream myStream( &myWorldFile );
836  myStream << myHeader;
837 } // saveAsImage
838 
839 
840 
842 {
843  return mapSettings().visibleExtent();
844 } // extent
845 
847 {
848  return mapSettings().fullExtent();
849 } // extent
850 
851 
853 {
854  QgsRectangle current = extent();
855 
856  if ( r == current )
857  return;
858 
859  if ( r.isEmpty() )
860  {
861  if ( !mSettings.hasValidSettings() )
862  {
863  // we can't even just move the map center
864  QgsDebugMsg( "Empty extent - ignoring" );
865  return;
866  }
867 
868  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
869  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
870  setCenter( r.center() );
871  }
872  else
873  {
874  mSettings.setExtent( r );
875  }
876  emit extentsChanged();
877  updateScale();
878  if ( mLastExtent.size() > 20 )
879  mLastExtent.removeAt( 0 );
880 
881  //clear all extent items after current index
882  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
883  {
884  mLastExtent.removeAt( i );
885  }
886 
887  mLastExtent.append( extent() );
888 
889  // adjust history to no more than 20
890  if ( mLastExtent.size() > 20 )
891  {
892  mLastExtent.removeAt( 0 );
893  }
894 
895  // the last item is the current extent
896  mLastExtentIndex = mLastExtent.size() - 1;
897 
898  // update controls' enabled state
899  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
900  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
901  // notify canvas items of change
903 
904 } // setExtent
905 
907 {
909  double x = center.x();
910  double y = center.y();
911  setExtent(
912  QgsRectangle(
913  x - r.width() / 2.0, y - r.height() / 2.0,
914  x + r.width() / 2.0, y + r.height() / 2.0
915  )
916  );
917 } // setCenter
918 
920 {
922  return r.center();
923 }
924 
925 
927 {
928  return mapSettings().rotation();
929 } // rotation
930 
931 void QgsMapCanvas::setRotation( double degrees )
932 {
933  if ( !rotationEnabled() )
934  return;
935 
936  double current = rotation();
937 
938  if ( degrees == current )
939  return;
940 
941  mSettings.setRotation( degrees );
942  emit rotationChanged( degrees );
943  emit extentsChanged(); // visible extent changes with rotation
944 
945  // notify canvas items of change (needed?)
947 
948 } // setRotation
949 
950 
952 {
953  emit scaleChanged( mapSettings().scale() );
954 }
955 
956 
958 {
959  refresh();
960 } // clear
961 
962 
963 
965 {
967  // If the full extent is an empty set, don't do the zoom
968  if ( !extent.isEmpty() )
969  {
970  // Add a 5% margin around the full extent
971  extent.scale( 1.05 );
972  setExtent( extent );
973  }
974  refresh();
975 
976 } // zoomToFullExtent
977 
978 
979 
981 {
982  if ( mLastExtentIndex > 0 )
983  {
984  mLastExtentIndex--;
985  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
986  emit extentsChanged();
987  updateScale();
988  refresh();
989  // update controls' enabled state
990  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
991  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
992  // notify canvas items of change
994  }
995 
996 } // zoomToPreviousExtent
997 
999 {
1000  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1001  {
1002  mLastExtentIndex++;
1003  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1004  emit extentsChanged();
1005  updateScale();
1006  refresh();
1007  // update controls' enabled state
1008  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1009  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1010  // notify canvas items of change
1012  }
1013 }// zoomToNextExtent
1014 
1016 {
1017  mLastExtent.clear(); // clear the zoom history list
1018  mLastExtent.append( extent() ) ; // set the current extent in the list
1019  mLastExtentIndex = mLastExtent.size() - 1;
1020  // update controls' enabled state
1021  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1022  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1023 }// clearExtentHistory
1024 
1025 
1027 {
1029 }
1030 
1032 {
1033  if ( layer == NULL )
1034  {
1035  // use current layer by default
1036  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1037  }
1038 
1039  if ( layer == NULL )
1040  {
1041  return;
1042  }
1043 
1044  if ( layer->selectedFeatureCount() == 0 )
1045  {
1046  return;
1047  }
1048 
1050 
1051  // no selected features, only one selected point feature
1052  //or two point features with the same x- or y-coordinates
1053  if ( rect.isEmpty() )
1054  {
1055  // zoom in
1056  QgsPoint c = rect.center();
1057  rect = extent();
1058  rect.scale( 1.0, &c );
1059  }
1060  //zoom to an area
1061  else
1062  {
1063  // Expand rect to give a bit of space around the selected
1064  // objects so as to keep them clear of the map boundaries
1065  // The same 5% should apply to all margins.
1066  rect.scale( 1.05 );
1067  }
1068 
1069  setExtent( rect );
1070  refresh();
1071 } // zoomToSelected
1072 
1074 {
1075  if ( layer == NULL )
1076  {
1077  // use current layer by default
1078  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1079  }
1080 
1081  if ( layer == NULL )
1082  {
1083  return;
1084  }
1085 
1086  if ( layer->selectedFeatureCount() == 0 )
1087  {
1088  return;
1089  }
1090 
1092  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1093  refresh();
1094 } // panToSelected
1095 
1096 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
1097 {
1098  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1099  {
1100  emit keyPressed( e );
1101  return;
1102  }
1103 
1104  QPainter paint;
1105  QPen pen( Qt::gray );
1106  QgsPoint ll, ur;
1107 
1108  if ( ! mCanvasProperties->mouseButtonDown )
1109  {
1110  // Don't want to interfer with mouse events
1111 
1112  QgsRectangle currentExtent = mapSettings().visibleExtent();
1113  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
1114  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
1115 
1116  switch ( e->key() )
1117  {
1118  case Qt::Key_Left:
1119  QgsDebugMsg( "Pan left" );
1120 
1121  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
1122  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
1123  setExtent( currentExtent );
1124  refresh();
1125  break;
1126 
1127  case Qt::Key_Right:
1128  QgsDebugMsg( "Pan right" );
1129 
1130  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
1131  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
1132  setExtent( currentExtent );
1133  refresh();
1134  break;
1135 
1136  case Qt::Key_Up:
1137  QgsDebugMsg( "Pan up" );
1138 
1139  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
1140  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
1141  setExtent( currentExtent );
1142  refresh();
1143  break;
1144 
1145  case Qt::Key_Down:
1146  QgsDebugMsg( "Pan down" );
1147 
1148  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
1149  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
1150  setExtent( currentExtent );
1151  refresh();
1152  break;
1153 
1154 
1155 
1156  case Qt::Key_Space:
1157  QgsDebugMsg( "Pressing pan selector" );
1158 
1159  //mCanvasProperties->dragging = true;
1160  if ( ! e->isAutoRepeat() )
1161  {
1162  mCanvasProperties->panSelectorDown = true;
1163  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1164  }
1165  break;
1166 
1167  case Qt::Key_PageUp:
1168  QgsDebugMsg( "Zoom in" );
1169  zoomIn();
1170  break;
1171 
1172  case Qt::Key_PageDown:
1173  QgsDebugMsg( "Zoom out" );
1174  zoomOut();
1175  break;
1176 
1177 #if 0
1178  case Qt::Key_P:
1179  mUseParallelRendering = !mUseParallelRendering;
1180  refresh();
1181  break;
1182 
1183  case Qt::Key_S:
1184  mDrawRenderingStats = !mDrawRenderingStats;
1185  refresh();
1186  break;
1187 #endif
1188 
1189  default:
1190  // Pass it on
1191  if ( mMapTool )
1192  {
1193  mMapTool->keyPressEvent( e );
1194  }
1195  else e->ignore();
1196 
1197  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1198  }
1199  }
1200 
1201  emit keyPressed( e );
1202 
1203 } //keyPressEvent()
1204 
1205 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
1206 {
1207  QgsDebugMsg( "keyRelease event" );
1208 
1209  switch ( e->key() )
1210  {
1211  case Qt::Key_Space:
1212  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1213  {
1214  QgsDebugMsg( "Releasing pan selector" );
1215 
1216  mCanvasProperties->panSelectorDown = false;
1217  panActionEnd( mCanvasProperties->mouseLastXY );
1218  }
1219  break;
1220 
1221  default:
1222  // Pass it on
1223  if ( mMapTool )
1224  {
1225  mMapTool->keyReleaseEvent( e );
1226  }
1227  else e->ignore();
1228 
1229  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1230  }
1231 
1232  emit keyReleased( e );
1233 
1234 } //keyReleaseEvent()
1235 
1236 
1238 {
1239  // call handler of current map tool
1240  if ( mMapTool )
1241  {
1242  mMapTool->canvasDoubleClickEvent( e );
1243  }
1244 }// mouseDoubleClickEvent
1245 
1246 
1247 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
1248 {
1249  //use middle mouse button for panning, map tools won't receive any events in that case
1250  if ( e->button() == Qt::MidButton )
1251  {
1252  mCanvasProperties->panSelectorDown = true;
1253  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1254  }
1255  else
1256  {
1257 
1258  // call handler of current map tool
1259  if ( mMapTool )
1260  {
1261  mMapTool->canvasPressEvent( e );
1262  }
1263  }
1264 
1265  if ( mCanvasProperties->panSelectorDown )
1266  {
1267  return;
1268  }
1269 
1270  mCanvasProperties->mouseButtonDown = true;
1271  mCanvasProperties->rubberStartPoint = e->pos();
1272 
1273 } // mousePressEvent
1274 
1275 
1276 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
1277 {
1278  //use middle mouse button for panning, map tools won't receive any events in that case
1279  if ( e->button() == Qt::MidButton )
1280  {
1281  mCanvasProperties->panSelectorDown = false;
1282  panActionEnd( mCanvasProperties->mouseLastXY );
1283  }
1284  else
1285  {
1286  // call handler of current map tool
1287  if ( mMapTool )
1288  {
1289  // right button was pressed in zoom tool? return to previous non zoom tool
1290  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1291  {
1292  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1293  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1294 
1295  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1296 
1297  // change to older non-zoom tool
1298  if ( mLastNonZoomMapTool
1299  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1300  {
1301  QgsMapTool* t = mLastNonZoomMapTool;
1302  mLastNonZoomMapTool = NULL;
1303  setMapTool( t );
1304  }
1305  return;
1306  }
1307  mMapTool->canvasReleaseEvent( e );
1308  }
1309  }
1310 
1311 
1312  mCanvasProperties->mouseButtonDown = false;
1313 
1314  if ( mCanvasProperties->panSelectorDown )
1315  return;
1316 
1317 } // mouseReleaseEvent
1318 
1319 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
1320 {
1321  QGraphicsView::resizeEvent( e );
1322  mResizeTimer->start( 500 );
1323 
1324  QSize lastSize = viewport()->size();
1325 
1326  mSettings.setOutputSize( lastSize );
1327  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1328 
1329  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1330 
1331  moveCanvasContents( true );
1332 
1333  // notify canvas items of change
1335 
1336  updateScale();
1337 
1338  //refresh();
1339 
1340  emit extentsChanged();
1341 }
1342 
1343 void QgsMapCanvas::paintEvent( QPaintEvent *e )
1344 {
1345  // no custom event handling anymore
1346 
1347  QGraphicsView::paintEvent( e );
1348 } // paintEvent
1349 
1351 {
1352  QList<QGraphicsItem*> list = mScene->items();
1353  QList<QGraphicsItem*>::iterator it = list.begin();
1354  while ( it != list.end() )
1355  {
1356  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1357 
1358  if ( item )
1359  {
1360  item->updatePosition();
1361  }
1362 
1363  ++it;
1364  }
1365 }
1366 
1367 
1368 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
1369 {
1370  // Zoom the map canvas in response to a mouse wheel event. Moving the
1371  // wheel forward (away) from the user zooms in
1372 
1373  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1374 
1375  if ( mMapTool )
1376  {
1377  mMapTool->wheelEvent( e );
1378  }
1379 
1380  if ( QgsApplication::keyboardModifiers() )
1381  {
1382  // leave the wheel for map tools if any modifier pressed
1383  return;
1384  }
1385 
1386  switch ( mWheelAction )
1387  {
1388  case WheelZoom:
1389  // zoom without changing extent
1390  if ( e->delta() > 0 )
1391  zoomIn();
1392  else
1393  zoomOut();
1394  break;
1395 
1396  case WheelZoomAndRecenter:
1397  // zoom and don't change extent
1398  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1399  break;
1400 
1402  {
1403  // zoom map to mouse cursor
1404  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1405 
1406  QgsPoint oldCenter = center();
1407  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1408  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1409  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1410 
1411  zoomByFactor( scaleFactor, &newCenter );
1412  break;
1413  }
1414 
1415  case WheelNothing:
1416  // well, nothing!
1417  break;
1418  }
1419 }
1420 
1421 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1422 {
1423  mWheelAction = action;
1424  mWheelZoomFactor = factor;
1425 }
1426 
1428 {
1429  zoomByFactor( 1 / mWheelZoomFactor );
1430 }
1431 
1433 {
1434  zoomByFactor( mWheelZoomFactor );
1435 }
1436 
1437 void QgsMapCanvas::zoomScale( double newScale )
1438 {
1439  zoomByFactor( newScale / scale() );
1440 }
1441 
1442 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1443 {
1444  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1445 
1446  // transform the mouse pos to map coordinates
1449  r.scale( scaleFactor, &center );
1450  setExtent( r );
1451  refresh();
1452 }
1453 
1454 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
1455 {
1456  mCanvasProperties->mouseLastXY = e->pos();
1457 
1458  if ( mCanvasProperties->panSelectorDown )
1459  {
1460  panAction( e );
1461  }
1462  else
1463  {
1464  // call handler of current map tool
1465  if ( mMapTool )
1466  {
1467  mMapTool->canvasMoveEvent( e );
1468  }
1469  }
1470 
1471  // show x y on status bar
1472  QPoint xy = e->pos();
1474  emit xyCoordinates( coord );
1475 } // mouseMoveEvent
1476 
1477 
1478 
1481 {
1482  if ( !tool )
1483  return;
1484 
1485  if ( mMapTool )
1486  {
1487  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1488  mMapTool->deactivate();
1489  }
1490 
1491  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1492  {
1493  // if zoom or pan tool will be active, save old tool
1494  // to bring it back on right click
1495  // (but only if it wasn't also zoom or pan tool)
1496  mLastNonZoomMapTool = mMapTool;
1497  }
1498  else
1499  {
1500  mLastNonZoomMapTool = NULL;
1501  }
1502 
1503  QgsMapTool* oldTool = mMapTool;
1504 
1505  // set new map tool and activate it
1506  mMapTool = tool;
1507  if ( mMapTool )
1508  {
1509  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1510  mMapTool->activate();
1511  }
1512 
1513  emit mapToolSet( mMapTool );
1514  emit mapToolSet( mMapTool, oldTool );
1515 } // setMapTool
1516 
1518 {
1519  if ( mMapTool && mMapTool == tool )
1520  {
1521  mMapTool->deactivate();
1522  mMapTool = NULL;
1523  emit mapToolSet( NULL );
1524  emit mapToolSet( NULL, mMapTool );
1525  setCursor( Qt::ArrowCursor );
1526  }
1527 
1528  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1529  {
1530  mLastNonZoomMapTool = NULL;
1531  }
1532 }
1533 
1535 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1536 {
1537  // background of map's pixmap
1538  mSettings.setBackgroundColor( theColor );
1539 
1540  // background of the QGraphicsView
1541  QBrush bgBrush( theColor );
1542  setBackgroundBrush( bgBrush );
1543 #if 0
1544  QPalette palette;
1545  palette.setColor( backgroundRole(), theColor );
1546  setPalette( palette );
1547 #endif
1548 
1549  // background of QGraphicsScene
1550  mScene->setBackgroundBrush( bgBrush );
1551 } // setBackgroundColor
1552 
1554 {
1555  return mScene->backgroundBrush().color();
1556 }
1557 
1558 void QgsMapCanvas::setSelectionColor( const QColor& color )
1559 {
1560  mSettings.setSelectionColor( color );
1561 }
1562 
1564 {
1565  return mapSettings().layers().size();
1566 } // layerCount
1567 
1568 
1569 QList<QgsMapLayer*> QgsMapCanvas::layers() const
1570 {
1571  QList<QgsMapLayer*> lst;
1572  foreach ( QString layerID, mapSettings().layers() )
1573  {
1575  if ( layer )
1576  lst.append( layer );
1577  }
1578  return lst;
1579 }
1580 
1581 
1583 {
1584  // called when a layer has changed visibility setting
1585 
1586  refresh();
1587 
1588 } // layerStateChange
1589 
1591 {
1592  // called when a layer's CRS has been changed
1593  QObject *theSender = sender();
1594  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1595  QString destAuthId = mSettings.destinationCrs().authid();
1596  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1597 
1598 } // layerCrsChange
1599 
1600 
1601 void QgsMapCanvas::freeze( bool frz )
1602 {
1603  mFrozen = frz;
1604 } // freeze
1605 
1607 {
1608  return mFrozen;
1609 } // freeze
1610 
1611 
1613 {
1615  return mMap->paintDevice();
1617 }
1618 
1620 {
1621  return mapSettings().mapUnitsPerPixel();
1622 } // mapUnitsPerPixel
1623 
1624 
1626 {
1627  if ( mSettings.mapUnits() == u )
1628  return;
1629 
1630  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1631  mSettings.setMapUnits( u );
1632 
1633  updateScale();
1634 
1635  refresh(); // this will force the scale bar to be updated
1636 
1637  emit mapUnitsChanged();
1638 }
1639 
1640 
1642 {
1643  return mapSettings().mapUnits();
1644 }
1645 
1646 
1647 void QgsMapCanvas::setRenderFlag( bool theFlag )
1648 {
1649  mRenderFlag = theFlag;
1650 
1651  if ( mRenderFlag )
1652  {
1653  refresh();
1654  }
1655  else
1656  stopRendering();
1657 }
1658 
1659 #if 0
1660 void QgsMapCanvas::connectNotify( const char * signal )
1661 {
1662  Q_UNUSED( signal );
1663  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1664 } //connectNotify
1665 #endif
1666 
1668 {
1669  if ( !mSettings.hasCrsTransformEnabled() )
1670  return;
1671 
1672  QString destAuthId = mSettings.destinationCrs().authid();
1673  foreach ( QString layerID, mSettings.layers() )
1674  {
1676  if ( !layer )
1677  continue;
1678 
1679  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1680  if ( vl && vl->geometryType() == QGis::NoGeometry )
1681  continue;
1682 
1683  // if there are more options, ask the user which datum transform to use
1684  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1685  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1686  }
1687 }
1688 
1689 
1690 
1692 {
1693  return mMapTool;
1694 }
1695 
1696 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
1697 {
1698  // move map image and other items to standard position
1699  moveCanvasContents( true ); // true means reset
1700 
1701  // use start and end box points to calculate the extent
1702  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1703  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1704 
1705  // modify the center
1706  double dx = end.x() - start.x();
1707  double dy = end.y() - start.y();
1708  QgsPoint c = center();
1709  c.set( c.x() - dx, c.y() - dy );
1710  setCenter( c );
1711 
1712  refresh();
1713 }
1714 
1715 void QgsMapCanvas::panAction( QMouseEvent * e )
1716 {
1717  Q_UNUSED( e );
1718 
1719  // move all map canvas items
1721 }
1722 
1724 {
1725  QPoint pnt( 0, 0 );
1726  if ( !reset )
1727  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1728 
1729  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1730 }
1731 
1733 {
1734  Q_UNUSED( mapLayer );
1735 }
1736 
1738 {
1739  return mCanvasProperties->mouseLastXY;
1740 }
1741 
1742 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1743 {
1744  if ( !mPreviewEffect )
1745  {
1746  return;
1747  }
1748 
1749  mPreviewEffect->setEnabled( previewEnabled );
1750 }
1751 
1753 {
1754  if ( !mPreviewEffect )
1755  {
1756  return false;
1757  }
1758 
1759  return mPreviewEffect->isEnabled();
1760 }
1761 
1763 {
1764  if ( !mPreviewEffect )
1765  {
1766  return;
1767  }
1768 
1769  mPreviewEffect->setMode( mode );
1770 }
1771 
1773 {
1774  if ( !mPreviewEffect )
1775  {
1777  }
1778 
1779  return mPreviewEffect->mode();
1780 }
1781 
1783 {
1784  if ( !mSnappingUtils )
1785  {
1786  // associate a dummy instance, but better than null pointer
1787  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1788  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1789  }
1790  return mSnappingUtils;
1791 }
1792 
1794 {
1795  mSnappingUtils = utils;
1796 }
1797 
1798 void QgsMapCanvas::readProject( const QDomDocument & doc )
1799 {
1800  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1801  if ( nodes.count() )
1802  {
1803  QDomNode node = nodes.item( 0 );
1804 
1805  QgsMapSettings tmpSettings;
1806  tmpSettings.readXML( node );
1807  setMapUnits( tmpSettings.mapUnits() );
1809  setDestinationCrs( tmpSettings.destinationCrs() );
1810  setExtent( tmpSettings.extent() );
1811  setRotation( tmpSettings.rotation() );
1812  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1813 
1814  clearExtentHistory(); // clear the extent history on project load
1815  }
1816  else
1817  {
1818  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1819  }
1820 }
1821 
1822 void QgsMapCanvas::writeProject( QDomDocument & doc )
1823 {
1824  // create node "mapcanvas" and call mMapRenderer->writeXML()
1825 
1826  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1827  if ( !nl.count() )
1828  {
1829  QgsDebugMsg( "Unable to find qgis element in project file" );
1830  return;
1831  }
1832  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1833 
1834  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1835  qgisNode.appendChild( mapcanvasNode );
1836 
1837  mSettings.writeXML( mapcanvasNode, doc );
1838  // TODO: store only units, extent, projections, dest CRS
1839 }
1840 
1842 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1843 {
1844  if ( !ml )
1845  {
1846  return;
1847  }
1848 
1849  //check if default datum transformation available
1850  QSettings s;
1851  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1852  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1853  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1854  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1855  {
1856  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1857  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1858  return;
1859  }
1860 
1861  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1862  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1863 
1864  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1865  {
1866  // just use the default transform
1867  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1868  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1869  return;
1870  }
1871 
1872  //get list of datum transforms
1873  QList< QList< int > > dt = QgsCoordinateTransform::datumTransformations( srcCRS, destCRS );
1874  if ( dt.size() < 2 )
1875  {
1876  return;
1877  }
1878 
1879  //if several possibilities: present dialog
1880  QgsDatumTransformDialog d( ml->name(), dt );
1881  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1882  if ( d.exec() == QDialog::Accepted )
1883  {
1884  int srcTransform = -1;
1885  int destTransform = -1;
1886  QList<int> t = d.selectedDatumTransform();
1887  if ( t.size() > 0 )
1888  {
1889  srcTransform = t.at( 0 );
1890  }
1891  if ( t.size() > 1 )
1892  {
1893  destTransform = t.at( 1 );
1894  }
1895  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1896  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1897  if ( d.rememberSelection() )
1898  {
1899  s.setValue( settingsString + "_srcTransform", srcTransform );
1900  s.setValue( settingsString + "_destTransform", destTransform );
1901  }
1902  }
1903  else
1904  {
1905  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1906  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1907  }
1908 }
1909 
1910 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1911 {
1913  r.scale( scaleFactor, center );
1914  setExtent( r );
1915  refresh();
1916 }
1917 
1919 {
1920  // Find out which layer it was that sent the signal.
1921  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1922  emit selectionChanged( layer );
1923  refresh();
1924 }
1925 
1926 void QgsMapCanvas::dragEnterEvent( QDragEnterEvent * e )
1927 {
1928  // By default graphics view delegates the drag events to graphics items.
1929  // But we do not want that and by ignoring the drag enter we let the
1930  // parent (e.g. QgisApp) to handle drops of map layers etc.
1931  e->ignore();
1932 }
1933 
1934 void QgsMapCanvas::mapToolDestroyed()
1935 {
1936  QgsDebugMsg( "maptool destroyed" );
1937  mMapTool = 0;
1938 }
1939 
1940 #ifdef HAVE_TOUCH
1941 bool QgsMapCanvas::event( QEvent * e )
1942 {
1943  bool done = false;
1944  if ( e->type() == QEvent::Gesture )
1945  {
1946  // call handler of current map tool
1947  if ( mMapTool )
1948  {
1949  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
1950  }
1951  }
1952  else
1953  {
1954  // pass other events to base class
1955  done = QGraphicsView::event( e );
1956  }
1957  return done;
1958 }
1959 #endif
1960 
1962 {
1963  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
1964 }
1965 
1966 void QgsMapCanvas::enableRotation( bool enable )
1967 {
1968  QSettings().setValue( "/qgis/canvasRotation", enable );
1969 }
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
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 ...
void setParallelRenderingEnabled(bool enabled)
Set whether the layers are rendered in parallel or sequentially.
const QgsDatumTransformStore & datumTransformStore() const
static unsigned index
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:49
Job implementation that renders everything sequentially using a custom painter.
void setRotation(double degrees)
Set the rotation of the map canvas in clockwise degrees.
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)
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)
double scale() const
Return the calculated scale of the map.
void zoomByFactor(double scaleFactor, const QgsPoint *center=0)
Zoom with the factor supplied.
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
A widget that displays an overview map.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:163
void clearExtentHistory()
void readXML(QDomNode &theNode)
QgsRectangle fullExtent() const
returns current extent of layer set
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.
void wheelEvent(QWheelEvent *e) override
Overridden mouse wheel event.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void stopRendering()
stop rendering (if there is any right now)
double rotation() const
Get the current map canvas rotation in clockwise degrees.
virtual void canvasMoveEvent(QMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:138
QgsRectangle extent() const
returns current extent
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
void keyPressEvent(QKeyEvent *e) override
Overridden key press event.
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:452
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:75
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.
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
bool isVisible() const
Definition: qgsmapcanvas.h:84
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&#39;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.
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.
Snapping utils instance that is connected to a canvas and updates the configuration (map settings + c...
const QgsMapToPixel & mapToPixel() const
QgsMapTool * mapTool()
Returns the currently active tool.
double rotation() const
Return the rotation of the resulting map image Units are clockwise degrees.
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:143
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:148
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
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:105
double x() const
Definition: qgspoint.h:126
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 setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
The QgsMapSettings class contains configuration for rendering of the map.
void resizeEvent(QResizeEvent *e) override
Overridden resize event.
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 setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QgsMapRenderer * mRenderer
Definition: qgsmapcanvas.h:724
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
void setSnappingUtils(QgsSnappingUtils *utils)
Assign an instance of snapping utils to the map canvas.
virtual void keyReleaseEvent(QKeyEvent *e)
Key event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:168
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.
QgsSnappingUtils * snappingUtils() const
Return snapping utility class that is associated with map canvas.
virtual void start() override
Start the rendering job and immediately return.
Q_DECL_DEPRECATED void clear()
Clear the map canvas.
void addEntry(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform, int destDatumTransform)
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
double scale()
Get the last reported scale of the canvas.
void rotationChanged(double)
Emitted when the rotation of the map changes.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
void zoomNextStatusChanged(bool)
Emitted when zoom next status changed.
void setRotation(double degrees)
Set the rotation of the resulting map image Units are clockwise degrees.
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 layerCrsChange()
This slot is connected to the layer&#39;s CRS change.
void setMapUnits(QGis::UnitType u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
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:168
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:723
void keyReleased(QKeyEvent *e)
Emit key release event.
Q_DECL_DEPRECATED QPaintDevice & paintDevice()
virtual void waitForFinished()=0
Block until the job has finished.
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Enable anti-aliasin for map rendering.
const QgsMapSettings & mapSettings() const
Return map settings with which this job was started.
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.
void mouseDoubleClickEvent(QMouseEvent *e) override
Overridden mouse double click event.
static bool rotationEnabled()
return if canvas rotation is enabled
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
void destinationCrsChanged()
Emitted when map CRS has changed.
double rotation() const
returns current rotation in clockwise degrees
double mapUnitsPerPixel() const
Return current map units per pixel.
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&#39;s geographical coordinates - used for scale calculation.
QGis::UnitType mapUnits() const
Get the current canvas map units.
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:93
virtual bool isEditTool()
Check whether this MapTool performs an edit operation.
Definition: qgsmaptool.cpp:190
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. Default implementation does nothing.
Definition: qgsmaptool.cpp:158
void refresh()
renders overview and updates panning widget
void set(double x, double y)
Definition: qgspoint.h:117
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.
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.
void currentLayerChanged(QgsMapLayer *layer)
Emitted when the current layer is changed.
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.
void setRotation(double degrees)
sets rotation value in clockwise degrees
QScopedPointer< CanvasProperties > mCanvasProperties
Handle pattern for implementation object.
Definition: qgsmapcanvas.h:588
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:319
void setPreviewModeEnabled(bool previewEnabled)
Enables a preview mode for the map canvas.
virtual void start()=0
Start the rendering job and immediately return.
static void enableRotation(bool enabled)
change canvas rotation support
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 mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
void keyReleaseEvent(QKeyEvent *e) override
Overridden key release event.
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:163
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:453
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QString what() const
Definition: qgsexception.h:35
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
QImage contentImage() const
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:85
virtual void canvasReleaseEvent(QMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:153
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 dragEnterEvent(QDragEnterEvent *e) override
Overridden drag enter event.
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:173
QgsPoint center() const
Get map center, in geographical coordinates.
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:351
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
Class for storing a coordinate reference system (CRS)
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
This class has all the configuration of snapping and can return answers to snapping queries...
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:185
double y() const
Definition: qgspoint.h:134
void setCenter(const QgsPoint &center)
Set the center of the map canvas, in geographical coordinates.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;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 paintEvent(QPaintEvent *e) override
Overridden paint event.
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.
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)
Custom exception class for Coordinate Reference System related exceptions.
void updateOverview()
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
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:696
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
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.
QGis::UnitType mapUnits() const
virtual void waitForFinished() override
Block until the job has finished.
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:183
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:82
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:208
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:87
void extentsChanged()
Emitted when the extents of the map change.
QgsPoint toMapPoint(qreal x, qreal y) const
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
QgsMapLayer * layer(int index)
return the map layer at position index in the layer stack
virtual bool isActive() const =0
Tell whether the rendering job is currently running in background.
Q_DECL_DEPRECATED void updateMap()
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:158
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
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.