QGIS API Documentation  2.14.18-Essen
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 
71 //TODO QGIS 3.0 - remove
73 {
74  public:
76 
79 
82 
85 
88 };
89 
90 
92  : QObject( canvas )
93  , mCanvas( canvas )
94  , mRenderer( renderer )
95  , mSyncingExtent( false )
96 {
97  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( onExtentC2R() ) );
98  connect( mRenderer, SIGNAL( extentsChanged() ), this, SLOT( onExtentR2C() ) );
99 
100  connect( mCanvas, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsC2R() ) );
101  connect( mRenderer, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsR2C() ) );
102 
103  connect( mCanvas, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationC2R() ) );
104  connect( mRenderer, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationR2C() ) );
105 
106  connect( mCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ), this, SLOT( onCrsTransformC2R() ) );
107  connect( mRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( onCrsTransformR2C() ) );
108 
109  connect( mCanvas, SIGNAL( destinationCrsChanged() ), this, SLOT( onDestCrsC2R() ) );
110  connect( mRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( onDestCrsR2C() ) );
111 
112  connect( mCanvas, SIGNAL( layersChanged() ), this, SLOT( onLayersC2R() ) );
113  // TODO: layers R2C ? (should not happen!)
114 
115 }
116 
118 {
119  // protection against possible bounce back
120  if ( mSyncingExtent )
121  return;
122 
123  mSyncingExtent = true;
125  mSyncingExtent = false;
126 }
127 
129 {
130  // protection against possible bounce back
131  if ( mSyncingExtent )
132  return;
133 
134  mSyncingExtent = true;
136  mSyncingExtent = false;
137 }
138 
140 {
142 }
143 
145 {
147 }
148 
150 {
152 }
153 
155 {
157 }
158 
160 {
162 }
163 
165 {
167 }
168 
170 {
172 }
173 
175 {
177 }
178 
180 {
182 }
183 
184 
185 
187  : QGraphicsView( parent )
188  , mCanvasProperties( new CanvasProperties )
189  , mJob( nullptr )
190  , mJobCancelled( false )
191  , mLabelingResults( nullptr )
192  , mUseParallelRendering( false )
193  , mDrawRenderingStats( false )
194  , mCache( nullptr )
195  , mPreviewEffect( nullptr )
196  , mSnappingUtils( nullptr )
197  , mExpressionContextScope( tr( "Map Canvas" ) )
198 {
199  setObjectName( name );
200  mScene = new QGraphicsScene();
201  setScene( mScene );
202  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
203  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
204  mLastExtentIndex = -1;
205  mCurrentLayer = nullptr;
206  mMapOverview = nullptr;
207  mMapTool = nullptr;
208  mLastNonZoomMapTool = nullptr;
209 
210  mFrozen = false;
211  mRefreshScheduled = false;
212 
214 
215  // by default, the canvas is rendered
216  mRenderFlag = true;
217 
218  setMouseTracking( true );
219  setFocusPolicy( Qt::StrongFocus );
220 
221  mMapRenderer = new QgsMapRenderer;
222 
223  mResizeTimer = new QTimer( this );
224  mResizeTimer->setSingleShot( true );
225  connect( mResizeTimer, SIGNAL( timeout() ), this, SLOT( refresh() ) );
226 
227  // create map canvas item which will show the map
228  mMap = new QgsMapCanvasMap( this );
229 
230  // project handling
231  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
232  this, SLOT( readProject( const QDomDocument & ) ) );
234  this, SLOT( writeProject( QDomDocument & ) ) );
235 
238 
239  // class that will sync most of the changes between canvas and (legacy) map renderer
240  // it is parented to map canvas, will be deleted automatically
241  new QgsMapCanvasRendererSync( this, mMapRenderer );
242 
243  QSize s = viewport()->size();
244  mSettings.setOutputSize( s );
245  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
246  setSceneRect( 0, 0, s.width(), s.height() );
247  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
248 
249  moveCanvasContents( true );
250 
251  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
252  mMapUpdateTimer.setInterval( 250 );
253 
254 #ifdef Q_OS_WIN
255  // Enable touch event on Windows.
256  // Qt on Windows needs to be told it can take touch events or else it ignores them.
257  grabGesture( Qt::PinchGesture );
258  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
259 #endif
260 
261  mPreviewEffect = new QgsPreviewEffect( this );
262  viewport()->setGraphicsEffect( mPreviewEffect );
263 
264  setInteractive( false );
265 
266  refresh();
267 
268 } // QgsMapCanvas ctor
269 
270 
272 {
273  if ( mMapTool )
274  {
275  mMapTool->deactivate();
276  mMapTool = nullptr;
277  }
278  mLastNonZoomMapTool = nullptr;
279 
280  // delete canvas items prior to deleteing the canvas
281  // because they might try to update canvas when it's
282  // already being destructed, ends with segfault
283  QList<QGraphicsItem*> list = mScene->items();
285  while ( it != list.end() )
286  {
287  QGraphicsItem* item = *it;
288  delete item;
289  ++it;
290  }
291 
292  mScene->deleteLater(); // crashes in python tests on windows
293 
294  delete mMapRenderer;
295  // mCanvasProperties auto-deleted via QScopedPointer
296  // CanvasProperties struct has its own dtor for freeing resources
297 
298  if ( mJob )
299  {
300  mJob->cancel();
301  Q_ASSERT( !mJob );
302  }
303 
304  delete mCache;
305 
306  delete mLabelingResults;
307 
308 } // dtor
309 
311 {
312  mSettings.setFlag( QgsMapSettings::Antialiasing, theFlag );
313 
314  if ( mMapOverview )
315  mMapOverview->enableAntiAliasing( theFlag );
316 } // anti aliasing
317 
319 {
320  mSettings.setFlag( QgsMapSettings::RenderMapTile, theFlag );
321 }
322 
323 void QgsMapCanvas::useImageToRender( bool theFlag )
324 {
325  Q_UNUSED( theFlag );
326 }
327 
329 {
330  return mMap;
331 }
332 
334 {
335  return mMapRenderer;
336 }
337 
338 
340 {
341  const QStringList& layers = mapSettings().layers();
342  if ( index >= 0 && index < ( int ) layers.size() )
343  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
344  else
345  return nullptr;
346 }
347 
348 
350 {
351  mCurrentLayer = layer;
352  emit currentLayerChanged( layer );
353 }
354 
356 {
357  return mapSettings().scale();
358 } // scale
359 
360 void QgsMapCanvas::setDirty( bool dirty )
361 {
362  if ( dirty )
363  refresh();
364 }
365 
367 {
368  return false;
369 }
370 
372 {
373  return nullptr != mJob;
374 } // isDrawing
375 
376 // return the current coordinate transform based on the extents and
377 // device size
379 {
380  return &mapSettings().mapToPixel();
381 }
382 
384 {
385  // create layer set
386  QStringList layerSet, layerSetOverview;
387 
388  int i;
389  for ( i = 0; i < layers.size(); i++ )
390  {
391  QgsMapCanvasLayer &lyr = layers[i];
392  if ( !lyr.layer() )
393  {
394  continue;
395  }
396 
397  if ( lyr.isVisible() )
398  {
399  layerSet.push_back( lyr.layer()->id() );
400  }
401 
402  if ( lyr.isInOverview() )
403  {
404  layerSetOverview.push_back( lyr.layer()->id() );
405  }
406  }
407 
408  const QStringList& layerSetOld = mapSettings().layers();
409 
410  bool layerSetChanged = layerSetOld != layerSet;
411 
412  // update only if needed
413  if ( layerSetChanged )
414  {
415  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
416 
417  for ( i = 0; i < layerCount(); i++ )
418  {
419  // Add check if vector layer when disconnecting from selectionChanged slot
420  // Ticket #811 - racicot
422  if ( !currentLayer )
423  continue;
424  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
425  disconnect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
426  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
427  if ( isVectLyr )
428  {
429  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
430  }
431  }
432 
433  mSettings.setLayers( layerSet );
434 
435  for ( i = 0; i < layerCount(); i++ )
436  {
437  // Add check if vector layer when connecting to selectionChanged slot
438  // Ticket #811 - racicot
440  if ( !currentLayer )
441  continue;
442  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
443  connect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
444  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
445  if ( isVectLyr )
446  {
447  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
448  }
449  }
450 
452 
453  QgsDebugMsg( "Layers have changed, refreshing" );
454  emit layersChanged();
455 
456  refresh();
457  }
458 
459  if ( mMapOverview )
460  {
461  const QStringList& layerSetOvOld = mMapOverview->layerSet();
462  if ( layerSetOvOld != layerSetOverview )
463  {
464  mMapOverview->setLayerSet( layerSetOverview );
465  }
466 
467  // refresh overview maplayers even if layer set is the same
468  // because full extent might have changed
469  updateOverview();
470  }
471 } // setLayerSet
472 
474 {
475  if ( mMapOverview )
476  {
477  // disconnect old map overview if exists
478  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
479  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
480  disconnect( this, SIGNAL( destinationCrsChanged() ),
481  mMapOverview, SLOT( destinationSrsChanged() ) );
482 
483  // map overview is not owned by map canvas so don't delete it...
484  }
485 
486  mMapOverview = overview;
487 
488  if ( overview )
489  {
490  // connect to the map render to copy its projection settings
491  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
492  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
493  connect( this, SIGNAL( destinationCrsChanged() ),
494  overview, SLOT( destinationSrsChanged() ) );
495  }
496 }
497 
499 {
500  return mSettings;
501 }
502 
504 {
505  if ( mSettings.hasCrsTransformEnabled() == enabled )
506  return;
507 
508  mSettings.setCrsTransformEnabled( enabled );
509 
511 
512  refresh();
513 
514  emit hasCrsTransformEnabledChanged( enabled );
515 }
516 
518 {
519  if ( mSettings.destinationCrs() == crs )
520  return;
521 
522  if ( mSettings.hasCrsTransformEnabled() )
523  {
524  // try to reproject current extent to the new one
526  if ( !mSettings.visibleExtent().isEmpty() )
527  {
528  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
529  try
530  {
531  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
532  }
533  catch ( QgsCsException &e )
534  {
535  Q_UNUSED( e );
536  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
537  }
538  }
539  if ( !rect.isEmpty() )
540  {
541  setExtent( rect );
542  }
543 
544  QgsDebugMsg( "refreshing after destination CRS changed" );
545  refresh();
546  }
547 
548  mSettings.setDestinationCrs( crs );
549 
551 
552  emit destinationCrsChanged();
553 }
554 
556 {
557  return mLabelingResults;
558 }
559 
561 {
562  if ( enabled == isCachingEnabled() )
563  return;
564 
565  if ( mJob && mJob->isActive() )
566  {
567  // wait for the current rendering to finish, before touching the cache
568  mJob->waitForFinished();
569  }
570 
571  if ( enabled )
572  {
573  mCache = new QgsMapRendererCache;
574  }
575  else
576  {
577  delete mCache;
578  mCache = nullptr;
579  }
580 }
581 
583 {
584  return nullptr != mCache;
585 }
586 
588 {
589  if ( mCache )
590  mCache->clear();
591 }
592 
594 {
595  mUseParallelRendering = enabled;
596 }
597 
599 {
600  return mUseParallelRendering;
601 }
602 
603 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
604 {
605  mMapUpdateTimer.setInterval( timeMiliseconds );
606 }
607 
609 {
610  return mMapUpdateTimer.interval();
611 }
612 
613 
615 {
616  // redraw overview
617  if ( mMapOverview )
618  {
619  mMapOverview->refresh();
620  }
621 }
622 
623 
625 {
626  return mCurrentLayer;
627 }
628 
629 
631 {
632  if ( !mSettings.hasValidSettings() )
633  {
634  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
635  return;
636  }
637 
638  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
639  {
640  QgsDebugMsg( "CANVAS render flag off" );
641  return;
642  }
643 
644  if ( mRefreshScheduled )
645  {
646  QgsDebugMsg( "CANVAS refresh already scheduled" );
647  return;
648  }
649 
650  mRefreshScheduled = true;
651 
652  QgsDebugMsg( "CANVAS refresh scheduling" );
653 
654  // schedule a refresh
655  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
656 } // refresh
657 
658 void QgsMapCanvas::refreshMap()
659 {
660  Q_ASSERT( mRefreshScheduled );
661 
662  QgsDebugMsg( "CANVAS refresh!" );
663 
664  stopRendering(); // if any...
665 
666  //build the expression context
667  QgsExpressionContext expressionContext;
668  expressionContext << QgsExpressionContextUtils::globalScope()
671  << new QgsExpressionContextScope( mExpressionContextScope );
672 
673  mSettings.setExpressionContext( expressionContext );
674 
675  // create the renderer job
676  Q_ASSERT( !mJob );
677  mJobCancelled = false;
678  if ( mUseParallelRendering )
679  mJob = new QgsMapRendererParallelJob( mSettings );
680  else
681  mJob = new QgsMapRendererSequentialJob( mSettings );
682  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
683  mJob->setCache( mCache );
684 
685  QStringList layersForGeometryCache;
686  Q_FOREACH ( const QString& id, mSettings.layers() )
687  {
688  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
689  {
690  if ( vl->isEditable() )
691  layersForGeometryCache << id;
692  }
693  }
694  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
695 
696  mJob->start();
697 
698  // from now on we can accept refresh requests again
699  // this must be reset only after the job has been started, because
700  // some providers (yes, it's you WCS and AMS!) during preparation
701  // do network requests and start an internal event loop, which may
702  // end up calling refresh() and would schedule another refresh,
703  // deleting the one we have just started.
704  mRefreshScheduled = false;
705 
706  mMapUpdateTimer.start();
707 
708  emit renderStarting();
709 }
710 
711 
712 void QgsMapCanvas::rendererJobFinished()
713 {
714  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
715 
716  mMapUpdateTimer.stop();
717 
718  // TODO: would be better to show the errors in message bar
719  Q_FOREACH ( const QgsMapRendererJob::Error& error, mJob->errors() )
720  {
721  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
722  }
723 
724  if ( !mJobCancelled )
725  {
726  // take labeling results before emitting renderComplete, so labeling map tools
727  // connected to signal work with correct results
728  delete mLabelingResults;
729  mLabelingResults = mJob->takeLabelingResults();
730 
731  QImage img = mJob->renderedImage();
732 
733  // emit renderComplete to get our decorations drawn
734  QPainter p( &img );
735  emit renderComplete( &p );
736 
737  QSettings settings;
738  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
739  {
740  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
741  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
742  }
743 
744  if ( mDrawRenderingStats )
745  {
746  int w = img.width(), h = img.height();
747  QFont fnt = p.font();
748  fnt.setBold( true );
749  p.setFont( fnt );
750  int lh = p.fontMetrics().height() * 2;
751  QRect r( 0, h - lh, w, lh );
752  p.setPen( Qt::NoPen );
753  p.setBrush( QColor( 0, 0, 0, 110 ) );
754  p.drawRect( r );
755  p.setPen( Qt::white );
756  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
757  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
758  }
759 
760  p.end();
761 
762  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
763  }
764 
765  // now we are in a slot called from mJob - do not delete it immediately
766  // so the class is still valid when the execution returns to the class
767  mJob->deleteLater();
768  mJob = nullptr;
769 
770  emit mapCanvasRefreshed();
771 }
772 
773 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
774 {
775  // This is a hack to pass QgsMapCanvasItem::setRect what it
776  // expects (encoding of position and size of the item)
777  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
778  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
779  double res = m2p.mapUnitsPerPixel();
780  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
781  return rect;
782 }
783 
784 void QgsMapCanvas::mapUpdateTimeout()
785 {
786  const QImage& img = mJob->renderedImage();
787  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
788 }
789 
791 {
792  if ( mJob )
793  {
794  QgsDebugMsg( "CANVAS stop rendering!" );
795  mJobCancelled = true;
796  mJob->cancel();
797  Q_ASSERT( !mJob ); // no need to delete here: already deleted in finished()
798  }
799 }
800 
802 {
803 }
804 
805 //the format defaults to "PNG" if not specified
806 void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat )
807 {
808  //
809  //check if the optional QPaintDevice was supplied
810  //
811  if ( theQPixmap )
812  {
813  // render
814  QPainter painter;
815  painter.begin( theQPixmap );
816  QgsMapRendererCustomPainterJob job( mSettings, &painter );
817  job.start();
818  job.waitForFinished();
819  emit renderComplete( &painter );
820  painter.end();
821 
822  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
823  }
824  else //use the map view
825  {
826  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
827  }
828  //create a world file to go with the image...
830  QString myHeader;
831  // note: use 17 places of precision for all numbers output
832  //Pixel XDim
833  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
834  //Rotation on y axis - hard coded
835  myHeader += "0 \r\n";
836  //Rotation on x axis - hard coded
837  myHeader += "0 \r\n";
838  //Pixel YDim - almost always negative - see
839  //http://en.wikipedia.org/wiki/World_file#cite_note-2
840  myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
841  //Origin X (center of top left cell)
842  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
843  //Origin Y (center of top left cell)
844  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
845  QFileInfo myInfo = QFileInfo( theFileName );
846  // allow dotted names
847  QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.completeBaseName() + '.' + theFormat + 'w';
848  QFile myWorldFile( myWorldFileName );
849  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
850  {
851  return;
852  }
853  QTextStream myStream( &myWorldFile );
854  myStream << myHeader;
855 } // saveAsImage
856 
857 
858 
860 {
861  return mapSettings().visibleExtent();
862 } // extent
863 
865 {
866  return mapSettings().fullExtent();
867 } // extent
868 
869 
871 {
872  QgsRectangle current = extent();
873 
874  if ( r == current )
875  return;
876 
877  if ( r.isEmpty() )
878  {
879  if ( !mSettings.hasValidSettings() )
880  {
881  // we can't even just move the map center
882  QgsDebugMsg( "Empty extent - ignoring" );
883  return;
884  }
885 
886  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
887  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
888  setCenter( r.center() );
889  }
890  else
891  {
892  mSettings.setExtent( r );
893  }
894  emit extentsChanged();
895  updateScale();
896  if ( mLastExtent.size() > 20 )
897  mLastExtent.removeAt( 0 );
898 
899  //clear all extent items after current index
900  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
901  {
902  mLastExtent.removeAt( i );
903  }
904 
905  mLastExtent.append( extent() );
906 
907  // adjust history to no more than 20
908  if ( mLastExtent.size() > 20 )
909  {
910  mLastExtent.removeAt( 0 );
911  }
912 
913  // the last item is the current extent
914  mLastExtentIndex = mLastExtent.size() - 1;
915 
916  // update controls' enabled state
917  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
918  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
919  // notify canvas items of change
921 
922 } // setExtent
923 
925 {
927  double x = center.x();
928  double y = center.y();
929  setExtent(
930  QgsRectangle(
931  x - r.width() / 2.0, y - r.height() / 2.0,
932  x + r.width() / 2.0, y + r.height() / 2.0
933  )
934  );
935 } // setCenter
936 
938 {
940  return r.center();
941 }
942 
943 
945 {
946  return mapSettings().rotation();
947 } // rotation
948 
949 void QgsMapCanvas::setRotation( double degrees )
950 {
951  if ( !rotationEnabled() )
952  return;
953 
954  double current = rotation();
955 
956  if ( degrees == current )
957  return;
958 
959  mSettings.setRotation( degrees );
960  emit rotationChanged( degrees );
961  emit extentsChanged(); // visible extent changes with rotation
962 
963  // notify canvas items of change (needed?)
965 
966 } // setRotation
967 
968 
970 {
971  emit scaleChanged( mapSettings().scale() );
972 }
973 
974 
976 {
977  refresh();
978 } // clear
979 
980 
981 
983 {
985  // If the full extent is an empty set, don't do the zoom
986  if ( !extent.isEmpty() )
987  {
988  // Add a 5% margin around the full extent
989  extent.scale( 1.05 );
990  setExtent( extent );
991  }
992  refresh();
993 
994 } // zoomToFullExtent
995 
996 
997 
999 {
1000  if ( mLastExtentIndex > 0 )
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 
1014 } // zoomToPreviousExtent
1015 
1017 {
1018  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1019  {
1020  mLastExtentIndex++;
1021  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1022  emit extentsChanged();
1023  updateScale();
1024  refresh();
1025  // update controls' enabled state
1026  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1027  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1028  // notify canvas items of change
1030  }
1031 }// zoomToNextExtent
1032 
1034 {
1035  mLastExtent.clear(); // clear the zoom history list
1036  mLastExtent.append( extent() ) ; // set the current extent in the list
1037  mLastExtentIndex = mLastExtent.size() - 1;
1038  // update controls' enabled state
1039  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1040  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1041 }// clearExtentHistory
1042 
1043 
1045 {
1047 }
1048 
1050 {
1051  if ( !layer )
1052  {
1053  // use current layer by default
1054  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1055  }
1056 
1057  if ( !layer || layer->selectedFeatureCount() == 0 )
1058  return;
1059 
1061  zoomToFeatureExtent( rect );
1062 } // zoomToSelected
1063 
1065 {
1066  // no selected features, only one selected point feature
1067  //or two point features with the same x- or y-coordinates
1068  if ( rect.isEmpty() )
1069  {
1070  // zoom in
1071  QgsPoint c = rect.center();
1072  rect = extent();
1073  rect.scale( 1.0, &c );
1074  }
1075  //zoom to an area
1076  else
1077  {
1078  // Expand rect to give a bit of space around the selected
1079  // objects so as to keep them clear of the map boundaries
1080  // The same 5% should apply to all margins.
1081  rect.scale( 1.05 );
1082  }
1083 
1084  setExtent( rect );
1085  refresh();
1086 }
1087 
1089 {
1090  if ( !layer )
1091  {
1092  return;
1093  }
1094 
1095  QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFids( ids ).setSubsetOfAttributes( QgsAttributeList() ) );
1097  rect.setMinimal();
1098  QgsFeature fet;
1099  int featureCount = 0;
1100  while ( it.nextFeature( fet ) )
1101  {
1102  const QgsGeometry* geom = fet.constGeometry();
1103  QString errorMessage;
1104  if ( !geom || geom->isEmpty() )
1105  {
1106  errorMessage = tr( "Feature does not have a geometry" );
1107  }
1108  else if ( geom->geometry()->isEmpty() )
1109  {
1110  errorMessage = tr( "Feature geometry is empty" );
1111  }
1112  if ( !errorMessage.isEmpty() )
1113  {
1114  emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1115  return;
1116  }
1118  rect.combineExtentWith( &r );
1119  featureCount++;
1120  }
1121 
1122  if ( featureCount != ids.count() )
1123  {
1124  return;
1125  }
1126 
1127  zoomToFeatureExtent( rect );
1128 }
1129 
1131 {
1132  if ( !layer )
1133  {
1134  // use current layer by default
1135  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1136  }
1137 
1138  if ( !layer || layer->selectedFeatureCount() == 0 )
1139  return;
1140 
1142  if ( !rect.isNull() )
1143  {
1144  setCenter( rect.center() );
1145  refresh();
1146  }
1147  else
1148  {
1149  emit messageEmitted( tr( "Cannot pan to selected feature(s)" ), tr( "Geometry is NULL" ), QgsMessageBar::WARNING );
1150  }
1151 } // panToSelected
1152 
1154 {
1155  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1156  {
1157  emit keyPressed( e );
1158  return;
1159  }
1160 
1161  QPainter paint;
1162  QPen pen( Qt::gray );
1163  QgsPoint ll, ur;
1164 
1165  if ( ! mCanvasProperties->mouseButtonDown )
1166  {
1167  // Don't want to interfer with mouse events
1168 
1169  QgsRectangle currentExtent = mapSettings().visibleExtent();
1170  double dx = qAbs( currentExtent.width() / 4 );
1171  double dy = qAbs( currentExtent.height() / 4 );
1172 
1173  switch ( e->key() )
1174  {
1175  case Qt::Key_Left:
1176  QgsDebugMsg( "Pan left" );
1177  setCenter( center() - QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1178  refresh();
1179  break;
1180 
1181  case Qt::Key_Right:
1182  QgsDebugMsg( "Pan right" );
1183  setCenter( center() + QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1184  refresh();
1185  break;
1186 
1187  case Qt::Key_Up:
1188  QgsDebugMsg( "Pan up" );
1189  setCenter( center() + QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1190  refresh();
1191  break;
1192 
1193  case Qt::Key_Down:
1194  QgsDebugMsg( "Pan down" );
1195  setCenter( center() - QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1196  refresh();
1197  break;
1198 
1199 
1200 
1201  case Qt::Key_Space:
1202  QgsDebugMsg( "Pressing pan selector" );
1203 
1204  //mCanvasProperties->dragging = true;
1205  if ( ! e->isAutoRepeat() )
1206  {
1207  QApplication::setOverrideCursor( Qt::ClosedHandCursor );
1208  mCanvasProperties->panSelectorDown = true;
1209  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1210  }
1211  break;
1212 
1213  case Qt::Key_PageUp:
1214  QgsDebugMsg( "Zoom in" );
1215  zoomIn();
1216  break;
1217 
1218  case Qt::Key_PageDown:
1219  QgsDebugMsg( "Zoom out" );
1220  zoomOut();
1221  break;
1222 
1223 #if 0
1224  case Qt::Key_P:
1225  mUseParallelRendering = !mUseParallelRendering;
1226  refresh();
1227  break;
1228 
1229  case Qt::Key_S:
1230  mDrawRenderingStats = !mDrawRenderingStats;
1231  refresh();
1232  break;
1233 #endif
1234 
1235  default:
1236  // Pass it on
1237  if ( mMapTool )
1238  {
1239  mMapTool->keyPressEvent( e );
1240  }
1241  else e->ignore();
1242 
1243  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1244  }
1245  }
1246 
1247  emit keyPressed( e );
1248 
1249 } //keyPressEvent()
1250 
1252 {
1253  QgsDebugMsg( "keyRelease event" );
1254 
1255  switch ( e->key() )
1256  {
1257  case Qt::Key_Space:
1258  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1259  {
1260  QgsDebugMsg( "Releasing pan selector" );
1262  mCanvasProperties->panSelectorDown = false;
1263  panActionEnd( mCanvasProperties->mouseLastXY );
1264  }
1265  break;
1266 
1267  default:
1268  // Pass it on
1269  if ( mMapTool )
1270  {
1271  mMapTool->keyReleaseEvent( e );
1272  }
1273  else e->ignore();
1274 
1275  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1276  }
1277 
1278  emit keyReleased( e );
1279 
1280 } //keyReleaseEvent()
1281 
1282 
1284 {
1285  // call handler of current map tool
1286  if ( mMapTool )
1287  {
1289  mMapTool->canvasDoubleClickEvent( me.data() );
1290  }
1291 }// mouseDoubleClickEvent
1292 
1293 
1295 {
1296  //use middle mouse button for panning, map tools won't receive any events in that case
1297  if ( e->button() == Qt::MidButton )
1298  {
1299  mCanvasProperties->panSelectorDown = true;
1300  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1301  }
1302  else
1303  {
1304 
1305  // call handler of current map tool
1306  if ( mMapTool )
1307  {
1309  mMapTool->canvasPressEvent( me.data() );
1310  }
1311  }
1312 
1313  if ( mCanvasProperties->panSelectorDown )
1314  {
1315  return;
1316  }
1317 
1318  mCanvasProperties->mouseButtonDown = true;
1319  mCanvasProperties->rubberStartPoint = e->pos();
1320 
1321 } // mousePressEvent
1322 
1323 
1325 {
1326  //use middle mouse button for panning, map tools won't receive any events in that case
1327  if ( e->button() == Qt::MidButton )
1328  {
1329  mCanvasProperties->panSelectorDown = false;
1330  panActionEnd( mCanvasProperties->mouseLastXY );
1331  }
1332  else
1333  {
1334  // call handler of current map tool
1335  if ( mMapTool )
1336  {
1337  // right button was pressed in zoom tool? return to previous non zoom tool
1338  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1339  {
1340  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1341  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1342 
1343  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1344 
1345  // change to older non-zoom tool
1346  if ( mLastNonZoomMapTool
1347  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1348  {
1349  QgsMapTool* t = mLastNonZoomMapTool;
1350  mLastNonZoomMapTool = nullptr;
1351  setMapTool( t );
1352  }
1353  return;
1354  }
1356  mMapTool->canvasReleaseEvent( me.data() );
1357  }
1358  }
1359 
1360 
1361  mCanvasProperties->mouseButtonDown = false;
1362 
1363  if ( mCanvasProperties->panSelectorDown )
1364  return;
1365 
1366 } // mouseReleaseEvent
1367 
1369 {
1371  mResizeTimer->start( 500 );
1372 
1373  QSize lastSize = viewport()->size();
1374 
1375  mSettings.setOutputSize( lastSize );
1376  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1377 
1378  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1379 
1380  moveCanvasContents( true );
1381 
1382  // notify canvas items of change
1384 
1385  updateScale();
1386 
1387  //refresh();
1388 
1389  emit extentsChanged();
1390 }
1391 
1393 {
1394  // no custom event handling anymore
1395 
1397 } // paintEvent
1398 
1400 {
1401  QList<QGraphicsItem*> list = mScene->items();
1403  while ( it != list.end() )
1404  {
1405  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1406 
1407  if ( item )
1408  {
1409  item->updatePosition();
1410  }
1411 
1412  ++it;
1413  }
1414 }
1415 
1416 
1418 {
1419  // Zoom the map canvas in response to a mouse wheel event. Moving the
1420  // wheel forward (away) from the user zooms in
1421 
1422  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1423 
1424  if ( mMapTool )
1425  {
1426  mMapTool->wheelEvent( e );
1427  }
1428 
1430  {
1431  // leave the wheel for map tools if any modifier pressed
1432  return;
1433  }
1434 
1435  switch ( mWheelAction )
1436  {
1437  case WheelZoom:
1438  // zoom without changing extent
1439  if ( e->delta() > 0 )
1440  zoomIn();
1441  else
1442  zoomOut();
1443  break;
1444 
1445  case WheelZoomAndRecenter:
1446  // zoom and don't change extent
1447  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1448  break;
1449 
1451  {
1452  // zoom map to mouse cursor
1453  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1454 
1455  QgsPoint oldCenter = center();
1456  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1457  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1458  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1459 
1460  zoomByFactor( scaleFactor, &newCenter );
1461  break;
1462  }
1463 
1464  case WheelNothing:
1465  // well, nothing!
1466  break;
1467  }
1468 }
1469 
1470 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1471 {
1472  mWheelAction = action;
1473  mWheelZoomFactor = factor;
1474 }
1475 
1477 {
1478  zoomByFactor( 1 / mWheelZoomFactor );
1479 }
1480 
1482 {
1483  zoomByFactor( mWheelZoomFactor );
1484 }
1485 
1486 void QgsMapCanvas::zoomScale( double newScale )
1487 {
1488  zoomByFactor( newScale / scale() );
1489 }
1490 
1491 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1492 {
1493  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1494 
1495  // transform the mouse pos to map coordinates
1498  r.scale( scaleFactor, &center );
1499  setExtent( r );
1500  refresh();
1501 }
1502 
1504 {
1505  mCanvasProperties->mouseLastXY = e->pos();
1506 
1507  if ( mCanvasProperties->panSelectorDown )
1508  {
1509  panAction( e );
1510  }
1511  else
1512  {
1513  // call handler of current map tool
1514  if ( mMapTool )
1515  {
1517  mMapTool->canvasMoveEvent( me.data() );
1518  }
1519  }
1520 
1521  // show x y on status bar
1522  QPoint xy = e->pos();
1524  emit xyCoordinates( coord );
1525 } // mouseMoveEvent
1526 
1527 
1528 
1531 {
1532  if ( !tool )
1533  return;
1534 
1535  if ( mMapTool )
1536  {
1537  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1538  mMapTool->deactivate();
1539  }
1540 
1541  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1542  {
1543  // if zoom or pan tool will be active, save old tool
1544  // to bring it back on right click
1545  // (but only if it wasn't also zoom or pan tool)
1546  mLastNonZoomMapTool = mMapTool;
1547  }
1548  else
1549  {
1550  mLastNonZoomMapTool = nullptr;
1551  }
1552 
1553  QgsMapTool* oldTool = mMapTool;
1554 
1555  // set new map tool and activate it
1556  mMapTool = tool;
1557  if ( mMapTool )
1558  {
1559  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1560  mMapTool->activate();
1561  }
1562 
1563  emit mapToolSet( mMapTool );
1564  emit mapToolSet( mMapTool, oldTool );
1565 } // setMapTool
1566 
1568 {
1569  if ( mMapTool && mMapTool == tool )
1570  {
1571  mMapTool->deactivate();
1572  mMapTool = nullptr;
1573  emit mapToolSet( nullptr );
1574  emit mapToolSet( nullptr, mMapTool );
1575  setCursor( Qt::ArrowCursor );
1576  }
1577 
1578  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1579  {
1580  mLastNonZoomMapTool = nullptr;
1581  }
1582 }
1583 
1585 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1586 {
1587  // background of map's pixmap
1588  mSettings.setBackgroundColor( theColor );
1589 
1590  // background of the QGraphicsView
1591  QBrush bgBrush( theColor );
1592  setBackgroundBrush( bgBrush );
1593 #if 0
1594  QPalette palette;
1595  palette.setColor( backgroundRole(), theColor );
1596  setPalette( palette );
1597 #endif
1598 
1599  // background of QGraphicsScene
1600  mScene->setBackgroundBrush( bgBrush );
1601 } // setBackgroundColor
1602 
1604 {
1605  return mScene->backgroundBrush().color();
1606 }
1607 
1609 {
1610  mSettings.setSelectionColor( color );
1611 }
1612 
1614 {
1615  return mapSettings().layers().size();
1616 } // layerCount
1617 
1618 
1620 {
1621  QList<QgsMapLayer*> lst;
1622  Q_FOREACH ( const QString& layerID, mapSettings().layers() )
1623  {
1625  if ( layer )
1626  lst.append( layer );
1627  }
1628  return lst;
1629 }
1630 
1631 
1633 {
1634  // called when a layer has changed visibility setting
1635 
1636  refresh();
1637 
1638 } // layerStateChange
1639 
1641 {
1642  // called when a layer's CRS has been changed
1643  QObject *theSender = sender();
1644  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1645  QString destAuthId = mSettings.destinationCrs().authid();
1646  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1647 
1648 } // layerCrsChange
1649 
1650 
1651 void QgsMapCanvas::freeze( bool frz )
1652 {
1653  mFrozen = frz;
1654 } // freeze
1655 
1657 {
1658  return mFrozen;
1659 } // freeze
1660 
1661 
1663 {
1665  return mMap->paintDevice();
1667 }
1668 
1670 {
1671  return mapSettings().mapUnitsPerPixel();
1672 } // mapUnitsPerPixel
1673 
1674 
1676 {
1677  if ( mSettings.mapUnits() == u )
1678  return;
1679 
1680  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1681  mSettings.setMapUnits( u );
1682 
1683  updateScale();
1684 
1685  refresh(); // this will force the scale bar to be updated
1686 
1687  emit mapUnitsChanged();
1688 }
1689 
1690 
1692 {
1693  return mapSettings().mapUnits();
1694 }
1695 
1697 {
1698  return mSettings.layerStyleOverrides();
1699 }
1700 
1702 {
1703  if ( overrides == mSettings.layerStyleOverrides() )
1704  return;
1705 
1706  mSettings.setLayerStyleOverrides( overrides );
1708 }
1709 
1710 
1711 void QgsMapCanvas::setRenderFlag( bool theFlag )
1712 {
1713  mRenderFlag = theFlag;
1714 
1715  if ( mRenderFlag )
1716  {
1717  refresh();
1718  }
1719  else
1720  stopRendering();
1721 }
1722 
1723 #if 0
1724 void QgsMapCanvas::connectNotify( const char * signal )
1725 {
1726  Q_UNUSED( signal );
1727  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1728 } //connectNotify
1729 #endif
1730 
1732 {
1733  if ( !mSettings.hasCrsTransformEnabled() )
1734  return;
1735 
1736  QString destAuthId = mSettings.destinationCrs().authid();
1737  Q_FOREACH ( const QString& layerID, mSettings.layers() )
1738  {
1740  if ( !layer )
1741  continue;
1742 
1743  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1744  if ( vl && vl->geometryType() == QGis::NoGeometry )
1745  continue;
1746 
1747  // if there are more options, ask the user which datum transform to use
1748  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1749  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1750  }
1751 }
1752 
1753 
1754 
1756 {
1757  return mMapTool;
1758 }
1759 
1761 {
1762  // move map image and other items to standard position
1763  moveCanvasContents( true ); // true means reset
1764 
1765  // use start and end box points to calculate the extent
1766  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1767  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1768 
1769  // modify the center
1770  double dx = end.x() - start.x();
1771  double dy = end.y() - start.y();
1772  QgsPoint c = center();
1773  c.set( c.x() - dx, c.y() - dy );
1774  setCenter( c );
1775 
1776  refresh();
1777 }
1778 
1780 {
1781  Q_UNUSED( e );
1782 
1783  // move all map canvas items
1785 }
1786 
1788 {
1789  QPoint pnt( 0, 0 );
1790  if ( !reset )
1791  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1792 
1793  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1794 }
1795 
1797 {
1798  Q_UNUSED( mapLayer );
1799 }
1800 
1802 {
1803  return mCanvasProperties->mouseLastXY;
1804 }
1805 
1806 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1807 {
1808  if ( !mPreviewEffect )
1809  {
1810  return;
1811  }
1812 
1813  mPreviewEffect->setEnabled( previewEnabled );
1814 }
1815 
1817 {
1818  if ( !mPreviewEffect )
1819  {
1820  return false;
1821  }
1822 
1823  return mPreviewEffect->isEnabled();
1824 }
1825 
1827 {
1828  if ( !mPreviewEffect )
1829  {
1830  return;
1831  }
1832 
1833  mPreviewEffect->setMode( mode );
1834 }
1835 
1837 {
1838  if ( !mPreviewEffect )
1839  {
1841  }
1842 
1843  return mPreviewEffect->mode();
1844 }
1845 
1847 {
1848  if ( !mSnappingUtils )
1849  {
1850  // associate a dummy instance, but better than null pointer
1851  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1852  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1853  }
1854  return mSnappingUtils;
1855 }
1856 
1858 {
1859  mSnappingUtils = utils;
1860 }
1861 
1863 {
1864  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1865  if ( nodes.count() )
1866  {
1867  QDomNode node = nodes.item( 0 );
1868 
1869  QgsMapSettings tmpSettings;
1870  tmpSettings.readXML( node );
1871  setMapUnits( tmpSettings.mapUnits() );
1873  setDestinationCrs( tmpSettings.destinationCrs() );
1874  setExtent( tmpSettings.extent() );
1875  setRotation( tmpSettings.rotation() );
1876  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1878 
1879  clearExtentHistory(); // clear the extent history on project load
1880  }
1881  else
1882  {
1883  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1884  }
1885 }
1886 
1888 {
1889  // create node "mapcanvas" and call mMapRenderer->writeXML()
1890 
1891  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1892  if ( !nl.count() )
1893  {
1894  QgsDebugMsg( "Unable to find qgis element in project file" );
1895  return;
1896  }
1897  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1898 
1899  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1900  qgisNode.appendChild( mapcanvasNode );
1901 
1902  mSettings.writeXML( mapcanvasNode, doc );
1903  // TODO: store only units, extent, projections, dest CRS
1904 }
1905 
1907 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1908 {
1909  if ( !ml )
1910  {
1911  return;
1912  }
1913 
1914  //check if default datum transformation available
1915  QSettings s;
1916  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1917  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1918  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1919  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1920  {
1921  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1922  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1923  return;
1924  }
1925 
1926  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1927  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1928 
1929  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1930  {
1931  // just use the default transform
1932  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1933  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1934  return;
1935  }
1936 
1937  //get list of datum transforms
1939  if ( dt.size() < 2 )
1940  {
1941  return;
1942  }
1943 
1944  //if several possibilities: present dialog
1945  QgsDatumTransformDialog d( ml->name(), dt );
1946  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1947  if ( d.exec() == QDialog::Accepted )
1948  {
1949  int srcTransform = -1;
1950  int destTransform = -1;
1951  QList<int> t = d.selectedDatumTransform();
1952  if ( !t.isEmpty() )
1953  {
1954  srcTransform = t.at( 0 );
1955  }
1956  if ( t.size() > 1 )
1957  {
1958  destTransform = t.at( 1 );
1959  }
1960  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1961  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1962  if ( d.rememberSelection() )
1963  {
1964  s.setValue( settingsString + "_srcTransform", srcTransform );
1965  s.setValue( settingsString + "_destTransform", destTransform );
1966  }
1967  }
1968  else
1969  {
1970  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1971  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1972  }
1973 }
1974 
1975 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1976 {
1978  r.scale( scaleFactor, center );
1979  setExtent( r );
1980  refresh();
1981 }
1982 
1984 {
1985  // Find out which layer it was that sent the signal.
1986  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1987  emit selectionChanged( layer );
1988  refresh();
1989 }
1990 
1992 {
1993  // By default graphics view delegates the drag events to graphics items.
1994  // But we do not want that and by ignoring the drag enter we let the
1995  // parent (e.g. QgisApp) to handle drops of map layers etc.
1996  e->ignore();
1997 }
1998 
1999 void QgsMapCanvas::mapToolDestroyed()
2000 {
2001  QgsDebugMsg( "maptool destroyed" );
2002  mMapTool = nullptr;
2003 }
2004 
2005 #ifdef HAVE_TOUCH
2006 bool QgsMapCanvas::event( QEvent * e )
2007 {
2008  bool done = false;
2009  if ( e->type() == QEvent::Gesture )
2010  {
2011  // call handler of current map tool
2012  if ( mMapTool )
2013  {
2014  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
2015  }
2016  }
2017  else
2018  {
2019  // pass other events to base class
2020  done = QGraphicsView::event( e );
2021  }
2022  return done;
2023 }
2024 #endif
2025 
2027 {
2028  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
2029 }
2030 
2031 void QgsMapCanvas::enableRotation( bool enable )
2032 {
2033  QSettings().setValue( "/qgis/canvasRotation", enable );
2034 }
2035 
2037 {
2038  // reload all layers in canvas
2039  for ( int i = 0; i < layerCount(); i++ )
2040  {
2041  QgsMapLayer *l = layer( i );
2042  if ( l )
2043  l->reload();
2044  }
2045 
2046  // clear the cache
2047  clearCache();
2048 
2049  // and then refresh
2050  refresh();
2051 }
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
void setInterval(int msec)
void setRequestedGeometryCacheForLayers(const QStringList &layerIds)
Set which vector layers should be cached while rendering.
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
void updateCanvasItemPositions()
called on resize or changed extent to notify canvas items to change their rectangle ...
const QgsMapSettings & mapSettings() const
Return map settings with which this job was started.
void setParallelRenderingEnabled(bool enabled)
Set whether the layers are rendered in parallel or sequentially.
static unsigned index
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
QPoint mouseLastXY
Last seen point of the mouse.
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.
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:217
virtual void canvasMoveEvent(QgsMapMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:145
bool isEmpty() const
Returns true if the geometry is empty.
int mapUpdateInterval() const
Find out how often map preview should be updated while it is being rendered (in milliseconds) ...
Type type() const
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
const QPalette & palette() const
QDomNode item(int index) const
void zoomToNextExtent()
Zoom to the next extent (view)
void zoomWithCenter(int x, int y, bool zoomIn)
Zooms in/out with a given center.
void freeze(bool frz=true)
Freeze/thaw the map canvas.
virtual void setCanvasColor(const QColor &_newVal)
Write property of QColor bgColor.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
int width() const
void enableOverviewMode(QgsMapOverviewCanvas *overview)
QList< QgsMapLayer * > layers() const
return list of layers within map canvas.
QgsMapCanvas(QWidget *parent=nullptr, const char *name=nullptr)
Constructor.
int x() const
int y() const
bool end()
void setCursor(const QCursor &)
Q_DECL_DEPRECATED bool isDirty() const
Return the state of the canvas (dirty or not)
Qt::KeyboardModifiers keyboardModifiers()
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Setter for stored overrides of styles for layers.
A widget that displays an overview map.
QDomNode appendChild(const QDomNode &newChild)
double rotation() const
Return the rotation of the resulting map image Units are clockwise degrees.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void clearExtentHistory()
void setColor(ColorGroup group, ColorRole role, const QColor &color)
void readXML(QDomNode &theNode)
void push_back(const T &value)
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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QList< QGraphicsItem * > items() const
void stopRendering()
stop rendering (if there is any right now)
void setFocusPolicy(Qt::FocusPolicy policy)
bool save(const QString &fileName, const char *format, int quality) const
QObject * sender() const
const QFont & font() const
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from layer&#39;s CRS to output CRS
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
double rotation() const
Get the current map canvas rotation in clockwise degrees.
QgsPreviewEffect::PreviewMode previewMode() const
Returns the current preview mode for the map canvas.
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.
void zoomToFeatureExtent(QgsRectangle &rect)
Zooms to feature extent.
const T & at(int i) const
virtual void reload()
Synchronises with changes in the datasource.
Definition: qgsmaplayer.h:236
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
void setBackgroundBrush(const QBrush &brush)
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
void removeAt(int i)
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:415
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 hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
int y() const
QgsPoint toMapPoint(double x, double y) const
int layerCount() const
return number of layers on the map
const QgsDatumTransformStore & datumTransformStore() const
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
QGis::UnitType mapUnits() const
Get units of map&#39;s geographical coordinates - used for scale calculation.
void setSceneRect(const QRectF &rect)
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QgsPoint toMapCoordinates(int x, int y) const
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.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
QWidget * viewport() const
void renderComplete(QPainter *)
Emitted when the canvas has rendered.
void setSceneRect(const QRectF &rect)
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 QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
bool isCachingEnabled() const
Check whether images of rendered layers are curerently being cached.
QString join(const QString &separator) const
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Set map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
QgsMapTool * mapTool()
Returns the currently active tool.
bool isAutoRepeat() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void setLayerSet(const QStringList &layers)
change current layer set
A non GUI class for rendering a map layer set onto a QPainter.
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
QImage contentImage() const
void setEnabled(bool enable)
QString tr(const char *sourceText, const char *disambiguation, int n)
virtual QImage renderedImage()=0
Get a preview/resulting image.
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
int x() const
int y() const
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...
virtual void canvasPressEvent(QgsMapMouseEvent *e)
Mouse press event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:155
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
int size() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:136
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
QString what() const
Definition: qgsexception.h:36
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)
Deprecated to be deleted, stuff from here should be moved elsewhere.
void hasCrsTransformEnabledChanged(bool flag)
Emitted when on-the-fly projection has been turned on/off.
void setBold(bool enable)
void setMapTool(QgsMapTool *mapTool)
Sets the map tool currently being used on the canvas.
void enableAntiAliasing(bool flag)
virtual void activate()
called when set as currently active map tool
Definition: qgsmaptool.cpp:83
void setValue(const QString &key, const QVariant &value)
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QgsMapRenderer * mRenderer
Definition: qgsmapcanvas.h:791
void drawRect(const QRectF &rectangle)
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:175
const char * name() const
QTransform transform() const
void setFont(const QFont &font)
int count() const
QString number(int n, int base)
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
void append(const T &value)
void setOutputSize(QSize size)
Set the size of the resulting map image.
Q_DECL_DEPRECATED void showError(QgsMapLayer *mapLayer)
bool save(const QString &fileName, const char *format, int quality) const
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
A rectangular graphics item representing the map on the canvas.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
void ignore()
void saveAsImage(const QString &theFileName, QPixmap *QPixmap=nullptr, const QString &="PNG")
Save the convtents of the map canvas to disk as an image.
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.
int toInt(bool *ok) const
int x() const
double scale()
Get the last reported scale of the canvas.
void rotationChanged(double)
Emitted when the rotation of the map changes.
void setInteractive(bool allowed)
void zoomNextStatusChanged(bool)
Emitted when zoom next status changed.
bool isEmpty() const
test if rectangle is empty.
void setRotation(double degrees)
Set the rotation of the resulting map image Units are clockwise degrees.
virtual bool event(QEvent *event)
void setPen(const QColor &color)
void clearCache()
Make sure to remove any rendered images from cache (does nothing if cache is not enabled) ...
int width() const
void layerCrsChange()
This slot is connected to the layer&#39;s CRS change.
void setBackgroundBrush(const QBrush &brush)
double scale() const
Return the calculated scale of the map.
QGis::UnitType mapUnits() const
Get the current canvas map units.
void setMapUnits(QGis::UnitType u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
Qt::MouseButton button() const
Job implementation that renders all layers in parallel.
QPalette::ColorRole backgroundRole() const
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
QString qgsDoubleToString(double a, int precision=17)
Definition: qgis.h:274
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QDomNodeList elementsByTagName(const QString &tagname) const
void setMapUpdateInterval(int timeMilliseconds)
Set how often map preview should be updated while it is being rendered (in milliseconds) ...
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:790
void setObjectName(const QString &name)
void keyReleased(QKeyEvent *e)
Emit key release event.
Q_DECL_DEPRECATED QPaintDevice & paintDevice()
bool isEmpty() const
virtual void waitForFinished()=0
Block until the job has finished.
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Enable anti-aliasing for map rendering.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
void setMapUnits(QGis::UnitType u)
void getDatumTransformInfo(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId)
ask user about datum transformation
#define M_PI
void enableMapTileRendering(bool theFlag)
sets map tile rendering flag
Q_DECL_DEPRECATED QPaintDevice & canvasPaintDevice()
Accessor for the canvas paint device.
void mouseDoubleClickEvent(QMouseEvent *e) override
Overridden mouse double click event.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
static bool rotationEnabled()
return if canvas rotation is enabled
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setOverrideCursor(const QCursor &cursor)
void panToSelected(QgsVectorLayer *layer=nullptr)
Pan to the selected features of current (vector) layer keeping same extent.
QList< int > QgsAttributeList
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
void setBrush(const QBrush &brush)
void setScene(QGraphicsScene *scene)
void drawText(const QPointF &position, const QString &text)
void restoreOverrideCursor()
void messageEmitted(const QString &title, const QString &message, QgsMessageBar::MessageLevel=QgsMessageBar::INFO)
emit a message (usually to be displayed in a message bar)
void destinationCrsChanged()
Emitted when map CRS has changed.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void updateDatumTransformEntries()
Make sure the datum transform store is properly populated.
void setRenderFlag(bool theFlag)
Whether to suppress rendering or not.
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
void deleteLater()
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:99
virtual bool isEditTool()
Check whether this MapTool performs an edit operation.
Definition: qgsmaptool.cpp:197
int count() const
Single scope for storing variables and functions for use within a QgsExpressionContext.
double mapUnitsPerPixel() const
Return current map units per pixel.
Q_DECL_DEPRECATED QgsMapCanvasMap * map()
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
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:165
void refresh()
renders overview and updates panning widget
void set(double x, double y)
Sets the x and y value of the point.
Definition: qgspoint.h:119
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:65
const QgsMapToPixel & mapToPixel() const
QgsRectangle extent() const
returns current extent
QRect rect() const
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.
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.
T * data() const
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.
virtual void connectNotify(const char *signal)
iterator end()
QByteArray toLocal8Bit() const
int key() const
void setRotation(double degrees)
sets rotation value in clockwise degrees
QScopedPointer< CanvasProperties > mCanvasProperties
Handle pattern for implementation object.
Definition: qgsmapcanvas.h:651
void zoomToSelected(QgsVectorLayer *layer=nullptr)
Zoom to the extent of the selected features of current (vector) layer.
A class to represent a vector.
Definition: qgspoint.h:32
PreviewMode mode() const
Returns the mode used for the preview effect.
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)
QMap< QString, QString > layerStyleOverrides() const
Getter for stored overrides of styles for layers.
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 stop()
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:170
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
virtual QColor canvasColor() const
Read property of QColor bgColor.
int delta() const
void clear()
invalidate the cache contents
Abstract base class for all map tools.
Definition: qgsmaptool.h:50
void selectionChangedSlot()
Receives signal about selection change, and pass it on with layer info.
virtual void paintEvent(QPaintEvent *event)
Draw map such that there are no problems between adjacent tiles.
Job implementation that renders everything sequentially in one thread.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:416
bool isVisible() const
Definition: qgsmapcanvas.h:83
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QGis::UnitType mapUnits() const
QVariant value(const QString &key, const QVariant &defaultValue) const
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
QStringList layerSet() const
QString name() const
Get the display name of the layer.
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
bool isInOverview() const
Definition: qgsmapcanvas.h:84
void zoomToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids)
Set canvas extent to the bounding box of a set of features.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
void setSelectionColor(const QColor &color)
Set color that is used for drawing of selected vector features.
void layerStyleOverridesChanged()
Emitted when the configuration of overridden layer styles changes.
virtual void canvasDoubleClickEvent(QgsMapMouseEvent *e)
Mouse double click event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:150
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
bool hasEntryForLayer(QgsMapLayer *layer) const
void dragEnterEvent(QDragEnterEvent *e) override
Overridden drag enter event.
QFontMetrics fontMetrics() const
void writeProject(QDomDocument &)
called to write map canvas settings to project
void panAction(QMouseEvent *event)
Called when mouse is moving and pan is activated.
QgsRectangle fullExtent() const
returns current extent of layer set
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:381
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
Class for storing a coordinate reference system (CRS)
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
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...
const QgsLabelingResults * labelingResults() const
Get access to the labeling results (may be null)
int height() const
QgsMapCanvasRendererSync(QgsMapCanvas *canvas, QgsMapRenderer *renderer)
int height() const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setGraphicsEffect(QGraphicsEffect *effect)
void refreshAllLayers()
Reload all layers, clear the cache and refresh the canvas.
void zoomScale(double scale)
Zoom to a specific scale.
Class for doing transforms between two map coordinate systems.
bool toBool() const
void setMouseTracking(bool enable)
UnitType
Map units that qgis supports.
Definition: qgis.h:155
char * data()
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
bool isFrozen()
Accessor for frozen status of canvas.
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:192
QString completeBaseName() const
void setCenter(const QgsPoint &center)
Set the center of the map canvas, in geographical coordinates.
void start(int msec)
bool isValid() const
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
void enableAntiAliasing(bool theFlag)
used to determine if anti-aliasing is enabled or not
int height() const
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
void setSelectionColor(const QColor &color)
Set color of selected vector features.
void paintEvent(QPaintEvent *e) override
Overridden paint event.
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.
This class is responsible for keeping cache of rendered images of individual layers.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
void setMapUnits(QGis::UnitType mapUnits)
Set map units (needed by project properties dialog)
Custom exception class for Coordinate Reference System related exceptions.
const QPoint & pos() const
void updateOverview()
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
Q_DECL_DEPRECATED void setDirty(bool _dirty)
Flag the canvas as dirty and needed a refresh.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
QPoint rubberStartPoint
Beginning point of a rubber band.
Class that does synchronization between QgsMapCanvas and its associated QgsMapRenderer: ...
Definition: qgsmapcanvas.h:763
QgsSnappingUtils * snappingUtils() const
Return snapping utility class that is associated with map canvas.
QString absolutePath() const
virtual QgsLabelingResults * takeLabelingResults()=0
Get pointer to internal labeling engine (in order to get access to the results)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void zoomIn()
Zoom in with fixed factor.
QObject * parent() const
int outputDpi() const
Return DPI used for conversion between real world units (e.g.
virtual void waitForFinished() override
Block until the job has finished.
Represents a vector layer which manages a vector based data sets.
bool begin(QPaintDevice *device)
virtual void updatePosition()
called on changed extent or resize event to update position of the item
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
int selectedFeatureCount()
The number of features that are selected in this layer.
QgsPoint center() const
Get map center, in geographical coordinates.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:91
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:86
void extentsChanged()
Emitted when the extents of the map change.
iterator begin()
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void destroyed(QObject *obj)
QgsMapLayer * layer(int index)
return the map layer at position index in the layer stack
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
double x() const
Get the x value of the point.
Definition: qgspoint.h:128
virtual bool isActive() const =0
Tell whether the rendering job is currently running in background.
Q_DECL_DEPRECATED void updateMap()
void zoomByFactor(double scaleFactor, const QgsPoint *center=nullptr)
Zoom with the factor supplied.
double rotation() const
returns current rotation in clockwise degrees
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
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()
Emitted when map units are changed.
bool previewModeEnabled() const
Returns whether a preview mode is enabled for the map canvas.
void grabGesture(Qt::GestureType gesture, QFlags< Qt::GestureFlag > flags)
void layersChanged()
Emitted when a new set of layers has been received.
void setSingleShot(bool singleShot)
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
void writeXML(QDomNode &theNode, QDomDocument &theDoc)
void mapToolSet(QgsMapTool *tool)
Emit map tool changed event.
virtual void resizeEvent(QResizeEvent *event)
virtual void canvasReleaseEvent(QgsMapMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:160