QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 <QTextStream>
34 #include <QResizeEvent>
35 #include <QString>
36 #include <QStringList>
37 #include <QWheelEvent>
38 
39 #include "qgis.h"
40 #include "qgsapplication.h"
41 #include "qgslogger.h"
42 #include "qgsmapcanvas.h"
43 #include "qgsmapcanvasmap.h"
44 #include "qgsmaplayer.h"
45 #include "qgsmaplayerregistry.h"
46 #include "qgsmaptoolpan.h"
47 #include "qgsmaptoolzoom.h"
48 #include "qgsmaptopixel.h"
49 #include "qgsmapoverviewcanvas.h"
50 #include "qgsmaprenderer.h"
51 #include "qgsmessagelog.h"
52 #include "qgsmessageviewer.h"
53 #include "qgsproject.h"
54 #include "qgsrubberband.h"
55 #include "qgsvectorlayer.h"
56 #include <math.h>
57 
60 {
61  public:
62 
64 
67 
69  QPoint mouseLastXY;
70 
73 
76 
77 };
78 
79 
80 
81 QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
82  : QGraphicsView( parent )
83  , mCanvasProperties( new CanvasProperties )
84  , mNewSize( QSize() )
85  , mPainting( false )
86  , mAntiAliasing( false )
87 {
88  setObjectName( name );
89  mScene = new QGraphicsScene();
90  setScene( mScene );
91  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
92  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
93  mLastExtentIndex = -1;
94  mCurrentLayer = NULL;
95  mMapOverview = NULL;
96  mMapTool = NULL;
97  mLastNonZoomMapTool = NULL;
98 
99  mBackbufferEnabled = true;
100  mDrawing = false;
101  mFrozen = false;
102  mDirty = true;
103 
105 
106  // by default, the canvas is rendered
107  mRenderFlag = true;
108 
109  setMouseTracking( true );
110  setFocusPolicy( Qt::StrongFocus );
111 
113 
114  // create map canvas item which will show the map
115  mMap = new QgsMapCanvasMap( this );
116  mScene->addItem( mMap );
117  mScene->update(); // porting??
118 
119  moveCanvasContents( true );
120 
121  connect( mMapRenderer, SIGNAL( drawError( QgsMapLayer* ) ), this, SLOT( showError( QgsMapLayer* ) ) );
122  connect( mMapRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ), this, SLOT( crsTransformEnabled( bool ) ) );
123 
125 
126  // project handling
127  connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
128  this, SLOT( readProject( const QDomDocument & ) ) );
129  connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
130  this, SLOT( writeProject( QDomDocument & ) ) );
131  mMap->resize( size() );
132 
133 #ifdef Q_OS_WIN
134  // Enable touch event on Windows.
135  // Qt on Windows needs to be told it can take touch events or else it ignores them.
136  grabGesture( Qt::PinchGesture );
137  viewport()->setAttribute( Qt::WA_AcceptTouchEvents );
138 #endif
139 } // QgsMapCanvas ctor
140 
141 
143 {
144  if ( mMapTool )
145  {
146  mMapTool->deactivate();
147  mMapTool = NULL;
148  }
149  mLastNonZoomMapTool = NULL;
150 
151  // delete canvas items prior to deleteing the canvas
152  // because they might try to update canvas when it's
153  // already being destructed, ends with segfault
154  QList<QGraphicsItem*> list = mScene->items();
155  QList<QGraphicsItem*>::iterator it = list.begin();
156  while ( it != list.end() )
157  {
158  QGraphicsItem* item = *it;
159  delete item;
160  it++;
161  }
162 
163  mScene->deleteLater(); // crashes in python tests on windows
164 
165  delete mMapRenderer;
166  // mCanvasProperties auto-deleted via std::auto_ptr
167  // CanvasProperties struct has its own dtor for freeing resources
168 
169 } // dtor
170 
172 {
173  mAntiAliasing = theFlag;
174  mMap->enableAntiAliasing( theFlag );
175  if ( mMapOverview )
176  mMapOverview->enableAntiAliasing( theFlag );
177 } // anti aliasing
178 
179 void QgsMapCanvas::useImageToRender( bool theFlag )
180 {
181  mMap->useImageToRender( theFlag );
182  refresh(); // redraw the map on change - prevents black map view
183 }
184 
186 {
187  return mMap;
188 }
189 
191 {
192  return mMapRenderer;
193 }
194 
195 
197 {
198  QStringList& layers = mMapRenderer->layerSet();
199  if ( index >= 0 && index < ( int ) layers.size() )
200  return QgsMapLayerRegistry::instance()->mapLayer( layers[index] );
201  else
202  return NULL;
203 }
204 
205 
207 {
209 }
210 
212 {
213  return mMapRenderer->scale();
214 } // scale
215 
216 void QgsMapCanvas::setDirty( bool dirty )
217 {
218  mDirty = dirty;
219 }
220 
222 {
223  return mDirty;
224 }
225 
226 
227 
229 {
230  return mDrawing;
231 } // isDrawing
232 
233 
234 // return the current coordinate transform based on the extents and
235 // device size
237 {
239 }
240 
241 void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers )
242 {
243  if ( mDrawing )
244  {
245  QgsDebugMsg( "NOT updating layer set while drawing" );
246  return;
247  }
248 
249  // create layer set
250  QStringList layerSet, layerSetOverview;
251 
252  int i;
253  for ( i = 0; i < layers.size(); i++ )
254  {
255  QgsMapCanvasLayer &lyr = layers[i];
256  if ( !lyr.layer() )
257  {
258  continue;
259  }
260 
261  if ( lyr.isVisible() )
262  {
263  layerSet.push_back( lyr.layer()->id() );
264  }
265 
266  if ( lyr.isInOverview() )
267  {
268  layerSetOverview.push_back( lyr.layer()->id() );
269  }
270  }
271 
272  QStringList& layerSetOld = mMapRenderer->layerSet();
273 
274  bool layerSetChanged = layerSetOld != layerSet;
275 
276  // update only if needed
277  if ( layerSetChanged )
278  {
279  QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) );
280 
281  for ( i = 0; i < layerCount(); i++ )
282  {
283  // Add check if vector layer when disconnecting from selectionChanged slot
284  // Ticket #811 - racicot
286  disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
287  disconnect( currentLayer, SIGNAL( screenUpdateRequested() ), this, SLOT( updateMap() ) );
288  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
289  if ( isVectLyr )
290  {
291  disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
292  }
293  }
294 
295  mMapRenderer->setLayerSet( layerSet );
296 
297  for ( i = 0; i < layerCount(); i++ )
298  {
299  // Add check if vector layer when connecting to selectionChanged slot
300  // Ticket #811 - racicot
302  connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) );
303  connect( currentLayer, SIGNAL( screenUpdateRequested() ), this, SLOT( updateMap() ) );
304  QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer );
305  if ( isVectLyr )
306  {
307  connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) );
308  }
309  }
310 
311  QgsDebugMsg( "Layers have changed, refreshing" );
312  emit layersChanged();
313 
314  refresh();
315  }
316 
317  if ( mMapOverview )
318  {
319  QStringList& layerSetOvOld = mMapOverview->layerSet();
320  if ( layerSetOvOld != layerSetOverview )
321  {
322  mMapOverview->setLayerSet( layerSetOverview );
323  }
324 
325  // refresh overview maplayers even if layer set is the same
326  // because full extent might have changed
327  updateOverview();
328  }
329 } // setLayerSet
330 
332 {
333  if ( mMapOverview )
334  {
335  // disconnect old map overview if exists
336  disconnect( mMapRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ),
337  mMapOverview, SLOT( hasCrsTransformEnabled( bool ) ) );
338  disconnect( mMapRenderer, SIGNAL( destinationSrsChanged() ),
339  mMapOverview, SLOT( destinationSrsChanged() ) );
340 
341  // map overview is not owned by map canvas so don't delete it...
342  }
343 
344  mMapOverview = overview;
345 
346  if ( overview )
347  {
348  // connect to the map render to copy its projection settings
349  connect( mMapRenderer, SIGNAL( hasCrsTransformEnabled( bool ) ),
350  overview, SLOT( hasCrsTransformEnabled( bool ) ) );
351  connect( mMapRenderer, SIGNAL( destinationSrsChanged() ),
352  overview, SLOT( destinationSrsChanged() ) );
353  }
354 }
355 
356 
358 {
359  // redraw overview
360  if ( mMapOverview )
361  {
363  }
364 }
365 
366 
368 {
369  return mCurrentLayer;
370 }
371 
372 
374 {
375  // we can't draw again if already drawing...
376  if ( mDrawing )
377  return;
378 
379  QSettings settings;
380  bool logRefresh = settings.value( "/Map/logCanvasRefreshEvent", false ).toBool();
381  QTime t;
382  if ( logRefresh )
383  {
384  t.start();
385  }
386 
387 #ifdef Q_WS_X11
388  bool enableBackbufferSetting = settings.value( "/Map/enableBackbuffer", 1 ).toBool();
389 #endif
390 
391 #ifdef Q_WS_X11
392 #ifndef ANDROID
393  // disable the update that leads to the resize crash on X11 systems
394  if ( viewport() )
395  {
396  if ( enableBackbufferSetting != mBackbufferEnabled )
397  {
398  qDebug() << "Enable back buffering: " << enableBackbufferSetting;
399  if ( enableBackbufferSetting )
400  {
401  viewport()->setAttribute( Qt::WA_PaintOnScreen, false );
402  }
403  else
404  {
405  viewport()->setAttribute( Qt::WA_PaintOnScreen, true );
406  }
407  mBackbufferEnabled = enableBackbufferSetting;
408  }
409  }
410 #endif // ANDROID
411 #endif // Q_WS_X11
412 
413  mDrawing = true;
414 
415  if ( mRenderFlag && !mFrozen )
416  {
417  clear();
418 
419  // Tell the user we're going to be a while
420  QApplication::setOverrideCursor( Qt::WaitCursor );
421 
422  emit renderStarting();
423 
424  mMap->render();
425 
426  mDirty = false;
427 
428  // notify any listeners that rendering is complete
429  QPainter p;
430  p.begin( &mMap->paintDevice() );
431  emit renderComplete( &p );
432  p.end();
433 
434  // notifies current map tool
435  if ( mMapTool )
437 
438  // Tell the user we've finished going to be a while
439  QApplication::restoreOverrideCursor();
440  }
441 
442  mDrawing = false;
443 
444  // Done refreshing
445  emit mapCanvasRefreshed();
446 
447  if ( logRefresh )
448  {
449  QString logMsg = tr( "Canvas refresh: %1 ms" ).arg( t.elapsed() );
450  QObject* senderObj = QObject::sender();
451  if ( senderObj )
452  {
453  logMsg += tr( ", sender '%1'" ).arg( senderObj->metaObject()->className() );
454  }
455  QgsMessageLog::logMessage( logMsg, tr( "Rendering" ) );
456  }
457 
458 } // refresh
459 
461 {
462  if ( mMap )
463  {
464  mMap->updateContents();
465  }
466 }
467 
468 //the format defaults to "PNG" if not specified
469 void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QString theFormat )
470 {
471  //
472  //check if the optional QPaintDevice was supplied
473  //
474  if ( theQPixmap != NULL )
475  {
476  // render
477  QPainter painter;
478  painter.begin( theQPixmap );
479  mMapRenderer->render( &painter );
480  emit renderComplete( &painter );
481  painter.end();
482 
483  theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() );
484  }
485  else //use the map view
486  {
487  QPixmap *pixmap = dynamic_cast<QPixmap *>( &mMap->paintDevice() );
488  if ( !pixmap )
489  return;
490 
491  pixmap->save( theFileName, theFormat.toLocal8Bit().data() );
492  }
493  //create a world file to go with the image...
494  QgsRectangle myRect = mMapRenderer->extent();
495  QString myHeader;
496  // note: use 17 places of precision for all numbers output
497  //Pixel XDim
498  myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
499  //Rotation on y axis - hard coded
500  myHeader += "0 \r\n";
501  //Rotation on x axis - hard coded
502  myHeader += "0 \r\n";
503  //Pixel YDim - almost always negative - see
504  //http://en.wikipedia.org/wiki/World_file#cite_note-2
505  myHeader += "-" + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
506  //Origin X (center of top left cell)
507  myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
508  //Origin Y (center of top left cell)
509  myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
510  QFileInfo myInfo = QFileInfo( theFileName );
511  // allow dotted names
512  QString myWorldFileName = myInfo.absolutePath() + "/" + myInfo.completeBaseName() + "." + theFormat + "w";
513  QFile myWorldFile( myWorldFileName );
514  if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text
515  {
516  return;
517  }
518  QTextStream myStream( &myWorldFile );
519  myStream << myHeader;
520 } // saveAsImage
521 
522 
523 
525 {
526  return mMapRenderer->extent();
527 } // extent
528 
530 {
531  return mMapRenderer->fullExtent();
532 } // extent
533 
535 {
536  // projection settings have changed
537 
538  QgsDebugMsg( "updating full extent" );
539 
541  refresh();
542 }
543 
545 {
546  if ( mDrawing )
547  {
548  return;
549  }
550 
551  QgsRectangle current = extent();
552 
553  if ( r.isEmpty() )
554  {
555  QgsDebugMsg( "Empty extent - keeping old extent with new center!" );
556  QgsRectangle e( QgsPoint( r.center().x() - current.width() / 2.0, r.center().y() - current.height() / 2.0 ),
557  QgsPoint( r.center().x() + current.width() / 2.0, r.center().y() + current.height() / 2.0 ) );
558  mMapRenderer->setExtent( e );
559  }
560  else
561  {
562  mMapRenderer->setExtent( r );
563  }
564  emit extentsChanged();
565  updateScale();
566  if ( mMapOverview )
568  if ( mLastExtent.size() > 20 )
569  mLastExtent.removeAt( 0 );
570 
571  //clear all extent items after current index
572  for ( int i = mLastExtent.size() - 1; i > mLastExtentIndex; i-- )
573  {
574  mLastExtent.removeAt( i );
575  }
576 
577  mLastExtent.append( extent() ) ;
578 
579  // adjust history to no more than 20
580  if ( mLastExtent.size() > 20 )
581  {
582  mLastExtent.removeAt( 0 );
583  }
584 
585  // the last item is the current extent
586  mLastExtentIndex = mLastExtent.size() - 1;
587 
588  // update controls' enabled state
589  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
590  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
591  // notify canvas items of change
593 
594 } // setExtent
595 
596 
598 {
599  double scale = mMapRenderer->scale();
600 
601  emit scaleChanged( scale );
602 }
603 
604 
606 {
607  // Indicate to the next paint event that we need to rebuild the canvas contents
608  setDirty( true );
609 
610 } // clear
611 
612 
613 
615 {
616  if ( mDrawing )
617  {
618  return;
619  }
620 
622  // If the full extent is an empty set, don't do the zoom
623  if ( !extent.isEmpty() )
624  {
625  // Add a 5% margin around the full extent
626  extent.scale( 1.05 );
627  setExtent( extent );
628  }
629  refresh();
630 
631 } // zoomToFullExtent
632 
633 
634 
636 {
637  if ( mDrawing )
638  {
639  return;
640  }
641 
642  if ( mLastExtentIndex > 0 )
643  {
646  emit extentsChanged();
647  updateScale();
648  if ( mMapOverview )
650  refresh();
651  // update controls' enabled state
652  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
653  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
654  // notify canvas items of change
656  }
657 
658 } // zoomToPreviousExtent
659 
661 {
662  if ( mDrawing )
663  {
664  return;
665  }
666  if ( mLastExtentIndex < mLastExtent.size() - 1 )
667  {
670  emit extentsChanged();
671  updateScale();
672  if ( mMapOverview )
674  refresh();
675  // update controls' enabled state
676  emit zoomLastStatusChanged( mLastExtentIndex > 0 );
677  emit zoomNextStatusChanged( mLastExtentIndex < mLastExtent.size() - 1 );
678  // notify canvas items of change
680  }
681 }// zoomToNextExtent
682 
684 {
685  mLastExtent.clear(); // clear the zoom history list
686  mLastExtent.append( extent() ) ; // set the current extent in the list
687  mLastExtentIndex = mLastExtent.size() - 1;
688  // update controls' enabled state
691 }// clearExtentHistory
692 
693 
695 {
697 }
698 
700 {
701  // We assume that if the map units have changed, the changed value
702  // will be accessible from QgsMapRenderer
703 
704  // And then force a redraw of the scale number in the status bar
705  updateScale();
706 
707  // And then redraw the map to force the scale bar to update
708  // itself. This is less than ideal as the entire map gets redrawn
709  // just to get the scale bar to redraw itself. If we ask the scale
710  // bar to redraw itself without redrawing the map, the existing
711  // scale bar is not removed, and we end up with two scale bars in
712  // the same location. This can perhaps be fixed when/if the scale
713  // bar is done as a transparent layer on top of the map canvas.
714  refresh();
715 }
716 
718 {
719  if ( mDrawing )
720  {
721  return;
722  }
723 
724  if ( layer == NULL )
725  {
726  // use current layer by default
727  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
728  }
729 
730  if ( layer == NULL )
731  {
732  return;
733  }
734 
735  if ( layer->selectedFeatureCount() == 0 )
736  {
737  return;
738  }
739 
741 
742  // no selected features, only one selected point feature
743  //or two point features with the same x- or y-coordinates
744  if ( rect.isEmpty() )
745  {
746  // zoom in
747  QgsPoint c = rect.center();
748  rect = extent();
749  rect.scale( 1.0, &c );
750  }
751  //zoom to an area
752  else
753  {
754  // Expand rect to give a bit of space around the selected
755  // objects so as to keep them clear of the map boundaries
756  // The same 5% should apply to all margins.
757  rect.scale( 1.05 );
758  }
759 
760  setExtent( rect );
761  refresh();
762 } // zoomToSelected
763 
765 {
766  if ( mDrawing )
767  {
768  return;
769  }
770 
771  if ( layer == NULL )
772  {
773  // use current layer by default
774  layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
775  }
776 
777  if ( layer == NULL )
778  {
779  return;
780  }
781 
782  if ( layer->selectedFeatureCount() == 0 )
783  {
784  return;
785  }
786 
788  setExtent( QgsRectangle( rect.center(), rect.center() ) );
789  refresh();
790 } // panToSelected
791 
792 void QgsMapCanvas::keyPressEvent( QKeyEvent * e )
793 {
794 
795  if ( mDrawing )
796  {
797  e->ignore();
798  }
799 
800  emit keyPressed( e );
801 
802  if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown )
803  return;
804 
805  QPainter paint;
806  QPen pen( Qt::gray );
807  QgsPoint ll, ur;
808 
809  if ( ! mCanvasProperties->mouseButtonDown )
810  {
811  // Don't want to interfer with mouse events
812 
813  QgsRectangle currentExtent = mMapRenderer->extent();
814  double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 );
815  double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 );
816 
817  switch ( e->key() )
818  {
819  case Qt::Key_Left:
820  QgsDebugMsg( "Pan left" );
821 
822  currentExtent.setXMinimum( currentExtent.xMinimum() - dx );
823  currentExtent.setXMaximum( currentExtent.xMaximum() - dx );
824  setExtent( currentExtent );
825  refresh();
826  break;
827 
828  case Qt::Key_Right:
829  QgsDebugMsg( "Pan right" );
830 
831  currentExtent.setXMinimum( currentExtent.xMinimum() + dx );
832  currentExtent.setXMaximum( currentExtent.xMaximum() + dx );
833  setExtent( currentExtent );
834  refresh();
835  break;
836 
837  case Qt::Key_Up:
838  QgsDebugMsg( "Pan up" );
839 
840  currentExtent.setYMaximum( currentExtent.yMaximum() + dy );
841  currentExtent.setYMinimum( currentExtent.yMinimum() + dy );
842  setExtent( currentExtent );
843  refresh();
844  break;
845 
846  case Qt::Key_Down:
847  QgsDebugMsg( "Pan down" );
848 
849  currentExtent.setYMaximum( currentExtent.yMaximum() - dy );
850  currentExtent.setYMinimum( currentExtent.yMinimum() - dy );
851  setExtent( currentExtent );
852  refresh();
853  break;
854 
855 
856 
857  case Qt::Key_Space:
858  QgsDebugMsg( "Pressing pan selector" );
859 
860  //mCanvasProperties->dragging = true;
861  if ( ! e->isAutoRepeat() )
862  {
863  mCanvasProperties->panSelectorDown = true;
864  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
865  }
866  break;
867 
868  case Qt::Key_PageUp:
869  QgsDebugMsg( "Zoom in" );
870  zoomIn();
871  break;
872 
873  case Qt::Key_PageDown:
874  QgsDebugMsg( "Zoom out" );
875  zoomOut();
876  break;
877 
878  default:
879  // Pass it on
880  if ( mMapTool )
881  {
882  mMapTool->keyPressEvent( e );
883  }
884  e->ignore();
885 
886  QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) );
887 
888  }
889  }
890 } //keyPressEvent()
891 
892 void QgsMapCanvas::keyReleaseEvent( QKeyEvent * e )
893 {
894  QgsDebugMsg( "keyRelease event" );
895 
896  if ( mDrawing )
897  {
898  return;
899  }
900 
901  switch ( e->key() )
902  {
903  case Qt::Key_Space:
904  if ( !e->isAutoRepeat() && mCanvasProperties->panSelectorDown )
905  {
906  QgsDebugMsg( "Releasing pan selector" );
907 
908  mCanvasProperties->panSelectorDown = false;
909  panActionEnd( mCanvasProperties->mouseLastXY );
910  }
911  break;
912 
913  default:
914  // Pass it on
915  if ( mMapTool )
916  {
918  }
919 
920  e->ignore();
921 
922  QgsDebugMsg( "Ignoring key release: " + QString::number( e->key() ) );
923  }
924 
925  emit keyReleased( e );
926 
927 } //keyReleaseEvent()
928 
929 
930 void QgsMapCanvas::mouseDoubleClickEvent( QMouseEvent * e )
931 {
932  if ( mDrawing )
933  {
934  return;
935  }
936 
937  // call handler of current map tool
938  if ( mMapTool )
940 } // mouseDoubleClickEvent
941 
942 
943 void QgsMapCanvas::mousePressEvent( QMouseEvent * e )
944 {
945  if ( mDrawing )
946  {
947  return;
948  }
949 
950  //use middle mouse button for panning, map tools won't receive any events in that case
951  if ( e->button() == Qt::MidButton )
952  {
953  mCanvasProperties->panSelectorDown = true;
954  mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY;
955  }
956  else
957  {
958 
959  // call handler of current map tool
960  if ( mMapTool )
962  }
963 
964  if ( mCanvasProperties->panSelectorDown )
965  {
966  return;
967  }
968 
969  mCanvasProperties->mouseButtonDown = true;
970  mCanvasProperties->rubberStartPoint = e->pos();
971 
972 } // mousePressEvent
973 
974 
975 void QgsMapCanvas::mouseReleaseEvent( QMouseEvent * e )
976 {
977  if ( mDrawing )
978  {
979  return;
980  }
981 
982  //use middle mouse button for panning, map tools won't receive any events in that case
983  if ( e->button() == Qt::MidButton )
984  {
985  mCanvasProperties->panSelectorDown = false;
986  panActionEnd( mCanvasProperties->mouseLastXY );
987  }
988  else
989  {
990  // call handler of current map tool
991  if ( mMapTool )
992  {
993  // right button was pressed in zoom tool? return to previous non zoom tool
994  if ( e->button() == Qt::RightButton && mMapTool->isTransient() )
995  {
996  QgsDebugMsg( "Right click in map tool zoom or pan, last tool is " +
997  QString( mLastNonZoomMapTool ? "not null." : "null." ) );
998 
999  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
1000 
1001  // change to older non-zoom tool
1002  if ( mLastNonZoomMapTool
1003  && ( !mLastNonZoomMapTool->isEditTool() || ( vlayer && vlayer->isEditable() ) ) )
1004  {
1006  mLastNonZoomMapTool = NULL;
1007  setMapTool( t );
1008  }
1009  return;
1010  }
1012  }
1013  }
1014 
1015 
1016  mCanvasProperties->mouseButtonDown = false;
1017 
1018  if ( mCanvasProperties->panSelectorDown )
1019  return;
1020 
1021 } // mouseReleaseEvent
1022 
1023 void QgsMapCanvas::resizeEvent( QResizeEvent * e )
1024 {
1025  mNewSize = e->size();
1026 }
1027 
1028 void QgsMapCanvas::paintEvent( QPaintEvent *e )
1029 {
1030  if ( mNewSize.isValid() )
1031  {
1032  if ( mPainting || mDrawing )
1033  {
1034  //cancel current render progress
1035  if ( mMapRenderer )
1036  {
1037  QgsRenderContext* theRenderContext = mMapRenderer->rendererContext();
1038  if ( theRenderContext )
1039  {
1040  theRenderContext->setRenderingStopped( true );
1041  }
1042  }
1043  return;
1044  }
1045 
1046  mPainting = true;
1047 
1048  while ( mNewSize.isValid() )
1049  {
1050  QSize lastSize = mNewSize;
1051  mNewSize = QSize();
1052 
1053  //set map size before scene size helps keep scene indexes updated properly
1054  // this was the cause of rubberband artifacts
1055  mMap->resize( lastSize );
1056  mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );
1057 
1058  // notify canvas items of change
1060 
1061  updateScale();
1062 
1063  refresh();
1064 
1065  emit extentsChanged();
1066  }
1067 
1068  mPainting = false;
1069  }
1070 
1071  QGraphicsView::paintEvent( e );
1072 } // paintEvent
1073 
1075 {
1076  QList<QGraphicsItem*> list = mScene->items();
1077  QList<QGraphicsItem*>::iterator it = list.begin();
1078  while ( it != list.end() )
1079  {
1080  QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem *>( *it );
1081 
1082  if ( item )
1083  {
1084  item->updatePosition();
1085  }
1086 
1087  it++;
1088  }
1089 }
1090 
1091 
1092 void QgsMapCanvas::wheelEvent( QWheelEvent *e )
1093 {
1094  // Zoom the map canvas in response to a mouse wheel event. Moving the
1095  // wheel forward (away) from the user zooms in
1096 
1097  QgsDebugMsg( "Wheel event delta " + QString::number( e->delta() ) );
1098 
1099  if ( mDrawing )
1100  {
1101  return;
1102  }
1103 
1104  if ( mMapTool )
1105  {
1106  mMapTool->wheelEvent( e );
1107  }
1108 
1109  if ( QgsApplication::keyboardModifiers() )
1110  {
1111  // leave the wheel for map tools if any modifier pressed
1112  return;
1113  }
1114 
1115  switch ( mWheelAction )
1116  {
1117  case WheelZoom:
1118  // zoom without changing extent
1119  if ( e->delta() > 0 )
1120  zoomIn();
1121  else
1122  zoomOut();
1123  break;
1124 
1125  case WheelZoomAndRecenter:
1126  // zoom and don't change extent
1127  zoomWithCenter( e->x(), e->y(), e->delta() > 0 );
1128  break;
1129 
1131  {
1132  // zoom map to mouse cursor
1133  double scaleFactor = e->delta() > 0 ? 1 / mWheelZoomFactor : mWheelZoomFactor;
1134 
1135  QgsPoint oldCenter( mMapRenderer->extent().center() );
1136  QgsPoint mousePos( getCoordinateTransform()->toMapPoint( e->x(), e->y() ) );
1137  QgsPoint newCenter( mousePos.x() + (( oldCenter.x() - mousePos.x() ) * scaleFactor ),
1138  mousePos.y() + (( oldCenter.y() - mousePos.y() ) * scaleFactor ) );
1139 
1140  // same as zoomWithCenter (no coordinate transformations are needed)
1142  extent.scale( scaleFactor, &newCenter );
1143  setExtent( extent );
1144  refresh();
1145  break;
1146  }
1147 
1148  case WheelNothing:
1149  // well, nothing!
1150  break;
1151  }
1152 }
1153 
1154 void QgsMapCanvas::setWheelAction( WheelAction action, double factor )
1155 {
1156  mWheelAction = action;
1157  mWheelZoomFactor = factor;
1158 }
1159 
1161 {
1163 }
1164 
1166 {
1168 }
1169 
1170 void QgsMapCanvas::zoomScale( double newScale )
1171 {
1172  zoomByFactor( newScale / scale() );
1173 }
1174 
1175 void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
1176 {
1177  if ( mDrawing )
1178  {
1179  return;
1180  }
1181 
1182  double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
1183 
1184  // transform the mouse pos to map coordinates
1185  QgsPoint center = getCoordinateTransform()->toMapPoint( x, y );
1187  r.scale( scaleFactor, &center );
1188  setExtent( r );
1189  refresh();
1190 }
1191 
1192 void QgsMapCanvas::mouseMoveEvent( QMouseEvent * e )
1193 {
1194  if ( mDrawing )
1195  {
1196  return;
1197  }
1198 
1199  mCanvasProperties->mouseLastXY = e->pos();
1200 
1201  if ( mCanvasProperties->panSelectorDown )
1202  {
1203  panAction( e );
1204  }
1205  else
1206  {
1207  // call handler of current map tool
1208  if ( mMapTool )
1209  mMapTool->canvasMoveEvent( e );
1210  }
1211 
1212  // show x y on status bar
1213  QPoint xy = e->pos();
1215  emit xyCoordinates( coord );
1216 } // mouseMoveEvent
1217 
1218 
1219 
1222 {
1223  if ( !tool )
1224  return;
1225 
1226  if ( mMapTool )
1227  {
1228  disconnect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1229  mMapTool->deactivate();
1230  }
1231 
1232  if ( tool->isTransient() && mMapTool && !mMapTool->isTransient() )
1233  {
1234  // if zoom or pan tool will be active, save old tool
1235  // to bring it back on right click
1236  // (but only if it wasn't also zoom or pan tool)
1238  }
1239  else
1240  {
1241  mLastNonZoomMapTool = NULL;
1242  }
1243 
1244  // set new map tool and activate it
1245  mMapTool = tool;
1246  if ( mMapTool )
1247  {
1248  connect( mMapTool, SIGNAL( destroyed() ), this, SLOT( mapToolDestroyed() ) );
1249  mMapTool->activate();
1250  }
1251 
1252  emit mapToolSet( mMapTool );
1253 } // setMapTool
1254 
1256 {
1257  if ( mMapTool && mMapTool == tool )
1258  {
1259  mMapTool->deactivate();
1260  mMapTool = NULL;
1261  emit mapToolSet( NULL );
1262  setCursor( Qt::ArrowCursor );
1263  }
1264 
1265  if ( mLastNonZoomMapTool && mLastNonZoomMapTool == tool )
1266  {
1267  mLastNonZoomMapTool = NULL;
1268  }
1269 }
1270 
1272 void QgsMapCanvas::setCanvasColor( const QColor & theColor )
1273 {
1274  // background of map's pixmap
1275  mMap->setBackgroundColor( theColor );
1276 
1277  // background of the QGraphicsView
1278  QBrush bgBrush( theColor );
1279  setBackgroundBrush( bgBrush );
1280 #if 0
1281  QPalette palette;
1282  palette.setColor( backgroundRole(), theColor );
1283  setPalette( palette );
1284 #endif
1285 
1286  // background of QGraphicsScene
1287  mScene->setBackgroundBrush( bgBrush );
1288 } // setBackgroundColor
1289 
1291 {
1292  return mScene->backgroundBrush().color();
1293 }
1294 
1296 {
1297  return mMapRenderer->layerSet().size();
1298 } // layerCount
1299 
1300 
1301 QList<QgsMapLayer*> QgsMapCanvas::layers() const
1302 {
1303  QList<QgsMapLayer*> lst;
1304  foreach ( QString layerID, mMapRenderer->layerSet() )
1305  {
1307  if ( layer )
1308  lst.append( layer );
1309  }
1310  return lst;
1311 }
1312 
1313 
1315 {
1316  // called when a layer has changed visibility setting
1317 
1318  refresh();
1319 
1320 } // layerStateChange
1321 
1322 
1323 
1324 void QgsMapCanvas::freeze( bool frz )
1325 {
1326  mFrozen = frz;
1327 } // freeze
1328 
1330 {
1331  return mFrozen;
1332 } // freeze
1333 
1334 
1336 {
1337  return mMap->paintDevice();
1338 }
1339 
1341 {
1342  return mMapRenderer->mapUnitsPerPixel();
1343 } // mapUnitsPerPixel
1344 
1345 
1347 {
1348  QgsDebugMsg( "Setting map units to " + QString::number( static_cast<int>( u ) ) );
1349  mMapRenderer->setMapUnits( u );
1350 }
1351 
1352 
1354 {
1355  return mMapRenderer->mapUnits();
1356 }
1357 
1358 
1359 void QgsMapCanvas::setRenderFlag( bool theFlag )
1360 {
1361  mRenderFlag = theFlag;
1362  if ( mMapRenderer )
1363  {
1365  if ( rc )
1366  {
1367  rc->setRenderingStopped( !theFlag );
1368  }
1369  }
1370 
1371  if ( mRenderFlag )
1372  {
1373  refresh();
1374  }
1375 }
1376 
1377 void QgsMapCanvas::connectNotify( const char * signal )
1378 {
1379  Q_UNUSED( signal );
1380  QgsDebugMsg( "QgsMapCanvas connected to " + QString( signal ) );
1381 } //connectNotify
1382 
1383 
1384 
1386 {
1387  return mMapTool;
1388 }
1389 
1390 void QgsMapCanvas::panActionEnd( QPoint releasePoint )
1391 {
1392  if ( mDrawing )
1393  {
1394  return;
1395  }
1396 
1397  // move map image and other items to standard position
1398  moveCanvasContents( true ); // true means reset
1399 
1400  // use start and end box points to calculate the extent
1401  QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
1402  QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
1403 
1404  double dx = qAbs( end.x() - start.x() );
1405  double dy = qAbs( end.y() - start.y() );
1406 
1407  // modify the extent
1409 
1410  if ( end.x() < start.x() )
1411  {
1412  r.setXMinimum( r.xMinimum() + dx );
1413  r.setXMaximum( r.xMaximum() + dx );
1414  }
1415  else
1416  {
1417  r.setXMinimum( r.xMinimum() - dx );
1418  r.setXMaximum( r.xMaximum() - dx );
1419  }
1420 
1421  if ( end.y() < start.y() )
1422  {
1423  r.setYMaximum( r.yMaximum() + dy );
1424  r.setYMinimum( r.yMinimum() + dy );
1425 
1426  }
1427  else
1428  {
1429  r.setYMaximum( r.yMaximum() - dy );
1430  r.setYMinimum( r.yMinimum() - dy );
1431 
1432  }
1433 
1434  setExtent( r );
1435  refresh();
1436 }
1437 
1438 void QgsMapCanvas::panAction( QMouseEvent * e )
1439 {
1440  Q_UNUSED( e );
1441 
1442  if ( mDrawing )
1443  {
1444  return;
1445  }
1446 
1447  // move all map canvas items
1449 
1450  // update canvas
1451  //updateContents(); // TODO: need to update?
1452 }
1453 
1455 {
1456  if ( mDrawing )
1457  {
1458  return;
1459  }
1460 
1461  QPoint pnt( 0, 0 );
1462  if ( !reset )
1463  pnt += mCanvasProperties->mouseLastXY - mCanvasProperties->rubberStartPoint;
1464 
1465  mMap->setPanningOffset( pnt );
1466 
1467  QList<QGraphicsItem*> list = mScene->items();
1468  QList<QGraphicsItem*>::iterator it = list.begin();
1469  while ( it != list.end() )
1470  {
1471  QGraphicsItem* item = *it;
1472 
1473  if ( item != mMap )
1474  {
1475  // this tells map canvas item to draw with offset
1476  QgsMapCanvasItem* canvasItem = dynamic_cast<QgsMapCanvasItem *>( item );
1477  if ( canvasItem )
1478  canvasItem->setPanningOffset( pnt );
1479  }
1480 
1481  it++;
1482  }
1483 
1484  // show items
1486 
1487 }
1488 
1490 {
1491 #if 0
1492  QMessageBox::warning(
1493  this,
1494  mapLayer->lastErrorTitle(),
1495  tr( "Could not draw %1 because:\n%2", "COMMENTED OUT" ).arg( mapLayer->name() ).arg( mapLayer->lastError() )
1496  );
1497 #endif
1498 
1499  QgsMessageViewer * mv = new QgsMessageViewer( this );
1500  mv->setWindowTitle( mapLayer->lastErrorTitle() );
1501  mv->setMessageAsPlainText( tr( "Could not draw %1 because:\n%2" )
1502  .arg( mapLayer->name() ).arg( mapLayer->lastError() ) );
1503  mv->exec();
1504  //MH
1505  //QgsMessageViewer automatically sets delete on close flag
1506  //so deleting mv would lead to a segfault
1507 }
1508 
1510 {
1511  return mCanvasProperties->mouseLastXY;
1512 }
1513 
1514 void QgsMapCanvas::readProject( const QDomDocument & doc )
1515 {
1516  QDomNodeList nodes = doc.elementsByTagName( "mapcanvas" );
1517  if ( nodes.count() )
1518  {
1519  QDomNode node = nodes.item( 0 );
1520  mMapRenderer->readXML( node );
1521  clearExtentHistory(); // clear the extent history on project load
1522  }
1523  else
1524  {
1525  QgsDebugMsg( "Couldn't read mapcanvas information from project" );
1526  }
1527 }
1528 
1529 void QgsMapCanvas::writeProject( QDomDocument & doc )
1530 {
1531  // create node "mapcanvas" and call mMapRenderer->writeXML()
1532 
1533  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1534  if ( !nl.count() )
1535  {
1536  QgsDebugMsg( "Unable to find qgis element in project file" );
1537  return;
1538  }
1539  QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
1540 
1541  QDomElement mapcanvasNode = doc.createElement( "mapcanvas" );
1542  qgisNode.appendChild( mapcanvasNode );
1543  mMapRenderer->writeXML( mapcanvasNode, doc );
1544 }
1545 
1546 void QgsMapCanvas::zoomByFactor( double scaleFactor )
1547 {
1548  if ( mDrawing )
1549  {
1550  return;
1551  }
1552 
1554  r.scale( scaleFactor );
1555  setExtent( r );
1556  refresh();
1557 }
1558 
1560 {
1561  // Find out which layer it was that sent the signal.
1562  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
1563  emit selectionChanged( layer );
1564  refresh();
1565 }
1566 
1567 void QgsMapCanvas::dragEnterEvent( QDragEnterEvent * e )
1568 {
1569  // By default graphics view delegates the drag events to graphics items.
1570  // But we do not want that and by ignoring the drag enter we let the
1571  // parent (e.g. QgisApp) to handle drops of map layers etc.
1572  e->ignore();
1573 }
1574 
1576 {
1577  if ( enabled )
1578  {
1579  QgsDebugMsg( "refreshing after reprojection was enabled" );
1580  refresh();
1581  connect( mMapRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( refresh() ) );
1582  }
1583  else
1584  disconnect( mMapRenderer, SIGNAL( destinationSrsChanged() ), this, SLOT( refresh() ) );
1585 }
1586 
1588 {
1589  QgsDebugMsg( "maptool destroyed" );
1590  mMapTool = 0;
1591 }
1592 
1593 #ifdef HAVE_TOUCH
1594 bool QgsMapCanvas::event( QEvent * e )
1595 {
1596  bool done = false;
1597  if ( mDrawing )
1598  {
1599  return done;
1600  }
1601  if ( e->type() == QEvent::Gesture )
1602  {
1603  // call handler of current map tool
1604  if ( mMapTool )
1605  {
1606  done = mMapTool->gestureEvent( static_cast<QGestureEvent*>( e ) );
1607  }
1608  }
1609  else
1610  {
1611  // pass other events to base class
1612  done = QGraphicsView::event( e );
1613  }
1614  return done;
1615 }
1616 #endif
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
QgsMapCanvasMap * mMap
owns pixmap with rendered map and controls rendering
Definition: qgsmapcanvas.h:435
const QgsMapToPixel * coordinateTransform()
void zoomToSelected(QgsVectorLayer *layer=NULL)
Zoom to the extent of the selected features of current (vector) layer.
void updateCanvasItemPositions()
called on resize or changed extent to notify canvas items to change their rectangle ...
QPoint mouseLastXY
Last seen point of the mouse.
void setRenderingStopped(bool stopped)
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:45
void render(QPainter *painter, double *forceWidthScale=0)
starts rendering @ param forceWidthScale Force a specific scale factor for line widths and marker siz...
bool isEmpty() const
test if rectangle is empty
void zoomToNextExtent()
Zoom to the next extent (view)
QGraphicsScene * mScene
graphics scene manages canvas items
Definition: qgsmapcanvas.h:471
void zoomWithCenter(int x, int y, bool zoomIn)
Zooms in/out with a given center.
bool isDirty() const
Return the state of the canvas (dirty or not)
void freeze(bool frz=true)
QgsRenderContext * rendererContext()
Accessor for render context.
virtual void setCanvasColor(const QColor &_newVal)
Write property of QColor bgColor.
void enableOverviewMode(QgsMapOverviewCanvas *overview)
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
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:160
void clearExtentHistory()
void resize(QSize size)
resize canvas item and pixmap
QgsMapRenderer * mMapRenderer
all map rendering is done in this class
Definition: qgsmapcanvas.h:432
bool mouseButtonDown
Flag to indicate status of mouse button.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:185
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
virtual void canvasMoveEvent(QMouseEvent *e)
Mouse move event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:119
virtual QString lastError()
If an operation returns 0 (e.g.
void zoomByFactor(double scaleFactor)
Zoom with the factor supplied. Factor > 1 zooms out, interval (0,1) zooms in.
void mouseReleaseEvent(QMouseEvent *e)
Overridden mouse release event.
QgsRectangle extent() const
returns current extent
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
QString qgsDoubleToString(const double &a)
Definition: qgis.h:250
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:69
bool hasCrsTransformEnabled()
A simple helper method to find out if on the fly projections are enabled or not.
void setCurrentLayer(QgsMapLayer *layer)
QList< QgsMapLayer * > layers() const
return list of layers within map canvas. Added in v1.5
void moveCanvasContents(bool reset=false)
called when panning is in action, reset indicates end of panning
WheelAction mWheelAction
Mouse wheel action.
Definition: qgsmapcanvas.h:487
bool isVisible() const
Definition: qgsmapcanvas.h:78
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.
QgsMapOverviewCanvas * mMapOverview
map overview widget - it's controlled by QgsMapCanvas
Definition: qgsmapcanvas.h:438
void refresh()
Repaints the canvas map.
void renderComplete(QPainter *)
Emitted when the canvas has rendered.
~QgsMapCanvas()
Destructor.
void keyReleaseEvent(QKeyEvent *e)
Overridden key release event.
QgsMapTool * mapTool()
Returns the currently active tool.
void setPanningOffset(const QPoint &point)
sets current offset, to be called from QgsMapCanvas
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:124
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:129
void updateContents()
Update contents - can be called while drawing to show the status.
void resizeEvent(QResizeEvent *e)
Overridden resize event.
QgsMapTool * mMapTool
pointer to current map tool
Definition: qgsmapcanvas.h:474
double x() const
Definition: qgspoint.h:110
void zoomLastStatusChanged(bool)
Emitted when zoom last status changed.
virtual void renderComplete()
Called when rendering has finished. Default implementation does nothing.
Definition: qgsmaptool.cpp:162
bool mAntiAliasing
indicates whether antialiasing will be used for rendering
Definition: qgsmapcanvas.h:496
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
void updateScale()
Emits signal scaleChanged to update scale in main window.
void mouseDoubleClickEvent(QMouseEvent *e)
Overridden mouse double click event.
QgsMapLayer * mCurrentLayer
current layer in legend
Definition: qgsmapcanvas.h:468
QSize mNewSize
resize canvas size
Definition: qgsmapcanvas.h:490
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:71
void paintEvent(QPaintEvent *e)
Overridden paint event.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
virtual void keyReleaseEvent(QKeyEvent *e)
Key event for overriding.
Definition: qgsmaptool.cpp:149
void showError(QgsMapLayer *mapLayer)
show whatever error is exposed by the QgsMapLayer.
A rectangular graphics item representing the map on the canvas.
void clear()
Clear the map canvas.
int mLastExtentIndex
Definition: qgsmapcanvas.h:481
void mapCanvasRefreshed()
Emitted when canvas finished a refresh request.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:190
double scale()
Get the last reported scale of the canvas.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:175
bool mBackbufferEnabled
If backbuffering is currently enabled.
Definition: qgsmapcanvas.h:441
void setBackgroundColor(const QColor &color)
void zoomNextStatusChanged(bool)
Emitted when zoom next status changed.
QgsMapTool * mLastNonZoomMapTool
previous tool if current is for zooming/panning
Definition: qgsmapcanvas.h:477
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
void mousePressEvent(QMouseEvent *e)
Overridden mouse press event.
double mapUnitsPerPixel() const
void render()
renders map using QgsMapRenderer to mPixmap
bool mDirty
Flag to track the state of the Map canvas.
Definition: qgsmapcanvas.h:457
void panToSelected(QgsVectorLayer *layer=NULL)
Pan to the selected features of current (vector) layer keeping same extent.
void setLayerSet(QList< QgsMapCanvasLayer > &layers)
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:165
double scale() const
Scale denominator.
void keyReleased(QKeyEvent *e)
Emit key release event.
QPaintDevice & paintDevice()
void mapToolDestroyed()
called when current maptool is destroyed
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
void setMapUnits(QGis::UnitType u)
QPaintDevice & canvasPaintDevice()
Accessor for the canvas paint device.
void setMessageAsPlainText(const QString &msg)
bool mPainting
currently in paint event
Definition: qgsmapcanvas.h:493
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:95
void wheelEvent(QWheelEvent *e)
Overridden mouse wheel event.
virtual QString lastErrorTitle()
If an operation returns 0 (e.g.
void setRenderFlag(bool theFlag)
Whether to suppress rendering or not.
QGis::UnitType mapUnits() const
Get the current canvas map units.
virtual void deactivate()
called when map tool is being deactivated
Definition: qgsmaptool.cpp:85
virtual bool isEditTool()
Check whether this MapTool performs an edit operation.
Definition: qgsmaptool.cpp:171
QgsMapCanvasMap * map()
virtual void wheelEvent(QWheelEvent *e)
Mouse wheel event for overriding.
Definition: qgsmaptool.cpp:139
void refresh()
renders overview and updates panning widget
void renderStarting()
Emitted when the canvas is about to be rendered.
A class to represent a point geometry.
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 updateFullExtent()
updates extent of the layer set
void zoomOut()
Zoom out with fixed factor.
void zoomToPreviousExtent()
Zoom to the previous extent (view)
void xyCoordinates(const QgsPoint &p)
emits current mouse position
bool isDrawing()
true if canvas currently drawing
bool writeXML(QDomNode &theNode, QDomDocument &theDoc)
write settings
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 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:144
QgsPoint toMapCoordinates(int x, int y) const
bool mDrawing
Flag indicating a map refresh is in progress.
Definition: qgsmapcanvas.h:443
Abstract base class for all map tools.
Definition: qgsmaptool.h:46
void selectionChangedSlot()
Receives signal about selection change, and pass it on with layer info.
double mWheelZoomFactor
Scale factor multiple for default zoom in/out.
Definition: qgsmapcanvas.h:484
bool mFrozen
Flag indicating if the map canvas is frozen.
Definition: qgsmapcanvas.h:446
QgsRectangle fullExtent()
returns current extent of layer set
Contains information about the context of a rendering operation.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void useImageToRender(bool theFlag)
Select which Qt class to render with.
bool isInOverview() const
Definition: qgsmapcanvas.h:79
virtual void canvasReleaseEvent(QMouseEvent *e)
Mouse release event for overriding. Default implementation does nothing.
Definition: qgsmaptool.cpp:134
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:170
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:358
QgsMapRenderer * mapRenderer()
void zoomToFullExtent()
Zoom to the full extent of all layers.
void enableAntiAliasing(bool flag)
bool mRenderFlag
determines whether user has requested to suppress rendering
Definition: qgsmapcanvas.h:460
A generic message view for displaying QGIS messages.
void zoomScale(double scale)
Zoom to a specific scale.
UnitType
Map units that qgis supports.
Definition: qgis.h:188
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:166
double y() const
Definition: qgspoint.h:118
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 useImageToRender(bool flag)
void layerStateChange()
This slot is connected to the visibility change of one or more layers.
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
QgsMapCanvas(QWidget *parent=0, const char *name=0)
Constructor.
void setMapUnits(QGis::UnitType mapUnits)
Set map units (needed by project properties dialog)
void updateOverview()
void connectNotify(const char *signal)
debugging member invoked when a connect() is made to this object
void crsTransformEnabled(bool)
void setDirty(bool _dirty)
Flag the canvas as dirty and needed a refresh.
void setPanningOffset(const QPoint &point)
QPoint rubberStartPoint
Beginning point of a rubber band.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:195
void zoomIn()
Zoom in with fixed factor.
virtual bool isEditable() const
Returns true if the provider is in editing mode.
QGis::UnitType mapUnits() const
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:75
virtual void updatePosition()
called on changed extent or resize event to update position of the item
bool readXML(QDomNode &theNode)
read settings
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:180
QList< QgsRectangle > mLastExtent
recently used extent
Definition: qgsmapcanvas.h:480
void updateFullExtent()
Updates the full extent.
QStringList & layerSet()
returns current layer set
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:205
QgsMapLayer * layer()
Definition: qgsmapcanvas.h:81
void extentsChanged()
Emitted when the extents of the map change.
std::auto_ptr< CanvasProperties > mCanvasProperties
Handle pattern for implementation object.
Definition: qgsmapcanvas.h:408
void mouseMoveEvent(QMouseEvent *e)
Overridden mouse move event.
QgsMapLayer * layer(int index)
return the map layer at position index in the layer stack
void updateMap()
updates pixmap on render progress
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:155
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent)
transform bounding box from layer's CRS to output CRS
void keyPressEvent(QKeyEvent *e)
Overridden key press event.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:200
void dragEnterEvent(QDragEnterEvent *e)
Overridden drag enter event.
QgsPoint toMapPoint(double x, double y) const
void drawExtentRect()
used for overview canvas to reflect changed extent in main map canvas
void panActionEnd(QPoint releasePoint)
Ends pan action and redraws the canvas.
void mapUnitsChanged()
The map units may have changed, so cope with that.
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 mapToolSet(QgsMapTool *tool)
Emit map tool changed event.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.