QGIS API Documentation  2.14.5-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  // from now on we can accept refresh requests again
667  mRefreshScheduled = false;
668 
669  //build the expression context
670  QgsExpressionContext expressionContext;
671  expressionContext << QgsExpressionContextUtils::globalScope()
674  << new QgsExpressionContextScope( mExpressionContextScope );
675 
676  mSettings.setExpressionContext( expressionContext );
677 
678  // create the renderer job
679  Q_ASSERT( !mJob );
680  mJobCancelled = false;
681  if ( mUseParallelRendering )
682  mJob = new QgsMapRendererParallelJob( mSettings );
683  else
684  mJob = new QgsMapRendererSequentialJob( mSettings );
685  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
686  mJob->setCache( mCache );
687 
688  QStringList layersForGeometryCache;
689  Q_FOREACH ( const QString& id, mSettings.layers() )
690  {
691  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
692  {
693  if ( vl->isEditable() )
694  layersForGeometryCache << id;
695  }
696  }
697  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
698 
699  mJob->start();
700 
701  mMapUpdateTimer.start();
702 
703  emit renderStarting();
704 }
705 
706 
707 void QgsMapCanvas::rendererJobFinished()
708 {
709  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
710 
711  mMapUpdateTimer.stop();
712 
713  // TODO: would be better to show the errors in message bar
714  Q_FOREACH ( const QgsMapRendererJob::Error& error, mJob->errors() )
715  {
716  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
717  }
718 
719  if ( !mJobCancelled )
720  {
721  // take labeling results before emitting renderComplete, so labeling map tools
722  // connected to signal work with correct results
723  delete mLabelingResults;
724  mLabelingResults = mJob->takeLabelingResults();
725 
726  QImage img = mJob->renderedImage();
727 
728  // emit renderComplete to get our decorations drawn
729  QPainter p( &img );
730  emit renderComplete( &p );
731 
732  QSettings settings;
733  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
734  {
735  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
736  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
737  }
738 
739  if ( mDrawRenderingStats )
740  {
741  int w = img.width(), h = img.height();
742  QFont fnt = p.font();
743  fnt.setBold( true );
744  p.setFont( fnt );
745  int lh = p.fontMetrics().height() * 2;
746  QRect r( 0, h - lh, w, lh );
747  p.setPen( Qt::NoPen );
748  p.setBrush( QColor( 0, 0, 0, 110 ) );
749  p.drawRect( r );
750  p.setPen( Qt::white );
751  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
752  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
753  }
754 
755  p.end();
756 
757  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
758  }
759 
760  // now we are in a slot called from mJob - do not delete it immediately
761  // so the class is still valid when the execution returns to the class
762  mJob->deleteLater();
763  mJob = nullptr;
764 
765  emit mapCanvasRefreshed();
766 }
767 
768 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
769 {
770  // This is a hack to pass QgsMapCanvasItem::setRect what it
771  // expects (encoding of position and size of the item)
772  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
773  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
774  double res = m2p.mapUnitsPerPixel();
775  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
776  return rect;
777 }
778 
779 void QgsMapCanvas::mapUpdateTimeout()
780 {
781  const QImage& img = mJob->renderedImage();
782  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
783 }
784 
786 {
787  if ( mJob )
788  {
789  QgsDebugMsg( "CANVAS stop rendering!" );
790  mJobCancelled = true;
791  mJob->cancel();
792  Q_ASSERT( !mJob ); // no need to delete here: already deleted in finished()
793  }
794 }
795 
797 {
798 }
799 
800 //the format defaults to "PNG" if not specified
801 void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat )
802 {
803  //
804  //check if the optional QPaintDevice was supplied
805  //
806  if ( theQPixmap )
807  {
808  // render
809  QPainter painter;
810  painter.begin( theQPixmap );
811  QgsMapRendererCustomPainterJob job( mSettings, &painter );
812  job.start();
813  job.waitForFinished();
814  emit renderComplete( &painter );
815  painter.end();
816 
817  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
818  }
819  else //use the map view
820  {
821  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
822  }
823  //create a world file to go with the image...
825  QString myHeader;
826  // note: use 17 places of precision for all numbers output
827  //Pixel XDim
828  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
829  //Rotation on y axis - hard coded
830  myHeader += "0 \r\n";
831  //Rotation on x axis - hard coded
832  myHeader += "0 \r\n";
833  //Pixel YDim - almost always negative - see
834  //http://en.wikipedia.org/wiki/World_file#cite_note-2
835  myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
836  //Origin X (center of top left cell)
837  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
838  //Origin Y (center of top left cell)
839  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
840  QFileInfo myInfo = QFileInfo( theFileName );
841  // allow dotted names
842  QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.completeBaseName() + '.' + theFormat + 'w';
843  QFile myWorldFile( myWorldFileName );
844  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
845  {
846  return;
847  }
848  QTextStream myStream( &myWorldFile );
849  myStream << myHeader;
850 } // saveAsImage
851 
852 
853 
855 {
856  return mapSettings().visibleExtent();
857 } // extent
858 
860 {
861  return mapSettings().fullExtent();
862 } // extent
863 
864 
866 {
867  QgsRectangle current = extent();
868 
869  if ( r == current )
870  return;
871 
872  if ( r.isEmpty() )
873  {
874  if ( !mSettings.hasValidSettings() )
875  {
876  // we can't even just move the map center
877  QgsDebugMsg( "Empty extent - ignoring" );
878  return;
879  }
880 
881  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
882  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
883  setCenter( r.center() );
884  }
885  else
886  {
887  mSettings.setExtent( r );
888  }
889  emit extentsChanged();
890  updateScale();
891  if ( mLastExtent.size() > 20 )
892  mLastExtent.removeAt( 0 );
893 
894  //clear all extent items after current index
895  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
896  {
897  mLastExtent.removeAt( i );
898  }
899 
900  mLastExtent.append( extent() );
901 
902  // adjust history to no more than 20
903  if ( mLastExtent.size() > 20 )
904  {
905  mLastExtent.removeAt( 0 );
906  }
907 
908  // the last item is the current extent
909  mLastExtentIndex = mLastExtent.size() - 1;
910 
911  // update controls' enabled state
912  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
913  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
914  // notify canvas items of change
916 
917 } // setExtent
918 
920 {
922  double x = center.x();
923  double y = center.y();
924  setExtent(
925  QgsRectangle(
926  x - r.width() / 2.0, y - r.height() / 2.0,
927  x + r.width() / 2.0, y + r.height() / 2.0
928  )
929  );
930 } // setCenter
931 
933 {
935  return r.center();
936 }
937 
938 
940 {
941  return mapSettings().rotation();
942 } // rotation
943 
944 void QgsMapCanvas::setRotation( double degrees )
945 {
946  if ( !rotationEnabled() )
947  return;
948 
949  double current = rotation();
950 
951  if ( degrees == current )
952  return;
953 
954  mSettings.setRotation( degrees );
955  emit rotationChanged( degrees );
956  emit extentsChanged(); // visible extent changes with rotation
957 
958  // notify canvas items of change (needed?)
960 
961 } // setRotation
962 
963 
965 {
966  emit scaleChanged( mapSettings().scale() );
967 }
968 
969 
971 {
972  refresh();
973 } // clear
974 
975 
976 
978 {
980  // If the full extent is an empty set, don't do the zoom
981  if ( !extent.isEmpty() )
982  {
983  // Add a 5% margin around the full extent
984  extent.scale( 1.05 );
985  setExtent( extent );
986  }
987  refresh();
988 
989 } // zoomToFullExtent
990 
991 
992 
994 {
995  if ( mLastExtentIndex > 0 )
996  {
997  mLastExtentIndex--;
998  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
999  emit extentsChanged();
1000  updateScale();
1001  refresh();
1002  // update controls' enabled state
1003  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1004  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1005  // notify canvas items of change
1007  }
1008 
1009 } // zoomToPreviousExtent
1010 
1012 {
1013  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1014  {
1015  mLastExtentIndex++;
1016  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1017  emit extentsChanged();
1018  updateScale();
1019  refresh();
1020  // update controls' enabled state
1021  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1022  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1023  // notify canvas items of change
1025  }
1026 }// zoomToNextExtent
1027 
1029 {
1030  mLastExtent.clear(); // clear the zoom history list
1031  mLastExtent.append( extent() ) ; // set the current extent in the list
1032  mLastExtentIndex = mLastExtent.size() - 1;
1033  // update controls' enabled state
1034  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1035  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1036 }// clearExtentHistory
1037 
1038 
1040 {
1042 }
1043 
1045 {
1046  if ( !layer )
1047  {
1048  // use current layer by default
1049  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1050  }
1051 
1052  if ( !layer || layer->selectedFeatureCount() == 0 )
1053  return;
1054 
1056  zoomToFeatureExtent( rect );
1057 } // zoomToSelected
1058 
1060 {
1061  // no selected features, only one selected point feature
1062  //or two point features with the same x- or y-coordinates
1063  if ( rect.isEmpty() )
1064  {
1065  // zoom in
1066  QgsPoint c = rect.center();
1067  rect = extent();
1068  rect.scale( 1.0, &c );
1069  }
1070  //zoom to an area
1071  else
1072  {
1073  // Expand rect to give a bit of space around the selected
1074  // objects so as to keep them clear of the map boundaries
1075  // The same 5% should apply to all margins.
1076  rect.scale( 1.05 );
1077  }
1078 
1079  setExtent( rect );
1080  refresh();
1081 }
1082 
1084 {
1085  if ( !layer )
1086  {
1087  return;
1088  }
1089 
1090  QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFids( ids ).setSubsetOfAttributes( QgsAttributeList() ) );
1092  rect.setMinimal();
1093  QgsFeature fet;
1094  int featureCount = 0;
1095  while ( it.nextFeature( fet ) )
1096  {
1097  const QgsGeometry* geom = fet.constGeometry();
1098  QString errorMessage;
1099  if ( !geom || geom->isEmpty() )
1100  {
1101  errorMessage = tr( "Feature does not have a geometry" );
1102  }
1103  else if ( geom->geometry()->isEmpty() )
1104  {
1105  errorMessage = tr( "Feature geometry is empty" );
1106  }
1107  if ( !errorMessage.isEmpty() )
1108  {
1109  emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1110  return;
1111  }
1113  rect.combineExtentWith( &r );
1114  featureCount++;
1115  }
1116 
1117  if ( featureCount != ids.count() )
1118  {
1119  return;
1120  }
1121 
1122  zoomToFeatureExtent( rect );
1123 }
1124 
1126 {
1127  if ( !layer )
1128  {
1129  // use current layer by default
1130  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1131  }
1132 
1133  if ( !layer || layer->selectedFeatureCount() == 0 )
1134  return;
1135 
1137  if ( !rect.isNull() )
1138  {
1139  setCenter( rect.center() );
1140  }
1141  else
1142  {
1143  emit messageEmitted( tr( "Cannot pan to selected feature(s)" ), tr( "Geometry is NULL" ), QgsMessageBar::WARNING );
1144  }
1145 } // panToSelected
1146 
1148 {
1149  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1150  {
1151  emit keyPressed( e );
1152  return;
1153  }
1154 
1155  QPainter paint;
1156  QPen pen( Qt::gray );
1157  QgsPoint ll, ur;
1158 
1159  if ( ! mCanvasProperties->mouseButtonDown )
1160  {
1161  // Don't want to interfer with mouse events
1162 
1163  QgsRectangle currentExtent = mapSettings().visibleExtent();
1164  double dx = qAbs( currentExtent.width() / 4 );
1165  double dy = qAbs( currentExtent.height() / 4 );
1166 
1167  switch ( e->key() )
1168  {
1169  case Qt::Key_Left:
1170  QgsDebugMsg( "Pan left" );
1171  setCenter( center() - QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1172  refresh();
1173  break;
1174 
1175  case Qt::Key_Right:
1176  QgsDebugMsg( "Pan right" );
1177  setCenter( center() + QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1178  refresh();
1179  break;
1180 
1181  case Qt::Key_Up:
1182  QgsDebugMsg( "Pan up" );
1183  setCenter( center() + QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1184  refresh();
1185  break;
1186 
1187  case Qt::Key_Down:
1188  QgsDebugMsg( "Pan down" );
1189  setCenter( center() - QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1190  refresh();
1191  break;
1192 
1193 
1194 
1195  case Qt::Key_Space:
1196  QgsDebugMsg( "Pressing pan selector" );
1197 
1198  //mCanvasProperties->dragging = true;
1199  if ( ! e->isAutoRepeat() )
1200  {
1201  QApplication::setOverrideCursor( Qt::ClosedHandCursor );
1202  mCanvasProperties->panSelectorDown = true;
1203  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1204  }
1205  break;
1206 
1207  case Qt::Key_PageUp:
1208  QgsDebugMsg( "Zoom in" );
1209  zoomIn();
1210  break;
1211 
1212  case Qt::Key_PageDown:
1213  QgsDebugMsg( "Zoom out" );
1214  zoomOut();
1215  break;
1216 
1217 #if 0
1218  case Qt::Key_P:
1219  mUseParallelRendering = !mUseParallelRendering;
1220  refresh();
1221  break;
1222 
1223  case Qt::Key_S:
1224  mDrawRenderingStats = !mDrawRenderingStats;
1225  refresh();
1226  break;
1227 #endif
1228 
1229  default:
1230  // Pass it on
1231  if ( mMapTool )
1232  {
1233  mMapTool->keyPressEvent( e );
1234  }
1235  else e->ignore();
1236 
1237  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1238  }
1239  }
1240 
1241  emit keyPressed( e );
1242 
1243 } //keyPressEvent()
1244 
1246 {
1247  QgsDebugMsg( "keyRelease event" );
1248 
1249  switch ( e->key() )
1250  {
1251  case Qt::Key_Space:
1252  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1253  {
1254  QgsDebugMsg( "Releasing pan selector" );
1256  mCanvasProperties->panSelectorDown = false;
1257  panActionEnd( mCanvasProperties->mouseLastXY );
1258  }
1259  break;
1260 
1261  default:
1262  // Pass it on
1263  if ( mMapTool )
1264  {
1265  mMapTool->keyReleaseEvent( e );
1266  }
1267  else e->ignore();
1268 
1269  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1270  }
1271 
1272  emit keyReleased( e );
1273 
1274 } //keyReleaseEvent()
1275 
1276 
1278 {
1279  // call handler of current map tool
1280  if ( mMapTool )
1281  {
1283  mMapTool->canvasDoubleClickEvent( me.data() );
1284  }
1285 }// mouseDoubleClickEvent
1286 
1287 
1289 {
1290  //use middle mouse button for panning, map tools won't receive any events in that case
1291  if ( e->button() == Qt::MidButton )
1292  {
1293  mCanvasProperties->panSelectorDown = true;
1294  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1295  }
1296  else
1297  {
1298 
1299  // call handler of current map tool
1300  if ( mMapTool )
1301  {
1303  mMapTool->canvasPressEvent( me.data() );
1304  }
1305  }
1306 
1307  if ( mCanvasProperties->panSelectorDown )
1308  {
1309  return;
1310  }
1311 
1312  mCanvasProperties->mouseButtonDown = true;
1313  mCanvasProperties->rubberStartPoint = e->pos();
1314 
1315 } // mousePressEvent
1316 
1317 
1319 {
1320  //use middle mouse button for panning, map tools won't receive any events in that case
1321  if ( e->button() == Qt::MidButton )
1322  {
1323  mCanvasProperties->panSelectorDown = false;
1324  panActionEnd( mCanvasProperties->mouseLastXY );
1325  }
1326  else
1327  {
1328  // call handler of current map tool
1329  if ( mMapTool )
1330  {
1331  // right button was pressed in zoom tool? return to previous non zoom tool
1332  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1333  {
1334  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1335  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1336 
1337  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1338 
1339  // change to older non-zoom tool
1340  if ( mLastNonZoomMapTool
1341  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1342  {
1343  QgsMapTool* t = mLastNonZoomMapTool;
1344  mLastNonZoomMapTool = nullptr;
1345  setMapTool( t );
1346  }
1347  return;
1348  }
1350  mMapTool->canvasReleaseEvent( me.data() );
1351  }
1352  }
1353 
1354 
1355  mCanvasProperties->mouseButtonDown = false;
1356 
1357  if ( mCanvasProperties->panSelectorDown )
1358  return;
1359 
1360 } // mouseReleaseEvent
1361 
1363 {
1365  mResizeTimer->start( 500 );
1366 
1367  QSize lastSize = viewport()->size();
1368 
1369  mSettings.setOutputSize( lastSize );
1370  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1371 
1372  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1373 
1374  moveCanvasContents( true );
1375 
1376  // notify canvas items of change
1378 
1379  updateScale();
1380 
1381  //refresh();
1382 
1383  emit extentsChanged();
1384 }
1385 
1387 {
1388  // no custom event handling anymore
1389 
1391 } // paintEvent
1392 
1394 {
1395  QList<QGraphicsItem*> list = mScene->items();
1397  while ( it != list.end() )
1398  {
1399  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1400 
1401  if ( item )
1402  {
1403  item->updatePosition();
1404  }
1405 
1406  ++it;
1407  }
1408 }
1409 
1410 
1412 {
1413  // Zoom the map canvas in response to a mouse wheel event. Moving the
1414  // wheel forward (away) from the user zooms in
1415 
1416  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1417 
1418  if ( mMapTool )
1419  {
1420  mMapTool->wheelEvent( e );
1421  }
1422 
1424  {
1425  // leave the wheel for map tools if any modifier pressed
1426  return;
1427  }
1428 
1429  switch ( mWheelAction )
1430  {
1431  case WheelZoom:
1432  // zoom without changing extent
1433  if ( e->delta() > 0 )
1434  zoomIn();
1435  else
1436  zoomOut();
1437  break;
1438 
1439  case WheelZoomAndRecenter:
1440  // zoom and don't change extent
1441  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1442  break;
1443 
1445  {
1446  // zoom map to mouse cursor
1447  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1448 
1449  QgsPoint oldCenter = center();
1450  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1451  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1452  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1453 
1454  zoomByFactor( scaleFactor, &newCenter );
1455  break;
1456  }
1457 
1458  case WheelNothing:
1459  // well, nothing!
1460  break;
1461  }
1462 }
1463 
1464 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1465 {
1466  mWheelAction = action;
1467  mWheelZoomFactor = factor;
1468 }
1469 
1471 {
1472  zoomByFactor( 1 / mWheelZoomFactor );
1473 }
1474 
1476 {
1477  zoomByFactor( mWheelZoomFactor );
1478 }
1479 
1480 void QgsMapCanvas::zoomScale( double newScale )
1481 {
1482  zoomByFactor( newScale / scale() );
1483 }
1484 
1485 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1486 {
1487  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1488 
1489  // transform the mouse pos to map coordinates
1492  r.scale( scaleFactor, &center );
1493  setExtent( r );
1494  refresh();
1495 }
1496 
1498 {
1499  mCanvasProperties->mouseLastXY = e->pos();
1500 
1501  if ( mCanvasProperties->panSelectorDown )
1502  {
1503  panAction( e );
1504  }
1505  else
1506  {
1507  // call handler of current map tool
1508  if ( mMapTool )
1509  {
1511  mMapTool->canvasMoveEvent( me.data() );
1512  }
1513  }
1514 
1515  // show x y on status bar
1516  QPoint xy = e->pos();
1518  emit xyCoordinates( coord );
1519 } // mouseMoveEvent
1520 
1521 
1522 
1525 {
1526  if ( !tool )
1527  return;
1528 
1529  if ( mMapTool )
1530  {
1531  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1532  mMapTool->deactivate();
1533  }
1534 
1535  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1536  {
1537  // if zoom or pan tool will be active, save old tool
1538  // to bring it back on right click
1539  // (but only if it wasn't also zoom or pan tool)
1540  mLastNonZoomMapTool = mMapTool;
1541  }
1542  else
1543  {
1544  mLastNonZoomMapTool = nullptr;
1545  }
1546 
1547  QgsMapTool* oldTool = mMapTool;
1548 
1549  // set new map tool and activate it
1550  mMapTool = tool;
1551  if ( mMapTool )
1552  {
1553  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1554  mMapTool->activate();
1555  }
1556 
1557  emit mapToolSet( mMapTool );
1558  emit mapToolSet( mMapTool, oldTool );
1559 } // setMapTool
1560 
1562 {
1563  if ( mMapTool && mMapTool == tool )
1564  {
1565  mMapTool->deactivate();
1566  mMapTool = nullptr;
1567  emit mapToolSet( nullptr );
1568  emit mapToolSet( nullptr, mMapTool );
1569  setCursor( Qt::ArrowCursor );
1570  }
1571 
1572  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1573  {
1574  mLastNonZoomMapTool = nullptr;
1575  }
1576 }
1577 
1579 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1580 {
1581  // background of map's pixmap
1582  mSettings.setBackgroundColor( theColor );
1583 
1584  // background of the QGraphicsView
1585  QBrush bgBrush( theColor );
1586  setBackgroundBrush( bgBrush );
1587 #if 0
1588  QPalette palette;
1589  palette.setColor( backgroundRole(), theColor );
1590  setPalette( palette );
1591 #endif
1592 
1593  // background of QGraphicsScene
1594  mScene->setBackgroundBrush( bgBrush );
1595 } // setBackgroundColor
1596 
1598 {
1599  return mScene->backgroundBrush().color();
1600 }
1601 
1603 {
1604  mSettings.setSelectionColor( color );
1605 }
1606 
1608 {
1609  return mapSettings().layers().size();
1610 } // layerCount
1611 
1612 
1614 {
1615  QList<QgsMapLayer*> lst;
1616  Q_FOREACH ( const QString& layerID, mapSettings().layers() )
1617  {
1619  if ( layer )
1620  lst.append( layer );
1621  }
1622  return lst;
1623 }
1624 
1625 
1627 {
1628  // called when a layer has changed visibility setting
1629 
1630  refresh();
1631 
1632 } // layerStateChange
1633 
1635 {
1636  // called when a layer's CRS has been changed
1637  QObject *theSender = sender();
1638  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1639  QString destAuthId = mSettings.destinationCrs().authid();
1640  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1641 
1642 } // layerCrsChange
1643 
1644 
1645 void QgsMapCanvas::freeze( bool frz )
1646 {
1647  mFrozen = frz;
1648 } // freeze
1649 
1651 {
1652  return mFrozen;
1653 } // freeze
1654 
1655 
1657 {
1659  return mMap->paintDevice();
1661 }
1662 
1664 {
1665  return mapSettings().mapUnitsPerPixel();
1666 } // mapUnitsPerPixel
1667 
1668 
1670 {
1671  if ( mSettings.mapUnits() == u )
1672  return;
1673 
1674  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1675  mSettings.setMapUnits( u );
1676 
1677  updateScale();
1678 
1679  refresh(); // this will force the scale bar to be updated
1680 
1681  emit mapUnitsChanged();
1682 }
1683 
1684 
1686 {
1687  return mapSettings().mapUnits();
1688 }
1689 
1691 {
1692  return mSettings.layerStyleOverrides();
1693 }
1694 
1696 {
1697  if ( overrides == mSettings.layerStyleOverrides() )
1698  return;
1699 
1700  mSettings.setLayerStyleOverrides( overrides );
1702 }
1703 
1704 
1705 void QgsMapCanvas::setRenderFlag( bool theFlag )
1706 {
1707  mRenderFlag = theFlag;
1708 
1709  if ( mRenderFlag )
1710  {
1711  refresh();
1712  }
1713  else
1714  stopRendering();
1715 }
1716 
1717 #if 0
1718 void QgsMapCanvas::connectNotify( const char * signal )
1719 {
1720  Q_UNUSED( signal );
1721  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1722 } //connectNotify
1723 #endif
1724 
1726 {
1727  if ( !mSettings.hasCrsTransformEnabled() )
1728  return;
1729 
1730  QString destAuthId = mSettings.destinationCrs().authid();
1731  Q_FOREACH ( const QString& layerID, mSettings.layers() )
1732  {
1734  if ( !layer )
1735  continue;
1736 
1737  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1738  if ( vl && vl->geometryType() == QGis::NoGeometry )
1739  continue;
1740 
1741  // if there are more options, ask the user which datum transform to use
1742  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1743  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1744  }
1745 }
1746 
1747 
1748 
1750 {
1751  return mMapTool;
1752 }
1753 
1755 {
1756  // move map image and other items to standard position
1757  moveCanvasContents( true ); // true means reset
1758 
1759  // use start and end box points to calculate the extent
1760  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1761  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1762 
1763  // modify the center
1764  double dx = end.x() - start.x();
1765  double dy = end.y() - start.y();
1766  QgsPoint c = center();
1767  c.set( c.x() - dx, c.y() - dy );
1768  setCenter( c );
1769 
1770  refresh();
1771 }
1772 
1774 {
1775  Q_UNUSED( e );
1776 
1777  // move all map canvas items
1779 }
1780 
1782 {
1783  QPoint pnt( 0, 0 );
1784  if ( !reset )
1785  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1786 
1787  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1788 }
1789 
1791 {
1792  Q_UNUSED( mapLayer );
1793 }
1794 
1796 {
1797  return mCanvasProperties->mouseLastXY;
1798 }
1799 
1800 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1801 {
1802  if ( !mPreviewEffect )
1803  {
1804  return;
1805  }
1806 
1807  mPreviewEffect->setEnabled( previewEnabled );
1808 }
1809 
1811 {
1812  if ( !mPreviewEffect )
1813  {
1814  return false;
1815  }
1816 
1817  return mPreviewEffect->isEnabled();
1818 }
1819 
1821 {
1822  if ( !mPreviewEffect )
1823  {
1824  return;
1825  }
1826 
1827  mPreviewEffect->setMode( mode );
1828 }
1829 
1831 {
1832  if ( !mPreviewEffect )
1833  {
1835  }
1836 
1837  return mPreviewEffect->mode();
1838 }
1839 
1841 {
1842  if ( !mSnappingUtils )
1843  {
1844  // associate a dummy instance, but better than null pointer
1845  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1846  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1847  }
1848  return mSnappingUtils;
1849 }
1850 
1852 {
1853  mSnappingUtils = utils;
1854 }
1855 
1857 {
1858  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1859  if ( nodes.count() )
1860  {
1861  QDomNode node = nodes.item( 0 );
1862 
1863  QgsMapSettings tmpSettings;
1864  tmpSettings.readXML( node );
1865  setMapUnits( tmpSettings.mapUnits() );
1867  setDestinationCrs( tmpSettings.destinationCrs() );
1868  setExtent( tmpSettings.extent() );
1869  setRotation( tmpSettings.rotation() );
1870  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1872 
1873  clearExtentHistory(); // clear the extent history on project load
1874  }
1875  else
1876  {
1877  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1878  }
1879 }
1880 
1882 {
1883  // create node "mapcanvas" and call mMapRenderer->writeXML()
1884 
1885  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1886  if ( !nl.count() )
1887  {
1888  QgsDebugMsg( "Unable to find qgis element in project file" );
1889  return;
1890  }
1891  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1892 
1893  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1894  qgisNode.appendChild( mapcanvasNode );
1895 
1896  mSettings.writeXML( mapcanvasNode, doc );
1897  // TODO: store only units, extent, projections, dest CRS
1898 }
1899 
1901 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1902 {
1903  if ( !ml )
1904  {
1905  return;
1906  }
1907 
1908  //check if default datum transformation available
1909  QSettings s;
1910  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1911  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1912  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1913  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1914  {
1915  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1916  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1917  return;
1918  }
1919 
1920  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1921  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1922 
1923  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1924  {
1925  // just use the default transform
1926  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1927  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1928  return;
1929  }
1930 
1931  //get list of datum transforms
1933  if ( dt.size() < 2 )
1934  {
1935  return;
1936  }
1937 
1938  //if several possibilities: present dialog
1939  QgsDatumTransformDialog d( ml->name(), dt );
1940  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1941  if ( d.exec() == QDialog::Accepted )
1942  {
1943  int srcTransform = -1;
1944  int destTransform = -1;
1945  QList<int> t = d.selectedDatumTransform();
1946  if ( !t.isEmpty() )
1947  {
1948  srcTransform = t.at( 0 );
1949  }
1950  if ( t.size() > 1 )
1951  {
1952  destTransform = t.at( 1 );
1953  }
1954  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1955  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1956  if ( d.rememberSelection() )
1957  {
1958  s.setValue( settingsString + "_srcTransform", srcTransform );
1959  s.setValue( settingsString + "_destTransform", destTransform );
1960  }
1961  }
1962  else
1963  {
1964  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1965  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1966  }
1967 }
1968 
1969 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1970 {
1972  r.scale( scaleFactor, center );
1973  setExtent( r );
1974  refresh();
1975 }
1976 
1978 {
1979  // Find out which layer it was that sent the signal.
1980  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1981  emit selectionChanged( layer );
1982  refresh();
1983 }
1984 
1986 {
1987  // By default graphics view delegates the drag events to graphics items.
1988  // But we do not want that and by ignoring the drag enter we let the
1989  // parent (e.g. QgisApp) to handle drops of map layers etc.
1990  e->ignore();
1991 }
1992 
1993 void QgsMapCanvas::mapToolDestroyed()
1994 {
1995  QgsDebugMsg( "maptool destroyed" );
1996  mMapTool = nullptr;
1997 }
1998 
1999 #ifdef HAVE_TOUCH
2000 bool QgsMapCanvas::event( QEvent * e )
2001 {
2002  bool done = false;
2003  if ( e->type() == QEvent::Gesture )
2004  {
2005  // call handler of current map tool
2006  if ( mMapTool )
2007  {
2008  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
2009  }
2010  }
2011  else
2012  {
2013  // pass other events to base class
2014  done = QGraphicsView::event( e );
2015  }
2016  return done;
2017 }
2018 #endif
2019 
2021 {
2022  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
2023 }
2024 
2025 void QgsMapCanvas::enableRotation( bool enable )
2026 {
2027  QSettings().setValue( "/qgis/canvasRotation", enable );
2028 }
2029 
2031 {
2032  // reload all layers in canvas
2033  for ( int i = 0; i < layerCount(); i++ )
2034  {
2035  QgsMapLayer *l = layer( i );
2036  if ( l )
2037  l->reload();
2038  }
2039 
2040  // clear the cache
2041  clearCache();
2042 
2043  // and then refresh
2044  refresh();
2045 }
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 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:197
#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.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
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.
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: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 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
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.
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
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.
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Enable anti-aliasing 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
#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.
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)
void restoreOverrideCursor()
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: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
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:416
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.
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:381
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:763
QString absolutePath() const
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
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:192
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:91
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:217
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 zoomByFactor(double scaleFactor, const QgsPoint *center=nullptr)
Zoom with the factor supplied.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
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()
Emitted 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