QGIS API Documentation  2.9.0-Master
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 
227  // project handling
228  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
229  this, SLOT( readProject( const QDomDocument & ) ) );
230  connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
231  this, SLOT( writeProject( QDomDocument & ) ) );
232 
235 
236  // class that will sync most of the changes between canvas and (legacy) map renderer
237  // it is parented to map canvas, will be deleted automatically
238  new QgsMapCanvasRendererSync( this, mMapRenderer );
239 
240  QSize s = viewport()->size();
241  mSettings.setOutputSize( s );
242  mMapRenderer->setOutputSize( s, mSettings.outputDpi() );
243  setSceneRect( 0, 0, s.width(), s.height() );
244  mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
245 
246  moveCanvasContents( true );
247 
248  connect( &mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
249  mMapUpdateTimer.setInterval( 250 );
250 
251 #ifdef Q_OS_WIN
252  // Enable touch event on Windows.
253  // Qt on Windows needs to be told it can take touch events or else it ignores them.
254  grabGesture( Qt::PinchGesture );
255  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
256 #endif
257 
258  mPreviewEffect = new QgsPreviewEffect( this );
259  viewport()->setGraphicsEffect( mPreviewEffect );
260 
261  setInteractive( false );
262 
263  refresh();
264 
265 } // QgsMapCanvas ctor
266 
267 
269 {
270  if ( mMapTool )
271  {
272  mMapTool->deactivate();
273  mMapTool = NULL;
274  }
275  mLastNonZoomMapTool = NULL;
276 
277  // delete canvas items prior to deleteing the canvas
278  // because they might try to update canvas when it's
279  // already being destructed, ends with segfault
280  QList<QGraphicsItem*> list = mScene->items();
281  QList<QGraphicsItem*>::iterator it = list.begin();
282  while ( it != list.end() )
283  {
284  QGraphicsItem* item = *it;
285  delete item;
286  ++it;
287  }
288 
289  mScene->deleteLater(); // crashes in python tests on windows
290 
291  delete mMapRenderer;
292  // mCanvasProperties auto-deleted via QScopedPointer
293  // CanvasProperties struct has its own dtor for freeing resources
294 
295  if ( mJob )
296  {
297  mJob->cancel();
298  Q_ASSERT( mJob == 0 );
299  }
300 
301  delete mCache;
302 
303  delete mLabelingResults;
304 
305 } // dtor
306 
308 {
309  mSettings.setFlag( QgsMapSettings::Antialiasing, theFlag );
310 
311  if ( mMapOverview )
312  mMapOverview->enableAntiAliasing( theFlag );
313 } // anti aliasing
314 
315 void QgsMapCanvas::useImageToRender( bool theFlag )
316 {
317  Q_UNUSED( theFlag );
318 }
319 
321 {
322  return mMap;
323 }
324 
326 {
327  return mMapRenderer;
328 }
329 
330 
332 {
333  const QStringList& layers = mapSettings().layers();
334  if ( index >= 0 && index < ( int ) layers.size() )
335  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
336  else
337  return NULL;
338 }
339 
340 
342 {
343  mCurrentLayer = layer;
344  emit currentLayerChanged( layer );
345 }
346 
348 {
349  return mapSettings().scale();
350 } // scale
351 
352 void QgsMapCanvas::setDirty( bool dirty )
353 {
354  if ( dirty )
355  refresh();
356 }
357 
359 {
360  return false;
361 }
362 
363 
364 
366 {
367  return mJob != 0;
368 } // isDrawing
369 
370 
371 // return the current coordinate transform based on the extents and
372 // device size
374 {
375  return &mapSettings().mapToPixel();
376 }
377 
378 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
379 {
380  // create layer set
381  QStringList layerSet, layerSetOverview;
382 
383  int i;
384  for ( i = 0; i < layers.size(); i++ )
385  {
386  QgsMapCanvasLayer &lyr = layers[i];
387  if ( !lyr.layer() )
388  {
389  continue;
390  }
391 
392  if ( lyr.isVisible() )
393  {
394  layerSet.push_back( lyr.layer()->id() );
395  }
396 
397  if ( lyr.isInOverview() )
398  {
399  layerSetOverview.push_back( lyr.layer()->id() );
400  }
401  }
402 
403  const QStringList& layerSetOld = mapSettings().layers();
404 
405  bool layerSetChanged = layerSetOld != layerSet;
406 
407  // update only if needed
408  if ( layerSetChanged )
409  {
410  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
411 
412  for ( i = 0; i < layerCount(); i++ )
413  {
414  // Add check if vector layer when disconnecting from selectionChanged slot
415  // Ticket #811 - racicot
417  if ( !currentLayer )
418  continue;
419  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
420  disconnect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
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  connect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) );
437  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
438  if ( isVectLyr )
439  {
440  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
441  }
442  }
443 
445 
446  QgsDebugMsg( "Layers have changed, refreshing" );
447  emit layersChanged();
448 
449  refresh();
450  }
451 
452  if ( mMapOverview )
453  {
454  const QStringList& layerSetOvOld = mMapOverview->layerSet();
455  if ( layerSetOvOld != layerSetOverview )
456  {
457  mMapOverview->setLayerSet( layerSetOverview );
458  }
459 
460  // refresh overview maplayers even if layer set is the same
461  // because full extent might have changed
462  updateOverview();
463  }
464 } // setLayerSet
465 
467 {
468  if ( mMapOverview )
469  {
470  // disconnect old map overview if exists
471  disconnect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
472  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
473  disconnect( this, SIGNAL( destinationCrsChanged() ),
474  mMapOverview, SLOT( destinationSrsChanged() ) );
475 
476  // map overview is not owned by map canvas so don't delete it...
477  }
478 
479  mMapOverview = overview;
480 
481  if ( overview )
482  {
483  // connect to the map render to copy its projection settings
484  connect( this, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
485  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
486  connect( this, SIGNAL( destinationCrsChanged() ),
487  overview, SLOT( destinationSrsChanged() ) );
488  }
489 }
490 
492 {
493  return mSettings;
494 }
495 
497 {
498  if ( mSettings.hasCrsTransformEnabled() == enabled )
499  return;
500 
501  mSettings.setCrsTransformEnabled( enabled );
502 
504 
505  refresh();
506 
507  emit hasCrsTransformEnabledChanged( enabled );
508 }
509 
511 {
512  if ( mSettings.destinationCrs() == crs )
513  return;
514 
515  if ( mSettings.hasCrsTransformEnabled() )
516  {
517  // try to reproject current extent to the new one
518  QgsRectangle rect;
519  if ( !mSettings.visibleExtent().isEmpty() )
520  {
521  QgsCoordinateTransform transform( mSettings.destinationCrs(), crs );
522  try
523  {
524  rect = transform.transformBoundingBox( mSettings.visibleExtent() );
525  }
526  catch ( QgsCsException &e )
527  {
528  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
529  }
530  }
531  if ( !rect.isEmpty() )
532  {
533  setExtent( rect );
534  }
535 
536  QgsDebugMsg( "refreshing after destination CRS changed" );
537  refresh();
538  }
539 
540  mSettings.setDestinationCrs( crs );
541 
543 
544  emit destinationCrsChanged();
545 }
546 
548 {
549  return mLabelingResults;
550 }
551 
553 {
554  if ( enabled == isCachingEnabled() )
555  return;
556 
557  if ( enabled )
558  {
559  mCache = new QgsMapRendererCache;
560  }
561  else
562  {
563  delete mCache;
564  mCache = 0;
565  }
566 }
567 
569 {
570  return mCache != 0;
571 }
572 
574 {
575  if ( mCache )
576  mCache->clear();
577 }
578 
580 {
581  mUseParallelRendering = enabled;
582 }
583 
585 {
586  return mUseParallelRendering;
587 }
588 
589 void QgsMapCanvas::setMapUpdateInterval( int timeMiliseconds )
590 {
591  mMapUpdateTimer.setInterval( timeMiliseconds );
592 }
593 
595 {
596  return mMapUpdateTimer.interval();
597 }
598 
599 
601 {
602  // redraw overview
603  if ( mMapOverview )
604  {
605  mMapOverview->refresh();
606  }
607 }
608 
609 
611 {
612  return mCurrentLayer;
613 }
614 
615 
617 {
618  if ( !mSettings.hasValidSettings() )
619  {
620  QgsDebugMsg( "CANVAS refresh - invalid settings -> nothing to do" );
621  return;
622  }
623 
624  if ( !mRenderFlag || mFrozen ) // do we really need two flags controlling rendering?
625  {
626  QgsDebugMsg( "CANVAS render flag off" );
627  return;
628  }
629 
630  if ( mRefreshScheduled )
631  {
632  QgsDebugMsg( "CANVAS refresh already scheduled" );
633  return;
634  }
635 
636  mRefreshScheduled = true;
637 
638  QgsDebugMsg( "CANVAS refresh scheduling" );
639 
640  // schedule a refresh
641  QTimer::singleShot( 1, this, SLOT( refreshMap() ) );
642 } // refresh
643 
644 void QgsMapCanvas::refreshMap()
645 {
646  Q_ASSERT( mRefreshScheduled );
647 
648  QgsDebugMsg( "CANVAS refresh!" );
649 
650  stopRendering(); // if any...
651 
652  // from now on we can accept refresh requests again
653  mRefreshScheduled = false;
654 
655  //update $map variable to canvas
656  QgsExpression::setSpecialColumn( "$map", tr( "canvas" ) );
657 
658  // create the renderer job
659  Q_ASSERT( mJob == 0 );
660  mJobCancelled = false;
661  if ( mUseParallelRendering )
662  mJob = new QgsMapRendererParallelJob( mSettings );
663  else
664  mJob = new QgsMapRendererSequentialJob( mSettings );
665  connect( mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
666  mJob->setCache( mCache );
667 
668  QStringList layersForGeometryCache;
669  foreach ( QString id, mSettings.layers() )
670  {
671  if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
672  {
673  if ( vl->isEditable() )
674  layersForGeometryCache << id;
675  }
676  }
677  mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
678 
679  mJob->start();
680 
681  mMapUpdateTimer.start();
682 
683  emit renderStarting();
684 }
685 
686 
687 void QgsMapCanvas::rendererJobFinished()
688 {
689  QgsDebugMsg( QString( "CANVAS finish! %1" ).arg( !mJobCancelled ) );
690 
691  mMapUpdateTimer.stop();
692 
693  // TODO: would be better to show the errors in message bar
694  foreach ( const QgsMapRendererJob::Error& error, mJob->errors() )
695  {
696  QgsMessageLog::logMessage( error.layerID + " :: " + error.message, tr( "Rendering" ) );
697  }
698 
699  if ( !mJobCancelled )
700  {
701  // take labeling results before emitting renderComplete, so labeling map tools
702  // connected to signal work with correct results
703  delete mLabelingResults;
704  mLabelingResults = mJob->takeLabelingResults();
705 
706  QImage img = mJob->renderedImage();
707 
708  // emit renderComplete to get our decorations drawn
709  QPainter p( &img );
710  emit renderComplete( &p );
711 
712  QSettings settings;
713  if ( settings.value( "/Map/logCanvasRefreshEvent", false ).toBool() )
714  {
715  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( mJob->renderingTime() );
716  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
717  }
718 
719  if ( mDrawRenderingStats )
720  {
721  int w = img.width(), h = img.height();
722  QFont fnt = p.font();
723  fnt.setBold( true );
724  p.setFont( fnt );
725  int lh = p.fontMetrics().height() * 2;
726  QRect r( 0, h - lh, w, lh );
727  p.setPen( Qt::NoPen );
728  p.setBrush( QColor( 0, 0, 0, 110 ) );
729  p.drawRect( r );
730  p.setPen( Qt::white );
731  QString msg = QString( "%1 :: %2 ms" ).arg( mUseParallelRendering ? "PARALLEL" : "SEQUENTIAL" ).arg( mJob->renderingTime() );
732  p.drawText( r, msg, QTextOption( Qt::AlignCenter ) );
733  }
734 
735  p.end();
736 
737  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
738  }
739 
740  // now we are in a slot called from mJob - do not delete it immediately
741  // so the class is still valid when the execution returns to the class
742  mJob->deleteLater();
743  mJob = 0;
744 
745  emit mapCanvasRefreshed();
746 }
747 
748 QgsRectangle QgsMapCanvas::imageRect( const QImage& img, const QgsMapSettings& mapSettings )
749 {
750  // This is a hack to pass QgsMapCanvasItem::setRect what it
751  // expects (encoding of position and size of the item)
752  const QgsMapToPixel& m2p = mapSettings.mapToPixel();
753  QgsPoint topLeft = m2p.toMapPoint( 0, 0 );
754  double res = m2p.mapUnitsPerPixel();
755  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + img.width()*res, topLeft.y() - img.height()*res );
756  return rect;
757 }
758 
759 void QgsMapCanvas::mapUpdateTimeout()
760 {
761  const QImage& img = mJob->renderedImage();
762  mMap->setContent( img, imageRect( img, mJob->mapSettings() ) );
763 }
764 
766 {
767  if ( mJob )
768  {
769  QgsDebugMsg( "CANVAS stop rendering!" );
770  mJobCancelled = true;
771  mJob->cancel();
772  Q_ASSERT( mJob == 0 ); // no need to delete here: already deleted in finished()
773  }
774 }
775 
777 {
778 }
779 
780 //the format defaults to "PNG" if not specified
781 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
782 {
783  //
784  //check if the optional QPaintDevice was supplied
785  //
786  if ( theQPixmap != NULL )
787  {
788  // render
789  QPainter painter;
790  painter.begin( theQPixmap );
791  QgsMapRendererCustomPainterJob job( mSettings, &painter );
792  job.start();
793  job.waitForFinished();
794  emit renderComplete( &painter );
795  painter.end();
796 
797  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
798  }
799  else //use the map view
800  {
801  mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() );
802  }
803  //create a world file to go with the image...
805  QString myHeader;
806  // note: use 17 places of precision for all numbers output
807  //Pixel XDim
808  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
809  //Rotation on y axis - hard coded
810  myHeader += "0 \r\n";
811  //Rotation on x axis - hard coded
812  myHeader += "0 \r\n";
813  //Pixel YDim - almost always negative - see
814  //http://en.wikipedia.org/wiki/World_file#cite_note-2
815  myHeader += "-" + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
816  //Origin X (center of top left cell)
817  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
818  //Origin Y (center of top left cell)
819  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
820  QFileInfo myInfo = QFileInfo( theFileName );
821  // allow dotted names
822  QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
823  QFile myWorldFile( myWorldFileName );
824  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
825  {
826  return;
827  }
828  QTextStream myStream( &myWorldFile );
829  myStream << myHeader;
830 } // saveAsImage
831 
832 
833 
835 {
836  return mapSettings().visibleExtent();
837 } // extent
838 
840 {
841  return mapSettings().fullExtent();
842 } // extent
843 
844 
846 {
847  QgsRectangle current = extent();
848 
849  if ( r == current )
850  return;
851 
852  if ( r.isEmpty() )
853  {
854  if ( !mSettings.hasValidSettings() )
855  {
856  // we can't even just move the map center
857  QgsDebugMsg( "Empty extent - ignoring" );
858  return;
859  }
860 
861  // ### QGIS 3: do not allow empty extent - require users to call setCenter() explicitly
862  QgsDebugMsg( "Empty extent - keeping old scale with new center!" );
863  setCenter( r.center() );
864  }
865  else
866  {
867  mSettings.setExtent( r );
868  }
869  emit extentsChanged();
870  updateScale();
871  if ( mLastExtent.size() > 20 )
872  mLastExtent.removeAt( 0 );
873 
874  //clear all extent items after current index
875  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
876  {
877  mLastExtent.removeAt( i );
878  }
879 
880  mLastExtent.append( extent() );
881 
882  // adjust history to no more than 20
883  if ( mLastExtent.size() > 20 )
884  {
885  mLastExtent.removeAt( 0 );
886  }
887 
888  // the last item is the current extent
889  mLastExtentIndex = mLastExtent.size() - 1;
890 
891  // update controls' enabled state
892  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
893  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
894  // notify canvas items of change
896 
897 } // setExtent
898 
899 void QgsMapCanvas::setCenter( const QgsPoint& center )
900 {
902  double x = center.x();
903  double y = center.y();
904  setExtent(
905  QgsRectangle(
906  x - r.width() / 2.0, y - r.height() / 2.0,
907  x + r.width() / 2.0, y + r.height() / 2.0
908  )
909  );
910 } // setCenter
911 
913 {
915  return r.center();
916 }
917 
918 
920 {
921  return mapSettings().rotation();
922 } // rotation
923 
924 void QgsMapCanvas::setRotation( double degrees )
925 {
926  if ( !rotationEnabled() )
927  return;
928 
929  double current = rotation();
930 
931  if ( degrees == current )
932  return;
933 
934  mSettings.setRotation( degrees );
935  emit rotationChanged( degrees );
936  emit extentsChanged(); // visible extent changes with rotation
937 
938  // notify canvas items of change (needed?)
940 
941 } // setRotation
942 
943 
945 {
946  emit scaleChanged( mapSettings().scale() );
947 }
948 
949 
951 {
952  refresh();
953 } // clear
954 
955 
956 
958 {
960  // If the full extent is an empty set, don't do the zoom
961  if ( !extent.isEmpty() )
962  {
963  // Add a 5% margin around the full extent
964  extent.scale( 1.05 );
965  setExtent( extent );
966  }
967  refresh();
968 
969 } // zoomToFullExtent
970 
971 
972 
974 {
975  if ( mLastExtentIndex > 0 )
976  {
977  mLastExtentIndex--;
978  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
979  emit extentsChanged();
980  updateScale();
981  refresh();
982  // update controls' enabled state
983  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
984  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
985  // notify canvas items of change
987  }
988 
989 } // zoomToPreviousExtent
990 
992 {
993  if ( mLastExtentIndex < mLastExtent.size() - 1 )
994  {
995  mLastExtentIndex++;
996  mSettings.setExtent( mLastExtent[mLastExtentIndex] );
997  emit extentsChanged();
998  updateScale();
999  refresh();
1000  // update controls' enabled state
1001  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1002  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1003  // notify canvas items of change
1005  }
1006 }// zoomToNextExtent
1007 
1009 {
1010  mLastExtent.clear(); // clear the zoom history list
1011  mLastExtent.append( extent() ) ; // set the current extent in the list
1012  mLastExtentIndex = mLastExtent.size() - 1;
1013  // update controls' enabled state
1014  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
1015  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
1016 }// clearExtentHistory
1017 
1018 
1020 {
1022 }
1023 
1025 {
1026  if ( layer == NULL )
1027  {
1028  // use current layer by default
1029  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1030  }
1031 
1032  if ( layer == NULL )
1033  {
1034  return;
1035  }
1036 
1037  if ( layer->selectedFeatureCount() == 0 )
1038  {
1039  return;
1040  }
1041 
1043 
1044  // no selected features, only one selected point feature
1045  //or two point features with the same x- or y-coordinates
1046  if ( rect.isEmpty() )
1047  {
1048  // zoom in
1049  QgsPoint c = rect.center();
1050  rect = extent();
1051  rect.scale( 1.0, &c );
1052  }
1053  //zoom to an area
1054  else
1055  {
1056  // Expand rect to give a bit of space around the selected
1057  // objects so as to keep them clear of the map boundaries
1058  // The same 5% should apply to all margins.
1059  rect.scale( 1.05 );
1060  }
1061 
1062  setExtent( rect );
1063  refresh();
1064 } // zoomToSelected
1065 
1067 {
1068  if ( layer == NULL )
1069  {
1070  // use current layer by default
1071  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1072  }
1073 
1074  if ( layer == NULL )
1075  {
1076  return;
1077  }
1078 
1079  if ( layer->selectedFeatureCount() == 0 )
1080  {
1081  return;
1082  }
1083 
1085  setExtent( QgsRectangle( rect.center(), rect.center() ) );
1086  refresh();
1087 } // panToSelected
1088 
1089 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
1090 {
1091  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
1092  {
1093  emit keyPressed( e );
1094  return;
1095  }
1096 
1097  QPainter paint;
1098  QPen pen( Qt::gray );
1099  QgsPoint ll, ur;
1100 
1101  if ( ! mCanvasProperties->mouseButtonDown )
1102  {
1103  // Don't want to interfer with mouse events
1104 
1105  QgsRectangle currentExtent = mapSettings().visibleExtent();
1106  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
1107  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
1108 
1109  switch ( e->key() )
1110  {
1111  case Qt::Key_Left:
1112  QgsDebugMsg( "Pan left" );
1113 
1114  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
1115  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
1116  setExtent( currentExtent );
1117  refresh();
1118  break;
1119 
1120  case Qt::Key_Right:
1121  QgsDebugMsg( "Pan right" );
1122 
1123  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
1124  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
1125  setExtent( currentExtent );
1126  refresh();
1127  break;
1128 
1129  case Qt::Key_Up:
1130  QgsDebugMsg( "Pan up" );
1131 
1132  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
1133  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
1134  setExtent( currentExtent );
1135  refresh();
1136  break;
1137 
1138  case Qt::Key_Down:
1139  QgsDebugMsg( "Pan down" );
1140 
1141  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
1142  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
1143  setExtent( currentExtent );
1144  refresh();
1145  break;
1146 
1147 
1148 
1149  case Qt::Key_Space:
1150  QgsDebugMsg( "Pressing pan selector" );
1151 
1152  //mCanvasProperties->dragging = true;
1153  if ( ! e->isAutoRepeat() )
1154  {
1155  mCanvasProperties->panSelectorDown = true;
1156  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1157  }
1158  break;
1159 
1160  case Qt::Key_PageUp:
1161  QgsDebugMsg( "Zoom in" );
1162  zoomIn();
1163  break;
1164 
1165  case Qt::Key_PageDown:
1166  QgsDebugMsg( "Zoom out" );
1167  zoomOut();
1168  break;
1169 
1170 #if 0
1171  case Qt::Key_P:
1172  mUseParallelRendering = !mUseParallelRendering;
1173  refresh();
1174  break;
1175 
1176  case Qt::Key_S:
1177  mDrawRenderingStats = !mDrawRenderingStats;
1178  refresh();
1179  break;
1180 #endif
1181 
1182  default:
1183  // Pass it on
1184  if ( mMapTool )
1185  {
1186  mMapTool->keyPressEvent( e );
1187  }
1188  else e->ignore();
1189 
1190  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
1191  }
1192  }
1193 
1194  emit keyPressed( e );
1195 
1196 } //keyPressEvent()
1197 
1198 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
1199 {
1200  QgsDebugMsg( "keyRelease event" );
1201 
1202  switch ( e->key() )
1203  {
1204  case Qt::Key_Space:
1205  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
1206  {
1207  QgsDebugMsg( "Releasing pan selector" );
1208 
1209  mCanvasProperties->panSelectorDown = false;
1210  panActionEnd( mCanvasProperties->mouseLastXY );
1211  }
1212  break;
1213 
1214  default:
1215  // Pass it on
1216  if ( mMapTool )
1217  {
1218  mMapTool->keyReleaseEvent( e );
1219  }
1220  else e->ignore();
1221 
1222  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
1223  }
1224 
1225  emit keyReleased( e );
1226 
1227 } //keyReleaseEvent()
1228 
1229 
1231 {
1232  // call handler of current map tool
1233  if ( mMapTool )
1234  {
1235  mMapTool->canvasDoubleClickEvent( e );
1236  }
1237 }// mouseDoubleClickEvent
1238 
1239 
1240 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
1241 {
1242  //use middle mouse button for panning, map tools won't receive any events in that case
1243  if ( e->button() == Qt::MidButton )
1244  {
1245  mCanvasProperties->panSelectorDown = true;
1246  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
1247  }
1248  else
1249  {
1250 
1251  // call handler of current map tool
1252  if ( mMapTool )
1253  {
1254  mMapTool->canvasPressEvent( e );
1255  }
1256  }
1257 
1258  if ( mCanvasProperties->panSelectorDown )
1259  {
1260  return;
1261  }
1262 
1263  mCanvasProperties->mouseButtonDown = true;
1264  mCanvasProperties->rubberStartPoint = e->pos();
1265 
1266 } // mousePressEvent
1267 
1268 
1269 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
1270 {
1271  //use middle mouse button for panning, map tools won't receive any events in that case
1272  if ( e->button() == Qt::MidButton )
1273  {
1274  mCanvasProperties->panSelectorDown = false;
1275  panActionEnd( mCanvasProperties->mouseLastXY );
1276  }
1277  else
1278  {
1279  // call handler of current map tool
1280  if ( mMapTool )
1281  {
1282  // right button was pressed in zoom tool? return to previous non zoom tool
1283  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
1284  {
1285  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
1286  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
1287 
1288  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1289 
1290  // change to older non-zoom tool
1291  if ( mLastNonZoomMapTool
1292  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1293  {
1294  QgsMapTool* t = mLastNonZoomMapTool;
1295  mLastNonZoomMapTool = NULL;
1296  setMapTool( t );
1297  }
1298  return;
1299  }
1300  mMapTool->canvasReleaseEvent( e );
1301  }
1302  }
1303 
1304 
1305  mCanvasProperties->mouseButtonDown = false;
1306 
1307  if ( mCanvasProperties->panSelectorDown )
1308  return;
1309 
1310 } // mouseReleaseEvent
1311 
1312 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
1313 {
1314  QGraphicsView::resizeEvent( e );
1315  mResizeTimer->start( 500 );
1316 
1317  QSize lastSize = viewport()->size();
1318 
1319  mSettings.setOutputSize( lastSize );
1320  mMapRenderer->setOutputSize( lastSize, mSettings.outputDpi() );
1321 
1322  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1323 
1324  moveCanvasContents( true );
1325 
1326  // notify canvas items of change
1328 
1329  updateScale();
1330 
1331  //refresh();
1332 
1333  emit extentsChanged();
1334 }
1335 
1336 void QgsMapCanvas::paintEvent( QPaintEvent *e )
1337 {
1338  // no custom event handling anymore
1339 
1340  QGraphicsView::paintEvent( e );
1341 } // paintEvent
1342 
1344 {
1345  QList<QGraphicsItem*> list = mScene->items();
1346  QList<QGraphicsItem*>::iterator it = list.begin();
1347  while ( it != list.end() )
1348  {
1349  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1350 
1351  if ( item )
1352  {
1353  item->updatePosition();
1354  }
1355 
1356  ++it;
1357  }
1358 }
1359 
1360 
1361 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
1362 {
1363  // Zoom the map canvas in response to a mouse wheel event. Moving the
1364  // wheel forward (away) from the user zooms in
1365 
1366  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1367 
1368  if ( mMapTool )
1369  {
1370  mMapTool->wheelEvent( e );
1371  }
1372 
1373  if ( QgsApplication::keyboardModifiers() )
1374  {
1375  // leave the wheel for map tools if any modifier pressed
1376  return;
1377  }
1378 
1379  switch ( mWheelAction )
1380  {
1381  case WheelZoom:
1382  // zoom without changing extent
1383  if ( e->delta() > 0 )
1384  zoomIn();
1385  else
1386  zoomOut();
1387  break;
1388 
1389  case WheelZoomAndRecenter:
1390  // zoom and don't change extent
1391  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1392  break;
1393 
1395  {
1396  // zoom map to mouse cursor
1397  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1398 
1399  QgsPoint oldCenter = center();
1400  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1401  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1402  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1403 
1404  zoomByFactor( scaleFactor, &newCenter );
1405  break;
1406  }
1407 
1408  case WheelNothing:
1409  // well, nothing!
1410  break;
1411  }
1412 }
1413 
1414 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1415 {
1416  mWheelAction = action;
1417  mWheelZoomFactor = factor;
1418 }
1419 
1421 {
1422  zoomByFactor( 1 / mWheelZoomFactor );
1423 }
1424 
1426 {
1427  zoomByFactor( mWheelZoomFactor );
1428 }
1429 
1430 void QgsMapCanvas::zoomScale( double newScale )
1431 {
1432  zoomByFactor( newScale / scale() );
1433 }
1434 
1435 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1436 {
1437  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1438 
1439  // transform the mouse pos to map coordinates
1442  r.scale( scaleFactor, &center );
1443  setExtent( r );
1444  refresh();
1445 }
1446 
1447 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
1448 {
1449  mCanvasProperties->mouseLastXY = e->pos();
1450 
1451  if ( mCanvasProperties->panSelectorDown )
1452  {
1453  panAction( e );
1454  }
1455  else
1456  {
1457  // call handler of current map tool
1458  if ( mMapTool )
1459  {
1460  mMapTool->canvasMoveEvent( e );
1461  }
1462  }
1463 
1464  // show x y on status bar
1465  QPoint xy = e->pos();
1467  emit xyCoordinates( coord );
1468 } // mouseMoveEvent
1469 
1470 
1471 
1474 {
1475  if ( !tool )
1476  return;
1477 
1478  if ( mMapTool )
1479  {
1480  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1481  mMapTool->deactivate();
1482  }
1483 
1484  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1485  {
1486  // if zoom or pan tool will be active, save old tool
1487  // to bring it back on right click
1488  // (but only if it wasn't also zoom or pan tool)
1489  mLastNonZoomMapTool = mMapTool;
1490  }
1491  else
1492  {
1493  mLastNonZoomMapTool = NULL;
1494  }
1495 
1496  QgsMapTool* oldTool = mMapTool;
1497 
1498  // set new map tool and activate it
1499  mMapTool = tool;
1500  if ( mMapTool )
1501  {
1502  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1503  mMapTool->activate();
1504  }
1505 
1506  emit mapToolSet( mMapTool );
1507  emit mapToolSet( mMapTool, oldTool );
1508 } // setMapTool
1509 
1511 {
1512  if ( mMapTool && mMapTool == tool )
1513  {
1514  mMapTool->deactivate();
1515  mMapTool = NULL;
1516  emit mapToolSet( NULL );
1517  emit mapToolSet( NULL, mMapTool );
1518  setCursor( Qt::ArrowCursor );
1519  }
1520 
1521  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1522  {
1523  mLastNonZoomMapTool = NULL;
1524  }
1525 }
1526 
1528 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1529 {
1530  // background of map's pixmap
1531  mSettings.setBackgroundColor( theColor );
1532 
1533  // background of the QGraphicsView
1534  QBrush bgBrush( theColor );
1535  setBackgroundBrush( bgBrush );
1536 #if 0
1537  QPalette palette;
1538  palette.setColor( backgroundRole(), theColor );
1539  setPalette( palette );
1540 #endif
1541 
1542  // background of QGraphicsScene
1543  mScene->setBackgroundBrush( bgBrush );
1544 } // setBackgroundColor
1545 
1547 {
1548  return mScene->backgroundBrush().color();
1549 }
1550 
1551 void QgsMapCanvas::setSelectionColor( const QColor& color )
1552 {
1553  mSettings.setSelectionColor( color );
1554 }
1555 
1557 {
1558  return mapSettings().layers().size();
1559 } // layerCount
1560 
1561 
1562 QList<QgsMapLayer*> QgsMapCanvas::layers() const
1563 {
1564  QList<QgsMapLayer*> lst;
1565  foreach ( QString layerID, mapSettings().layers() )
1566  {
1568  if ( layer )
1569  lst.append( layer );
1570  }
1571  return lst;
1572 }
1573 
1574 
1576 {
1577  // called when a layer has changed visibility setting
1578 
1579  refresh();
1580 
1581 } // layerStateChange
1582 
1584 {
1585  // called when a layer's CRS has been changed
1586  QObject *theSender = sender();
1587  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( theSender );
1588  QString destAuthId = mSettings.destinationCrs().authid();
1589  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1590 
1591 } // layerCrsChange
1592 
1593 
1594 void QgsMapCanvas::freeze( bool frz )
1595 {
1596  mFrozen = frz;
1597 } // freeze
1598 
1600 {
1601  return mFrozen;
1602 } // freeze
1603 
1604 
1606 {
1608  return mMap->paintDevice();
1610 }
1611 
1613 {
1614  return mapSettings().mapUnitsPerPixel();
1615 } // mapUnitsPerPixel
1616 
1617 
1619 {
1620  if ( mSettings.mapUnits() == u )
1621  return;
1622 
1623  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1624  mSettings.setMapUnits( u );
1625 
1626  updateScale();
1627 
1628  refresh(); // this will force the scale bar to be updated
1629 
1630  emit mapUnitsChanged();
1631 }
1632 
1633 
1635 {
1636  return mapSettings().mapUnits();
1637 }
1638 
1639 
1640 void QgsMapCanvas::setRenderFlag( bool theFlag )
1641 {
1642  mRenderFlag = theFlag;
1643 
1644  if ( mRenderFlag )
1645  {
1646  refresh();
1647  }
1648  else
1649  stopRendering();
1650 }
1651 
1652 #if 0
1653 void QgsMapCanvas::connectNotify( const char * signal )
1654 {
1655  Q_UNUSED( signal );
1656  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1657 } //connectNotify
1658 #endif
1659 
1661 {
1662  if ( !mSettings.hasCrsTransformEnabled() )
1663  return;
1664 
1665  QString destAuthId = mSettings.destinationCrs().authid();
1666  foreach ( QString layerID, mSettings.layers() )
1667  {
1669  if ( !layer )
1670  continue;
1671 
1672  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
1673  if ( vl && vl->geometryType() == QGis::NoGeometry )
1674  continue;
1675 
1676  // if there are more options, ask the user which datum transform to use
1677  if ( !mSettings.datumTransformStore().hasEntryForLayer( layer ) )
1678  getDatumTransformInfo( layer, layer->crs().authid(), destAuthId );
1679  }
1680 }
1681 
1682 
1683 
1685 {
1686  return mMapTool;
1687 }
1688 
1689 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
1690 {
1691  // move map image and other items to standard position
1692  moveCanvasContents( true ); // true means reset
1693 
1694  // use start and end box points to calculate the extent
1695  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1696  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1697 
1698  // modify the center
1699  double dx = end.x() - start.x();
1700  double dy = end.y() - start.y();
1701  QgsPoint c = center();
1702  c.set( c.x() - dx, c.y() - dy );
1703  setCenter( c );
1704 
1705  refresh();
1706 }
1707 
1708 void QgsMapCanvas::panAction( QMouseEvent * e )
1709 {
1710  Q_UNUSED( e );
1711 
1712  // move all map canvas items
1714 }
1715 
1717 {
1718  QPoint pnt( 0, 0 );
1719  if ( !reset )
1720  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1721 
1722  setSceneRect( -pnt.x(), -pnt.y(), viewport()->size().width(), viewport()->size().height() );
1723 }
1724 
1726 {
1727  Q_UNUSED( mapLayer );
1728 }
1729 
1731 {
1732  return mCanvasProperties->mouseLastXY;
1733 }
1734 
1735 void QgsMapCanvas::setPreviewModeEnabled( bool previewEnabled )
1736 {
1737  if ( !mPreviewEffect )
1738  {
1739  return;
1740  }
1741 
1742  mPreviewEffect->setEnabled( previewEnabled );
1743 }
1744 
1746 {
1747  if ( !mPreviewEffect )
1748  {
1749  return false;
1750  }
1751 
1752  return mPreviewEffect->isEnabled();
1753 }
1754 
1756 {
1757  if ( !mPreviewEffect )
1758  {
1759  return;
1760  }
1761 
1762  mPreviewEffect->setMode( mode );
1763 }
1764 
1766 {
1767  if ( !mPreviewEffect )
1768  {
1770  }
1771 
1772  return mPreviewEffect->mode();
1773 }
1774 
1776 {
1777  if ( !mSnappingUtils )
1778  {
1779  // associate a dummy instance, but better than null pointer
1780  QgsMapCanvas* c = const_cast<QgsMapCanvas*>( this );
1781  c->mSnappingUtils = new QgsMapCanvasSnappingUtils( c, c );
1782  }
1783  return mSnappingUtils;
1784 }
1785 
1787 {
1788  mSnappingUtils = utils;
1789 }
1790 
1791 void QgsMapCanvas::readProject( const QDomDocument & doc )
1792 {
1793  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1794  if ( nodes.count() )
1795  {
1796  QDomNode node = nodes.item( 0 );
1797 
1798  QgsMapSettings tmpSettings;
1799  tmpSettings.readXML( node );
1800  setMapUnits( tmpSettings.mapUnits() );
1802  setDestinationCrs( tmpSettings.destinationCrs() );
1803  setExtent( tmpSettings.extent() );
1804  setRotation( tmpSettings.rotation() );
1805  mSettings.datumTransformStore() = tmpSettings.datumTransformStore();
1806 
1807  clearExtentHistory(); // clear the extent history on project load
1808  }
1809  else
1810  {
1811  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1812  }
1813 }
1814 
1815 void QgsMapCanvas::writeProject( QDomDocument & doc )
1816 {
1817  // create node "mapcanvas" and call mMapRenderer->writeXML()
1818 
1819  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1820  if ( !nl.count() )
1821  {
1822  QgsDebugMsg( "Unable to find qgis element in project file" );
1823  return;
1824  }
1825  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1826 
1827  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1828  qgisNode.appendChild( mapcanvasNode );
1829 
1830  mSettings.writeXML( mapcanvasNode, doc );
1831  // TODO: store only units, extent, projections, dest CRS
1832 }
1833 
1835 void QgsMapCanvas::getDatumTransformInfo( const QgsMapLayer* ml, const QString& srcAuthId, const QString& destAuthId )
1836 {
1837  if ( !ml )
1838  {
1839  return;
1840  }
1841 
1842  //check if default datum transformation available
1843  QSettings s;
1844  QString settingsString = "/Projections/" + srcAuthId + "//" + destAuthId;
1845  QVariant defaultSrcTransform = s.value( settingsString + "_srcTransform" );
1846  QVariant defaultDestTransform = s.value( settingsString + "_destTransform" );
1847  if ( defaultSrcTransform.isValid() && defaultDestTransform.isValid() )
1848  {
1849  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1850  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, defaultSrcTransform.toInt(), defaultDestTransform.toInt() );
1851  return;
1852  }
1853 
1854  const QgsCoordinateReferenceSystem& srcCRS = QgsCRSCache::instance()->crsByAuthId( srcAuthId );
1855  const QgsCoordinateReferenceSystem& destCRS = QgsCRSCache::instance()->crsByAuthId( destAuthId );
1856 
1857  if ( !s.value( "/Projections/showDatumTransformDialog", false ).toBool() )
1858  {
1859  // just use the default transform
1860  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1861  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1862  return;
1863  }
1864 
1865  //get list of datum transforms
1866  QList< QList< int > > dt = QgsCoordinateTransform::datumTransformations( srcCRS, destCRS );
1867  if ( dt.size() < 2 )
1868  {
1869  return;
1870  }
1871 
1872  //if several possibilities: present dialog
1873  QgsDatumTransformDialog d( ml->name(), dt );
1874  d.setDatumTransformInfo( srcCRS.authid(), destCRS.authid() );
1875  if ( d.exec() == QDialog::Accepted )
1876  {
1877  int srcTransform = -1;
1878  int destTransform = -1;
1879  QList<int> t = d.selectedDatumTransform();
1880  if ( t.size() > 0 )
1881  {
1882  srcTransform = t.at( 0 );
1883  }
1884  if ( t.size() > 1 )
1885  {
1886  destTransform = t.at( 1 );
1887  }
1888  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1889  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, srcTransform, destTransform );
1890  if ( d.rememberSelection() )
1891  {
1892  s.setValue( settingsString + "_srcTransform", srcTransform );
1893  s.setValue( settingsString + "_destTransform", destTransform );
1894  }
1895  }
1896  else
1897  {
1898  mSettings.datumTransformStore().addEntry( ml->id(), srcAuthId, destAuthId, -1, -1 );
1899  mMapRenderer->addLayerCoordinateTransform( ml->id(), srcAuthId, destAuthId, -1, -1 );
1900  }
1901 }
1902 
1903 void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center )
1904 {
1906  r.scale( scaleFactor, center );
1907  setExtent( r );
1908  refresh();
1909 }
1910 
1912 {
1913  // Find out which layer it was that sent the signal.
1914  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1915  emit selectionChanged( layer );
1916  refresh();
1917 }
1918 
1919 void QgsMapCanvas::dragEnterEvent( QDragEnterEvent * e )
1920 {
1921  // By default graphics view delegates the drag events to graphics items.
1922  // But we do not want that and by ignoring the drag enter we let the
1923  // parent (e.g. QgisApp) to handle drops of map layers etc.
1924  e->ignore();
1925 }
1926 
1927 void QgsMapCanvas::mapToolDestroyed()
1928 {
1929  QgsDebugMsg( "maptool destroyed" );
1930  mMapTool = 0;
1931 }
1932 
1933 #ifdef HAVE_TOUCH
1934 bool QgsMapCanvas::event( QEvent * e )
1935 {
1936  bool done = false;
1937  if ( e->type() == QEvent::Gesture )
1938  {
1939  // call handler of current map tool
1940  if ( mMapTool )
1941  {
1942  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
1943  }
1944  }
1945  else
1946  {
1947  // pass other events to base class
1948  done = QGraphicsView::event( e );
1949  }
1950  return done;
1951 }
1952 #endif
1953 
1955 {
1956  return QSettings().value( "/qgis/canvasRotation", true ).toBool();
1957 }
1958 
1959 void QgsMapCanvas::enableRotation( bool enable )
1960 {
1961  QSettings().setValue( "/qgis/canvasRotation", enable );
1962 }
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:167
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:192
#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:139
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.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:461
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:144
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:149
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:724
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:169
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:197
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:182
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 layerCrsChange()
This slot is connected to the layer's CRS change.
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:172
QgsMapCanvas * mCanvas
Definition: qgsmapcanvas.h:723
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.
const QgsMapSettings & mapSettings() const
Return map settings with which this job was started.
void setMapUnits(QGis::UnitType u)
void getDatumTransformInfo(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId)
ask user about datum transformation
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:99
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:191
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:159
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:588
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:339
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:164
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:462
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QString what() const
Definition: qgsexception.h:35
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
QImage contentImage() const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
Q_DECL_DEPRECATED void useImageToRender(bool theFlag)
Select which Qt class to render with.
void setContent(const QImage &image, const QgsRectangle &rect)
bool isInOverview() const
Definition: qgsmapcanvas.h:85
virtual void canvasReleaseEvent(QMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:154
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:177
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:351
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:186
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.
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)
Custom exception class for Coordinate Reference System related exceptions.
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:696
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:202
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:187
static QgsCRSCache * instance()
Definition: qgscrscache.cpp:87
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:212
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:87
void extentsChanged()
Emitted when the extents of the map change.
QgsPoint toMapPoint(qreal x, qreal y) const
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:162
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:207
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.