QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
245 
246  //segmentation parameters
247  QSettings settings;
248  double segmentationTolerance = settings.value( "/qgis/segmentationTolerance", "0.01745" ).toDouble();
249  QgsAbstractGeometryV2::SegmentationToleranceType toleranceType = QgsAbstractGeometryV2::SegmentationToleranceType( settings.value( "/qgis/segmentationToleranceType", 0 ).toInt() );
250  mSettings.setSegmentationTolerance( segmentationTolerance );
251  mSettings.setSegmentationToleranceType( toleranceType );
252 
253  mWheelZoomFactor = settings.value( "/qgis/zoom_factor", 2 ).toDouble();
254 
255  // class that will sync most of the changes between canvas and (legacy) map renderer
256  // it is parented to map canvas, will be deleted automatically
257  new QgsMapCanvasRendererSync( this, mMapRenderer );
258 
259  QSize s = viewport()->size();
260  mSettings.setOutputSize( s );
261  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
262  setSceneRect( 0, 0, s.width(), s.height() );
263  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
264 
265  moveCanvasContents( true );
266 
267  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
268  mMapUpdateTimer.setInterval( 250 );
269 
270 #ifdef Q_OS_WIN
271  // Enable touch event on Windows.
272  // Qt on Windows needs to be told it can take touch events or else it ignores them.
273  grabGesture( Qt::PinchGesture );
274  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
275 #endif
276 
277  mPreviewEffect = new QgsPreviewEffect( this );
278  viewport()->setGraphicsEffect( mPreviewEffect );
279 
280  QPixmap zoomPixmap = QPixmap(( const char ** )( zoom_in ) );
281  mZoomCursor = QCursor( zoomPixmap, 7, 7 );
282 
283  setInteractive( false );
284 
285  refresh();
286 
287 } // QgsMapCanvas ctor
288 
289 
291 {
292  if ( mMapTool )
293  {
294  mMapTool->deactivate();
295  mMapTool = nullptr;
296  }
297  mLastNonZoomMapTool = nullptr;
298 
299  // delete canvas items prior to deleteing the canvas
300  // because they might try to update canvas when it's
301  // already being destructed, ends with segfault
302  QList<QGraphicsItem*> list = mScene->items();
304  while ( it != list.end() )
305  {
306  QGraphicsItem* item = *it;
307  delete item;
308  ++it;
309  }
310 
311  mScene->deleteLater(); // crashes in python tests on windows
312 
313  delete mMapRenderer;
314  // mCanvasProperties auto-deleted via QScopedPointer
315  // CanvasProperties struct has its own dtor for freeing resources
316 
317  if ( mJob )
318  {
319  mJob->cancel();
320  Q_ASSERT( !mJob );
321  }
322 
323  delete mCache;
324 
325  delete mLabelingResults;
326 
327 } // dtor
328 
330 {
331  // do not go higher or lower than min max magnification ratio
332  double magnifierMin = QgisGui::CANVAS_MAGNIFICATION_MIN;
333  double magnifierMax = QgisGui::CANVAS_MAGNIFICATION_MAX;
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  //build the expression context
709  QgsExpressionContext expressionContext;
710  expressionContext << QgsExpressionContextUtils::globalScope()
713  << new QgsExpressionContextScope( mExpressionContextScope );
714 
715  mSettings.setExpressionContext( expressionContext );
716 
717  // create the renderer job
718  Q_ASSERT( !mJob );
719  mJobCancelled = false;
720  if ( mUseParallelRendering )
721  mJob = new QgsMapRendererParallelJob( mSettings );
722  else
723  mJob = new QgsMapRendererSequentialJob( mSettings );
724  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
725  mJob->setCache( mCache );
726 
727  QStringList layersForGeometryCache;
728  Q_FOREACH ( const QString& id, mSettings.layers() )
729  {
730  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
731  {
732  if ( vl->isEditable() )
733  layersForGeometryCache << id;
734  }
735  }
736  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
737 
738  mJob->start();
739 
740  // from now on we can accept refresh requests again
741  // this must be reset only after the job has been started, because
742  // some providers (yes, it's you WCS and AMS!) during preparation
743  // do network requests and start an internal event loop, which may
744  // end up calling refresh() and would schedule another refresh,
745  // deleting the one we have just started.
746  mRefreshScheduled = false;
747 
748  mMapUpdateTimer.start();
749 
750  emit renderStarting();
751 }
752 
753 
754 void QgsMapCanvas::rendererJobFinished()
755 {
756  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
757 
758  mMapUpdateTimer.stop();
759 
760  // TODO: would be better to show the errors in message bar
761  Q_FOREACH ( const QgsMapRendererJob::Error& error, mJob->errors() )
762  {
763  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
764  }
765 
766  if ( !mJobCancelled )
767  {
768  // take labeling results before emitting renderComplete, so labeling map tools
769  // connected to signal work with correct results
770  delete mLabelingResults;
771  mLabelingResults = mJob->takeLabelingResults();
772 
773  QImage img = mJob->renderedImage();
774 
775  // emit renderComplete to get our decorations drawn
776  QPainter p( &img );
777  emit renderComplete( &p );
778 
779  QSettings settings;
780  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
781  {
782  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
783  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
784  }
785 
786  if ( mDrawRenderingStats )
787  {
788  int w = img.width(), h = img.height();
789  QFont fnt = p.font();
790  fnt.setBold( true );
791  p.setFont( fnt );
792  int lh = p.fontMetrics().height() * 2;
793  QRect r( 0, h - lh, w, lh );
794  p.setPen( Qt::NoPen );
795  p.setBrush( QColor( 0, 0, 0, 110 ) );
796  p.drawRect( r );
797  p.setPen( Qt::white );
798  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
799  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
800  }
801 
802  p.end();
803 
804  mMap->setContent( img, imageRect( img, mSettings ) );
805  }
806 
807  // now we are in a slot called from mJob - do not delete it immediately
808  // so the class is still valid when the execution returns to the class
809  mJob->deleteLater();
810  mJob = nullptr;
811 
812  emit mapCanvasRefreshed();
813 }
814 
815 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
816 {
817  // This is a hack to pass QgsMapCanvasItem::setRect what it
818  // expects (encoding of position and size of the item)
819  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
820  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
821  double res = m2p.mapUnitsPerPixel();
822  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
823  return rect;
824 }
825 
826 void QgsMapCanvas::mapUpdateTimeout()
827 {
828  if ( mJob )
829  {
830  const QImage& img = mJob->renderedImage();
831  mMap->setContent( img, imageRect( img, mSettings ) );
832  }
833 }
834 
836 {
837  if ( mJob )
838  {
839  QgsDebugMsg( "CANVAS stop rendering!" );
840  mJobCancelled = true;
841  disconnect( mJob, SIGNAL( finished() ), this, SLOT( rendererJobFinished() ) );
842  connect( mJob, SIGNAL( finished() ), mJob, SLOT( deleteLater() ) );
843  mJob->cancelWithoutBlocking();
844  mJob = nullptr;
845  }
846 }
847 
849 {
850 }
851 
852 //the format defaults to "PNG" if not specified
853 void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat )
854 {
855  QPainter painter;
856  QImage image;
857 
858  //
859  //check if the optional QPaintDevice was supplied
860  //
861  if ( theQPixmap )
862  {
863  image = theQPixmap->toImage();
864  painter.begin( &image );
865 
866  // render
867  QgsMapRendererCustomPainterJob job( mSettings, &painter );
868  job.start();
869  job.waitForFinished();
870  emit renderComplete( &painter );
871  }
872  else //use the map view
873  {
874  image = mMap->contentImage().copy();
875  painter.begin( &image );
876  }
877 
878  // draw annotations
880  option.initFrom( this );
881  QGraphicsItem* item;
883  i.toBack();
884  while ( i.hasPrevious() )
885  {
886  item = i.previous();
887 
888  if ( !item || item->data( 0 ).toString() != "AnnotationItem" )
889  {
890  continue;
891  }
892 
893  painter.save();
894 
895  QPointF itemScenePos = item->scenePos();
896  painter.translate( itemScenePos.x(), itemScenePos.y() );
897 
898  item->paint( &painter, &option );
899 
900  painter.restore();
901  }
902 
903  painter.end();
904  image.save( theFileName, theFormat.toLocal8Bit().data() );
905 
906  //create a world file to go with the image...
908  QString myHeader;
909  // note: use 17 places of precision for all numbers output
910  //Pixel XDim
911  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
912  //Rotation on y axis - hard coded
913  myHeader += "0 \r\n";
914  //Rotation on x axis - hard coded
915  myHeader += "0 \r\n";
916  //Pixel YDim - almost always negative - see
917  //http://en.wikipedia.org/wiki/World_file#cite_note-2
918  myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
919  //Origin X (center of top left cell)
920  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
921  //Origin Y (center of top left cell)
922  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
923  QFileInfo myInfo = QFileInfo( theFileName );
924  // build the world file name
925  QString outputSuffix = myInfo.suffix();
926  QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.baseName() + '.'
927  + outputSuffix.at( 0 ) + outputSuffix.at( myInfo.suffix().size() - 1 ) + 'w';
928  QFile myWorldFile( myWorldFileName );
929  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
930  {
931  return;
932  }
933  QTextStream myStream( &myWorldFile );
934  myStream << myHeader;
935 } // saveAsImage
936 
937 
938 
940 {
941  return mapSettings().visibleExtent();
942 } // extent
943 
945 {
946  return mapSettings().fullExtent();
947 } // extent
948 
949 
950 void QgsMapCanvas::setExtent( const QgsRectangle& r, bool magnified )
951 {
952  QgsRectangle current = extent();
953 
954  if (( r == current ) && magnified )
955  return;
956 
957  if ( r.isEmpty() )
958  {
959  if ( !mSettings.hasValidSettings() )
960  {
961  // we can't even just move the map center
962  QgsDebugMsg( "Empty extent - ignoring" );
963  return;
964  }
965 
966  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
967  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
968  setCenter( r.center() );
969  }
970  else
971  {
972  mSettings.setExtent( r, magnified );
973  }
974  emit extentsChanged();
975  updateScale();
976  if ( mLastExtent.size() > 20 )
977  mLastExtent.removeAt( 0 );
978 
979  //clear all extent items after current index
980  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
981  {
982  mLastExtent.removeAt( i );
983  }
984 
985  mLastExtent.append( extent() );
986 
987  // adjust history to no more than 20
988  if ( mLastExtent.size() > 20 )
989  {
990  mLastExtent.removeAt( 0 );
991  }
992 
993  // the last item is the current extent
994  mLastExtentIndex = mLastExtent.size() - 1;
995 
996  // update controls' enabled state
997  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
998  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
999  // notify canvas items of change
1001 
1002 } // setExtent
1003 
1005 {
1007  double x = center.x();
1008  double y = center.y();
1009  setExtent(
1010  QgsRectangle(
1011  x - r.width() / 2.0, y - r.height() / 2.0,
1012  x + r.width() / 2.0, y + r.height() / 2.0
1013  ),
1014  true
1015  );
1016 } // setCenter
1017 
1019 {
1021  return r.center();
1022 }
1023 
1024 
1026 {
1027  return mapSettings().rotation();
1028 } // rotation
1029 
1030 void QgsMapCanvas::setRotation( double degrees )
1031 {
1032  if ( !rotationEnabled() )
1033  return;
1034 
1035  double current = rotation();
1036 
1037  if ( degrees == current )
1038  return;
1039 
1040  mSettings.setRotation( degrees );
1041  emit rotationChanged( degrees );
1042  emit extentsChanged(); // visible extent changes with rotation
1043 
1044  // notify canvas items of change (needed?)
1046 
1047 } // setRotation
1048 
1049 
1051 {
1052  emit scaleChanged( mapSettings().scale() );
1053 }
1054 
1055 
1057 {
1058  refresh();
1059 } // clear
1060 
1061 
1063 {
1065  // If the full extent is an empty set, don't do the zoom
1066  if ( !extent.isEmpty() )
1067  {
1068  // Add a 5% margin around the full extent
1069  extent.scale( 1.05 );
1070  setExtent( extent );
1071  }
1072  refresh();
1073 
1074 } // zoomToFullExtent
1075 
1076 
1077 
1079 {
1080  if ( mLastExtentIndex > 0 )
1081  {
1082  mLastExtentIndex--;
1083  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1084  emit extentsChanged();
1085  updateScale();
1086  refresh();
1087  // update controls' enabled state
1088  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1089  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1090  // notify canvas items of change
1092  }
1093 
1094 } // zoomToPreviousExtent
1095 
1097 {
1098  if ( mLastExtentIndex < mLastExtent.size() - 1 )
1099  {
1100  mLastExtentIndex++;
1101  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
1102  emit extentsChanged();
1103  updateScale();
1104  refresh();
1105  // update controls' enabled state
1106  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1107  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1108  // notify canvas items of change
1110  }
1111 }// zoomToNextExtent
1112 
1114 {
1115  mLastExtent.clear(); // clear the zoom history list
1116  mLastExtent.append( extent() ) ; // set the current extent in the list
1117  mLastExtentIndex = mLastExtent.size() - 1;
1118  // update controls' enabled state
1119  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1120  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1121 }// clearExtentHistory
1122 
1123 
1125 {
1127 }
1128 
1130 {
1131  if ( !layer )
1132  {
1133  // use current layer by default
1134  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1135  }
1136 
1137  if ( !layer || layer->selectedFeatureCount() == 0 )
1138  return;
1139 
1141  zoomToFeatureExtent( rect );
1142 } // zoomToSelected
1143 
1145 {
1146  // no selected features, only one selected point feature
1147  //or two point features with the same x- or y-coordinates
1148  if ( rect.isEmpty() )
1149  {
1150  // zoom in
1151  QgsPoint c = rect.center();
1152  rect = extent();
1153  rect.scale( 1.0, &c );
1154  }
1155  //zoom to an area
1156  else
1157  {
1158  // Expand rect to give a bit of space around the selected
1159  // objects so as to keep them clear of the map boundaries
1160  // The same 5% should apply to all margins.
1161  rect.scale( 1.05 );
1162  }
1163 
1164  setExtent( rect );
1165  refresh();
1166 }
1167 
1169 {
1170  if ( !layer )
1171  {
1172  return;
1173  }
1174 
1175  QgsFeatureIterator it = layer->getFeatures( QgsFeatureRequest().setFilterFids( ids ).setSubsetOfAttributes( QgsAttributeList() ) );
1177  rect.setMinimal();
1178  QgsFeature fet;
1179  int featureCount = 0;
1180  while ( it.nextFeature( fet ) )
1181  {
1182  const QgsGeometry* geom = fet.constGeometry();
1183  QString errorMessage;
1184  if ( !geom || geom->isEmpty() )
1185  {
1186  errorMessage = tr( "Feature does not have a geometry" );
1187  }
1188  else if ( geom->geometry()->isEmpty() )
1189  {
1190  errorMessage = tr( "Feature geometry is empty" );
1191  }
1192  if ( !errorMessage.isEmpty() )
1193  {
1194  emit messageEmitted( tr( "Zoom to feature id failed" ), errorMessage, QgsMessageBar::WARNING );
1195  return;
1196  }
1198  rect.combineExtentWith( r );
1199  featureCount++;
1200  }
1201 
1202  if ( featureCount != ids.count() )
1203  {
1204  return;
1205  }
1206 
1207  zoomToFeatureExtent( rect );
1208 }
1209 
1211 {
1212  if ( !layer )
1213  {
1214  // use current layer by default
1215  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1216  }
1217 
1218  if ( !layer || layer->selectedFeatureCount() == 0 )
1219  return;
1220 
1222  if ( !rect.isNull() )
1223  {
1224  setCenter( rect.center() );
1225  refresh();
1226  }
1227  else
1228  {
1229  emit messageEmitted( tr( "Cannot pan to selected feature(s)" ), tr( "Geometry is NULL" ), QgsMessageBar::WARNING );
1230  }
1231 } // panToSelected
1232 
1234 {
1235  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1236  {
1237  emit keyPressed( e );
1238  return;
1239  }
1240 
1241  if ( ! mCanvasProperties->mouseButtonDown )
1242  {
1243  // Don't want to interfer with mouse events
1244 
1245  QgsRectangle currentExtent = mapSettings().visibleExtent();
1246  double dx = qAbs( currentExtent.width() / 4 );
1247  double dy = qAbs( currentExtent.height() / 4 );
1248 
1249  switch ( e->key() )
1250  {
1251  case Qt::Key_Left:
1252  QgsDebugMsg( "Pan left" );
1253  setCenter( center() - QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1254  refresh();
1255  break;
1256 
1257  case Qt::Key_Right:
1258  QgsDebugMsg( "Pan right" );
1259  setCenter( center() + QgsVector( dx, 0 ).rotateBy( rotation() * M_PI / 180.0 ) );
1260  refresh();
1261  break;
1262 
1263  case Qt::Key_Up:
1264  QgsDebugMsg( "Pan up" );
1265  setCenter( center() + QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1266  refresh();
1267  break;
1268 
1269  case Qt::Key_Down:
1270  QgsDebugMsg( "Pan down" );
1271  setCenter( center() - QgsVector( 0, dy ).rotateBy( rotation() * M_PI / 180.0 ) );
1272  refresh();
1273  break;
1274 
1275 
1276 
1277  case Qt::Key_Space:
1278  QgsDebugMsg( "Pressing pan selector" );
1279 
1280  //mCanvasProperties->dragging = true;
1281  if ( ! e->isAutoRepeat() )
1282  {
1283  QApplication::setOverrideCursor( Qt::ClosedHandCursor );
1284  mCanvasProperties->panSelectorDown = true;
1285  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1286  }
1287  break;
1288 
1289  case Qt::Key_PageUp:
1290  QgsDebugMsg( "Zoom in" );
1291  zoomIn();
1292  break;
1293 
1294  case Qt::Key_PageDown:
1295  QgsDebugMsg( "Zoom out" );
1296  zoomOut();
1297  break;
1298 
1299 #if 0
1300  case Qt::Key_P:
1301  mUseParallelRendering = !mUseParallelRendering;
1302  refresh();
1303  break;
1304 
1305  case Qt::Key_S:
1306  mDrawRenderingStats = !mDrawRenderingStats;
1307  refresh();
1308  break;
1309 #endif
1310 
1311  default:
1312  // Pass it on
1313  if ( mMapTool )
1314  {
1315  mMapTool->keyPressEvent( e );
1316  }
1317  else e->ignore();
1318 
1319  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1320  }
1321  }
1322 
1323  emit keyPressed( e );
1324 
1325 } //keyPressEvent()
1326 
1328 {
1329  QgsDebugMsg( "keyRelease event" );
1330 
1331  switch ( e->key() )
1332  {
1333  case Qt::Key_Space:
1334  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1335  {
1336  QgsDebugMsg( "Releasing pan selector" );
1338  mCanvasProperties->panSelectorDown = false;
1339  panActionEnd( mCanvasProperties->mouseLastXY );
1340  }
1341  break;
1342 
1343  default:
1344  // Pass it on
1345  if ( mMapTool )
1346  {
1347  mMapTool->keyReleaseEvent( e );
1348  }
1349  else e->ignore();
1350 
1351  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1352  }
1353 
1354  emit keyReleased( e );
1355 
1356 } //keyReleaseEvent()
1357 
1358 
1360 {
1361  // call handler of current map tool
1362  if ( mMapTool )
1363  {
1365  mMapTool->canvasDoubleClickEvent( me.data() );
1366  }
1367 }// mouseDoubleClickEvent
1368 
1369 
1370 void QgsMapCanvas::beginZoomRect( QPoint pos )
1371 {
1372  mZoomRect.setRect( 0, 0, 0, 0 );
1373  QApplication::setOverrideCursor( mZoomCursor );
1374  mZoomDragging = true;
1375  mZoomRubberBand.reset( new QgsRubberBand( this, QGis::Polygon ) );
1376  QColor color( Qt::blue );
1377  color.setAlpha( 63 );
1378  mZoomRubberBand->setColor( color );
1379  mZoomRect.setTopLeft( pos );
1380 }
1381 
1382 void QgsMapCanvas::endZoomRect( QPoint pos )
1383 {
1384  mZoomDragging = false;
1385  mZoomRubberBand.reset( nullptr );
1387 
1388  // store the rectangle
1389  mZoomRect.setRight( pos.x() );
1390  mZoomRect.setBottom( pos.y() );
1391 
1392  if ( mZoomRect.width() < 5 && mZoomRect.height() < 5 )
1393  {
1394  //probably a mistake - would result in huge zoom!
1395  return;
1396  }
1397 
1398  //account for bottom right -> top left dragging
1399  mZoomRect = mZoomRect.normalized();
1400 
1401  // set center and zoom
1402  const QSize& zoomRectSize = mZoomRect.size();
1403  const QSize& canvasSize = mSettings.outputSize();
1404  double sfx = ( double )zoomRectSize.width() / canvasSize.width();
1405  double sfy = ( double )zoomRectSize.height() / canvasSize.height();
1406  double sf = qMax( sfx, sfy );
1407 
1408  QgsPoint c = mSettings.mapToPixel().toMapCoordinates( mZoomRect.center() );
1409 
1410  zoomByFactor( sf, &c );
1411  refresh();
1412 }
1413 
1415 {
1416  //use middle mouse button for panning, map tools won't receive any events in that case
1417  if ( e->button() == Qt::MidButton )
1418  {
1419  QApplication::setOverrideCursor( Qt::ClosedHandCursor );
1420  mCanvasProperties->panSelectorDown = true;
1421  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1422  }
1423  else
1424  {
1425  // call handler of current map tool
1426  if ( mMapTool )
1427  {
1428  if ( mMapTool->flags() & QgsMapTool::AllowZoomRect && e->button() == Qt::LeftButton
1429  && e->modifiers() & Qt::ShiftModifier )
1430  {
1431  beginZoomRect( e->pos() );
1432  return;
1433  }
1434  else
1435  {
1437  mMapTool->canvasPressEvent( me.data() );
1438  }
1439  }
1440  }
1441 
1442  if ( mCanvasProperties->panSelectorDown )
1443  {
1444  return;
1445  }
1446 
1447  mCanvasProperties->mouseButtonDown = true;
1448  mCanvasProperties->rubberStartPoint = e->pos();
1449 
1450 } // mousePressEvent
1451 
1452 
1454 {
1455  //use middle mouse button for panning, map tools won't receive any events in that case
1456  if ( e->button() == Qt::MidButton )
1457  {
1459  mCanvasProperties->panSelectorDown = false;
1460  panActionEnd( mCanvasProperties->mouseLastXY );
1461  }
1462  else
1463  {
1464  if ( mZoomDragging && e->button() == Qt::LeftButton )
1465  {
1466  endZoomRect( e->pos() );
1467  return;
1468  }
1469 
1470  // call handler of current map tool
1471  if ( mMapTool )
1472  {
1473  // right button was pressed in zoom tool? return to previous non zoom tool
1474  if ( e->button() == Qt::RightButton && mMapTool->flags() & QgsMapTool::Transient )
1475  {
1476  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1477  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1478 
1479  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1480 
1481  // change to older non-zoom tool
1482  if ( mLastNonZoomMapTool
1483  && ( !( mLastNonZoomMapTool->flags() & QgsMapTool::EditTool )
1484  || ( vlayer && vlayer->isEditable() ) ) )
1485  {
1486  QgsMapTool* t = mLastNonZoomMapTool;
1487  mLastNonZoomMapTool = nullptr;
1488  setMapTool( t );
1489  }
1490  return;
1491  }
1493  mMapTool->canvasReleaseEvent( me.data() );
1494  }
1495  }
1496 
1497 
1498  mCanvasProperties->mouseButtonDown = false;
1499 
1500  if ( mCanvasProperties->panSelectorDown )
1501  return;
1502 
1503 } // mouseReleaseEvent
1504 
1506 {
1508  mResizeTimer->start( 500 );
1509 
1510  QSize lastSize = viewport()->size();
1511 
1512  mSettings.setOutputSize( lastSize );
1513  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1514 
1515  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1516 
1517  moveCanvasContents( true );
1518 
1519  // notify canvas items of change
1521 
1522  updateScale();
1523 
1524  //refresh();
1525 
1526  emit extentsChanged();
1527 }
1528 
1530 {
1531  // no custom event handling anymore
1532 
1534 } // paintEvent
1535 
1537 {
1538  QList<QGraphicsItem*> list = mScene->items();
1540  while ( it != list.end() )
1541  {
1542  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1543 
1544  if ( item )
1545  {
1546  item->updatePosition();
1547  }
1548 
1549  ++it;
1550  }
1551 }
1552 
1553 
1555 {
1556  // Zoom the map canvas in response to a mouse wheel event. Moving the
1557  // wheel forward (away) from the user zooms in
1558 
1559  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1560 
1561  if ( mMapTool )
1562  {
1563  mMapTool->wheelEvent( e );
1564  if ( e->isAccepted() )
1565  return;
1566  }
1567 
1568  double zoomFactor = mWheelZoomFactor;
1569  if ( e->modifiers() & Qt::ControlModifier )
1570  {
1571  //holding ctrl while wheel zooming results in a finer zoom
1572  zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1573  }
1574 
1575  double signedWheelFactor = e->delta() > 0 ? 1 / zoomFactor : zoomFactor;
1576 
1577  // zoom map to mouse cursor by scaling
1578  QgsPoint oldCenter = center();
1579  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1580  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * signedWheelFactor ),
1581  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * signedWheelFactor ) );
1582 
1583  zoomByFactor( signedWheelFactor, &newCenter );
1584 }
1585 
1586 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1587 {
1588  Q_UNUSED( action );
1589  setWheelFactor( factor );
1590 }
1591 
1592 void QgsMapCanvas::setWheelFactor( double factor )
1593 {
1594  mWheelZoomFactor = factor;
1595 }
1596 
1598 {
1599  // magnification is alreday handled in zoomByFactor
1600  zoomByFactor( 1 / mWheelZoomFactor );
1601 }
1602 
1604 {
1605  // magnification is alreday handled in zoomByFactor
1606  zoomByFactor( mWheelZoomFactor );
1607 }
1608 
1609 void QgsMapCanvas::zoomScale( double newScale )
1610 {
1611  zoomByFactor( newScale / scale() );
1612 }
1613 
1614 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1615 {
1616  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1617 
1618  if ( mScaleLocked )
1619  {
1621  }
1622  else
1623  {
1624  // transform the mouse pos to map coordinates
1627  r.scale( scaleFactor, &center );
1628  setExtent( r, true );
1629  refresh();
1630  }
1631 }
1632 
1633 void QgsMapCanvas::setScaleLocked( bool isLocked )
1634 {
1635  mScaleLocked = isLocked;
1636 }
1637 
1639 {
1640  mCanvasProperties->mouseLastXY = e->pos();
1641 
1642  if ( mCanvasProperties->panSelectorDown )
1643  {
1644  panAction( e );
1645  }
1646  else if ( mZoomDragging )
1647  {
1648  mZoomRect.setBottomRight( e->pos() );
1649  mZoomRubberBand->setToCanvasRectangle( mZoomRect );
1650  mZoomRubberBand->show();
1651  }
1652  else
1653  {
1654  // call handler of current map tool
1655  if ( mMapTool )
1656  {
1658  mMapTool->canvasMoveEvent( me.data() );
1659  }
1660  }
1661 
1662  // show x y on status bar
1663  QPoint xy = e->pos();
1665  emit xyCoordinates( coord );
1666 } // mouseMoveEvent
1667 
1668 
1669 
1672 {
1673  if ( !tool )
1674  return;
1675 
1676  if ( mMapTool )
1677  {
1678  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1679  mMapTool->deactivate();
1680  }
1681 
1682  if (( tool->flags() & QgsMapTool::Transient )
1683  && mMapTool && !( mMapTool->flags() & QgsMapTool::Transient ) )
1684  {
1685  // if zoom or pan tool will be active, save old tool
1686  // to bring it back on right click
1687  // (but only if it wasn't also zoom or pan tool)
1688  mLastNonZoomMapTool = mMapTool;
1689  }
1690  else
1691  {
1692  mLastNonZoomMapTool = nullptr;
1693  }
1694 
1695  QgsMapTool* oldTool = mMapTool;
1696 
1697  // set new map tool and activate it
1698  mMapTool = tool;
1699  if ( mMapTool )
1700  {
1701  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1702  mMapTool->activate();
1703  }
1704 
1705  emit mapToolSet( mMapTool );
1706  emit mapToolSet( mMapTool, oldTool );
1707 } // setMapTool
1708 
1710 {
1711  if ( mMapTool && mMapTool == tool )
1712  {
1713  mMapTool->deactivate();
1714  mMapTool = nullptr;
1715  emit mapToolSet( nullptr );
1716  emit mapToolSet( nullptr, mMapTool );
1717  setCursor( Qt::ArrowCursor );
1718  }
1719 
1720  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1721  {
1722  mLastNonZoomMapTool = nullptr;
1723  }
1724 }
1725 
1727 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1728 {
1729  // background of map's pixmap
1730  mSettings.setBackgroundColor( theColor );
1731 
1732  // background of the QGraphicsView
1733  QBrush bgBrush( theColor );
1734  setBackgroundBrush( bgBrush );
1735 #if 0
1736  QPalette palette;
1737  palette.setColor( backgroundRole(), theColor );
1738  setPalette( palette );
1739 #endif
1740 
1741  // background of QGraphicsScene
1742  mScene->setBackgroundBrush( bgBrush );
1743 } // setBackgroundColor
1744 
1746 {
1747  return mScene->backgroundBrush().color();
1748 }
1749 
1751 {
1752  mSettings.setSelectionColor( color );
1753 }
1754 
1756 {
1757  return mapSettings().layers().size();
1758 } // layerCount
1759 
1760 
1762 {
1763  QList<QgsMapLayer*> lst;
1764  Q_FOREACH ( const QString& layerID, mapSettings().layers() )
1765  {
1767  if ( layer )
1768  lst.append( layer );
1769  }
1770  return lst;
1771 }
1772 
1773 
1775 {
1776  // called when a layer has changed visibility setting
1777 
1778  refresh();
1779 
1780 } // layerStateChange
1781 
1783 {
1784  // called when a layer's CRS has been changed
1785  QObject *theSender = sender();
1786  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1787  QString destAuthId = mSettings.destinationCrs().authid();
1788  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1789 
1790 } // layerCrsChange
1791 
1792 
1793 void QgsMapCanvas::freeze( bool frz )
1794 {
1795  mFrozen = frz;
1796 } // freeze
1797 
1799 {
1800  return mFrozen;
1801 } // freeze
1802 
1803 
1805 {
1807  return mMap->paintDevice();
1809 }
1810 
1812 {
1813  return mapSettings().mapUnitsPerPixel();
1814 } // mapUnitsPerPixel
1815 
1816 
1818 {
1819  if ( mSettings.mapUnits() == u )
1820  return;
1821 
1822  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1823  mSettings.setMapUnits( u );
1824 
1825  updateScale();
1826 
1827  refresh(); // this will force the scale bar to be updated
1828 
1829  emit mapUnitsChanged();
1830 }
1831 
1832 
1834 {
1835  return mapSettings().mapUnits();
1836 }
1837 
1839 {
1840  return mSettings.layerStyleOverrides();
1841 }
1842 
1844 {
1845  if ( overrides == mSettings.layerStyleOverrides() )
1846  return;
1847 
1848  mSettings.setLayerStyleOverrides( overrides );
1850 }
1851 
1852 
1853 void QgsMapCanvas::setRenderFlag( bool theFlag )
1854 {
1855  mRenderFlag = theFlag;
1856 
1857  if ( mRenderFlag )
1858  {
1859  refresh();
1860  }
1861  else
1862  stopRendering();
1863 }
1864 
1865 #if 0
1866 void QgsMapCanvas::connectNotify( const char * signal )
1867 {
1868  Q_UNUSED( signal );
1869  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1870 } //connectNotify
1871 #endif
1872 
1874 {
1875  if ( !mSettings.hasCrsTransformEnabled() )
1876  return;
1877 
1878  QString destAuthId = mSettings.destinationCrs().authid();
1879  Q_FOREACH ( const QString& layerID, mSettings.layers() )
1880  {
1882  if ( !layer )
1883  continue;
1884 
1885  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1886  if ( vl && vl->geometryType() == QGis::NoGeometry )
1887  continue;
1888 
1889  // if there are more options, ask the user which datum transform to use
1890  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1891  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1892  }
1893 }
1894 
1895 
1896 
1898 {
1899  return mMapTool;
1900 }
1901 
1903 {
1904  // move map image and other items to standard position
1905  moveCanvasContents( true ); // true means reset
1906 
1907  // use start and end box points to calculate the extent
1908  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1909  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1910 
1911  // modify the center
1912  double dx = end.x() - start.x();
1913  double dy = end.y() - start.y();
1914  QgsPoint c = center();
1915  c.set( c.x() - dx, c.y() - dy );
1916  setCenter( c );
1917 
1918  refresh();
1919 }
1920 
1922 {
1923  Q_UNUSED( e );
1924 
1925  // move all map canvas items
1927 }
1928 
1930 {
1931  QPoint pnt( 0, 0 );
1932  if ( !reset )
1933  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1934 
1935  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1936 }
1937 
1939 {
1940  Q_UNUSED( mapLayer );
1941 }
1942 
1944 {
1945  return mCanvasProperties->mouseLastXY;
1946 }
1947 
1948 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1949 {
1950  if ( !mPreviewEffect )
1951  {
1952  return;
1953  }
1954 
1955  mPreviewEffect->setEnabled( previewEnabled );
1956 }
1957 
1959 {
1960  if ( !mPreviewEffect )
1961  {
1962  return false;
1963  }
1964 
1965  return mPreviewEffect->isEnabled();
1966 }
1967 
1969 {
1970  if ( !mPreviewEffect )
1971  {
1972  return;
1973  }
1974 
1975  mPreviewEffect->setMode( mode );
1976 }
1977 
1979 {
1980  if ( !mPreviewEffect )
1981  {
1983  }
1984 
1985  return mPreviewEffect->mode();
1986 }
1987 
1989 {
1990  if ( !mSnappingUtils )
1991  {
1992  // associate a dummy instance, but better than null pointer
1993  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1994  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1995  }
1996  return mSnappingUtils;
1997 }
1998 
2000 {
2001  mSnappingUtils = utils;
2002 }
2003 
2005 {
2006  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
2007  if ( nodes.count() )
2008  {
2009  QDomNode node = nodes.item( 0 );
2010 
2011  QgsMapSettings tmpSettings;
2012  tmpSettings.readXML( node );
2013  setMapUnits( tmpSettings.mapUnits() );
2015  setDestinationCrs( tmpSettings.destinationCrs() );
2016  setExtent( tmpSettings.extent() );
2017  setRotation( tmpSettings.rotation() );
2018  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
2020 
2021  clearExtentHistory(); // clear the extent history on project load
2022  }
2023  else
2024  {
2025  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
2026  }
2027 }
2028 
2030 {
2031  // create node "mapcanvas" and call mMapRenderer->writeXML()
2032 
2033  QDomNodeList nl = doc.elementsByTagName( "qgis" );
2034  if ( !nl.count() )
2035  {
2036  QgsDebugMsg( "Unable to find qgis element in project file" );
2037  return;
2038  }
2039  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
2040 
2041  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
2042  qgisNode.appendChild( mapcanvasNode );
2043 
2044  mSettings.writeXML( mapcanvasNode, doc );
2045  // TODO: store only units, extent, projections, dest CRS
2046 }
2047 
2049 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
2050 {
2051  if ( !ml )
2052  {
2053  return;
2054  }
2055 
2056  //check if default datum transformation available
2057  QSettings s;
2058  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
2059  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
2060  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
2061  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
2062  {
2063  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
2064  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
2065  return;
2066  }
2067 
2070 
2071  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
2072  {
2073  // just use the default transform
2074  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
2075  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
2076  return;
2077  }
2078 
2079  //get list of datum transforms
2081  if ( dt.size() < 2 )
2082  {
2083  return;
2084  }
2085 
2086  //if several possibilities: present dialog
2087  QgsDatumTransformDialog d( ml->name(), dt );
2088  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
2089  if ( d.exec() == QDialog::Accepted )
2090  {
2091  int srcTransform = -1;
2092  int destTransform = -1;
2093  QList<int> t = d.selectedDatumTransform();
2094  if ( !t.isEmpty() )
2095  {
2096  srcTransform = t.at( 0 );
2097  }
2098  if ( t.size() > 1 )
2099  {
2100  destTransform = t.at( 1 );
2101  }
2102  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
2103  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
2104  if ( d.rememberSelection() )
2105  {
2106  s.setValue( settingsString + "_srcTransform", srcTransform );
2107  s.setValue( settingsString + "_destTransform", destTransform );
2108  }
2109  }
2110  else
2111  {
2112  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
2113  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
2114  }
2115 }
2116 
2117 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
2118 {
2119  if ( mScaleLocked )
2120  {
2121  // zoom map to mouse cursor by magnifying
2123  }
2124  else
2125  {
2127  r.scale( scaleFactor, center );
2128  setExtent( r, true );
2129  refresh();
2130  }
2131 }
2132 
2134 {
2135  // Find out which layer it was that sent the signal.
2136  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
2137  emit selectionChanged( layer );
2138  refresh();
2139 }
2140 
2142 {
2143  // By default graphics view delegates the drag events to graphics items.
2144  // But we do not want that and by ignoring the drag enter we let the
2145  // parent (e.g. QgisApp) to handle drops of map layers etc.
2146  e->ignore();
2147 }
2148 
2149 void QgsMapCanvas::mapToolDestroyed()
2150 {
2151  QgsDebugMsg( "maptool destroyed" );
2152  mMapTool = nullptr;
2153 }
2154 
2155 #ifdef HAVE_TOUCH
2156 bool QgsMapCanvas::event( QEvent * e )
2157 {
2158  bool done = false;
2159  if ( e->type() == QEvent::Gesture )
2160  {
2161  // call handler of current map tool
2162  if ( mMapTool )
2163  {
2164  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
2165  }
2166  }
2167  else
2168  {
2169  // pass other events to base class
2170  done = QGraphicsView::event( e );
2171  }
2172  return done;
2173 }
2174 #endif
2175 
2177 {
2178  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
2179 }
2180 
2181 void QgsMapCanvas::enableRotation( bool enable )
2182 {
2183  QSettings().setValue( "/qgis/canvasRotation", enable );
2184 }
2185 
2187 {
2188  // reload all layers in canvas
2189  for ( int i = 0; i < layerCount(); i++ )
2190  {
2191  QgsMapLayer *l = layer( i );
2192  if ( l )
2193  l->reload();
2194  }
2195 
2196  // clear the cache
2197  clearCache();
2198 
2199  // and then refresh
2200  refresh();
2201 }
2202 
2204 {
2205  mSettings.setSegmentationTolerance( tolerance );
2206 }
2207 
2209 {
2210  mSettings.setSegmentationToleranceType( type );
2211 }
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.
static unsigned index
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
QPoint mouseLastXY
Last seen point of the mouse.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
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.
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:217
virtual void canvasMoveEvent(QgsMapMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:145
bool isEmpty() const
Returns true if the geometry is empty.
QSize size() const
int mapUpdateInterval() const
Find out how often map preview should be updated while it is being rendered (in milliseconds) ...
Type type() const
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.
QgsCoordinateReferenceSystem crsByOgcWmsCrs(const QString &ogcCrs) const
Returns the CRS from a given OGC WMS-format Coordinate Reference System string.
void freeze(bool frz=true)
Freeze/thaw the map canvas.
virtual void setCanvasColor(const QColor &_newVal)
Write property of QColor bgColor.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
int width() const
void enableOverviewMode(QgsMapOverviewCanvas *overview)
QList< QgsMapLayer * > layers() const
return list of layers within map canvas.
QgsMapCanvas(QWidget *parent=nullptr, const char *name=nullptr)
Constructor.
int x() const
int y() const
bool end()
void setCursor(const QCursor &)
Q_DECL_DEPRECATED bool isDirty() const
Return the state of the canvas (dirty or not)
const char * zoom_in[]
Bitmap cursors for map operations.
Definition: qgscursors.cpp:21
QList< QGraphicsItem * > items() const
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)=0
void setBottomRight(const QPoint &position)
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Setter for stored overrides of styles for layers.
double magnificationFactor() const
Return the magnification factor.
A widget that displays an overview map.
QDomNode appendChild(const QDomNode &newChild)
double rotation() const
Return the rotation of the resulting map image Units are clockwise degrees.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void clearExtentHistory()
void setColor(ColorGroup group, ColorRole role, const QColor &color)
void readXML(QDomNode &theNode)
void push_back(const T &value)
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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QList< QGraphicsItem * > items() const
void stopRendering()
stop rendering (if there is any right now)
void setFocusPolicy(Qt::FocusPolicy policy)
bool save(const QString &fileName, const char *format, int quality) const
QObject * sender() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
const QFont & font() const
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent) const
transform bounding box from layer&#39;s CRS to output CRS
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
double rotation() const
Get the current map canvas rotation in clockwise degrees.
QgsPreviewEffect::PreviewMode previewMode() const
Returns the current preview mode for the map canvas.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
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
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
int size() const
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: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.
void setCurrentLayer(QgsMapLayer *layer)
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
int y() const
QgsPoint toMapPoint(double x, double y) const
void save()
int layerCount() const
return number of layers on the map
const QgsDatumTransformStore & datumTransformStore() const
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
QGis::UnitType mapUnits() const
Get units of map&#39;s geographical coordinates - used for scale calculation.
void setSceneRect(const QRectF &rect)
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QgsPoint toMapCoordinates(int x, int y) const
void readProject(const QDomDocument &)
called to read map canvas settings from project
bool panSelectorDown
Flag to indicate the pan selector key is held down by user.
void refresh()
Repaints the canvas map.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
QWidget * viewport() const
void renderComplete(QPainter *)
Emitted when the canvas has rendered.
void 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 QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
bool isCachingEnabled() const
Check whether images of rendered layers are curerently being cached.
QString join(const QString &separator) const
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Set map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
QgsMapTool * mapTool()
Returns the currently active tool.
bool isAutoRepeat() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void setLayerSet(const QStringList &layers)
change current layer set
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.
virtual Flags flags() const
Returns the flags for the map tool.
Definition: qgsmaptool.h:72
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
QImage contentImage() const
void 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.
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:109
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
int x() const
int y() const
void zoomLastStatusChanged(bool)
Emitted when zoom last status changed.
A graphics effect which can be applied to a widget to simulate various printing and color blindness m...
virtual void canvasPressEvent(QgsMapMouseEvent *e)
Mouse press event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:155
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
int size() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
void magnificationChanged(double)
Emitted when the scale of the map changes.
QString what() const
Definition: qgsexception.h:36
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void updateScale()
Emits signal scaleChanged to update scale in main window.
void 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)
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
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)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
A rectangular graphics item representing the map on the canvas.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
bool isAccepted() const
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
void ignore()
void saveAsImage(const QString &theFileName, QPixmap *QPixmap=nullptr, const QString &="PNG")
Save the convtents of the map canvas to disk as an image.
virtual void start() override
Start the rendering job and immediately return.
Q_DECL_DEPRECATED void clear()
Clear the map canvas.
void addEntry(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform, int destDatumTransform)
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
int toInt(bool *ok) const
int x() const
double scale()
Get the last reported scale of the canvas.
void rotationChanged(double)
Emitted when the rotation of the map changes.
void setMagnificationFactor(double factor)
Set the magnification factor.
void setInteractive(bool allowed)
void zoomNextStatusChanged(bool)
Emitted when zoom next status changed.
bool isEmpty() const
test if rectangle is empty.
void setRotation(double degrees)
Set the rotation of the resulting map image Units are clockwise degrees.
virtual bool event(QEvent *event)
void setPen(const QColor &color)
void clearCache()
Make sure to remove any rendered images from cache (does nothing if cache is not enabled) ...
int width() const
void layerCrsChange()
This slot is connected to the layer&#39;s CRS change.
void setBackgroundBrush(const QBrush &brush)
A class for drawing transient features (e.g.
Definition: qgsrubberband.h:32
double scale() const
Return the calculated scale of the map.
QGis::UnitType mapUnits() const
Get the current canvas map units.
void setMapUnits(QGis::UnitType u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
Errors errors() const
List of errors that happened during the rendering job - available when the rendering has been finishe...
Qt::MouseButton button() const
Job implementation that renders all layers in parallel.
QPalette::ColorRole backgroundRole() const
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
QString qgsDoubleToString(double a, int precision=17)
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.
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
QGis::UnitType mapUnits() const
Returns the units for the projection used by the CRS.
Enable anti-aliasing for map rendering.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
void setMapUnits(QGis::UnitType u)
void getDatumTransformInfo(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId)
ask user about datum transformation
#define M_PI
void enableMapTileRendering(bool theFlag)
sets map tile rendering flag
Q_DECL_DEPRECATED QPaintDevice & canvasPaintDevice()
Accessor for the canvas paint device.
void mouseDoubleClickEvent(QMouseEvent *e) override
Overridden mouse double click event.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
static bool rotationEnabled()
return if canvas rotation is enabled
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setOverrideCursor(const QCursor &cursor)
void panToSelected(QgsVectorLayer *layer=nullptr)
Pan to the selected features of current (vector) layer keeping same extent.
QList< int > QgsAttributeList
QPoint pos() const
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
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
void messageEmitted(const QString &title, const QString &message, QgsMessageBar::MessageLevel=QgsMessageBar::INFO)
emit a message (usually to be displayed in a message bar)
void destinationCrsChanged()
Emitted when map CRS has changed.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void updateDatumTransformEntries()
Make sure the datum transform store is properly populated.
void 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.
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
void deleteLater()
void 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.
double mapUnitsPerPixel() const
Return current map units per pixel.
Q_DECL_DEPRECATED QgsMapCanvasMap * map()
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
void setPreviewMode(QgsPreviewEffect::PreviewMode mode)
Sets a preview mode for the map canvas.
virtual void wheelEvent(QWheelEvent *e)
Mouse wheel event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:165
void refresh()
renders overview and updates panning widget
void set(double x, double y)
Sets the x and y value of the point.
Definition: qgspoint.h: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
const QgsMapToPixel & mapToPixel() const
QgsRectangle extent() const
returns current extent
QRect rect() const
void keyPressed(QKeyEvent *e)
Emit key press event.
void currentLayerChanged(QgsMapLayer *layer)
Emitted when the current layer is changed.
void zoomOut()
Zoom out with fixed factor.
Enable drawing of vertex markers for layers in editing mode.
void zoomToPreviousExtent()
Zoom to the previous extent (view)
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
PreviewMode mode() const
Returns the mode used for the preview effect.
void setPreviewModeEnabled(bool previewEnabled)
Enables a preview mode for the map canvas.
virtual void start()=0
Start the rendering job and immediately return.
static void enableRotation(bool enabled)
change canvas rotation support
QPoint mouseLastXY()
returns last position of mouse cursor
double magnificationFactor() const
Returns the magnification factor.
QgsMapLayer * currentLayer()
returns current layer (set by legend widget)
QMap< QString, QString > layerStyleOverrides() const
Getter for stored overrides of styles for layers.
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 hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
virtual QColor canvasColor() const
Read property of QColor bgColor.
int delta() const
void clear()
invalidate the cache contents
Abstract base class for all map tools.
Definition: qgsmaptool.h:50
void selectionChangedSlot()
Receives signal about selection change, and pass it on with layer info.
virtual void paintEvent(QPaintEvent *event)
Draw map such that there are no problems between adjacent tiles.
Job implementation that renders everything sequentially in one thread.
void restore()
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:516
bool isVisible() const
Definition: qgsmapcanvas.h:87
void setTopLeft(const QPoint &position)
double outputDpi() const
Return DPI used for conversion between real world units (e.g.
void setRight(int x)
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QGis::UnitType mapUnits() const
QVariant value(const QString &key, const QVariant &defaultValue) const
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
bool hasPrevious() const
QVariant data(int key) const
QStringList layerSet() const
QMap< QString, QString > layerStyleOverrides() const
Get map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
bool isInOverview() const
Definition: qgsmapcanvas.h:88
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.
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
QString suffix() const
void setSelectionColor(const QColor &color)
Set color that is used for drawing of selected vector features.
void layerStyleOverridesChanged()
Emitted when the configuration of overridden layer styles changes.
virtual void canvasDoubleClickEvent(QgsMapMouseEvent *e)
Mouse double click event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:150
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
bool hasEntryForLayer(QgsMapLayer *layer) const
void dragEnterEvent(QDragEnterEvent *e) override
Overridden drag enter event.
void setRect(int x, int y, int width, int height)
QFontMetrics fontMetrics() const
void writeProject(QDomDocument &)
called to write map canvas settings to project
void panAction(QMouseEvent *event)
Called when mouse is moving and pan is activated.
QgsRectangle fullExtent() const
returns current extent of layer set
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.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
Class for storing a coordinate reference system (CRS)
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
This class has all the configuration of snapping and can return answers to snapping queries...
const QgsLabelingResults * labelingResults() const
Get access to the labeling results (may be null)
int height() const
QgsMapCanvasRendererSync(QgsMapCanvas *canvas, QgsMapRenderer *renderer)
int height() const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setGraphicsEffect(QGraphicsEffect *effect)
void refreshAllLayers()
Reload all layers, clear the cache and refresh the canvas.
void zoomScale(double scale)
Zoom to a specific scale.
Class for doing transforms between two map coordinate systems.
void setExtent(const QgsRectangle &r, bool magnified=false)
Set the extent of the map canvas.
bool toBool() const
void translate(const QPointF &offset)
static const double CANVAS_MAGNIFICATION_MIN
Minimum magnification level allowed in map canvases.
Definition: qgisgui.h:57
void setMouseTracking(bool enable)
UnitType
Map units that qgis supports.
Definition: qgis.h:159
char * data()
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
bool isFrozen()
Accessor for frozen status of canvas.
const QgsMapToPixel * getCoordinateTransform()
Get the current coordinate transform.
void scaleChanged(double)
Emitted when the scale of the map changes.
void setCenter(const QgsPoint &center)
Set the center of the map canvas, in geographical coordinates.
void start(int msec)
bool isValid() const
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
void enableAntiAliasing(bool theFlag)
used to determine if anti-aliasing is enabled or not
virtual void cancelWithoutBlocking()=0
Triggers cancellation of the rendering job without blocking.
int height() const
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
void setSelectionColor(const QColor &color)
Set color of selected vector features.
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.
void setScaleLocked(bool isLocked)
Lock the scale, so zooming can be performed using magnication.
Class that stores computed placement from labeling engine.
This class is responsible for keeping cache of rendered images of individual layers.
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
void setMapUnits(QGis::UnitType mapUnits)
Set map units (needed by project properties dialog)
Custom exception class for Coordinate Reference System related exceptions.
const QPoint & pos() const
void updateOverview()
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
QImage toImage() const
Q_DECL_DEPRECATED void setDirty(bool _dirty)
Flag the canvas as dirty and needed a refresh.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
QStringList layers() const
Get list of layer IDs for map rendering The layers are stored in the reverse order of how they are re...
QPoint rubberStartPoint
Beginning point of a rubber band.
Class that does synchronization between QgsMapCanvas and its associated QgsMapRenderer: ...
Definition: qgsmapcanvas.h:833
QgsSnappingUtils * snappingUtils() const
Return snapping utility class that is associated with map canvas.
QString absolutePath() const
static const double CANVAS_MAGNIFICATION_MAX
Maximum magnification level allowed in map canvases.
Definition: qgisgui.h:65
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
virtual void waitForFinished() override
Block until the job has finished.
Represents a vector layer which manages a vector based data sets.
bool begin(QPaintDevice *device)
virtual void updatePosition()
called on changed extent or resize event to update position of the item
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
int selectedFeatureCount()
The number of features that are selected in this layer.
QgsPoint center() const
Get map center, in geographical coordinates.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
Definition: qgscrscache.cpp:91
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:90
void extentsChanged()
Emitted when the extents of the map change.
QString baseName() const
iterator begin()
QSize outputSize() const
Return the size of the resulting map image.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
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
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
virtual bool isActive() const =0
Tell whether the rendering job is currently running in background.
Q_DECL_DEPRECATED void updateMap()
void zoomByFactor(double scaleFactor, const QgsPoint *center=nullptr)
Zoom with the factor supplied.
double rotation() const
returns current rotation in clockwise degrees
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
void 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.
bool previewModeEnabled() const
Returns whether a preview mode is enabled for the map canvas.
void grabGesture(Qt::GestureType gesture, QFlags< Qt::GestureFlag > flags)
void layersChanged()
Emitted when a new set of layers has been received.
void setSingleShot(bool singleShot)
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
void writeXML(QDomNode &theNode, QDomDocument &theDoc)
void mapToolSet(QgsMapTool *tool)
Emit map tool changed event.
virtual void resizeEvent(QResizeEvent *event)
virtual void canvasReleaseEvent(QgsMapMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:160