QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsmapoverviewcanvas.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmapoverviewcanvas.cpp
3  Map canvas subclassed for overview
4  -------------------
5  begin : 09/14/2005
6  copyright : (C) 2005 by Martin Dobias
7  email : won.der at centrum.sk
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgsmapcanvas.h"
20 #include "qgsmaplayer.h"
21 #include "qgsmaplayerregistry.h"
22 #include "qgsmapoverviewcanvas.h"
24 #include "qgsmaptopixel.h"
25 
26 #include <QPainter>
27 #include <QPaintEvent>
28 #include <QResizeEvent>
29 #include <QMouseEvent>
30 #include "qgslogger.h"
31 #include <limits.h>
32 
34 class QgsPanningWidget : public QWidget
35 {
36  QPolygon mPoly;
37 
38  public:
39  QgsPanningWidget( QWidget* parent )
40  : QWidget( parent )
41  {
42  setObjectName( "panningWidget" );
43  setMinimumSize( 5, 5 );
44  setAttribute( Qt::WA_NoSystemBackground );
45  }
46 
47  void setPolygon( const QPolygon& p )
48  {
49  if ( p == mPoly ) return;
50  mPoly = p;
51  setGeometry( p.boundingRect() );
52  update();
53  }
54 
55 
56  void paintEvent( QPaintEvent* pe ) override
57  {
58  Q_UNUSED( pe );
59 
60  QPainter p;
61  p.begin( this );
62  p.setPen( Qt::red );
63  QPolygonF t = mPoly.translated( -mPoly.boundingRect().left(), -mPoly.boundingRect().top() );
64  p.drawConvexPolygon( t );
65  p.end();
66  }
67 
68 };
69 
70 
71 
73  : QWidget( parent )
74  , mMapCanvas( mapCanvas )
75  , mJob( 0 )
76 {
77  setObjectName( "theOverviewCanvas" );
78  mPanningWidget = new QgsPanningWidget( this );
79 
81 
82  connect( mMapCanvas, SIGNAL( extentsChanged() ), this, SLOT( drawExtentRect() ) );
83 }
84 
86 {
87 }
88 
89 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent* e )
90 {
91  mPixmap = QPixmap();
92 
93  mSettings.setOutputSize( e->size() );
94 
96 
97  refresh();
98 
99  QWidget::resizeEvent( e );
100 }
101 
102 void QgsMapOverviewCanvas::paintEvent( QPaintEvent* pe )
103 {
104  if ( !mPixmap.isNull() )
105  {
106  QPainter paint( this );
107  paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() );
108  }
109 }
110 
111 
113 {
114  if ( !mMapCanvas ) return;
115 
116  const QgsRectangle& extent = mMapCanvas->extent();
117 
118  // show only when valid extent is set
119  if ( extent.isEmpty() || mSettings.visibleExtent().isEmpty() )
120  {
121  mPanningWidget->hide();
122  return;
123  }
124 
125  const QPolygonF& vPoly = mMapCanvas->mapSettings().visiblePolygon();
126  const QgsMapToPixel& cXf = mSettings.mapToPixel();
127  QVector< QPoint > pts;
128  pts.push_back( cXf.transform( QgsPoint( vPoly[0] ) ).toQPointF().toPoint() );
129  pts.push_back( cXf.transform( QgsPoint( vPoly[1] ) ).toQPointF().toPoint() );
130  pts.push_back( cXf.transform( QgsPoint( vPoly[2] ) ).toQPointF().toPoint() );
131  pts.push_back( cXf.transform( QgsPoint( vPoly[3] ) ).toQPointF().toPoint() );
132  mPanningWidget->setPolygon( QPolygon( pts ) );
133  mPanningWidget->show(); // show if hidden
134 }
135 
136 
138 {
139 // if (mPanningWidget->isHidden())
140 // return;
141 
142  // set offset in panning widget if inside it
143  // for better experience with panning :)
144  if ( mPanningWidget->geometry().contains( e->pos() ) )
145  {
146  mPanningCursorOffset = e->pos() - mPanningWidget->pos();
147  }
148  else
149  {
150  // use center of the panning widget if outside
151  QSize s = mPanningWidget->size();
152  mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 );
153  }
154  updatePanningWidget( e->pos() );
155 }
156 
157 
159 {
160 // if (mPanningWidget->isHidden())
161 // return;
162 
163  if ( e->button() == Qt::LeftButton )
164  {
165  // set new extent
166  const QgsMapToPixel& cXf = mSettings.mapToPixel();
167  QRect rect = mPanningWidget->geometry();
168 
169  QgsPoint center = cXf.toMapCoordinates( rect.center() );
170  mMapCanvas->setCenter( center );
171  mMapCanvas->refresh();
172  }
173 }
174 
175 
177 {
178  // move with panning widget if tracking cursor
179  if (( e->buttons() & Qt::LeftButton ) == Qt::LeftButton )
180  {
181  updatePanningWidget( e->pos() );
182  }
183 }
184 
185 
187 {
188 // if (mPanningWidget->isHidden())
189 // return;
190  mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() );
191 }
192 
194 {
196 
197  if ( !mSettings.hasValidSettings() )
198  {
199  mPixmap = QPixmap();
200  update();
201  return; // makes no sense to render anything
202  }
203 
204  if ( mJob )
205  {
206  QgsDebugMsg( "oveview - cancelling old" );
207  mJob->cancel();
208  QgsDebugMsg( "oveview - deleting old" );
209  delete mJob; // get rid of previous job (if any)
210  }
211 
212  QgsDebugMsg( "oveview - starting new" );
213 
214  // TODO: setup overview mode
216  connect( mJob, SIGNAL( finished() ), this, SLOT( mapRenderingFinished() ) );
217  mJob->start();
218 
220 
221  // schedule repaint
222  update();
223 
224  // update panning widget
225  drawExtentRect();
226 }
227 
229 {
230  QgsDebugMsg( "overview - finished" );
231  mPixmap = QPixmap::fromImage( mJob->renderedImage() );
232 
233  delete mJob;
234  mJob = 0;
235 
236  // schedule repaint
237  update();
238 }
239 
241 {
242  refresh();
243 }
244 
245 
246 void QgsMapOverviewCanvas::setBackgroundColor( const QColor& color )
247 {
248  mSettings.setBackgroundColor( color );
249 
250  // set erase color
251  QPalette palette;
252  palette.setColor( backgroundRole(), color );
253  setPalette( palette );
254 }
255 
256 void QgsMapOverviewCanvas::setLayerSet( const QStringList& layerSet )
257 {
258  QgsDebugMsg( "layerSet: " + layerSet.join( ", " ) );
259 
260  foreach ( const QString& layerID, mSettings.layers() )
261  {
262  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
263  disconnect( ml, SIGNAL( repaintRequested() ), this, SLOT( layerRepaintRequested() ) );
264  }
265 
266  mSettings.setLayers( layerSet );
267 
268  foreach ( const QString& layerID, mSettings.layers() )
269  {
270  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
271  connect( ml, SIGNAL( repaintRequested() ), this, SLOT( layerRepaintRequested() ) );
272  }
273 
275 }
276 
278 {
279  QgsRectangle rect;
280  if ( mSettings.hasValidSettings() )
281  rect = mSettings.fullExtent();
282  else
283  rect = mMapCanvas->fullExtent();
284 
285  // expand a bit to keep features on margin
286  rect.scale( 1.1 );
287 
288  mSettings.setExtent( rect );
289  drawExtentRect();
290 }
291 
293 {
295 }
296 
298 {
300 }
301 
303 {
304  return mSettings.layers();
305 }
QPoint mPanningCursorOffset
position of cursor inside panning widget
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
bool isEmpty() const
test if rectangle is empty.
QgsRectangle fullExtent() const
returns current extent of layer set
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QgsMapCanvas * mMapCanvas
main map canvas - used to get/set extent
QgsMapRendererQImageJob * mJob
for rendering overview
QgsPoint transform(const QgsPoint &p) const
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void refresh()
Repaints the canvas map.
const QgsMapToPixel & mapToPixel() const
void setBackgroundColor(const QColor &color)
changes background color
widget that serves as rectangle showing current extent in overview
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
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
Enable drawing of labels on top of the map.
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
QgsPanningWidget * mPanningWidget
widget for panning map in overview
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QgsMapSettings mSettings
map settings used for rendering of the overview map
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
QgsPanningWidget(QWidget *parent)
void mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
void refresh()
renders overview and updates panning widget
A class to represent a point.
Definition: qgspoint.h:63
QColor backgroundColor() const
Get the background color of the map.
virtual void start()=0
Start the rendering job and immediately return.
void hasCrsTransformEnabled(bool flag)
QgsPoint toMapCoordinates(int x, int y) const
Job implementation that renders everything sequentially in one thread.
void setBackgroundColor(const QColor &color)
Set the background color of the map.
void paintEvent(QPaintEvent *pe) override
Overridden paint event.
QPixmap mPixmap
pixmap where the map is stored
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
void setOutputSize(const QSize &size)
Set the size of the resulting map image.
void setPolygon(const QPolygon &p)
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
void setCenter(const QgsPoint &center)
Set the center of the map canvas, in geographical coordinates.
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 resizeEvent(QResizeEvent *e) override
Overridden resize event.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
void paintEvent(QPaintEvent *pe) override
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
QPolygonF visiblePolygon() const
Return the visible area as a polygon (may be rotated)
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
QgsMapOverviewCanvas(QWidget *parent=0, QgsMapCanvas *mapCanvas=NULL)
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
void updatePanningWidget(const QPoint &pos)
called when panning to reflect mouse movement
void drawExtentRect()
used for overview canvas to reflect changed extent in main map canvas
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QStringList layerSet() const
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspoint.cpp:121
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.