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