QGIS API Documentation  2.13.0-Master
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  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
536  }
537  }
538  if ( !rect.isEmpty() )
539  {
540  setExtent( rect );
541  }
542 
543  QgsDebugMsg( "refreshing after destination CRS changed" );
544  refresh();
545  }
546 
547  mSettings.setDestinationCrs( crs );
548 
550 
551  emit destinationCrsChanged();
552 }
553 
555 {
556  return mLabelingResults;
557 }
558 
560 {
561  if ( enabled == isCachingEnabled() )
562  return;
563 
564  if ( mJob && mJob->isActive() )
565  {
566  // wait for the current rendering to finish, before touching the cache
567  mJob->waitForFinished();
568  }
569 
570  if ( enabled )
571  {
572  mCache = new QgsMapRendererCache;
573  }
574  else
575  {
576  delete mCache;
577  mCache = nullptr;
578  }
579 }
580 
582 {
583  return nullptr != mCache;
584 }
585 
587 {
588  if ( mCache )
589  mCache->clear();
590 }
591 
593 {
594  mUseParallelRendering = enabled;
595 }
596 
598 {
599  return mUseParallelRendering;
600 }
601 
602 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
603 {
604  mMapUpdateTimer.setInterval( timeMiliseconds );
605 }
606 
608 {
609  return mMapUpdateTimer.interval();
610 }
611 
612 
614 {
615  // redraw overview
616  if ( mMapOverview )
617  {
618  mMapOverview->refresh();
619  }
620 }
621 
622 
624 {
625  return mCurrentLayer;
626 }
627 
628 
630 {
631  if ( !mSettings.hasValidSettings() )
632  {
633  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
634  return;
635  }
636 
637  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
638  {
639  QgsDebugMsg( "CANVAS render flag off" );
640  return;
641  }
642 
643  if ( mRefreshScheduled )
644  {
645  QgsDebugMsg( "CANVAS refresh already scheduled" );
646  return;
647  }
648 
649  mRefreshScheduled = true;
650 
651  QgsDebugMsg( "CANVAS refresh scheduling" );
652 
653  // schedule a refresh
654  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
655 } // refresh
656 
657 void QgsMapCanvas::refreshMap()
658 {
659  Q_ASSERT( mRefreshScheduled );
660 
661  QgsDebugMsg( "CANVAS refresh!" );
662 
663  stopRendering(); // if any...
664 
665  // from now on we can accept refresh requests again
666  mRefreshScheduled = false;
667 
668  //build the expression context
669  QgsExpressionContext expressionContext;
670  expressionContext << QgsExpressionContextUtils::globalScope()
673  << new QgsExpressionContextScope( mExpressionContextScope );
674 
675  mSettings.setExpressionContext( expressionContext );
676 
677  // create the renderer job
678  Q_ASSERT( !mJob );
679  mJobCancelled = false;
680  if ( mUseParallelRendering )
681  mJob = new QgsMapRendererParallelJob( mSettings );
682  else
683  mJob = new QgsMapRendererSequentialJob( mSettings );
684  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
685  mJob->setCache( mCache );
686 
687  QStringList layersForGeometryCache;
688  Q_FOREACH ( const QString& id, mSettings.layers() )
689  {
690  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
691  {
692  if ( vl->isEditable() )
693  layersForGeometryCache << id;
694  }
695  }
696  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
697 
698  mJob->start();
699 
700  mMapUpdateTimer.start();
701 
702  emit renderStarting();
703 }
704 
705 
706 void QgsMapCanvas::rendererJobFinished()
707 {
708  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
709 
710  mMapUpdateTimer.stop();
711 
712  // TODO: would be better to show the errors in message bar
713  Q_FOREACH ( const QgsMapRendererJob::Error& error, mJob->errors() )
714  {
715  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
716  }
717 
718  if ( !mJobCancelled )
719  {
720  // take labeling results before emitting renderComplete, so labeling map tools
721  // connected to signal work with correct results
722  delete mLabelingResults;
723  mLabelingResults = mJob->takeLabelingResults();
724 
725  QImage img = mJob->renderedImage();
726 
727  // emit renderComplete to get our decorations drawn
728  QPainter p( &img );
729  emit renderComplete( &p );
730 
731  QSettings settings;
732  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
733  {
734  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
735  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
736  }
737 
738  if ( mDrawRenderingStats )
739  {
740  int w = img.width(), h = img.height();
741  QFont fnt = p.font();
742  fnt.setBold( true );
743  p.setFont( fnt );
744  int lh = p.fontMetrics().height() * 2;
745  QRect r( 0, h - lh, w, lh );
746  p.setPen( Qt::NoPen );
747  p.setBrush( QColor( 0, 0, 0, 110 ) );
748  p.drawRect( r );
749  p.setPen( Qt::white );
750  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
751  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
752  }
753 
754  p.end();
755 
756  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
757  }
758 
759  // now we are in a slot called from mJob - do not delete it immediately
760  // so the class is still valid when the execution returns to the class
761  mJob->deleteLater();
762  mJob = nullptr;
763 
764  emit mapCanvasRefreshed();
765 }
766 
767 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
768 {
769  // This is a hack to pass QgsMapCanvasItem::setRect what it
770  // expects (encoding of position and size of the item)
771  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
772  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
773  double res = m2p.mapUnitsPerPixel();
774  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
775  return rect;
776 }
777 
778 void QgsMapCanvas::mapUpdateTimeout()
779 {
780  const QImage& img = mJob->renderedImage();
781  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
782 }
783 
785 {
786  if ( mJob )
787  {
788  QgsDebugMsg( "CANVAS stop rendering!" );
789  mJobCancelled = true;
790  mJob->cancel();
791  Q_ASSERT( !mJob ); // no need to delete here: already deleted in finished()
792  }
793 }
794 
796 {
797 }
798 
799 //the format defaults to "PNG" if not specified
800 void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat )
801 {
802  //
803  //check if the optional QPaintDevice was supplied
804  //
805  if ( theQPixmap )
806  {
807  // render
808  QPainter painter;
809  painter.begin( theQPixmap );
810  QgsMapRendererCustomPainterJob job( mSettings, &painter );
811  job.start();
812  job.waitForFinished();
813  emit renderComplete( &painter );
814  painter.end();
815 
816  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
817  }
818  else //use the map view
819  {
820  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
821  }
822  //create a world file to go with the image...
824  QString myHeader;
825  // note: use 17 places of precision for all numbers output
826  //Pixel XDim
827  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
828  //Rotation on y axis - hard coded
829  myHeader += "0 \r\n";
830  //Rotation on x axis - hard coded
831  myHeader += "0 \r\n";
832  //Pixel YDim - almost always negative - see
833  //http://en.wikipedia.org/wiki/World_file#cite_note-2
834  myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
835  //Origin X (center of top left cell)
836  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
837  //Origin Y (center of top left cell)
838  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
839  QFileInfo myInfo = QFileInfo( theFileName );
840  // allow dotted names
841  QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.completeBaseName() + '.' + theFormat + 'w';
842  QFile myWorldFile( myWorldFileName );
843  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
844  {
845  return;
846  }
847  QTextStream myStream( &myWorldFile );
848  myStream << myHeader;
849 } // saveAsImage
850 
851 
852 
854 {
855  return mapSettings().visibleExtent();
856 } // extent
857 
859 {
860  return mapSettings().fullExtent();
861 } // extent
862 
863 
865 {
866  QgsRectangle current = extent();
867 
868  if ( r == current )
869  return;
870 
871  if ( r.isEmpty() )
872  {
873  if ( !mSettings.hasValidSettings() )
874  {
875  // we can't even just move the map center
876  QgsDebugMsg( "Empty extent - ignoring" );
877  return;
878  }
879 
880  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
881  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
882  setCenter( r.center() );
883  }
884  else
885  {
886  mSettings.setExtent( r );
887  }
888  emit extentsChanged();
889  updateScale();
890  if ( mLastExtent.size() > 20 )
891  mLastExtent.removeAt( 0 );
892 
893  //clear all extent items after current index
894  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
895  {
896  mLastExtent.removeAt( i );
897  }
898 
899  mLastExtent.append( extent() );
900 
901  // adjust history to no more than 20
902  if ( mLastExtent.size() > 20 )
903  {
904  mLastExtent.removeAt( 0 );
905  }
906 
907  // the last item is the current extent
908  mLastExtentIndex = mLastExtent.size() - 1;
909 
910  // update controls' enabled state
911  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
912  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
913  // notify canvas items of change
915 
916 } // setExtent
917 
919 {
921  double x = center.x();
922  double y = center.y();
923  setExtent(
924  QgsRectangle(
925  x - r.width() / 2.0, y - r.height() / 2.0,
926  x + r.width() / 2.0, y + r.height() / 2.0
927  )
928  );
929 } // setCenter
930 
932 {
934  return r.center();
935 }
936 
937 
939 {
940  return mapSettings().rotation();
941 } // rotation
942 
943 void QgsMapCanvas::setRotation( double degrees )
944 {
945  if ( !rotationEnabled() )
946  return;
947 
948  double current = rotation();
949 
950  if ( degrees == current )
951  return;
952 
953  mSettings.setRotation( degrees );
954  emit rotationChanged( degrees );
955  emit extentsChanged(); // visible extent changes with rotation
956 
957  // notify canvas items of change (needed?)
959 
960 } // setRotation
961 
962 
964 {
965  emit scaleChanged( mapSettings().scale() );
966 }
967 
968 
970 {
971  refresh();
972 } // clear
973 
974 
975 
977 {
979  // If the full extent is an empty set, don't do the zoom
980  if ( !extent.isEmpty() )
981  {
982  // Add a 5% margin around the full extent
983  extent.scale( 1.05 );
984  setExtent( extent );
985  }
986  refresh();
987 
988 } // zoomToFullExtent
989 
990 
991 
993 {
994  if ( mLastExtentIndex > 0 )
995  {
996  mLastExtentIndex--;
997  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
998  emit extentsChanged();
999  updateScale();
1000  refresh();
1001  // update controls' enabled state
1002  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1003  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1004  // notify canvas items of change
1006  }
1007 
1008 } // zoomToPreviousExtent
1009 
1011 {
1012  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1013  {
1014  mLastExtentIndex++;
1015  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1016  emit extentsChanged();
1017  updateScale();
1018  refresh();
1019  // update controls' enabled state
1020  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1021  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1022  // notify canvas items of change
1024  }
1025 }// zoomToNextExtent
1026 
1028 {
1029  mLastExtent.clear(); // clear the zoom history list
1030  mLastExtent.append( extent() ) ; // set the current extent in the list
1031  mLastExtentIndex = mLastExtent.size() - 1;
1032  // update controls' enabled state
1033  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1034  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1035 }// clearExtentHistory
1036 
1037 
1039 {
1041 }
1042 
1044 {
1045  if ( !layer )
1046  {
1047  // use current layer by default
1048  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1049  }
1050 
1051  if ( !layer || layer->selectedFeatureCount() == 0 )
1052  return;
1053 
1055  zoomToFeatureExtent( rect );
1056 } // zoomToSelected
1057 
1059 {
1060  // no selected features, only one selected point feature
1061  //or two point features with the same x- or y-coordinates
1062  if ( rect.isEmpty() )
1063  {
1064  // zoom in
1065  QgsPoint c = rect.center();
1066  rect = extent();
1067  rect.scale( 1.0, &c );
1068  }
1069  //zoom to an area
1070  else
1071  {
1072  // Expand rect to give a bit of space around the selected
1073  // objects so as to keep them clear of the map boundaries
1074  // The same 5% should apply to all margins.
1075  rect.scale( 1.05 );
1076  }
1077 
1078  setExtent( rect );
1079  refresh();
1080 }
1081 
1083 {
1084  if ( !layer )
1085  {
1086  return;
1087  }
1088 
1089  QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFids( ids ).setSubsetOfAttributes( QgsAttributeList() ) );
1091  rect.setMinimal();
1092  QgsFeature fet;
1093  int featureCount = 0;
1094  while ( it.nextFeature( fet ) )
1095  {
1096  const QgsGeometry* geom = fet.constGeometry();
1097  QString errorMessage;
1098  if ( !geom || geom->isEmpty() )
1099  {
1100  errorMessage = tr( "Feature does not have a geometry" );
1101  }
1102  else if ( geom->geometry()->isEmpty() )
1103  {
1104  errorMessage = tr( "Feature geometry is empty" );
1105  }
1106  if ( !errorMessage.isEmpty() )
1107  {
1108  emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1109  return;
1110  }
1112  rect.combineExtentWith( &r );
1113  featureCount++;
1114  }
1115 
1116  if ( featureCount != ids.count() )
1117  {
1118  return;
1119  }
1120 
1121  zoomToFeatureExtent( rect );
1122 }
1123 
1125 {
1126  if ( !layer )
1127  {
1128  // use current layer by default
1129  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1130  }
1131 
1132  if ( !layer || layer->selectedFeatureCount() == 0 )
1133  return;
1134 
1136  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1137  refresh();
1138 } // panToSelected
1139 
1141 {
1142  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1143  {
1144  emit keyPressed( e );
1145  return;
1146  }
1147 
1148  QPainter paint;
1149  QPen pen( Qt::gray );
1150  QgsPoint ll, ur;
1151 
1152  if ( ! mCanvasProperties->mouseButtonDown )
1153  {
1154  // Don't want to interfer with mouse events
1155 
1156  QgsRectangle currentExtent = mapSettings().visibleExtent();
1157  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
1158  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
1159 
1160  switch ( e->key() )
1161  {
1162  case Qt::Key_Left:
1163  QgsDebugMsg( "Pan left" );
1164 
1165  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
1166  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
1167  setExtent( currentExtent );
1168  refresh();
1169  break;
1170 
1171  case Qt::Key_Right:
1172  QgsDebugMsg( "Pan right" );
1173 
1174  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
1175  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
1176  setExtent( currentExtent );
1177  refresh();
1178  break;
1179 
1180  case Qt::Key_Up:
1181  QgsDebugMsg( "Pan up" );
1182 
1183  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
1184  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
1185  setExtent( currentExtent );
1186  refresh();
1187  break;
1188 
1189  case Qt::Key_Down:
1190  QgsDebugMsg( "Pan down" );
1191 
1192  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
1193  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
1194  setExtent( currentExtent );
1195  refresh();
1196  break;
1197 
1198 
1199 
1200  case Qt::Key_Space:
1201  QgsDebugMsg( "Pressing pan selector" );
1202 
1203  //mCanvasProperties->dragging = true;
1204  if ( ! e->isAutoRepeat() )
1205  {
1206  mCanvasProperties->panSelectorDown = true;
1207  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1208  }
1209  break;
1210 
1211  case Qt::Key_PageUp:
1212  QgsDebugMsg( "Zoom in" );
1213  zoomIn();
1214  break;
1215 
1216  case Qt::Key_PageDown:
1217  QgsDebugMsg( "Zoom out" );
1218  zoomOut();
1219  break;
1220 
1221 #if 0
1222  case Qt::Key_P:
1223  mUseParallelRendering = !mUseParallelRendering;
1224  refresh();
1225  break;
1226 
1227  case Qt::Key_S:
1228  mDrawRenderingStats = !mDrawRenderingStats;
1229  refresh();
1230  break;
1231 #endif
1232 
1233  default:
1234  // Pass it on
1235  if ( mMapTool )
1236  {
1237  mMapTool->keyPressEvent( e );
1238  }
1239  else e->ignore();
1240 
1241  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1242  }
1243  }
1244 
1245  emit keyPressed( e );
1246 
1247 } //keyPressEvent()
1248 
1250 {
1251  QgsDebugMsg( "keyRelease event" );
1252 
1253  switch ( e->key() )
1254  {
1255  case Qt::Key_Space:
1256  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1257  {
1258  QgsDebugMsg( "Releasing pan selector" );
1259 
1260  mCanvasProperties->panSelectorDown = false;
1261  panActionEnd( mCanvasProperties->mouseLastXY );
1262  }
1263  break;
1264 
1265  default:
1266  // Pass it on
1267  if ( mMapTool )
1268  {
1269  mMapTool->keyReleaseEvent( e );
1270  }
1271  else e->ignore();
1272 
1273  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1274  }
1275 
1276  emit keyReleased( e );
1277 
1278 } //keyReleaseEvent()
1279 
1280 
1282 {
1283  // call handler of current map tool
1284  if ( mMapTool )
1285  {
1287  mMapTool->canvasDoubleClickEvent( me.data() );
1288  }
1289 }// mouseDoubleClickEvent
1290 
1291 
1293 {
1294  //use middle mouse button for panning, map tools won't receive any events in that case
1295  if ( e->button() == Qt::MidButton )
1296  {
1297  mCanvasProperties->panSelectorDown = true;
1298  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1299  }
1300  else
1301  {
1302 
1303  // call handler of current map tool
1304  if ( mMapTool )
1305  {
1307  mMapTool->canvasPressEvent( me.data() );
1308  }
1309  }
1310 
1311  if ( mCanvasProperties->panSelectorDown )
1312  {
1313  return;
1314  }
1315 
1316  mCanvasProperties->mouseButtonDown = true;
1317  mCanvasProperties->rubberStartPoint = e->pos();
1318 
1319 } // mousePressEvent
1320 
1321 
1323 {
1324  //use middle mouse button for panning, map tools won't receive any events in that case
1325  if ( e->button() == Qt::MidButton )
1326  {
1327  mCanvasProperties->panSelectorDown = false;
1328  panActionEnd( mCanvasProperties->mouseLastXY );
1329  }
1330  else
1331  {
1332  // call handler of current map tool
1333  if ( mMapTool )
1334  {
1335  // right button was pressed in zoom tool? return to previous non zoom tool
1336  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1337  {
1338  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1339  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1340 
1341  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1342 
1343  // change to older non-zoom tool
1344  if ( mLastNonZoomMapTool
1345  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1346  {
1347  QgsMapTool* t = mLastNonZoomMapTool;
1348  mLastNonZoomMapTool = nullptr;
1349  setMapTool( t );
1350  }
1351  return;
1352  }
1354  mMapTool->canvasReleaseEvent( me.data() );
1355  }
1356  }
1357 
1358 
1359  mCanvasProperties->mouseButtonDown = false;
1360 
1361  if ( mCanvasProperties->panSelectorDown )
1362  return;
1363 
1364 } // mouseReleaseEvent
1365 
1367 {
1369  mResizeTimer->start( 500 );
1370 
1371  QSize lastSize = viewport()->size();
1372 
1373  mSettings.setOutputSize( lastSize );
1374  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1375 
1376  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1377 
1378  moveCanvasContents( true );
1379 
1380  // notify canvas items of change
1382 
1383  updateScale();
1384 
1385  //refresh();
1386 
1387  emit extentsChanged();
1388 }
1389 
1391 {
1392  // no custom event handling anymore
1393 
1395 } // paintEvent
1396 
1398 {
1399  QList<QGraphicsItem*> list = mScene->items();
1401  while ( it != list.end() )
1402  {
1403  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1404 
1405  if ( item )
1406  {
1407  item->updatePosition();
1408  }
1409 
1410  ++it;
1411  }
1412 }
1413 
1414 
1416 {
1417  // Zoom the map canvas in response to a mouse wheel event. Moving the
1418  // wheel forward (away) from the user zooms in
1419 
1420  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1421 
1422  if ( mMapTool )
1423  {
1424  mMapTool->wheelEvent( e );
1425  }
1426 
1428  {
1429  // leave the wheel for map tools if any modifier pressed
1430  return;
1431  }
1432 
1433  switch ( mWheelAction )
1434  {
1435  case WheelZoom:
1436  // zoom without changing extent
1437  if ( e->delta() > 0 )
1438  zoomIn();
1439  else
1440  zoomOut();
1441  break;
1442 
1443  case WheelZoomAndRecenter:
1444  // zoom and don't change extent
1445  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1446  break;
1447 
1449  {
1450  // zoom map to mouse cursor
1451  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1452 
1453  QgsPoint oldCenter = center();
1454  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1455  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1456  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1457 
1458  zoomByFactor( scaleFactor, &newCenter );
1459  break;
1460  }
1461 
1462  case WheelNothing:
1463  // well, nothing!
1464  break;
1465  }
1466 }
1467 
1468 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1469 {
1470  mWheelAction = action;
1471  mWheelZoomFactor = factor;
1472 }
1473 
1475 {
1476  zoomByFactor( 1 / mWheelZoomFactor );
1477 }
1478 
1480 {
1481  zoomByFactor( mWheelZoomFactor );
1482 }
1483 
1484 void QgsMapCanvas::zoomScale( double newScale )
1485 {
1486  zoomByFactor( newScale / scale() );
1487 }
1488 
1489 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1490 {
1491  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1492 
1493  // transform the mouse pos to map coordinates
1496  r.scale( scaleFactor, &center );
1497  setExtent( r );
1498  refresh();
1499 }
1500 
1502 {
1503  mCanvasProperties->mouseLastXY = e->pos();
1504 
1505  if ( mCanvasProperties->panSelectorDown )
1506  {
1507  panAction( e );
1508  }
1509  else
1510  {
1511  // call handler of current map tool
1512  if ( mMapTool )
1513  {
1515  mMapTool->canvasMoveEvent( me.data() );
1516  }
1517  }
1518 
1519  // show x y on status bar
1520  QPoint xy = e->pos();
1522  emit xyCoordinates( coord );
1523 } // mouseMoveEvent
1524 
1525 
1526 
1529 {
1530  if ( !tool )
1531  return;
1532 
1533  if ( mMapTool )
1534  {
1535  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1536  mMapTool->deactivate();
1537  }
1538 
1539  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1540  {
1541  // if zoom or pan tool will be active, save old tool
1542  // to bring it back on right click
1543  // (but only if it wasn't also zoom or pan tool)
1544  mLastNonZoomMapTool = mMapTool;
1545  }
1546  else
1547  {
1548  mLastNonZoomMapTool = nullptr;
1549  }
1550 
1551  QgsMapTool* oldTool = mMapTool;
1552 
1553  // set new map tool and activate it
1554  mMapTool = tool;
1555  if ( mMapTool )
1556  {
1557  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1558  mMapTool->activate();
1559  }
1560 
1561  emit mapToolSet( mMapTool );
1562  emit mapToolSet( mMapTool, oldTool );
1563 } // setMapTool
1564 
1566 {
1567  if ( mMapTool && mMapTool == tool )
1568  {
1569  mMapTool->deactivate();
1570  mMapTool = nullptr;
1571  emit mapToolSet( nullptr );
1572  emit mapToolSet( nullptr, mMapTool );
1573  setCursor( Qt::ArrowCursor );
1574  }
1575 
1576  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1577  {
1578  mLastNonZoomMapTool = nullptr;
1579  }
1580 }
1581 
1583 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1584 {
1585  // background of map's pixmap
1586  mSettings.setBackgroundColor( theColor );
1587 
1588  // background of the QGraphicsView
1589  QBrush bgBrush( theColor );
1590  setBackgroundBrush( bgBrush );
1591 #if 0
1592  QPalette palette;
1593  palette.setColor( backgroundRole(), theColor );
1594  setPalette( palette );
1595 #endif
1596 
1597  // background of QGraphicsScene
1598  mScene->setBackgroundBrush( bgBrush );
1599 } // setBackgroundColor
1600 
1602 {
1603  return mScene->backgroundBrush().color();
1604 }
1605 
1607 {
1608  mSettings.setSelectionColor( color );
1609 }
1610 
1612 {
1613  return mapSettings().layers().size();
1614 } // layerCount
1615 
1616 
1618 {
1619  QList<QgsMapLayer*> lst;
1620  Q_FOREACH ( const QString& layerID, mapSettings().layers() )
1621  {
1623  if ( layer )
1624  lst.append( layer );
1625  }
1626  return lst;
1627 }
1628 
1629 
1631 {
1632  // called when a layer has changed visibility setting
1633 
1634  refresh();
1635 
1636 } // layerStateChange
1637 
1639 {
1640  // called when a layer's CRS has been changed
1641  QObject *theSender = sender();
1642  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1643  QString destAuthId = mSettings.destinationCrs().authid();
1644  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1645 
1646 } // layerCrsChange
1647 
1648 
1649 void QgsMapCanvas::freeze( bool frz )
1650 {
1651  mFrozen = frz;
1652 } // freeze
1653 
1655 {
1656  return mFrozen;
1657 } // freeze
1658 
1659 
1661 {
1663  return mMap->paintDevice();
1665 }
1666 
1668 {
1669  return mapSettings().mapUnitsPerPixel();
1670 } // mapUnitsPerPixel
1671 
1672 
1674 {
1675  if ( mSettings.mapUnits() == u )
1676  return;
1677 
1678  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1679  mSettings.setMapUnits( u );
1680 
1681  updateScale();
1682 
1683  refresh(); // this will force the scale bar to be updated
1684 
1685  emit mapUnitsChanged();
1686 }
1687 
1688 
1690 {
1691  return mapSettings().mapUnits();
1692 }
1693 
1695 {
1696  return mSettings.layerStyleOverrides();
1697 }
1698 
1700 {
1701  if ( overrides == mSettings.layerStyleOverrides() )
1702  return;
1703 
1704  mSettings.setLayerStyleOverrides( overrides );
1706 }
1707 
1708 
1709 void QgsMapCanvas::setRenderFlag( bool theFlag )
1710 {
1711  mRenderFlag = theFlag;
1712 
1713  if ( mRenderFlag )
1714  {
1715  refresh();
1716  }
1717  else
1718  stopRendering();
1719 }
1720 
1721 #if 0
1722 void QgsMapCanvas::connectNotify( const char * signal )
1723 {
1724  Q_UNUSED( signal );
1725  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1726 } //connectNotify
1727 #endif
1728 
1730 {
1731  if ( !mSettings.hasCrsTransformEnabled() )
1732  return;
1733 
1734  QString destAuthId = mSettings.destinationCrs().authid();
1735  Q_FOREACH ( const QString& layerID, mSettings.layers() )
1736  {
1738  if ( !layer )
1739  continue;
1740 
1741  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1742  if ( vl && vl->geometryType() == QGis::NoGeometry )
1743  continue;
1744 
1745  // if there are more options, ask the user which datum transform to use
1746  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1747  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1748  }
1749 }
1750 
1751 
1752 
1754 {
1755  return mMapTool;
1756 }
1757 
1759 {
1760  // move map image and other items to standard position
1761  moveCanvasContents( true ); // true means reset
1762 
1763  // use start and end box points to calculate the extent
1764  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1765  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1766 
1767  // modify the center
1768  double dx = end.x() - start.x();
1769  double dy = end.y() - start.y();
1770  QgsPoint c = center();
1771  c.set( c.x() - dx, c.y() - dy );
1772  setCenter( c );
1773 
1774  refresh();
1775 }
1776 
1778 {
1779  Q_UNUSED( e );
1780 
1781  // move all map canvas items
1783 }
1784 
1786 {
1787  QPoint pnt( 0, 0 );
1788  if ( !reset )
1789  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1790 
1791  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1792 }
1793 
1795 {
1796  Q_UNUSED( mapLayer );
1797 }
1798 
1800 {
1801  return mCanvasProperties->mouseLastXY;
1802 }
1803 
1804 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1805 {
1806  if ( !mPreviewEffect )
1807  {
1808  return;
1809  }
1810 
1811  mPreviewEffect->setEnabled( previewEnabled );
1812 }
1813 
1815 {
1816  if ( !mPreviewEffect )
1817  {
1818  return false;
1819  }
1820 
1821  return mPreviewEffect->isEnabled();
1822 }
1823 
1825 {
1826  if ( !mPreviewEffect )
1827  {
1828  return;
1829  }
1830 
1831  mPreviewEffect->setMode( mode );
1832 }
1833 
1835 {
1836  if ( !mPreviewEffect )
1837  {
1839  }
1840 
1841  return mPreviewEffect->mode();
1842 }
1843 
1845 {
1846  if ( !mSnappingUtils )
1847  {
1848  // associate a dummy instance, but better than null pointer
1849  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1850  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1851  }
1852  return mSnappingUtils;
1853 }
1854 
1856 {
1857  mSnappingUtils = utils;
1858 }
1859 
1861 {
1862  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1863  if ( nodes.count() )
1864  {
1865  QDomNode node = nodes.item( 0 );
1866 
1867  QgsMapSettings tmpSettings;
1868  tmpSettings.readXML( node );
1869  setMapUnits( tmpSettings.mapUnits() );
1871  setDestinationCrs( tmpSettings.destinationCrs() );
1872  setExtent( tmpSettings.extent() );
1873  setRotation( tmpSettings.rotation() );
1874  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1876 
1877  clearExtentHistory(); // clear the extent history on project load
1878  }
1879  else
1880  {
1881  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1882  }
1883 }
1884 
1886 {
1887  // create node "mapcanvas" and call mMapRenderer->writeXML()
1888 
1889  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1890  if ( !nl.count() )
1891  {
1892  QgsDebugMsg( "Unable to find qgis element in project file" );
1893  return;
1894  }
1895  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1896 
1897  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1898  qgisNode.appendChild( mapcanvasNode );
1899 
1900  mSettings.writeXML( mapcanvasNode, doc );
1901  // TODO: store only units, extent, projections, dest CRS
1902 }
1903 
1905 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1906 {
1907  if ( !ml )
1908  {
1909  return;
1910  }
1911 
1912  //check if default datum transformation available
1913  QSettings s;
1914  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1915  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1916  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1917  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1918  {
1919  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1920  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1921  return;
1922  }
1923 
1924  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1925  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1926 
1927  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1928  {
1929  // just use the default transform
1930  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1931  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1932  return;
1933  }
1934 
1935  //get list of datum transforms
1937  if ( dt.size() < 2 )
1938  {
1939  return;
1940  }
1941 
1942  //if several possibilities: present dialog
1943  QgsDatumTransformDialog d( ml->name(), dt );
1944  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1945  if ( d.exec() == QDialog::Accepted )
1946  {
1947  int srcTransform = -1;
1948  int destTransform = -1;
1949  QList<int> t = d.selectedDatumTransform();
1950  if ( !t.isEmpty() )
1951  {
1952  srcTransform = t.at( 0 );
1953  }
1954  if ( t.size() > 1 )
1955  {
1956  destTransform = t.at( 1 );
1957  }
1958  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1959  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1960  if ( d.rememberSelection() )
1961  {
1962  s.setValue( settingsString + "_srcTransform", srcTransform );
1963  s.setValue( settingsString + "_destTransform", destTransform );
1964  }
1965  }
1966  else
1967  {
1968  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1969  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1970  }
1971 }
1972 
1973 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1974 {
1976  r.scale( scaleFactor, center );
1977  setExtent( r );
1978  refresh();
1979 }
1980 
1982 {
1983  // Find out which layer it was that sent the signal.
1984  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1985  emit selectionChanged( layer );
1986  refresh();
1987 }
1988 
1990 {
1991  // By default graphics view delegates the drag events to graphics items.
1992  // But we do not want that and by ignoring the drag enter we let the
1993  // parent (e.g. QgisApp) to handle drops of map layers etc.
1994  e->ignore();
1995 }
1996 
1997 void QgsMapCanvas::mapToolDestroyed()
1998 {
1999  QgsDebugMsg( "maptool destroyed" );
2000  mMapTool = nullptr;
2001 }
2002 
2003 #ifdef HAVE_TOUCH
2004 bool QgsMapCanvas::event( QEvent * e )
2005 {
2006  bool done = false;
2007  if ( e->type() == QEvent::Gesture )
2008  {
2009  // call handler of current map tool
2010  if ( mMapTool )
2011  {
2012  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
2013  }
2014  }
2015  else
2016  {
2017  // pass other events to base class
2018  done = QGraphicsView::event( e );
2019  }
2020  return done;
2021 }
2022 #endif
2023 
2025 {
2026  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
2027 }
2028 
2029 void QgsMapCanvas::enableRotation( bool enable )
2030 {
2031  QSettings().setValue( "/qgis/canvasRotation", enable );
2032 }
2033 
2035 {
2036  // reload all layers in canvas
2037  for ( int i = 0; i < layerCount(); i++ )
2038  {
2039  QgsMapLayer *l = layer( i );
2040  if ( l )
2041  l->reload();
2042  }
2043 
2044  // clear the cache
2045  clearCache();
2046 
2047  // and then refresh
2048  refresh();
2049 }
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 ...
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.
virtual void canvasMoveEvent(QgsMapMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:145
Type type() const
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
bool isEmpty() const
test if rectangle is empty.
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.
Q_DECL_DEPRECATED bool isDirty() const
Return the state of the canvas (dirty or not)
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)
QgsMapCanvas(QWidget *parent=nullptr, const char *name=nullptr)
Constructor.
int x() const
int y() const
bool end()
void setCursor(const QCursor &)
double scale() const
Return the calculated scale of the map.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
bool hasEntryForLayer(QgsMapLayer *layer) const
Qt::KeyboardModifiers keyboardModifiers()
int layerCount() const
return number of layers on the map
QString name() const
Get the display name of the layer.
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)
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:171
void clearExtentHistory()
void setColor(ColorGroup group, ColorRole role, const QColor &color)
void readXML(QDomNode &theNode)
QgsRectangle fullExtent() const
returns current extent of layer set
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.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:196
#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)
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
bool save(const QString &fileName, const char *format, int quality) const
QObject * sender() const
double rotation() const
Get the current map canvas rotation in clockwise degrees.
const QFont & font() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
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.
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
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:407
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.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
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.
int y() const
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
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.
void setSceneRect(const QRectF &rect)
bool isVisible() const
Definition: qgsmapcanvas.h:83
void setAttribute(Qt::WidgetAttribute attribute, bool on)
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.
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 QgsMapToPixel & mapToPixel() const
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.
double rotation() const
Return the rotation of the resulting map image Units are clockwise degrees.
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
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.
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
QMap< QString, QString > layerStyleOverrides() const
Getter for stored overrides of styles for layers.
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.
void setEnabled(bool enable)
QString tr(const char *sourceText, const char *disambiguation, int n)
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
Get the x value of the point.
Definition: qgspoint.h:128
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
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
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:790
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 outputDpi() const
Return DPI used for conversion between real world units (e.g.
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 ...
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.
QgsSnappingUtils * snappingUtils() const
Return snapping utility class that is associated with map 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
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:201
int x() const
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:186
void setInteractive(bool allowed)
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.
virtual bool event(QEvent *event)
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 setPen(const QColor &color)
void clearCache()
Make sure to remove any rendered images from cache (does nothing if cache is not enabled) ...
bool isEmpty() const
Returns true if the geometry is empty.
int width() const
void layerCrsChange()
This slot is connected to the layer&#39;s CRS change.
void setBackgroundBrush(const QBrush &brush)
void setMapUnits(QGis::UnitType u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
Qt::MouseButton button() const
Job implementation that renders all layers in parallel.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
QPalette::ColorRole backgroundRole() const
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
QString qgsDoubleToString(double a, int precision=17)
Definition: qgis.h:274
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:176
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:789
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.
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
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 panToSelected(QgsVectorLayer *layer=nullptr)
Pan to the selected features of current (vector) layer keeping same extent.
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
QList< int > QgsAttributeList
void setBrush(const QBrush &brush)
void setScene(QGraphicsScene *scene)
void drawText(const QPointF &position, const QString &text)
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
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.
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.
void deleteLater()
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: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.
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
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.
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.
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:650
void zoomToSelected(QgsVectorLayer *layer=nullptr)
Zoom to the extent of the selected features of current (vector) layer.
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 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 isCachingEnabled() const
Check whether images of rendered layers are curerently being cached.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
QgsPoint toMapCoordinates(int x, int y) const
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:408
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QString what() const
Definition: qgsexception.h:36
QVariant value(const QString &key, const QVariant &defaultValue) const
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
QImage contentImage() const
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.
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
bool isInOverview() const
Definition: qgsmapcanvas.h:84
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
void dragEnterEvent(QDragEnterEvent *e) override
Overridden drag enter event.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:181
QFontMetrics fontMetrics() const
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:379
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...
int height() const
QgsMapCanvasRendererSync(QgsMapCanvas *canvas, QgsMapRenderer *renderer)
int height() const
void setGraphicsEffect(QGraphicsEffect *effect)
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
void refreshAllLayers()
Reload all layers, clear the cache and refresh the canvas.
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
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()
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
double y() const
Get the y value of the point.
Definition: qgspoint.h:136
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.
void start(int msec)
bool isValid() const
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
int height() const
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.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
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.
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()
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
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.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
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:762
QString absolutePath() const
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:206
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
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.
bool begin(QPaintDevice *device)
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.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:191
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:91
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:216
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:86
void extentsChanged()
Emitted when the extents of the map change.
iterator begin()
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
void destroyed(QObject *obj)
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:166
void zoomByFactor(double scaleFactor, const QgsPoint *center=nullptr)
Zoom with the factor supplied.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:211
QgsPoint toMapPoint(double x, double y) const
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
void panActionEnd(QPoint releasePoint)
Ends pan action and redraws the canvas.
void mapUnitsChanged()
Emmitted when map units are changed.
QStringList layerSet() const
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
void 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