QGIS API Documentation  2.15.0-Master (13f053b)
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  : mouseButtonDown( false )
77  , panSelectorDown( false )
78  { }
79 
82 
85 
88 
91 };
92 
93 
95  : QObject( canvas )
96  , mCanvas( canvas )
97  , mRenderer( renderer )
98  , mSyncingExtent( false )
99 {
100  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( onExtentC2R() ) );
101  connect( mRenderer, SIGNAL( extentsChanged() ), this, SLOT( onExtentR2C() ) );
102 
103  connect( mCanvas, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsC2R() ) );
104  connect( mRenderer, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsR2C() ) );
105 
106  connect( mCanvas, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationC2R() ) );
107  connect( mRenderer, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationR2C() ) );
108 
109  connect( mCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ), this, SLOT( onCrsTransformC2R() ) );
110  connect( mRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( onCrsTransformR2C() ) );
111 
112  connect( mCanvas, SIGNAL( destinationCrsChanged() ), this, SLOT( onDestCrsC2R() ) );
113  connect( mRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( onDestCrsR2C() ) );
114 
115  connect( mCanvas, SIGNAL( layersChanged() ), this, SLOT( onLayersC2R() ) );
116  // TODO: layers R2C ? (should not happen!)
117 
118 }
119 
121 {
122  // protection against possible bounce back
123  if ( mSyncingExtent )
124  return;
125 
126  mSyncingExtent = true;
128  mSyncingExtent = false;
129 }
130 
132 {
133  // protection against possible bounce back
134  if ( mSyncingExtent )
135  return;
136 
137  mSyncingExtent = true;
139  mSyncingExtent = false;
140 }
141 
143 {
145 }
146 
148 {
150 }
151 
153 {
155 }
156 
158 {
160 }
161 
163 {
165 }
166 
168 {
170 }
171 
173 {
175 }
176 
178 {
180 }
181 
183 {
185 }
186 
187 
188 
190  : QGraphicsView( parent )
191  , mCanvasProperties( new CanvasProperties )
192  , mMagnificationFactor( 1.0 )
193  , mJob( nullptr )
194  , mJobCancelled( false )
195  , mLabelingResults( nullptr )
196  , mUseParallelRendering( false )
197  , mDrawRenderingStats( false )
198  , mCache( nullptr )
199  , mPreviewEffect( nullptr )
200  , mSnappingUtils( nullptr )
201  , mExpressionContextScope( tr( "Map Canvas" ) )
202 {
203  setObjectName( name );
204  mScene = new QGraphicsScene();
205  setScene( mScene );
206  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
207  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
208  mLastExtentIndex = -1;
209  mCurrentLayer = nullptr;
210  mMapOverview = nullptr;
211  mMapTool = nullptr;
212  mLastNonZoomMapTool = nullptr;
213 
214  mFrozen = false;
215  mRefreshScheduled = false;
216 
218 
219  // by default, the canvas is rendered
220  mRenderFlag = true;
221 
222  setMouseTracking( true );
223  setFocusPolicy( Qt::StrongFocus );
224 
225  mMapRenderer = new QgsMapRenderer;
226 
227  mResizeTimer = new QTimer( this );
228  mResizeTimer->setSingleShot( true );
229  connect( mResizeTimer, SIGNAL( timeout() ), this, SLOT( refresh() ) );
230 
231  // create map canvas item which will show the map
232  mMap = new QgsMapCanvasMap( this );
233 
234  // project handling
235  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
236  this, SLOT( readProject( const QDomDocument & ) ) );
238  this, SLOT( writeProject( QDomDocument & ) ) );
239 
242 
243  //segmentation parameters
244  QSettings settings;
245  double segmentationTolerance = settings.value( "/qgis/segmentationTolerance", "0.01745" ).toDouble();
246  QgsAbstractGeometryV2::SegmentationToleranceType toleranceType = QgsAbstractGeometryV2::SegmentationToleranceType( settings.value( "/qgis/segmentationToleranceType", 0 ).toInt() );
247  mSettings.setSegmentationTolerance( segmentationTolerance );
248  mSettings.setSegmentationToleranceType( toleranceType );
249 
250  // class that will sync most of the changes between canvas and (legacy) map renderer
251  // it is parented to map canvas, will be deleted automatically
252  new QgsMapCanvasRendererSync( this, mMapRenderer );
253 
254  QSize s = viewport()->size();
255  mSettings.setOutputSize( s );
256  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
257  setSceneRect( 0, 0, s.width(), s.height() );
258  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
259 
260  moveCanvasContents( true );
261 
262  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
263  mMapUpdateTimer.setInterval( 250 );
264 
265 #ifdef Q_OS_WIN
266  // Enable touch event on Windows.
267  // Qt on Windows needs to be told it can take touch events or else it ignores them.
268  grabGesture( Qt::PinchGesture );
269  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
270 #endif
271 
272  mPreviewEffect = new QgsPreviewEffect( this );
273  viewport()->setGraphicsEffect( mPreviewEffect );
274 
275  setInteractive( false );
276 
277  refresh();
278 
279 } // QgsMapCanvas ctor
280 
281 
283 {
284  if ( mMapTool )
285  {
286  mMapTool->deactivate();
287  mMapTool = nullptr;
288  }
289  mLastNonZoomMapTool = nullptr;
290 
291  // delete canvas items prior to deleteing the canvas
292  // because they might try to update canvas when it's
293  // already being destructed, ends with segfault
294  QList<QGraphicsItem*> list = mScene->items();
296  while ( it != list.end() )
297  {
298  QGraphicsItem* item = *it;
299  delete item;
300  ++it;
301  }
302 
303  mScene->deleteLater(); // crashes in python tests on windows
304 
305  delete mMapRenderer;
306  // mCanvasProperties auto-deleted via QScopedPointer
307  // CanvasProperties struct has its own dtor for freeing resources
308 
309  if ( mJob )
310  {
311  mJob->cancel();
312  Q_ASSERT( !mJob );
313  }
314 
315  delete mCache;
316 
317  delete mLabelingResults;
318 
319 } // dtor
320 
322 {
323  mSettings.setMagnificationFactor( level );
324  refresh();
325 }
326 
328 {
329  return mSettings.magnificationFactor();
330 }
331 
333 {
334  mSettings.setFlag( QgsMapSettings::Antialiasing, theFlag );
335 
336  if ( mMapOverview )
337  mMapOverview->enableAntiAliasing( theFlag );
338 } // anti aliasing
339 
341 {
342  mSettings.setFlag( QgsMapSettings::RenderMapTile, theFlag );
343 }
344 
345 void QgsMapCanvas::useImageToRender( bool theFlag )
346 {
347  Q_UNUSED( theFlag );
348 }
349 
351 {
352  return mMap;
353 }
354 
356 {
357  return mMapRenderer;
358 }
359 
360 
362 {
363  const QStringList& layers = mapSettings().layers();
364  if ( index >= 0 && index < ( int ) layers.size() )
365  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
366  else
367  return nullptr;
368 }
369 
370 
372 {
373  mCurrentLayer = layer;
374  emit currentLayerChanged( layer );
375 }
376 
378 {
379  return mapSettings().scale();
380 } // scale
381 
382 void QgsMapCanvas::setDirty( bool dirty )
383 {
384  if ( dirty )
385  refresh();
386 }
387 
389 {
390  return false;
391 }
392 
394 {
395  return nullptr != mJob;
396 } // isDrawing
397 
398 // return the current coordinate transform based on the extents and
399 // device size
401 {
402  return &mapSettings().mapToPixel();
403 }
404 
406 {
407  // create layer set
408  QStringList layerSet, layerSetOverview;
409 
410  int i;
411  for ( i = 0; i < layers.size(); i++ )
412  {
413  QgsMapCanvasLayer &lyr = layers[i];
414  if ( !lyr.layer() )
415  {
416  continue;
417  }
418 
419  if ( lyr.isVisible() )
420  {
421  layerSet.push_back( lyr.layer()->id() );
422  }
423 
424  if ( lyr.isInOverview() )
425  {
426  layerSetOverview.push_back( lyr.layer()->id() );
427  }
428  }
429 
430  const QStringList& layerSetOld = mapSettings().layers();
431 
432  bool layerSetChanged = layerSetOld != layerSet;
433 
434  // update only if needed
435  if ( layerSetChanged )
436  {
437  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
438 
439  for ( i = 0; i < layerCount(); i++ )
440  {
441  // Add check if vector layer when disconnecting from selectionChanged slot
442  // Ticket #811 - racicot
444  if ( !currentLayer )
445  continue;
446  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
447  disconnect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
448  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
449  if ( isVectLyr )
450  {
451  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
452  }
453  }
454 
455  mSettings.setLayers( layerSet );
456 
457  for ( i = 0; i < layerCount(); i++ )
458  {
459  // Add check if vector layer when connecting to selectionChanged slot
460  // Ticket #811 - racicot
462  if ( !currentLayer )
463  continue;
464  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
465  connect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
466  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
467  if ( isVectLyr )
468  {
469  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
470  }
471  }
472 
474 
475  QgsDebugMsg( "Layers have changed, refreshing" );
476  emit layersChanged();
477 
478  refresh();
479  }
480 
481  if ( mMapOverview )
482  {
483  const QStringList& layerSetOvOld = mMapOverview->layerSet();
484  if ( layerSetOvOld != layerSetOverview )
485  {
486  mMapOverview->setLayerSet( layerSetOverview );
487  }
488 
489  // refresh overview maplayers even if layer set is the same
490  // because full extent might have changed
491  updateOverview();
492  }
493 } // setLayerSet
494 
496 {
497  if ( mMapOverview )
498  {
499  // disconnect old map overview if exists
500  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
501  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
502  disconnect( this, SIGNAL( destinationCrsChanged() ),
503  mMapOverview, SLOT( destinationSrsChanged() ) );
504 
505  // map overview is not owned by map canvas so don't delete it...
506  }
507 
508  mMapOverview = overview;
509 
510  if ( overview )
511  {
512  // connect to the map render to copy its projection settings
513  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
514  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
515  connect( this, SIGNAL( destinationCrsChanged() ),
516  overview, SLOT( destinationSrsChanged() ) );
517  }
518 }
519 
521 {
522  return mSettings;
523 }
524 
526 {
527  if ( mSettings.hasCrsTransformEnabled() == enabled )
528  return;
529 
530  mSettings.setCrsTransformEnabled( enabled );
531 
533 
534  refresh();
535 
536  emit hasCrsTransformEnabledChanged( enabled );
537 }
538 
540 {
541  if ( mSettings.destinationCrs() == crs )
542  return;
543 
544  if ( mSettings.hasCrsTransformEnabled() )
545  {
546  // try to reproject current extent to the new one
548  if ( !mSettings.visibleExtent().isEmpty() )
549  {
550  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
551  try
552  {
553  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
554  }
555  catch ( QgsCsException &e )
556  {
557  Q_UNUSED( e );
558  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
559  }
560  }
561  if ( !rect.isEmpty() )
562  {
563  setExtent( rect );
564  }
565 
566  QgsDebugMsg( "refreshing after destination CRS changed" );
567  refresh();
568  }
569 
570  mSettings.setDestinationCrs( crs );
571 
573 
574  emit destinationCrsChanged();
575 }
576 
578 {
579  return mLabelingResults;
580 }
581 
583 {
584  if ( enabled == isCachingEnabled() )
585  return;
586 
587  if ( mJob && mJob->isActive() )
588  {
589  // wait for the current rendering to finish, before touching the cache
590  mJob->waitForFinished();
591  }
592 
593  if ( enabled )
594  {
595  mCache = new QgsMapRendererCache;
596  }
597  else
598  {
599  delete mCache;
600  mCache = nullptr;
601  }
602 }
603 
605 {
606  return nullptr != mCache;
607 }
608 
610 {
611  if ( mCache )
612  mCache->clear();
613 }
614 
616 {
617  mUseParallelRendering = enabled;
618 }
619 
621 {
622  return mUseParallelRendering;
623 }
624 
625 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
626 {
627  mMapUpdateTimer.setInterval( timeMiliseconds );
628 }
629 
631 {
632  return mMapUpdateTimer.interval();
633 }
634 
635 
637 {
638  // redraw overview
639  if ( mMapOverview )
640  {
641  mMapOverview->refresh();
642  }
643 }
644 
645 
647 {
648  return mCurrentLayer;
649 }
650 
651 
653 {
654  if ( !mSettings.hasValidSettings() )
655  {
656  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
657  return;
658  }
659 
660  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
661  {
662  QgsDebugMsg( "CANVAS render flag off" );
663  return;
664  }
665 
666  if ( mRefreshScheduled )
667  {
668  QgsDebugMsg( "CANVAS refresh already scheduled" );
669  return;
670  }
671 
672  mRefreshScheduled = true;
673 
674  QgsDebugMsg( "CANVAS refresh scheduling" );
675 
676  // schedule a refresh
677  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
678 } // refresh
679 
680 void QgsMapCanvas::refreshMap()
681 {
682  Q_ASSERT( mRefreshScheduled );
683 
684  QgsDebugMsg( "CANVAS refresh!" );
685 
686  stopRendering(); // if any...
687 
688  // from now on we can accept refresh requests again
689  mRefreshScheduled = false;
690 
691  //build the expression context
692  QgsExpressionContext expressionContext;
693  expressionContext << QgsExpressionContextUtils::globalScope()
696  << new QgsExpressionContextScope( mExpressionContextScope );
697 
698  mSettings.setExpressionContext( expressionContext );
699 
700  // create the renderer job
701  Q_ASSERT( !mJob );
702  mJobCancelled = false;
703  if ( mUseParallelRendering )
704  mJob = new QgsMapRendererParallelJob( mSettings );
705  else
706  mJob = new QgsMapRendererSequentialJob( mSettings );
707  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
708  mJob->setCache( mCache );
709 
710  QStringList layersForGeometryCache;
711  Q_FOREACH ( const QString& id, mSettings.layers() )
712  {
713  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
714  {
715  if ( vl->isEditable() )
716  layersForGeometryCache << id;
717  }
718  }
719  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
720 
721  mJob->start();
722 
723  mMapUpdateTimer.start();
724 
725  emit renderStarting();
726 }
727 
728 
729 void QgsMapCanvas::rendererJobFinished()
730 {
731  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
732 
733  mMapUpdateTimer.stop();
734 
735  // TODO: would be better to show the errors in message bar
736  Q_FOREACH ( const QgsMapRendererJob::Error& error, mJob->errors() )
737  {
738  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
739  }
740 
741  if ( !mJobCancelled )
742  {
743  // take labeling results before emitting renderComplete, so labeling map tools
744  // connected to signal work with correct results
745  delete mLabelingResults;
746  mLabelingResults = mJob->takeLabelingResults();
747 
748  QImage img = mJob->renderedImage();
749 
750  // emit renderComplete to get our decorations drawn
751  QPainter p( &img );
752  emit renderComplete( &p );
753 
754  QSettings settings;
755  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
756  {
757  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
758  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
759  }
760 
761  if ( mDrawRenderingStats )
762  {
763  int w = img.width(), h = img.height();
764  QFont fnt = p.font();
765  fnt.setBold( true );
766  p.setFont( fnt );
767  int lh = p.fontMetrics().height() * 2;
768  QRect r( 0, h - lh, w, lh );
769  p.setPen( Qt::NoPen );
770  p.setBrush( QColor( 0, 0, 0, 110 ) );
771  p.drawRect( r );
772  p.setPen( Qt::white );
773  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
774  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
775  }
776 
777  p.end();
778 
779  mMap->setContent( img, imageRect( img, mSettings ) );
780  }
781 
782  // now we are in a slot called from mJob - do not delete it immediately
783  // so the class is still valid when the execution returns to the class
784  mJob->deleteLater();
785  mJob = nullptr;
786 
787  emit mapCanvasRefreshed();
788 }
789 
790 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
791 {
792  // This is a hack to pass QgsMapCanvasItem::setRect what it
793  // expects (encoding of position and size of the item)
794  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
795  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
796  double res = m2p.mapUnitsPerPixel();
797  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
798  return rect;
799 }
800 
801 void QgsMapCanvas::mapUpdateTimeout()
802 {
803  const QImage& img = mJob->renderedImage();
804  mMap->setContent( img, imageRect( img, mSettings ) );
805 }
806 
808 {
809  if ( mJob )
810  {
811  QgsDebugMsg( "CANVAS stop rendering!" );
812  mJobCancelled = true;
813  mJob->cancel();
814  Q_ASSERT( !mJob ); // no need to delete here: already deleted in finished()
815  }
816 }
817 
819 {
820 }
821 
822 //the format defaults to "PNG" if not specified
823 void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat )
824 {
825  QPainter painter;
826  QImage image;
827 
828  //
829  //check if the optional QPaintDevice was supplied
830  //
831  if ( theQPixmap )
832  {
833  image = theQPixmap->toImage();
834  painter.begin( &image );
835 
836  // render
837  QgsMapRendererCustomPainterJob job( mSettings, &painter );
838  job.start();
839  job.waitForFinished();
840  emit renderComplete( &painter );
841  }
842  else //use the map view
843  {
844  image = mMap->contentImage().copy();
845  painter.begin( &image );
846  }
847 
848  // draw annotations
850  option.initFrom( this );
851  QGraphicsItem* item;
853  i.toBack();
854  while ( i.hasPrevious() )
855  {
856  item = i.previous();
857 
858  if ( !item || item->data( 0 ).toString() != "AnnotationItem" )
859  {
860  continue;
861  }
862 
863  painter.save();
864 
865  QPointF itemScenePos = item->scenePos();
866  painter.translate( itemScenePos.x(), itemScenePos.y() );
867 
868  item->paint( &painter, &option );
869 
870  painter.restore();
871  }
872 
873  painter.end();
874  image.save( theFileName, theFormat.toLocal8Bit().data() );
875 
876  //create a world file to go with the image...
878  QString myHeader;
879  // note: use 17 places of precision for all numbers output
880  //Pixel XDim
881  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
882  //Rotation on y axis - hard coded
883  myHeader += "0 \r\n";
884  //Rotation on x axis - hard coded
885  myHeader += "0 \r\n";
886  //Pixel YDim - almost always negative - see
887  //http://en.wikipedia.org/wiki/World_file#cite_note-2
888  myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
889  //Origin X (center of top left cell)
890  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
891  //Origin Y (center of top left cell)
892  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
893  QFileInfo myInfo = QFileInfo( theFileName );
894  // allow dotted names
895  QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.completeBaseName() + '.' + theFormat + 'w';
896  QFile myWorldFile( myWorldFileName );
897  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
898  {
899  return;
900  }
901  QTextStream myStream( &myWorldFile );
902  myStream << myHeader;
903 } // saveAsImage
904 
905 
906 
908 {
909  return mapSettings().visibleExtent();
910 } // extent
911 
913 {
914  return mapSettings().fullExtent();
915 } // extent
916 
917 
918 void QgsMapCanvas::setExtent( QgsRectangle const & r, bool magnified )
919 {
920  QgsRectangle current = extent();
921 
922  if (( r == current ) && magnified )
923  return;
924 
925  if ( r.isEmpty() )
926  {
927  if ( !mSettings.hasValidSettings() )
928  {
929  // we can't even just move the map center
930  QgsDebugMsg( "Empty extent - ignoring" );
931  return;
932  }
933 
934  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
935  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
936  setCenter( r.center() );
937  }
938  else
939  {
940  mSettings.setExtent( r, magnified );
941  }
942  emit extentsChanged();
943  updateScale();
944  if ( mLastExtent.size() > 20 )
945  mLastExtent.removeAt( 0 );
946 
947  //clear all extent items after current index
948  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
949  {
950  mLastExtent.removeAt( i );
951  }
952 
953  mLastExtent.append( extent() );
954 
955  // adjust history to no more than 20
956  if ( mLastExtent.size() > 20 )
957  {
958  mLastExtent.removeAt( 0 );
959  }
960 
961  // the last item is the current extent
962  mLastExtentIndex = mLastExtent.size() - 1;
963 
964  // update controls' enabled state
965  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
966  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
967  // notify canvas items of change
969 
970 } // setExtent
971 
973 {
975  double x = center.x();
976  double y = center.y();
977  setExtent(
978  QgsRectangle(
979  x - r.width() / 2.0, y - r.height() / 2.0,
980  x + r.width() / 2.0, y + r.height() / 2.0
981  ),
982  true
983  );
984 } // setCenter
985 
987 {
989  return r.center();
990 }
991 
992 
994 {
995  return mapSettings().rotation();
996 } // rotation
997 
998 void QgsMapCanvas::setRotation( double degrees )
999 {
1000  if ( !rotationEnabled() )
1001  return;
1002 
1003  double current = rotation();
1004 
1005  if ( degrees == current )
1006  return;
1007 
1008  mSettings.setRotation( degrees );
1009  emit rotationChanged( degrees );
1010  emit extentsChanged(); // visible extent changes with rotation
1011 
1012  // notify canvas items of change (needed?)
1014 
1015 } // setRotation
1016 
1017 
1019 {
1020  emit scaleChanged( mapSettings().scale() );
1021 }
1022 
1023 
1025 {
1026  refresh();
1027 } // clear
1028 
1029 
1030 
1032 {
1034  // If the full extent is an empty set, don't do the zoom
1035  if ( !extent.isEmpty() )
1036  {
1037  // Add a 5% margin around the full extent
1038  extent.scale( 1.05 );
1039  setExtent( extent );
1040  }
1041  refresh();
1042 
1043 } // zoomToFullExtent
1044 
1045 
1046 
1048 {
1049  if ( mLastExtentIndex > 0 )
1050  {
1051  mLastExtentIndex--;
1052  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1053  emit extentsChanged();
1054  updateScale();
1055  refresh();
1056  // update controls' enabled state
1057  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1058  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1059  // notify canvas items of change
1061  }
1062 
1063 } // zoomToPreviousExtent
1064 
1066 {
1067  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1068  {
1069  mLastExtentIndex++;
1070  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1071  emit extentsChanged();
1072  updateScale();
1073  refresh();
1074  // update controls' enabled state
1075  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1076  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1077  // notify canvas items of change
1079  }
1080 }// zoomToNextExtent
1081 
1083 {
1084  mLastExtent.clear(); // clear the zoom history list
1085  mLastExtent.append( extent() ) ; // set the current extent in the list
1086  mLastExtentIndex = mLastExtent.size() - 1;
1087  // update controls' enabled state
1088  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1089  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1090 }// clearExtentHistory
1091 
1092 
1094 {
1096 }
1097 
1099 {
1100  if ( !layer )
1101  {
1102  // use current layer by default
1103  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1104  }
1105 
1106  if ( !layer || layer->selectedFeatureCount() == 0 )
1107  return;
1108 
1110  zoomToFeatureExtent( rect );
1111 } // zoomToSelected
1112 
1114 {
1115  // no selected features, only one selected point feature
1116  //or two point features with the same x- or y-coordinates
1117  if ( rect.isEmpty() )
1118  {
1119  // zoom in
1120  QgsPoint c = rect.center();
1121  rect = extent();
1122  rect.scale( 1.0, &c );
1123  }
1124  //zoom to an area
1125  else
1126  {
1127  // Expand rect to give a bit of space around the selected
1128  // objects so as to keep them clear of the map boundaries
1129  // The same 5% should apply to all margins.
1130  rect.scale( 1.05 );
1131  }
1132 
1133  setExtent( rect );
1134  refresh();
1135 }
1136 
1138 {
1139  if ( !layer )
1140  {
1141  return;
1142  }
1143 
1144  QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFids( ids ).setSubsetOfAttributes( QgsAttributeList() ) );
1146  rect.setMinimal();
1147  QgsFeature fet;
1148  int featureCount = 0;
1149  while ( it.nextFeature( fet ) )
1150  {
1151  const QgsGeometry* geom = fet.constGeometry();
1152  QString errorMessage;
1153  if ( !geom || geom->isEmpty() )
1154  {
1155  errorMessage = tr( "Feature does not have a geometry" );
1156  }
1157  else if ( geom->geometry()->isEmpty() )
1158  {
1159  errorMessage = tr( "Feature geometry is empty" );
1160  }
1161  if ( !errorMessage.isEmpty() )
1162  {
1163  emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1164  return;
1165  }
1167  rect.combineExtentWith( &r );
1168  featureCount++;
1169  }
1170 
1171  if ( featureCount != ids.count() )
1172  {
1173  return;
1174  }
1175 
1176  zoomToFeatureExtent( rect );
1177 }
1178 
1180 {
1181  if ( !layer )
1182  {
1183  // use current layer by default
1184  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1185  }
1186 
1187  if ( !layer || layer->selectedFeatureCount() == 0 )
1188  return;
1189 
1191  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1192  refresh();
1193 } // panToSelected
1194 
1196 {
1197  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1198  {
1199  emit keyPressed( e );
1200  return;
1201  }
1202 
1203  if ( ! mCanvasProperties->mouseButtonDown )
1204  {
1205  // Don't want to interfer with mouse events
1206 
1207  QgsRectangle currentExtent = mapSettings().visibleExtent();
1208  double dx = qAbs( currentExtent.width() / 4 );
1209  double dy = qAbs( currentExtent.height() / 4 );
1210 
1211  switch ( e->key() )
1212  {
1213  case Qt::Key_Left:
1214  QgsDebugMsg( "Pan left" );
1215  setCenter( center() - QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1216  refresh();
1217  break;
1218 
1219  case Qt::Key_Right:
1220  QgsDebugMsg( "Pan right" );
1221  setCenter( center() + QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1222  refresh();
1223  break;
1224 
1225  case Qt::Key_Up:
1226  QgsDebugMsg( "Pan up" );
1227  setCenter( center() + QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1228  refresh();
1229  break;
1230 
1231  case Qt::Key_Down:
1232  QgsDebugMsg( "Pan down" );
1233  setCenter( center() - QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1234  refresh();
1235  break;
1236 
1237 
1238 
1239  case Qt::Key_Space:
1240  QgsDebugMsg( "Pressing pan selector" );
1241 
1242  //mCanvasProperties->dragging = true;
1243  if ( ! e->isAutoRepeat() )
1244  {
1245  mCanvasProperties->panSelectorDown = true;
1246  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1247  }
1248  break;
1249 
1250  case Qt::Key_PageUp:
1251  QgsDebugMsg( "Zoom in" );
1252  zoomIn();
1253  break;
1254 
1255  case Qt::Key_PageDown:
1256  QgsDebugMsg( "Zoom out" );
1257  zoomOut();
1258  break;
1259 
1260 #if 0
1261  case Qt::Key_P:
1262  mUseParallelRendering = !mUseParallelRendering;
1263  refresh();
1264  break;
1265 
1266  case Qt::Key_S:
1267  mDrawRenderingStats = !mDrawRenderingStats;
1268  refresh();
1269  break;
1270 #endif
1271 
1272  default:
1273  // Pass it on
1274  if ( mMapTool )
1275  {
1276  mMapTool->keyPressEvent( e );
1277  }
1278  else e->ignore();
1279 
1280  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1281  }
1282  }
1283 
1284  emit keyPressed( e );
1285 
1286 } //keyPressEvent()
1287 
1289 {
1290  QgsDebugMsg( "keyRelease event" );
1291 
1292  switch ( e->key() )
1293  {
1294  case Qt::Key_Space:
1295  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1296  {
1297  QgsDebugMsg( "Releasing pan selector" );
1298 
1299  mCanvasProperties->panSelectorDown = false;
1300  panActionEnd( mCanvasProperties->mouseLastXY );
1301  }
1302  break;
1303 
1304  default:
1305  // Pass it on
1306  if ( mMapTool )
1307  {
1308  mMapTool->keyReleaseEvent( e );
1309  }
1310  else e->ignore();
1311 
1312  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1313  }
1314 
1315  emit keyReleased( e );
1316 
1317 } //keyReleaseEvent()
1318 
1319 
1321 {
1322  // call handler of current map tool
1323  if ( mMapTool )
1324  {
1326  mMapTool->canvasDoubleClickEvent( me.data() );
1327  }
1328 }// mouseDoubleClickEvent
1329 
1330 
1332 {
1333  //use middle mouse button for panning, map tools won't receive any events in that case
1334  if ( e->button() == Qt::MidButton )
1335  {
1336  mCanvasProperties->panSelectorDown = true;
1337  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1338  }
1339  else
1340  {
1341 
1342  // call handler of current map tool
1343  if ( mMapTool )
1344  {
1346  mMapTool->canvasPressEvent( me.data() );
1347  }
1348  }
1349 
1350  if ( mCanvasProperties->panSelectorDown )
1351  {
1352  return;
1353  }
1354 
1355  mCanvasProperties->mouseButtonDown = true;
1356  mCanvasProperties->rubberStartPoint = e->pos();
1357 
1358 } // mousePressEvent
1359 
1360 
1362 {
1363  //use middle mouse button for panning, map tools won't receive any events in that case
1364  if ( e->button() == Qt::MidButton )
1365  {
1366  mCanvasProperties->panSelectorDown = false;
1367  panActionEnd( mCanvasProperties->mouseLastXY );
1368  }
1369  else
1370  {
1371  // call handler of current map tool
1372  if ( mMapTool )
1373  {
1374  // right button was pressed in zoom tool? return to previous non zoom tool
1375  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1376  {
1377  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1378  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1379 
1380  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1381 
1382  // change to older non-zoom tool
1383  if ( mLastNonZoomMapTool
1384  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1385  {
1386  QgsMapTool* t = mLastNonZoomMapTool;
1387  mLastNonZoomMapTool = nullptr;
1388  setMapTool( t );
1389  }
1390  return;
1391  }
1393  mMapTool->canvasReleaseEvent( me.data() );
1394  }
1395  }
1396 
1397 
1398  mCanvasProperties->mouseButtonDown = false;
1399 
1400  if ( mCanvasProperties->panSelectorDown )
1401  return;
1402 
1403 } // mouseReleaseEvent
1404 
1405 void QgsMapCanvas::updateMapSize()
1406 {
1407  mResizeTimer->start( 500 );
1408 
1409  QSize lastSize = viewport()->size();
1410  mSettings.setOutputSize( lastSize );
1411  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1412 
1413  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1414 
1415  moveCanvasContents( true );
1416 
1417  // notify canvas items of change
1419 
1420  updateScale();
1421 
1422  //refresh();
1423 
1424  emit extentsChanged();
1425 }
1426 
1427 
1429 {
1431 
1432  QSize size = viewport()->size();
1433  if ( size.width() > mSettings.outputSize().width() || size.height() > mSettings.outputSize().height() )
1434  {
1435  updateMapSize();
1436  }
1437  else
1438  {
1439  moveCanvasContents( true );
1440  }
1441 }
1442 
1444 {
1445  // no custom event handling anymore
1446 
1448 }
1449 
1451 {
1452  QList<QGraphicsItem*> list = mScene->items();
1454  while ( it != list.end() )
1455  {
1456  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1457 
1458  if ( item )
1459  {
1460  item->updatePosition();
1461  }
1462 
1463  ++it;
1464  }
1465 }
1466 
1467 
1469 {
1470  // Zoom the map canvas in response to a mouse wheel event. Moving the
1471  // wheel forward (away) from the user zooms in
1472 
1473  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1474 
1475  if ( mMapTool )
1476  {
1477  mMapTool->wheelEvent( e );
1478  }
1479 
1481  {
1482  // leave the wheel for map tools if any modifier pressed
1483  return;
1484  }
1485 
1486  switch ( mWheelAction )
1487  {
1488  case WheelZoom:
1489  // zoom without changing extent
1490  if ( e->delta() > 0 )
1491  zoomIn();
1492  else
1493  zoomOut();
1494  break;
1495 
1496  case WheelZoomAndRecenter:
1497  // zoom and don't change extent
1498  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1499  break;
1500 
1502  {
1503  // zoom map to mouse cursor
1504  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1505 
1506  QgsPoint oldCenter = center();
1507  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1508  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1509  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1510 
1511  zoomByFactor( scaleFactor, &newCenter );
1512  break;
1513  }
1514 
1515  case WheelNothing:
1516  // well, nothing!
1517  break;
1518  }
1519 }
1520 
1521 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1522 {
1523  mWheelAction = action;
1524  mWheelZoomFactor = factor;
1525 }
1526 
1528 {
1529  zoomByFactor( 1 / mWheelZoomFactor );
1530 }
1531 
1533 {
1534  zoomByFactor( mWheelZoomFactor );
1535 }
1536 
1537 void QgsMapCanvas::zoomScale( double newScale )
1538 {
1539  zoomByFactor( newScale / scale() );
1540 }
1541 
1542 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1543 {
1544  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1545 
1546  // transform the mouse pos to map coordinates
1549  r.scale( scaleFactor, &center );
1550  setExtent( r, true );
1551  refresh();
1552 }
1553 
1555 {
1556  mCanvasProperties->mouseLastXY = e->pos();
1557 
1558  if ( mCanvasProperties->panSelectorDown )
1559  {
1560  panAction( e );
1561  }
1562  else
1563  {
1564  // call handler of current map tool
1565  if ( mMapTool )
1566  {
1568  mMapTool->canvasMoveEvent( me.data() );
1569  }
1570  }
1571 
1572  // show x y on status bar
1573  QPoint xy = e->pos();
1575  emit xyCoordinates( coord );
1576 } // mouseMoveEvent
1577 
1578 
1579 
1582 {
1583  if ( !tool )
1584  return;
1585 
1586  if ( mMapTool )
1587  {
1588  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1589  mMapTool->deactivate();
1590  }
1591 
1592  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1593  {
1594  // if zoom or pan tool will be active, save old tool
1595  // to bring it back on right click
1596  // (but only if it wasn't also zoom or pan tool)
1597  mLastNonZoomMapTool = mMapTool;
1598  }
1599  else
1600  {
1601  mLastNonZoomMapTool = nullptr;
1602  }
1603 
1604  QgsMapTool* oldTool = mMapTool;
1605 
1606  // set new map tool and activate it
1607  mMapTool = tool;
1608  if ( mMapTool )
1609  {
1610  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1611  mMapTool->activate();
1612  }
1613 
1614  emit mapToolSet( mMapTool );
1615  emit mapToolSet( mMapTool, oldTool );
1616 } // setMapTool
1617 
1619 {
1620  if ( mMapTool && mMapTool == tool )
1621  {
1622  mMapTool->deactivate();
1623  mMapTool = nullptr;
1624  emit mapToolSet( nullptr );
1625  emit mapToolSet( nullptr, mMapTool );
1626  setCursor( Qt::ArrowCursor );
1627  }
1628 
1629  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1630  {
1631  mLastNonZoomMapTool = nullptr;
1632  }
1633 }
1634 
1636 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1637 {
1638  // background of map's pixmap
1639  mSettings.setBackgroundColor( theColor );
1640 
1641  // background of the QGraphicsView
1642  QBrush bgBrush( theColor );
1643  setBackgroundBrush( bgBrush );
1644 #if 0
1645  QPalette palette;
1646  palette.setColor( backgroundRole(), theColor );
1647  setPalette( palette );
1648 #endif
1649 
1650  // background of QGraphicsScene
1651  mScene->setBackgroundBrush( bgBrush );
1652 } // setBackgroundColor
1653 
1655 {
1656  return mScene->backgroundBrush().color();
1657 }
1658 
1660 {
1661  mSettings.setSelectionColor( color );
1662 }
1663 
1665 {
1666  return mapSettings().layers().size();
1667 } // layerCount
1668 
1669 
1671 {
1672  QList<QgsMapLayer*> lst;
1673  Q_FOREACH ( const QString& layerID, mapSettings().layers() )
1674  {
1676  if ( layer )
1677  lst.append( layer );
1678  }
1679  return lst;
1680 }
1681 
1682 
1684 {
1685  // called when a layer has changed visibility setting
1686 
1687  refresh();
1688 
1689 } // layerStateChange
1690 
1692 {
1693  // called when a layer's CRS has been changed
1694  QObject *theSender = sender();
1695  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1696  QString destAuthId = mSettings.destinationCrs().authid();
1697  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1698 
1699 } // layerCrsChange
1700 
1701 
1702 void QgsMapCanvas::freeze( bool frz )
1703 {
1704  mFrozen = frz;
1705 } // freeze
1706 
1708 {
1709  return mFrozen;
1710 } // freeze
1711 
1712 
1714 {
1716  return mMap->paintDevice();
1718 }
1719 
1721 {
1722  return mapSettings().mapUnitsPerPixel();
1723 } // mapUnitsPerPixel
1724 
1725 
1727 {
1728  if ( mSettings.mapUnits() == u )
1729  return;
1730 
1731  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1732  mSettings.setMapUnits( u );
1733 
1734  updateScale();
1735 
1736  refresh(); // this will force the scale bar to be updated
1737 
1738  emit mapUnitsChanged();
1739 }
1740 
1741 
1743 {
1744  return mapSettings().mapUnits();
1745 }
1746 
1748 {
1749  return mSettings.layerStyleOverrides();
1750 }
1751 
1753 {
1754  if ( overrides == mSettings.layerStyleOverrides() )
1755  return;
1756 
1757  mSettings.setLayerStyleOverrides( overrides );
1759 }
1760 
1761 
1762 void QgsMapCanvas::setRenderFlag( bool theFlag )
1763 {
1764  mRenderFlag = theFlag;
1765 
1766  if ( mRenderFlag )
1767  {
1768  refresh();
1769  }
1770  else
1771  stopRendering();
1772 }
1773 
1774 #if 0
1775 void QgsMapCanvas::connectNotify( const char * signal )
1776 {
1777  Q_UNUSED( signal );
1778  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1779 } //connectNotify
1780 #endif
1781 
1783 {
1784  if ( !mSettings.hasCrsTransformEnabled() )
1785  return;
1786 
1787  QString destAuthId = mSettings.destinationCrs().authid();
1788  Q_FOREACH ( const QString& layerID, mSettings.layers() )
1789  {
1791  if ( !layer )
1792  continue;
1793 
1794  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1795  if ( vl && vl->geometryType() == QGis::NoGeometry )
1796  continue;
1797 
1798  // if there are more options, ask the user which datum transform to use
1799  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1800  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1801  }
1802 }
1803 
1804 
1805 
1807 {
1808  return mMapTool;
1809 }
1810 
1812 {
1813  // move map image and other items to standard position
1814  moveCanvasContents( true ); // true means reset
1815 
1816  // use start and end box points to calculate the extent
1817  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1818  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1819 
1820  // modify the center
1821  double dx = end.x() - start.x();
1822  double dy = end.y() - start.y();
1823  QgsPoint c = center();
1824  c.set( c.x() - dx, c.y() - dy );
1825  setCenter( c );
1826 
1827  refresh();
1828 }
1829 
1831 {
1832  Q_UNUSED( e );
1833 
1834  // move all map canvas items
1836 }
1837 
1839 {
1840  QPoint pnt( 0, 0 );
1841  if ( !reset )
1842  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1843 
1844  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1845 }
1846 
1848 {
1849  Q_UNUSED( mapLayer );
1850 }
1851 
1853 {
1854  return mCanvasProperties->mouseLastXY;
1855 }
1856 
1857 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1858 {
1859  if ( !mPreviewEffect )
1860  {
1861  return;
1862  }
1863 
1864  mPreviewEffect->setEnabled( previewEnabled );
1865 }
1866 
1868 {
1869  if ( !mPreviewEffect )
1870  {
1871  return false;
1872  }
1873 
1874  return mPreviewEffect->isEnabled();
1875 }
1876 
1878 {
1879  if ( !mPreviewEffect )
1880  {
1881  return;
1882  }
1883 
1884  mPreviewEffect->setMode( mode );
1885 }
1886 
1888 {
1889  if ( !mPreviewEffect )
1890  {
1892  }
1893 
1894  return mPreviewEffect->mode();
1895 }
1896 
1898 {
1899  if ( !mSnappingUtils )
1900  {
1901  // associate a dummy instance, but better than null pointer
1902  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1903  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1904  }
1905  return mSnappingUtils;
1906 }
1907 
1909 {
1910  mSnappingUtils = utils;
1911 }
1912 
1914 {
1915  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1916  if ( nodes.count() )
1917  {
1918  QDomNode node = nodes.item( 0 );
1919 
1920  QgsMapSettings tmpSettings;
1921  tmpSettings.readXML( node );
1922  setMapUnits( tmpSettings.mapUnits() );
1924  setDestinationCrs( tmpSettings.destinationCrs() );
1925  setExtent( tmpSettings.extent() );
1926  setRotation( tmpSettings.rotation() );
1927  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1929 
1930  clearExtentHistory(); // clear the extent history on project load
1931  }
1932  else
1933  {
1934  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1935  }
1936 }
1937 
1939 {
1940  // create node "mapcanvas" and call mMapRenderer->writeXML()
1941 
1942  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1943  if ( !nl.count() )
1944  {
1945  QgsDebugMsg( "Unable to find qgis element in project file" );
1946  return;
1947  }
1948  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1949 
1950  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1951  qgisNode.appendChild( mapcanvasNode );
1952 
1953  mSettings.writeXML( mapcanvasNode, doc );
1954  // TODO: store only units, extent, projections, dest CRS
1955 }
1956 
1958 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1959 {
1960  if ( !ml )
1961  {
1962  return;
1963  }
1964 
1965  //check if default datum transformation available
1966  QSettings s;
1967  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1968  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1969  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1970  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1971  {
1972  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1973  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1974  return;
1975  }
1976 
1977  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1978  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1979 
1980  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1981  {
1982  // just use the default transform
1983  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1984  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1985  return;
1986  }
1987 
1988  //get list of datum transforms
1990  if ( dt.size() < 2 )
1991  {
1992  return;
1993  }
1994 
1995  //if several possibilities: present dialog
1996  QgsDatumTransformDialog d( ml->name(), dt );
1997  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1998  if ( d.exec() == QDialog::Accepted )
1999  {
2000  int srcTransform = -1;
2001  int destTransform = -1;
2002  QList<int> t = d.selectedDatumTransform();
2003  if ( !t.isEmpty() )
2004  {
2005  srcTransform = t.at( 0 );
2006  }
2007  if ( t.size() > 1 )
2008  {
2009  destTransform = t.at( 1 );
2010  }
2011  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
2012  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
2013  if ( d.rememberSelection() )
2014  {
2015  s.setValue( settingsString + "_srcTransform", srcTransform );
2016  s.setValue( settingsString + "_destTransform", destTransform );
2017  }
2018  }
2019  else
2020  {
2021  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
2022  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
2023  }
2024 }
2025 
2026 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
2027 {
2029  r.scale( scaleFactor, center );
2030  setExtent( r, true );
2031  refresh();
2032 }
2033 
2035 {
2036  // Find out which layer it was that sent the signal.
2037  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
2038  emit selectionChanged( layer );
2039  refresh();
2040 }
2041 
2043 {
2044  // By default graphics view delegates the drag events to graphics items.
2045  // But we do not want that and by ignoring the drag enter we let the
2046  // parent (e.g. QgisApp) to handle drops of map layers etc.
2047  e->ignore();
2048 }
2049 
2050 void QgsMapCanvas::mapToolDestroyed()
2051 {
2052  QgsDebugMsg( "maptool destroyed" );
2053  mMapTool = nullptr;
2054 }
2055 
2056 #ifdef HAVE_TOUCH
2057 bool QgsMapCanvas::event( QEvent * e )
2058 {
2059  bool done = false;
2060  if ( e->type() == QEvent::Gesture )
2061  {
2062  // call handler of current map tool
2063  if ( mMapTool )
2064  {
2065  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
2066  }
2067  }
2068  else
2069  {
2070  // pass other events to base class
2071  done = QGraphicsView::event( e );
2072  }
2073  return done;
2074 }
2075 #endif
2076 
2078 {
2079  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
2080 }
2081 
2082 void QgsMapCanvas::enableRotation( bool enable )
2083 {
2084  QSettings().setValue( "/qgis/canvasRotation", enable );
2085 }
2086 
2088 {
2089  // reload all layers in canvas
2090  for ( int i = 0; i < layerCount(); i++ )
2091  {
2092  QgsMapLayer *l = layer( i );
2093  if ( l )
2094  l->reload();
2095  }
2096 
2097  // clear the cache
2098  clearCache();
2099 
2100  // and then refresh
2101  refresh();
2102 }
2103 
2105 {
2106  mSettings.setSegmentationTolerance( tolerance );
2107 }
2108 
2110 {
2111  mSettings.setSegmentationToleranceType( type );
2112 }
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
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
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.
QList< QGraphicsItem * > items() const
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)=0
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)
const T & previous()
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.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
QgsRectangle extent() const
returns current extent
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:239
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:504
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 save()
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:86
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)
QImage copy(const QRect &rectangle) const
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 setSegmentationTolerance(double tolerance)
Sets the segmentation tolerance applied when rendering curved geometries.
void setEnabled(bool enable)
QString tr(const char *sourceText, const char *disambiguation, int n)
virtual QImage renderedImage()=0
Get a preview/resulting image.
void setMagnificationFactor(double level)
Sets the factor of magnification to apply to the map canvas.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:108
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
int x() const
int y() const
void zoomLastStatusChanged(bool)
Emitted when zoom last status changed.
double magnificationFactor() const
Returns the magnification factor.
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 initFrom(const QWidget *widget)
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:819
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 ...
qreal x() const
qreal y() const
void append(const T &value)
void setOutputSize(QSize size)
Set the size of the resulting map image.
Q_DECL_DEPRECATED void showError(QgsMapLayer *mapLayer)
double magnificationFactor() const
Return the magnification factor.
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.
QSize outputSize() const
Return the size of the resulting map image.
void setMagnificationFactor(double factor)
Set the magnification factor.
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)
Returns a string representation of a double.
Definition: qgis.h:340
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 setSegmentationTolerance(double tolerance)
Sets the segmentation tolerance applied when rendering curved geometries.
void setMapUpdateInterval(int timeMilliseconds)
Set how often map preview should be updated while it is being rendered (in milliseconds) ...
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:818
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.
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 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 setSegmentationToleranceType(QgsAbstractGeometryV2::SegmentationToleranceType type)
Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
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:176
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:117
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:672
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.
void restore()
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:505
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
bool hasPrevious() const
QVariant data(int key) 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:87
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:388
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
Class for storing a coordinate reference system (CRS)
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.
void setExtent(const QgsRectangle &r, bool magnified=false)
Set the extent of the map canvas.
bool toBool() const
void translate(const QPointF &offset)
void setMouseTracking(bool enable)
UnitType
Map units that qgis supports.
Definition: qgis.h:159
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:193
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.
double toDouble(bool *ok) const
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...
QImage toImage() const
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:791
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
QString toString() const
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:89
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)
QPointF scenePos() const
void destroyed(QObject *obj)
void setSegmentationToleranceType(QgsAbstractGeometryV2::SegmentationToleranceType type)
Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
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