QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsmapcanvas.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmapcanvas.cpp - description
3  -------------------
4 begin : Sun Jun 30 2002
5 copyright : (C) 2002 by Gary E.Sherman
6 email : sherman at mrcc.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
19 #include <QtGlobal>
20 #include <QApplication>
21 #include <QCursor>
22 #include <QDir>
23 #include <QFile>
24 #include <QGraphicsItem>
25 #include <QGraphicsScene>
26 #include <QGraphicsView>
27 #include <QKeyEvent>
28 #include <QMouseEvent>
29 #include <QPainter>
30 #include <QPaintEvent>
31 #include <QPixmap>
32 #include <QRect>
33 #include <QSettings>
34 #include <QTextStream>
35 #include <QResizeEvent>
36 #include <QString>
37 #include <QStringList>
38 #include <QWheelEvent>
39 
40 #include "qgis.h"
41 #include "qgsapplication.h"
42 #include "qgscrscache.h"
44 #include "qgslogger.h"
45 #include "qgsmapcanvas.h"
46 #include "qgsmapcanvasmap.h"
48 #include "qgsmaplayer.h"
49 #include "qgsmaplayerregistry.h"
50 #include "qgsmaptoolpan.h"
51 #include "qgsmaptoolzoom.h"
52 #include "qgsmaptopixel.h"
53 #include "qgsmapoverviewcanvas.h"
54 #include "qgsmaprenderer.h"
55 #include "qgsmaprenderercache.h"
59 #include "qgsmessagelog.h"
60 #include "qgsmessageviewer.h"
61 #include "qgspallabeling.h"
62 #include "qgsproject.h"
63 #include "qgsrubberband.h"
64 #include "qgsvectorlayer.h"
65 #include <math.h>
66 
67 
70 {
71  public:
72 
74 
77 
79  QPoint mouseLastXY;
80 
83 
86 };
87 
88 
90  : QObject( canvas )
91  , mCanvas( canvas )
92  , mRenderer( renderer )
93  , mSyncingExtent( false )
94 {
95  connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( onExtentC2R() ) );
96  connect( mRenderer, SIGNAL( extentsChanged() ), this, SLOT( onExtentR2C() ) );
97 
98  connect( mCanvas, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsC2R() ) );
99  connect( mRenderer, SIGNAL( mapUnitsChanged() ), this, SLOT( onMapUnitsR2C() ) );
100 
101  connect( mCanvas, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationC2R() ) );
102  connect( mRenderer, SIGNAL( rotationChanged( double ) ), this, SLOT( onMapRotationR2C() ) );
103 
104  connect( mCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ), this, SLOT( onCrsTransformC2R() ) );
105  connect( mRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( onCrsTransformR2C() ) );
106 
107  connect( mCanvas, SIGNAL( destinationCrsChanged() ), this, SLOT( onDestCrsC2R() ) );
108  connect( mRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( onDestCrsR2C() ) );
109 
110  connect( mCanvas, SIGNAL( layersChanged() ), this, SLOT( onLayersC2R() ) );
111  // TODO: layers R2C ? (should not happen!)
112 
113 }
114 
116 {
117  // protection against possible bounce back
118  if ( mSyncingExtent )
119  return;
120 
121  mSyncingExtent = true;
123  mSyncingExtent = false;
124 }
125 
127 {
128  // protection against possible bounce back
129  if ( mSyncingExtent )
130  return;
131 
132  mSyncingExtent = true;
134  mSyncingExtent = false;
135 }
136 
138 {
140 }
141 
143 {
145 }
146 
148 {
150 }
151 
153 {
155 }
156 
158 {
160 }
161 
163 {
165 }
166 
168 {
170 }
171 
173 {
175 }
176 
178 {
180 }
181 
182 
183 
184 QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
185  : QGraphicsView( parent )
186  , mCanvasProperties( new CanvasProperties )
187  , mJob( 0 )
188  , mJobCancelled( false )
189  , mLabelingResults( 0 )
190  , mUseParallelRendering( false )
191  , mDrawRenderingStats( false )
192  , mCache( 0 )
193  , mPreviewEffect( 0 )
194  , mSnappingUtils( 0 )
195 {
196  setObjectName( name );
197  mScene = new QGraphicsScene();
198  setScene( mScene );
199  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
200  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
201  mLastExtentIndex = -1;
202  mCurrentLayer = NULL;
203  mMapOverview = NULL;
204  mMapTool = NULL;
205  mLastNonZoomMapTool = NULL;
206 
207  mFrozen = false;
208  mRefreshScheduled = false;
209 
211 
212  // by default, the canvas is rendered
213  mRenderFlag = true;
214 
215  setMouseTracking( true );
216  setFocusPolicy( Qt::StrongFocus );
217 
218  mMapRenderer = new QgsMapRenderer;
219 
220  mResizeTimer = new QTimer( this );
221  mResizeTimer->setSingleShot( true );
222  connect( mResizeTimer, SIGNAL( timeout() ), this, SLOT( refresh() ) );
223 
224  // create map canvas item which will show the map
225  mMap = new QgsMapCanvasMap( this );
226  mScene->addItem( mMap );
227 
228  // project handling
229  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
230  this, SLOT( readProject( const QDomDocument & ) ) );
231  connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
232  this, SLOT( writeProject( QDomDocument & ) ) );
233 
236 
237  // class that will sync most of the changes between canvas and (legacy) map renderer
238  // it is parented to map canvas, will be deleted automatically
239  new QgsMapCanvasRendererSync( this, mMapRenderer );
240 
241  QSize s = viewport()->size();
242  mSettings.setOutputSize( s );
243  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
244  setSceneRect( 0, 0, s.width(), s.height() );
245  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
246 
247  moveCanvasContents( true );
248 
249  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
250  mMapUpdateTimer.setInterval( 250 );
251 
252 #ifdef Q_OS_WIN
253  // Enable touch event on Windows.
254  // Qt on Windows needs to be told it can take touch events or else it ignores them.
255  grabGesture( Qt::PinchGesture );
256  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
257 #endif
258 
259  mPreviewEffect = new QgsPreviewEffect( this );
260  viewport()->setGraphicsEffect( mPreviewEffect );
261 
262  setInteractive( false );
263 
264  refresh();
265 
266 } // QgsMapCanvas ctor
267 
268 
270 {
271  if ( mMapTool )
272  {
273  mMapTool->deactivate();
274  mMapTool = NULL;
275  }
276  mLastNonZoomMapTool = NULL;
277 
278  // delete canvas items prior to deleteing the canvas
279  // because they might try to update canvas when it's
280  // already being destructed, ends with segfault
281  QList<QGraphicsItem*> list = mScene->items();
282  QList<QGraphicsItem*>::iterator it = list.begin();
283  while ( it != list.end() )
284  {
285  QGraphicsItem* item = *it;
286  delete item;
287  ++it;
288  }
289 
290  mScene->deleteLater(); // crashes in python tests on windows
291 
292  delete mMapRenderer;
293  // mCanvasProperties auto-deleted via QScopedPointer
294  // CanvasProperties struct has its own dtor for freeing resources
295 
296  if ( mJob )
297  {
298  mJob->cancel();
299  Q_ASSERT( mJob == 0 );
300  }
301 
302  delete mCache;
303 
304  delete mLabelingResults;
305 
306 } // dtor
307 
309 {
310  mSettings.setFlag( QgsMapSettings::Antialiasing, theFlag );
311 
312  if ( mMapOverview )
313  mMapOverview->enableAntiAliasing( theFlag );
314 } // anti aliasing
315 
316 void QgsMapCanvas::useImageToRender( bool theFlag )
317 {
318  Q_UNUSED( theFlag );
319 }
320 
322 {
323  return mMap;
324 }
325 
327 {
328  return mMapRenderer;
329 }
330 
331 
333 {
334  const QStringList& layers = mapSettings().layers();
335  if ( index >= 0 && index < ( int ) layers.size() )
336  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
337  else
338  return NULL;
339 }
340 
341 
343 {
344  mCurrentLayer = layer;
345  emit currentLayerChanged( layer );
346 }
347 
349 {
350  return mapSettings().scale();
351 } // scale
352 
353 void QgsMapCanvas::setDirty( bool dirty )
354 {
355  if ( dirty )
356  refresh();
357 }
358 
360 {
361  return false;
362 }
363 
364 
365 
367 {
368  return mJob != 0;
369 } // isDrawing
370 
371 
372 // return the current coordinate transform based on the extents and
373 // device size
375 {
376  return &mapSettings().mapToPixel();
377 }
378 
379 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
380 {
381  // create layer set
382  QStringList layerSet, layerSetOverview;
383 
384  int i;
385  for ( i = 0; i < layers.size(); i++ )
386  {
387  QgsMapCanvasLayer &lyr = layers[i];
388  if ( !lyr.layer() )
389  {
390  continue;
391  }
392 
393  if ( lyr.isVisible() )
394  {
395  layerSet.push_back( lyr.layer()->id() );
396  }
397 
398  if ( lyr.isInOverview() )
399  {
400  layerSetOverview.push_back( lyr.layer()->id() );
401  }
402  }
403 
404  const QStringList& layerSetOld = mapSettings().layers();
405 
406  bool layerSetChanged = layerSetOld != layerSet;
407 
408  // update only if needed
409  if ( layerSetChanged )
410  {
411  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
412 
413  for ( i = 0; i < layerCount(); i++ )
414  {
415  // Add check if vector layer when disconnecting from selectionChanged slot
416  // Ticket #811 - racicot
418  if ( !currentLayer )
419  continue;
420  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
421  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
422  if ( isVectLyr )
423  {
424  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
425  }
426  }
427 
428  mSettings.setLayers( layerSet );
429 
430  for ( i = 0; i < layerCount(); i++ )
431  {
432  // Add check if vector layer when connecting to selectionChanged slot
433  // Ticket #811 - racicot
435  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
436  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
437  if ( isVectLyr )
438  {
439  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
440  }
441  }
442 
444 
445  QgsDebugMsg( "Layers have changed, refreshing" );
446  emit layersChanged();
447 
448  refresh();
449  }
450 
451  if ( mMapOverview )
452  {
453  const QStringList& layerSetOvOld = mMapOverview->layerSet();
454  if ( layerSetOvOld != layerSetOverview )
455  {
456  mMapOverview->setLayerSet( layerSetOverview );
457  }
458 
459  // refresh overview maplayers even if layer set is the same
460  // because full extent might have changed
461  updateOverview();
462  }
463 } // setLayerSet
464 
466 {
467  if ( mMapOverview )
468  {
469  // disconnect old map overview if exists
470  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
471  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
472  disconnect( this, SIGNAL( destinationCrsChanged() ),
473  mMapOverview, SLOT( destinationSrsChanged() ) );
474 
475  // map overview is not owned by map canvas so don't delete it...
476  }
477 
478  mMapOverview = overview;
479 
480  if ( overview )
481  {
482  // connect to the map render to copy its projection settings
483  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
484  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
485  connect( this, SIGNAL( destinationCrsChanged() ),
486  overview, SLOT( destinationSrsChanged() ) );
487  }
488 }
489 
491 {
492  return mSettings;
493 }
494 
496 {
497  if ( mSettings.hasCrsTransformEnabled() == enabled )
498  return;
499 
500  mSettings.setCrsTransformEnabled( enabled );
501 
503 
504  refresh();
505 
506  emit hasCrsTransformEnabledChanged( enabled );
507 }
508 
510 {
511  if ( mSettings.destinationCrs() == crs )
512  return;
513 
514  if ( mSettings.hasCrsTransformEnabled() )
515  {
516  // try to reproject current extent to the new one
517  QgsRectangle rect;
518  if ( !mSettings.visibleExtent().isEmpty() )
519  {
520  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
521  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
522  }
523  if ( !rect.isEmpty() )
524  {
525  setExtent( rect );
526  }
527 
528  QgsDebugMsg( "refreshing after destination CRS changed" );
529  refresh();
530  }
531 
532  mSettings.setDestinationCrs( crs );
533 
535 
536  emit destinationCrsChanged();
537 }
538 
540 {
541  return mLabelingResults;
542 }
543 
545 {
546  if ( enabled == isCachingEnabled() )
547  return;
548 
549  if ( enabled )
550  {
551  mCache = new QgsMapRendererCache;
552  }
553  else
554  {
555  delete mCache;
556  mCache = 0;
557  }
558 }
559 
561 {
562  return mCache != 0;
563 }
564 
566 {
567  if ( mCache )
568  mCache->clear();
569 }
570 
572 {
573  mUseParallelRendering = enabled;
574 }
575 
577 {
578  return mUseParallelRendering;
579 }
580 
581 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
582 {
583  mMapUpdateTimer.setInterval( timeMiliseconds );
584 }
585 
587 {
588  return mMapUpdateTimer.interval();
589 }
590 
591 
593 {
594  // redraw overview
595  if ( mMapOverview )
596  {
597  mMapOverview->refresh();
598  }
599 }
600 
601 
603 {
604  return mCurrentLayer;
605 }
606 
607 
609 {
610  if ( !mSettings.hasValidSettings() )
611  {
612  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
613  return;
614  }
615 
616  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
617  {
618  QgsDebugMsg( "CANVAS render flag off" );
619  return;
620  }
621 
622  if ( mRefreshScheduled )
623  {
624  QgsDebugMsg( "CANVAS refresh already scheduled" );
625  return;
626  }
627 
628  mRefreshScheduled = true;
629 
630  QgsDebugMsg( "CANVAS refresh scheduling" );
631 
632  // schedule a refresh
633  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
634 } // refresh
635 
636 void QgsMapCanvas::refreshMap()
637 {
638  Q_ASSERT( mRefreshScheduled );
639 
640  QgsDebugMsg( "CANVAS refresh!" );
641 
642  stopRendering(); // if any...
643 
644  // from now on we can accept refresh requests again
645  mRefreshScheduled = false;
646 
647  //update $map variable to canvas
648  QgsExpression::setSpecialColumn( "$map", tr( "canvas" ) );
649 
650  // create the renderer job
651  Q_ASSERT( mJob == 0 );
652  mJobCancelled = false;
653  if ( mUseParallelRendering )
654  mJob = new QgsMapRendererParallelJob( mSettings );
655  else
656  mJob = new QgsMapRendererSequentialJob( mSettings );
657  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
658  mJob->setCache( mCache );
659 
660  QStringList layersForGeometryCache;
661  foreach ( QString id, mSettings.layers() )
662  {
663  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
664  {
665  if ( vl->isEditable() )
666  layersForGeometryCache << id;
667  }
668  }
669  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
670 
671  mJob->start();
672 
673  mMapUpdateTimer.start();
674 
675  emit renderStarting();
676 }
677 
678 
679 void QgsMapCanvas::rendererJobFinished()
680 {
681  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
682 
683  mMapUpdateTimer.stop();
684 
685  // TODO: would be better to show the errors in message bar
686  foreach ( const QgsMapRendererJob::Error& error, mJob->errors() )
687  {
688  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
689  }
690 
691  if ( !mJobCancelled )
692  {
693  // take labeling results before emitting renderComplete, so labeling map tools
694  // connected to signal work with correct results
695  delete mLabelingResults;
696  mLabelingResults = mJob->takeLabelingResults();
697 
698  QImage img = mJob->renderedImage();
699 
700  // emit renderComplete to get our decorations drawn
701  QPainter p( &img );
702  emit renderComplete( &p );
703 
704  QSettings settings;
705  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
706  {
707  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
708  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
709  }
710 
711  if ( mDrawRenderingStats )
712  {
713  int w = img.width(), h = img.height();
714  QFont fnt = p.font();
715  fnt.setBold( true );
716  p.setFont( fnt );
717  int lh = p.fontMetrics().height() * 2;
718  QRect r( 0, h - lh, w, lh );
719  p.setPen( Qt::NoPen );
720  p.setBrush( QColor( 0, 0, 0, 110 ) );
721  p.drawRect( r );
722  p.setPen( Qt::white );
723  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
724  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
725  }
726 
727  p.end();
728 
729  mMap->setContent( img, imageRect( img ) );
730  }
731 
732  // now we are in a slot called from mJob - do not delete it immediately
733  // so the class is still valid when the execution returns to the class
734  mJob->deleteLater();
735  mJob = 0;
736 
737  emit mapCanvasRefreshed();
738 }
739 
740 QgsRectangle QgsMapCanvas::imageRect( const QImage& img )
741 {
742  // This is an hack to pass QgsMapCanvasItem::setRect what it
743  // expects (encoding of position and size of the item)
744  const QgsMapToPixel& m2p = mSettings.mapToPixel();
745  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
746  double res = m2p.mapUnitsPerPixel();
747  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
748  return rect;
749 }
750 
751 void QgsMapCanvas::mapUpdateTimeout()
752 {
753  const QImage& img = mJob->renderedImage();
754  mMap->setContent( img, imageRect( img ) );
755 }
756 
758 {
759  if ( mJob )
760  {
761  QgsDebugMsg( "CANVAS stop rendering!" );
762  mJobCancelled = true;
763  mJob->cancel();
764  Q_ASSERT( mJob == 0 ); // no need to delete here: already deleted in finished()
765  }
766 }
767 
769 {
770 }
771 
772 //the format defaults to "PNG" if not specified
773 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
774 {
775  //
776  //check if the optional QPaintDevice was supplied
777  //
778  if ( theQPixmap != NULL )
779  {
780  // render
781  QPainter painter;
782  painter.begin( theQPixmap );
783  QgsMapRendererCustomPainterJob job( mSettings, &painter );
784  job.start();
785  job.waitForFinished();
786  emit renderComplete( &painter );
787  painter.end();
788 
789  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
790  }
791  else //use the map view
792  {
793  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
794  }
795  //create a world file to go with the image...
797  QString myHeader;
798  // note: use 17 places of precision for all numbers output
799  //Pixel XDim
800  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
801  //Rotation on y axis - hard coded
802  myHeader += "0 \r\n";
803  //Rotation on x axis - hard coded
804  myHeader += "0 \r\n";
805  //Pixel YDim - almost always negative - see
806  //http://en.wikipedia.org/wiki/World_file#cite_note-2
807  myHeader += "-" + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
808  //Origin X (center of top left cell)
809  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
810  //Origin Y (center of top left cell)
811  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
812  QFileInfo myInfo = QFileInfo( theFileName );
813  // allow dotted names
814  QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
815  QFile myWorldFile( myWorldFileName );
816  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
817  {
818  return;
819  }
820  QTextStream myStream( &myWorldFile );
821  myStream << myHeader;
822 } // saveAsImage
823 
824 
825 
827 {
828  return mapSettings().visibleExtent();
829 } // extent
830 
832 {
833  return mapSettings().fullExtent();
834 } // extent
835 
836 
838 {
839  QgsRectangle current = extent();
840 
841  if ( r == current )
842  return;
843 
844  if ( r.isEmpty() )
845  {
846  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
847  setCenter( r.center() );
848  }
849  else
850  {
851  mSettings.setExtent( r );
852  }
853  emit extentsChanged();
854  updateScale();
855  if ( mLastExtent.size() > 20 )
856  mLastExtent.removeAt( 0 );
857 
858  //clear all extent items after current index
859  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
860  {
861  mLastExtent.removeAt( i );
862  }
863 
864  mLastExtent.append( extent() );
865 
866  // adjust history to no more than 20
867  if ( mLastExtent.size() > 20 )
868  {
869  mLastExtent.removeAt( 0 );
870  }
871 
872  // the last item is the current extent
873  mLastExtentIndex = mLastExtent.size() - 1;
874 
875  // update controls' enabled state
876  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
877  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
878  // notify canvas items of change
880 
881 } // setExtent
882 
883 void QgsMapCanvas::setCenter( const QgsPoint& center )
884 {
886  double x = center.x();
887  double y = center.y();
888  setExtent(
889  QgsRectangle(
890  x - r.width() / 2.0, y - r.height() / 2.0,
891  x + r.width() / 2.0, y + r.height() / 2.0
892  )
893  );
894 } // setCenter
895 
897 {
899  return r.center();
900 }
901 
902 
904 {
905  return mapSettings().rotation();
906 } // rotation
907 
908 void QgsMapCanvas::setRotation( double degrees )
909 {
910  if ( !rotationEnabled() )
911  return;
912 
913  double current = rotation();
914 
915  if ( degrees == current )
916  return;
917 
918  mSettings.setRotation( degrees );
919  emit rotationChanged( degrees );
920  emit extentsChanged(); // visible extent changes with rotation
921 
922  // notify canvas items of change (needed?)
924 
925 } // setRotation
926 
927 
929 {
930  emit scaleChanged( mapSettings().scale() );
931 }
932 
933 
935 {
936  refresh();
937 } // clear
938 
939 
940 
942 {
944  // If the full extent is an empty set, don't do the zoom
945  if ( !extent.isEmpty() )
946  {
947  // Add a 5% margin around the full extent
948  extent.scale( 1.05 );
949  setExtent( extent );
950  }
951  refresh();
952 
953 } // zoomToFullExtent
954 
955 
956 
958 {
959  if ( mLastExtentIndex > 0 )
960  {
961  mLastExtentIndex--;
962  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
963  emit extentsChanged();
964  updateScale();
965  refresh();
966  // update controls' enabled state
967  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
968  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
969  // notify canvas items of change
971  }
972 
973 } // zoomToPreviousExtent
974 
976 {
977  if ( mLastExtentIndex < mLastExtent.size() - 1 )
978  {
979  mLastExtentIndex++;
980  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
981  emit extentsChanged();
982  updateScale();
983  refresh();
984  // update controls' enabled state
985  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
986  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
987  // notify canvas items of change
989  }
990 }// zoomToNextExtent
991 
993 {
994  mLastExtent.clear(); // clear the zoom history list
995  mLastExtent.append( extent() ) ; // set the current extent in the list
996  mLastExtentIndex = mLastExtent.size() - 1;
997  // update controls' enabled state
998  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
999  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1000 }// clearExtentHistory
1001 
1002 
1004 {
1006 }
1007 
1009 {
1010  if ( layer == NULL )
1011  {
1012  // use current layer by default
1013  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1014  }
1015 
1016  if ( layer == NULL )
1017  {
1018  return;
1019  }
1020 
1021  if ( layer->selectedFeatureCount() == 0 )
1022  {
1023  return;
1024  }
1025 
1027 
1028  // no selected features, only one selected point feature
1029  //or two point features with the same x- or y-coordinates
1030  if ( rect.isEmpty() )
1031  {
1032  // zoom in
1033  QgsPoint c = rect.center();
1034  rect = extent();
1035  rect.scale( 1.0, &c );
1036  }
1037  //zoom to an area
1038  else
1039  {
1040  // Expand rect to give a bit of space around the selected
1041  // objects so as to keep them clear of the map boundaries
1042  // The same 5% should apply to all margins.
1043  rect.scale( 1.05 );
1044  }
1045 
1046  setExtent( rect );
1047  refresh();
1048 } // zoomToSelected
1049 
1051 {
1052  if ( layer == NULL )
1053  {
1054  // use current layer by default
1055  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1056  }
1057 
1058  if ( layer == NULL )
1059  {
1060  return;
1061  }
1062 
1063  if ( layer->selectedFeatureCount() == 0 )
1064  {
1065  return;
1066  }
1067 
1069  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1070  refresh();
1071 } // panToSelected
1072 
1073 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
1074 {
1075  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1076  {
1077  emit keyPressed( e );
1078  return;
1079  }
1080 
1081  QPainter paint;
1082  QPen pen( Qt::gray );
1083  QgsPoint ll, ur;
1084 
1085  if ( ! mCanvasProperties->mouseButtonDown )
1086  {
1087  // Don't want to interfer with mouse events
1088 
1089  QgsRectangle currentExtent = mapSettings().visibleExtent();
1090  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
1091  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
1092 
1093  switch ( e->key() )
1094  {
1095  case Qt::Key_Left:
1096  QgsDebugMsg( "Pan left" );
1097 
1098  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
1099  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
1100  setExtent( currentExtent );
1101  refresh();
1102  break;
1103 
1104  case Qt::Key_Right:
1105  QgsDebugMsg( "Pan right" );
1106 
1107  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
1108  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
1109  setExtent( currentExtent );
1110  refresh();
1111  break;
1112 
1113  case Qt::Key_Up:
1114  QgsDebugMsg( "Pan up" );
1115 
1116  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
1117  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
1118  setExtent( currentExtent );
1119  refresh();
1120  break;
1121 
1122  case Qt::Key_Down:
1123  QgsDebugMsg( "Pan down" );
1124 
1125  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
1126  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
1127  setExtent( currentExtent );
1128  refresh();
1129  break;
1130 
1131 
1132 
1133  case Qt::Key_Space:
1134  QgsDebugMsg( "Pressing pan selector" );
1135 
1136  //mCanvasProperties->dragging = true;
1137  if ( ! e->isAutoRepeat() )
1138  {
1139  mCanvasProperties->panSelectorDown = true;
1140  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1141  }
1142  break;
1143 
1144  case Qt::Key_PageUp:
1145  QgsDebugMsg( "Zoom in" );
1146  zoomIn();
1147  break;
1148 
1149  case Qt::Key_PageDown:
1150  QgsDebugMsg( "Zoom out" );
1151  zoomOut();
1152  break;
1153 
1154 #if 0
1155  case Qt::Key_P:
1156  mUseParallelRendering = !mUseParallelRendering;
1157  refresh();
1158  break;
1159 
1160  case Qt::Key_S:
1161  mDrawRenderingStats = !mDrawRenderingStats;
1162  refresh();
1163  break;
1164 #endif
1165 
1166  default:
1167  // Pass it on
1168  if ( mMapTool )
1169  {
1170  mMapTool->keyPressEvent( e );
1171  }
1172  else e->ignore();
1173 
1174  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1175  }
1176  }
1177 
1178  emit keyPressed( e );
1179 
1180 } //keyPressEvent()
1181 
1182 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
1183 {
1184  QgsDebugMsg( "keyRelease event" );
1185 
1186  switch ( e->key() )
1187  {
1188  case Qt::Key_Space:
1189  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1190  {
1191  QgsDebugMsg( "Releasing pan selector" );
1192 
1193  mCanvasProperties->panSelectorDown = false;
1194  panActionEnd( mCanvasProperties->mouseLastXY );
1195  }
1196  break;
1197 
1198  default:
1199  // Pass it on
1200  if ( mMapTool )
1201  {
1202  mMapTool->keyReleaseEvent( e );
1203  }
1204  else e->ignore();
1205 
1206  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1207  }
1208 
1209  emit keyReleased( e );
1210 
1211 } //keyReleaseEvent()
1212 
1213 
1215 {
1216  // call handler of current map tool
1217  if ( mMapTool )
1218  {
1219  mMapTool->canvasDoubleClickEvent( e );
1220  }
1221 }// mouseDoubleClickEvent
1222 
1223 
1224 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
1225 {
1226  //use middle mouse button for panning, map tools won't receive any events in that case
1227  if ( e->button() == Qt::MidButton )
1228  {
1229  mCanvasProperties->panSelectorDown = true;
1230  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1231  }
1232  else
1233  {
1234 
1235  // call handler of current map tool
1236  if ( mMapTool )
1237  {
1238  mMapTool->canvasPressEvent( e );
1239  }
1240  }
1241 
1242  if ( mCanvasProperties->panSelectorDown )
1243  {
1244  return;
1245  }
1246 
1247  mCanvasProperties->mouseButtonDown = true;
1248  mCanvasProperties->rubberStartPoint = e->pos();
1249 
1250 } // mousePressEvent
1251 
1252 
1253 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
1254 {
1255  //use middle mouse button for panning, map tools won't receive any events in that case
1256  if ( e->button() == Qt::MidButton )
1257  {
1258  mCanvasProperties->panSelectorDown = false;
1259  panActionEnd( mCanvasProperties->mouseLastXY );
1260  }
1261  else
1262  {
1263  // call handler of current map tool
1264  if ( mMapTool )
1265  {
1266  // right button was pressed in zoom tool? return to previous non zoom tool
1267  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1268  {
1269  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1270  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1271 
1272  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1273 
1274  // change to older non-zoom tool
1275  if ( mLastNonZoomMapTool
1276  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1277  {
1278  QgsMapTool* t = mLastNonZoomMapTool;
1279  mLastNonZoomMapTool = NULL;
1280  setMapTool( t );
1281  }
1282  return;
1283  }
1284  mMapTool->canvasReleaseEvent( e );
1285  }
1286  }
1287 
1288 
1289  mCanvasProperties->mouseButtonDown = false;
1290 
1291  if ( mCanvasProperties->panSelectorDown )
1292  return;
1293 
1294 } // mouseReleaseEvent
1295 
1296 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
1297 {
1298  QGraphicsView::resizeEvent( e );
1299  mResizeTimer->start( 500 );
1300 
1301  QSize lastSize = viewport()->size();
1302 
1303  mSettings.setOutputSize( lastSize );
1304  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1305 
1306  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1307 
1308  moveCanvasContents( true );
1309 
1310  // notify canvas items of change
1312 
1313  updateScale();
1314 
1315  //refresh();
1316 
1317  emit extentsChanged();
1318 }
1319 
1320 void QgsMapCanvas::paintEvent( QPaintEvent *e )
1321 {
1322  // no custom event handling anymore
1323 
1324  QGraphicsView::paintEvent( e );
1325 } // paintEvent
1326 
1328 {
1329  QList<QGraphicsItem*> list = mScene->items();
1330  QList<QGraphicsItem*>::iterator it = list.begin();
1331  while ( it != list.end() )
1332  {
1333  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1334 
1335  if ( item )
1336  {
1337  item->updatePosition();
1338  }
1339 
1340  ++it;
1341  }
1342 }
1343 
1344 
1345 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
1346 {
1347  // Zoom the map canvas in response to a mouse wheel event. Moving the
1348  // wheel forward (away) from the user zooms in
1349 
1350  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1351 
1352  if ( mMapTool )
1353  {
1354  mMapTool->wheelEvent( e );
1355  }
1356 
1357  if ( QgsApplication::keyboardModifiers() )
1358  {
1359  // leave the wheel for map tools if any modifier pressed
1360  return;
1361  }
1362 
1363  switch ( mWheelAction )
1364  {
1365  case WheelZoom:
1366  // zoom without changing extent
1367  if ( e->delta() > 0 )
1368  zoomIn();
1369  else
1370  zoomOut();
1371  break;
1372 
1373  case WheelZoomAndRecenter:
1374  // zoom and don't change extent
1375  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1376  break;
1377 
1379  {
1380  // zoom map to mouse cursor
1381  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1382 
1383  QgsPoint oldCenter = center();
1384  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1385  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1386  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1387 
1388  zoomByFactor( scaleFactor, &newCenter );
1389  break;
1390  }
1391 
1392  case WheelNothing:
1393  // well, nothing!
1394  break;
1395  }
1396 }
1397 
1398 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1399 {
1400  mWheelAction = action;
1401  mWheelZoomFactor = factor;
1402 }
1403 
1405 {
1406  zoomByFactor( 1 / mWheelZoomFactor );
1407 }
1408 
1410 {
1411  zoomByFactor( mWheelZoomFactor );
1412 }
1413 
1414 void QgsMapCanvas::zoomScale( double newScale )
1415 {
1416  zoomByFactor( newScale / scale() );
1417 }
1418 
1419 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1420 {
1421  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1422 
1423  // transform the mouse pos to map coordinates
1426  r.scale( scaleFactor, &center );
1427  setExtent( r );
1428  refresh();
1429 }
1430 
1431 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
1432 {
1433  mCanvasProperties->mouseLastXY = e->pos();
1434 
1435  if ( mCanvasProperties->panSelectorDown )
1436  {
1437  panAction( e );
1438  }
1439  else
1440  {
1441  // call handler of current map tool
1442  if ( mMapTool )
1443  {
1444  mMapTool->canvasMoveEvent( e );
1445  }
1446  }
1447 
1448  // show x y on status bar
1449  QPoint xy = e->pos();
1451  emit xyCoordinates( coord );
1452 } // mouseMoveEvent
1453 
1454 
1455 
1458 {
1459  if ( !tool )
1460  return;
1461 
1462  if ( mMapTool )
1463  {
1464  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1465  mMapTool->deactivate();
1466  }
1467 
1468  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1469  {
1470  // if zoom or pan tool will be active, save old tool
1471  // to bring it back on right click
1472  // (but only if it wasn't also zoom or pan tool)
1473  mLastNonZoomMapTool = mMapTool;
1474  }
1475  else
1476  {
1477  mLastNonZoomMapTool = NULL;
1478  }
1479 
1480  QgsMapTool* oldTool = mMapTool;
1481 
1482  // set new map tool and activate it
1483  mMapTool = tool;
1484  if ( mMapTool )
1485  {
1486  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1487  mMapTool->activate();
1488  }
1489 
1490  emit mapToolSet( mMapTool );
1491  emit mapToolSet( mMapTool, oldTool );
1492 } // setMapTool
1493 
1495 {
1496  if ( mMapTool && mMapTool == tool )
1497  {
1498  mMapTool->deactivate();
1499  mMapTool = NULL;
1500  emit mapToolSet( NULL );
1501  emit mapToolSet( NULL, mMapTool );
1502  setCursor( Qt::ArrowCursor );
1503  }
1504 
1505  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1506  {
1507  mLastNonZoomMapTool = NULL;
1508  }
1509 }
1510 
1512 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1513 {
1514  // background of map's pixmap
1515  mSettings.setBackgroundColor( theColor );
1516 
1517  // background of the QGraphicsView
1518  QBrush bgBrush( theColor );
1519  setBackgroundBrush( bgBrush );
1520 #if 0
1521  QPalette palette;
1522  palette.setColor( backgroundRole(), theColor );
1523  setPalette( palette );
1524 #endif
1525 
1526  // background of QGraphicsScene
1527  mScene->setBackgroundBrush( bgBrush );
1528 } // setBackgroundColor
1529 
1531 {
1532  return mScene->backgroundBrush().color();
1533 }
1534 
1535 void QgsMapCanvas::setSelectionColor( const QColor& color )
1536 {
1537  mSettings.setSelectionColor( color );
1538 }
1539 
1541 {
1542  return mapSettings().layers().size();
1543 } // layerCount
1544 
1545 
1546 QList<QgsMapLayer*> QgsMapCanvas::layers() const
1547 {
1548  QList<QgsMapLayer*> lst;
1549  foreach ( QString layerID, mapSettings().layers() )
1550  {
1552  if ( layer )
1553  lst.append( layer );
1554  }
1555  return lst;
1556 }
1557 
1558 
1560 {
1561  // called when a layer has changed visibility setting
1562 
1563  refresh();
1564 
1565 } // layerStateChange
1566 
1567 
1568 
1569 void QgsMapCanvas::freeze( bool frz )
1570 {
1571  mFrozen = frz;
1572 } // freeze
1573 
1575 {
1576  return mFrozen;
1577 } // freeze
1578 
1579 
1581 {
1583  return mMap->paintDevice();
1585 }
1586 
1588 {
1589  return mapSettings().mapUnitsPerPixel();
1590 } // mapUnitsPerPixel
1591 
1592 
1594 {
1595  if ( mSettings.mapUnits() == u )
1596  return;
1597 
1598  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1599  mSettings.setMapUnits( u );
1600 
1601  updateScale();
1602 
1603  refresh(); // this will force the scale bar to be updated
1604 
1605  emit mapUnitsChanged();
1606 }
1607 
1608 
1610 {
1611  return mapSettings().mapUnits();
1612 }
1613 
1614 
1615 void QgsMapCanvas::setRenderFlag( bool theFlag )
1616 {
1617  mRenderFlag = theFlag;
1618 
1619  if ( mRenderFlag )
1620  {
1621  refresh();
1622  }
1623  else
1624  stopRendering();
1625 }
1626 
1627 void QgsMapCanvas::connectNotify( const char * signal )
1628 {
1629  Q_UNUSED( signal );
1630  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1631 } //connectNotify
1632 
1633 
1635 {
1636  if ( !mSettings.hasCrsTransformEnabled() )
1637  return;
1638 
1639  QString destAuthId = mSettings.destinationCrs().authid();
1640  foreach ( QString layerID, mSettings.layers() )
1641  {
1643  if ( !layer )
1644  continue;
1645 
1646  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1647  if ( vl && vl->geometryType() == QGis::NoGeometry )
1648  continue;
1649 
1650  // if there are more options, ask the user which datum transform to use
1651  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1652  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1653  }
1654 }
1655 
1656 
1657 
1659 {
1660  return mMapTool;
1661 }
1662 
1663 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
1664 {
1665  // move map image and other items to standard position
1666  moveCanvasContents( true ); // true means reset
1667 
1668  // use start and end box points to calculate the extent
1669  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1670  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1671 
1672  // modify the center
1673  double dx = end.x() - start.x();
1674  double dy = end.y() - start.y();
1675  QgsPoint c = center();
1676  c.set( c.x() - dx, c.y() - dy );
1677  setCenter( c );
1678 
1679  refresh();
1680 }
1681 
1682 void QgsMapCanvas::panAction( QMouseEvent * e )
1683 {
1684  Q_UNUSED( e );
1685 
1686  // move all map canvas items
1688 }
1689 
1691 {
1692  QPoint pnt( 0, 0 );
1693  if ( !reset )
1694  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1695 
1696  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1697 }
1698 
1700 {
1701  Q_UNUSED( mapLayer );
1702 }
1703 
1705 {
1706  return mCanvasProperties->mouseLastXY;
1707 }
1708 
1709 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1710 {
1711  if ( !mPreviewEffect )
1712  {
1713  return;
1714  }
1715 
1716  mPreviewEffect->setEnabled( previewEnabled );
1717 }
1718 
1720 {
1721  if ( !mPreviewEffect )
1722  {
1723  return false;
1724  }
1725 
1726  return mPreviewEffect->isEnabled();
1727 }
1728 
1730 {
1731  if ( !mPreviewEffect )
1732  {
1733  return;
1734  }
1735 
1736  mPreviewEffect->setMode( mode );
1737 }
1738 
1740 {
1741  if ( !mPreviewEffect )
1742  {
1744  }
1745 
1746  return mPreviewEffect->mode();
1747 }
1748 
1750 {
1751  if ( !mSnappingUtils )
1752  {
1753  // associate a dummy instance, but better than null pointer
1754  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1755  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1756  }
1757  return mSnappingUtils;
1758 }
1759 
1761 {
1762  mSnappingUtils = utils;
1763 }
1764 
1765 void QgsMapCanvas::readProject( const QDomDocument & doc )
1766 {
1767  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1768  if ( nodes.count() )
1769  {
1770  QDomNode node = nodes.item( 0 );
1771 
1772  QgsMapSettings tmpSettings;
1773  tmpSettings.readXML( node );
1774  setMapUnits( tmpSettings.mapUnits() );
1776  setDestinationCrs( tmpSettings.destinationCrs() );
1777  setExtent( tmpSettings.extent() );
1778  setRotation( tmpSettings.rotation() );
1779  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1780 
1781  clearExtentHistory(); // clear the extent history on project load
1782  }
1783  else
1784  {
1785  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1786  }
1787 }
1788 
1789 void QgsMapCanvas::writeProject( QDomDocument & doc )
1790 {
1791  // create node "mapcanvas" and call mMapRenderer->writeXML()
1792 
1793  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1794  if ( !nl.count() )
1795  {
1796  QgsDebugMsg( "Unable to find qgis element in project file" );
1797  return;
1798  }
1799  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1800 
1801  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1802  qgisNode.appendChild( mapcanvasNode );
1803 
1804  mSettings.writeXML( mapcanvasNode, doc );
1805  // TODO: store only units, extent, projections, dest CRS
1806 }
1807 
1809 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1810 {
1811  if ( !ml )
1812  {
1813  return;
1814  }
1815 
1816  //check if default datum transformation available
1817  QSettings s;
1818  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1819  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1820  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1821  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1822  {
1823  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1824  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1825  return;
1826  }
1827 
1828  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1829  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1830 
1831  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1832  {
1833  // just use the default transform
1834  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1835  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1836  return;
1837  }
1838 
1839  //get list of datum transforms
1840  QList< QList< int > > dt = QgsCoordinateTransform::datumTransformations( srcCRS, destCRS );
1841  if ( dt.size() < 2 )
1842  {
1843  return;
1844  }
1845 
1846  //if several possibilities: present dialog
1847  QgsDatumTransformDialog d( ml->name(), dt );
1848  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1849  if ( d.exec() == QDialog::Accepted )
1850  {
1851  int srcTransform = -1;
1852  int destTransform = -1;
1853  QList<int> t = d.selectedDatumTransform();
1854  if ( t.size() > 0 )
1855  {
1856  srcTransform = t.at( 0 );
1857  }
1858  if ( t.size() > 1 )
1859  {
1860  destTransform = t.at( 1 );
1861  }
1862  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1863  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1864  if ( d.rememberSelection() )
1865  {
1866  s.setValue( settingsString + "_srcTransform", srcTransform );
1867  s.setValue( settingsString + "_destTransform", destTransform );
1868  }
1869  }
1870  else
1871  {
1872  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1873  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1874  }
1875 }
1876 
1877 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1878 {
1880  r.scale( scaleFactor, center );
1881  setExtent( r );
1882  refresh();
1883 }
1884 
1886 {
1887  // Find out which layer it was that sent the signal.
1888  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1889  emit selectionChanged( layer );
1890  refresh();
1891 }
1892 
1893 void QgsMapCanvas::dragEnterEvent( QDragEnterEvent * e )
1894 {
1895  // By default graphics view delegates the drag events to graphics items.
1896  // But we do not want that and by ignoring the drag enter we let the
1897  // parent (e.g. QgisApp) to handle drops of map layers etc.
1898  e->ignore();
1899 }
1900 
1901 void QgsMapCanvas::mapToolDestroyed()
1902 {
1903  QgsDebugMsg( "maptool destroyed" );
1904  mMapTool = 0;
1905 }
1906 
1907 #ifdef HAVE_TOUCH
1908 bool QgsMapCanvas::event( QEvent * e )
1909 {
1910  bool done = false;
1911  if ( e->type() == QEvent::Gesture )
1912  {
1913  // call handler of current map tool
1914  if ( mMapTool )
1915  {
1916  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
1917  }
1918  }
1919  else
1920  {
1921  // pass other events to base class
1922  done = QGraphicsView::event( e );
1923  }
1924  return done;
1925 }
1926 #endif
1927 
1929 {
1930  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
1931 }
1932 
1933 void QgsMapCanvas::enableRotation( bool enable )
1934 {
1935  QSettings().setValue( "/qgis/canvasRotation", enable );
1936 }
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
void zoomToSelected(QgsVectorLayer *layer=NULL)
Zoom to the extent of the selected features of current (vector) layer.
void setRequestedGeometryCacheForLayers(const QStringList &layerIds)
Set which vector layers should be cached while rendering.
void updateCanvasItemPositions()
called on resize or changed extent to notify canvas items to change their rectangle ...
void setParallelRenderingEnabled(bool enabled)
Set whether the layers are rendered in parallel or sequentially.
const QgsDatumTransformStore & datumTransformStore() const
static unsigned index
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
QPoint mouseLastXY
Last seen point of the mouse.
virtual QColor canvasColor() const
Read property of QColor bgColor.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
Job implementation that renders everything sequentially using a custom painter.
void setRotation(double degrees)
Set the rotation of the map canvas in clockwise degrees.
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
bool isEmpty() const
test if rectangle is empty.
void zoomToNextExtent()
Zoom to the next extent (view)
void zoomWithCenter(int x, int y, bool zoomIn)
Zooms in/out with a given center.
Q_DECL_DEPRECATED bool isDirty() const
Return the state of the canvas (dirty or not)
void freeze(bool frz=true)
virtual void setCanvasColor(const QColor &_newVal)
Write property of QColor bgColor.
void enableOverviewMode(QgsMapOverviewCanvas *overview)
double scale() const
Return the calculated scale of the map.
void zoomByFactor(double scaleFactor, const QgsPoint *center=0)
Zoom with the factor supplied.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
bool hasEntryForLayer(QgsMapLayer *layer) const
int layerCount() const
return number of layers on the map
A widget that displays an overview map.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:163
void clearExtentHistory()
void readXML(QDomNode &theNode)
QgsRectangle fullExtent() const
returns current extent of layer set
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:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
UnitType
Map units that qgis supports.
Definition: qgis.h:229
void stopRendering()
stop rendering (if there is any right now)
double rotation() const
Get the current map canvas rotation in clockwise degrees.
virtual void canvasMoveEvent(QMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:138
QgsRectangle extent() const
returns current extent
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
void keyPressEvent(QKeyEvent *e) override
Overridden key press event.
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:439
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 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.
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
bool isVisible() const
Definition: qgsmapcanvas.h:84
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'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.
void renderComplete(QPainter *)
Emitted when the canvas has rendered.
void setProjectionsEnabled(bool enabled)
sets whether to use projections for this layer set
~QgsMapCanvas()
Destructor.
Snapping utils instance that is connected to a canvas and updates the configuration (map settings + c...
const QgsMapToPixel & mapToPixel() const
QgsMapTool * mapTool()
Returns the currently active tool.
double rotation() const
Return the rotation of the resulting map image Units are clockwise degrees.
void setLayerSet(const QStringList &layers)
change current layer set
virtual void canvasDoubleClickEvent(QMouseEvent *e)
Mouse double click event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:143
const QgsLabelingResults * labelingResults() const
Get access to the labeling results (may be null)
A non GUI class for rendering a map layer set onto a QPainter.
virtual void canvasPressEvent(QMouseEvent *e)
Mouse press event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:148
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
virtual QImage renderedImage()=0
Get a preview/resulting image.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
double x() const
Definition: qgspoint.h:126
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...
void setCache(QgsMapRendererCache *cache)
Assign a cache to be used for reading and storing rendered images of individual layers.
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void updateScale()
Emits signal scaleChanged to update scale in main window.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
The QgsMapSettings class contains configuration for rendering of the map.
void resizeEvent(QResizeEvent *e) override
Overridden resize event.
void setDatumTransformInfo(const QString &srcCRSauthId, const QString &destCRSauthId)
void hasCrsTransformEnabledChanged(bool flag)
Emitted when on-the-fly projection has been turned on/off.
void setMapTool(QgsMapTool *mapTool)
Sets the map tool currently being used on the canvas.
void enableAntiAliasing(bool flag)
const QString & name() const
Get the display name of the layer.
virtual void activate()
called when set as currently active map tool
Definition: qgsmaptool.cpp:77
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QgsMapRenderer * mRenderer
Definition: qgsmapcanvas.h:720
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:168
int outputDpi() const
Return DPI used for conversion between real world units (e.g.
Q_DECL_DEPRECATED void showError(QgsMapLayer *mapLayer)
A rectangular graphics item representing the map on the canvas.
QgsSnappingUtils * snappingUtils() const
Return snapping utility class that is associated with map canvas.
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.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
double scale()
Get the last reported scale of the canvas.
void rotationChanged(double)
Emitted when the rotation of the map changes.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
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.
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 clearCache()
Make sure to remove any rendered images from cache (does nothing if cache is not enabled) ...
void setMapUnits(QGis::UnitType u)
Set units of map's geographical coordinates - used for scale calculation.
Job implementation that renders all layers in parallel.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void panToSelected(QgsVectorLayer *layer=NULL)
Pan to the selected features of current (vector) layer keeping same extent.
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:168
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:719
void keyReleased(QKeyEvent *e)
Emit key release event.
Q_DECL_DEPRECATED QPaintDevice & paintDevice()
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Enable anti-aliasin for map rendering.
void setMapUnits(QGis::UnitType u)
void getDatumTransformInfo(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId)
ask user about datum transformation
Q_DECL_DEPRECATED QPaintDevice & canvasPaintDevice()
Accessor for the canvas paint device.
void mouseDoubleClickEvent(QMouseEvent *e) override
Overridden mouse double click event.
static bool rotationEnabled()
return if canvas rotation is enabled
double mapUnitsPerPixel() const
Return the distance in geographical coordinates that equals to one pixel in the map.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:98
void destinationCrsChanged()
Emitted when map CRS has changed.
double rotation() const
returns current rotation in clockwise degrees
double mapUnitsPerPixel() const
Return current map units per pixel.
int mapUpdateInterval() const
Find out how often map preview should be updated while it is being rendered (in milliseconds) ...
void updateDatumTransformEntries()
Make sure the datum transform store is properly populated.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
void setRenderFlag(bool theFlag)
Whether to suppress rendering or not.
QGis::UnitType mapUnits() const
Get units of map's geographical coordinates - used for scale calculation.
QGis::UnitType mapUnits() const
Get the current canvas map units.
void setOutputSize(QSize size, int dpi)
void setCachingEnabled(bool enabled)
Set whether to cache images of rendered layers.
virtual void deactivate()
called when map tool is being deactivated
Definition: qgsmaptool.cpp:93
virtual bool isEditTool()
Check whether this MapTool performs an edit operation.
Definition: qgsmaptool.cpp:190
QgsMapCanvasMap * map()
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:158
void refresh()
renders overview and updates panning widget
void set(double x, double y)
Definition: qgspoint.h:117
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:63
void saveAsImage(QString theFileName, QPixmap *QPixmap=0, QString="PNG")
Save the convtents of the map canvas to disk as an image.
void keyPressed(QKeyEvent *e)
Emit key press event.
void currentLayerChanged(QgsMapLayer *layer)
Emitted when the current layer is changed.
void zoomOut()
Zoom out with fixed factor.
QgsPreviewEffect::PreviewMode previewMode() const
Returns the current preview mode for the map canvas.
Enable drawing of vertex markers for layers in editing mode.
void zoomToPreviousExtent()
Zoom to the previous extent (view)
void xyCoordinates(const QgsPoint &p)
emits current mouse position
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.
void setRotation(double degrees)
sets rotation value in clockwise degrees
QScopedPointer< CanvasProperties > mCanvasProperties
Handle pattern for implementation object.
Definition: qgsmapcanvas.h:585
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:317
void setPreviewModeEnabled(bool previewEnabled)
Enables a preview mode for the map canvas.
virtual void start()=0
Start the rendering job and immediately return.
static void enableRotation(bool enabled)
change canvas rotation support
QPoint mouseLastXY()
returns last position of mouse cursor
QgsMapLayer * currentLayer()
returns current layer (set by legend widget)
void setWheelAction(WheelAction action, double factor=2)
set wheel action and zoom factor (should be greater than 1)
void mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
void keyReleaseEvent(QKeyEvent *e) override
Overridden key release event.
void 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:163
bool isCachingEnabled() const
Check whether images of rendered layers are curerently being cached.
QgsPoint toMapCoordinates(int x, int y) const
void clear()
invalidate the cache contents
Abstract base class for all map tools.
Definition: qgsmaptool.h:48
void selectionChangedSlot()
Receives signal about selection change, and pass it on with layer info.
Job implementation that renders everything sequentially in one thread.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
void setBackgroundColor(const QColor &color)
Set the background color of the map.
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
QImage contentImage() const
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
bool isInOverview() const
Definition: qgsmapcanvas.h:85
virtual void canvasReleaseEvent(QMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:153
void setSelectionColor(const QColor &color)
Set color that is used for drawing of selected vector features.
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
void dragEnterEvent(QDragEnterEvent *e) override
Overridden drag enter event.
void setOutputSize(const QSize &size)
Set the size of the resulting map image.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:173
QgsPoint center() const
Get map center, in geographical coordinates.
void writeProject(QDomDocument &)
called to write map canvas settings to project
void panAction(QMouseEvent *event)
Called when mouse is moving and pan is activated.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:362
Q_DECL_DEPRECATED QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
Class for storing a coordinate reference system (CRS)
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
This class has all the configuration of snapping and can return answers to snapping queries...
QgsMapCanvasRendererSync(QgsMapCanvas *canvas, QgsMapRenderer *renderer)
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
void zoomScale(double scale)
Zoom to a specific scale.
Class for doing transforms between two map coordinate systems.
const QgsMapToPixel * getCoordinateTransform()
Get the current coordinate transform.
void scaleChanged(double)
Emitted when the scale of the map changes.
virtual bool isTransient()
Check whether this MapTool performs a zoom or pan operation.
Definition: qgsmaptool.cpp:185
double y() const
Definition: qgspoint.h:134
void setCenter(const QgsPoint &center)
Set the center of the map canvas, in geographical coordinates.
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
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
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
void setSelectionColor(const QColor &color)
Set color of selected vector features.
void paintEvent(QPaintEvent *e) override
Overridden paint event.
void setMapUpdateInterval(int timeMiliseconds)
Set how often map preview should be updated while it is being rendered (in milliseconds) ...
void layerStateChange()
This slot is connected to the visibility change of one or more layers.
Enable vector simplification and other rendering optimizations.
Class that stores computed placement from labeling engine.
void connectNotify(const char *signal) override
debugging member invoked when a connect() is made to this object
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.
QgsMapCanvas(QWidget *parent=0, const char *name=0)
Constructor.
void setMapUnits(QGis::UnitType mapUnits)
Set map units (needed by project properties dialog)
void updateOverview()
bool isParallelRenderingEnabled() const
Check whether the layers are rendered in parallel or sequentially.
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.
static void setSpecialColumn(const QString &name, QVariant value)
Assign a special column.
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:692
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
virtual QgsLabelingResults * takeLabelingResults()=0
Get pointer to internal labeling engine (in order to get access to the results)
void zoomIn()
Zoom in with fixed factor.
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.
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.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:183
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:80
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:208
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:87
void extentsChanged()
Emitted when the extents of the map change.
int renderingTime() const
Find out how log it took to finish the job (in miliseconds)
QgsMapLayer * layer(int index)
return the map layer at position index in the layer stack
Q_DECL_DEPRECATED void updateMap()
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:158
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
QgsPoint toMapPoint(double x, double y) const
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
void panActionEnd(QPoint releasePoint)
Ends pan action and redraws the canvas.
void mapUnitsChanged()
Emmitted when map units are changed.
QStringList layerSet() const
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
void layersChanged()
Emitted when a new set of layers has been received.
QgsRectangle boundingBoxOfSelected()
Returns the bounding box of the selected features.
#define tr(sourceText)
void writeXML(QDomNode &theNode, QDomDocument &theDoc)
void mapToolSet(QgsMapTool *tool)
Emit map tool changed event.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.