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