QGIS API Documentation  3.13.0-Master (788156190c)
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 "qgsproject.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>
32 
33 
35  : QWidget( parent )
36  , mMapCanvas( mapCanvas )
37 
38 {
39  setAutoFillBackground( true );
40  setObjectName( QStringLiteral( "theOverviewCanvas" ) );
41  mPanningWidget = new QgsPanningWidget( this );
42 
45 
49 }
50 
51 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent *e )
52 {
53  mPixmap = QPixmap();
54 
55  mSettings.setOutputSize( e->size() );
56 
58 
59  refresh();
60 
61  QWidget::resizeEvent( e );
62 }
63 
64 void QgsMapOverviewCanvas::showEvent( QShowEvent *e )
65 {
66  refresh();
67  QWidget::showEvent( e );
68 }
69 
70 void QgsMapOverviewCanvas::paintEvent( QPaintEvent *pe )
71 {
72  if ( !mPixmap.isNull() )
73  {
74  QPainter paint( this );
75  paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() );
76  }
77 }
78 
79 
81 {
82  if ( !mMapCanvas ) return;
83 
84  const QgsRectangle &extent = mMapCanvas->extent();
85 
86  // show only when valid extent is set
87  if ( extent.isEmpty() || mSettings.visibleExtent().isEmpty() )
88  {
89  mPanningWidget->hide();
90  return;
91  }
92 
93  const QPolygonF &vPoly = mMapCanvas->mapSettings().visiblePolygon();
94  const QgsMapToPixel &cXf = mSettings.mapToPixel();
95  QVector< QPoint > pts;
96  pts.push_back( cXf.transform( QgsPointXY( vPoly[0] ) ).toQPointF().toPoint() );
97  pts.push_back( cXf.transform( QgsPointXY( vPoly[1] ) ).toQPointF().toPoint() );
98  pts.push_back( cXf.transform( QgsPointXY( vPoly[2] ) ).toQPointF().toPoint() );
99  pts.push_back( cXf.transform( QgsPointXY( vPoly[3] ) ).toQPointF().toPoint() );
100  mPanningWidget->setPolygon( QPolygon( pts ) );
101  mPanningWidget->show(); // show if hidden
102 }
103 
104 
106 {
107 // if (mPanningWidget->isHidden())
108 // return;
109 
110  // set offset in panning widget if inside it
111  // for better experience with panning :)
112  if ( mPanningWidget->geometry().contains( e->pos() ) )
113  {
114  mPanningCursorOffset = e->pos() - mPanningWidget->pos();
115  }
116  else
117  {
118  // use center of the panning widget if outside
119  QSize s = mPanningWidget->size();
120  mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 );
121  }
122  updatePanningWidget( e->pos() );
123 }
124 
125 
127 {
128 // if (mPanningWidget->isHidden())
129 // return;
130 
131  if ( e->button() == Qt::LeftButton )
132  {
133  // set new extent
134  const QgsMapToPixel &cXf = mSettings.mapToPixel();
135  QRect rect = mPanningWidget->geometry();
136 
137  QgsPointXY center = cXf.toMapCoordinates( rect.center() );
138  mMapCanvas->setCenter( center );
139  mMapCanvas->refresh();
140  }
141 }
142 
143 
145 {
146  // move with panning widget if tracking cursor
147  if ( ( e->buttons() & Qt::LeftButton ) == Qt::LeftButton )
148  {
149  updatePanningWidget( e->pos() );
150  }
151 }
152 
153 
155 {
156 // if (mPanningWidget->isHidden())
157 // return;
158  mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() );
159 }
160 
162 {
163  if ( !isVisible() )
164  return;
165 
167 
168  if ( !mSettings.hasValidSettings() )
169  {
170  mPixmap = QPixmap();
171  update();
172  return; // makes no sense to render anything
173  }
174 
175  if ( mJob )
176  {
177  QgsDebugMsg( QStringLiteral( "oveview - canceling old" ) );
178  mJob->cancel();
179  QgsDebugMsg( QStringLiteral( "oveview - deleting old" ) );
180  delete mJob; // get rid of previous job (if any)
181  }
182 
183  QgsDebugMsg( QStringLiteral( "oveview - starting new" ) );
184 
185  // TODO: setup overview mode
188  mJob->start();
189 
191 
192  // schedule repaint
193  update();
194 
195  // update panning widget
196  drawExtentRect();
197 }
198 
200 {
201  QgsDebugMsg( QStringLiteral( "overview - finished" ) );
202  mPixmap = QPixmap::fromImage( mJob->renderedImage() );
203 
204  delete mJob;
205  mJob = nullptr;
206 
207  // schedule repaint
208  update();
209 }
210 
212 {
213  if ( !deferred )
214  refresh();
215 }
216 
217 
218 void QgsMapOverviewCanvas::setBackgroundColor( const QColor &color )
219 {
220  mSettings.setBackgroundColor( color );
221 
222  // set erase color
223  QPalette palette;
224  palette.setColor( backgroundRole(), color );
225  setPalette( palette );
226 }
227 
228 void QgsMapOverviewCanvas::setLayers( const QList<QgsMapLayer *> &layers )
229 {
230  const auto oldLayers = mSettings.layers();
231  for ( QgsMapLayer *ml : oldLayers )
232  {
234  }
235 
237 
238  const auto newLayers = mSettings.layers();
239  for ( QgsMapLayer *ml : newLayers )
240  {
242  }
243 
245 
246  refresh();
247 }
248 
250 {
251  QgsRectangle rect;
252  if ( mSettings.hasValidSettings() )
253  rect = mSettings.fullExtent();
254  else
255  rect = mMapCanvas->fullExtent();
256 
257  // expand a bit to keep features on margin
258  rect.scale( 1.1 );
259 
260  mSettings.setExtent( rect );
261  drawExtentRect();
262 }
263 
265 {
267 }
268 
270 {
272 }
273 
274 QList<QgsMapLayer *> QgsMapOverviewCanvas::layers() const
275 {
276  return mSettings.layers();
277 }
278 
279 
281 
282 QgsPanningWidget::QgsPanningWidget( QWidget *parent )
283  : QWidget( parent )
284 {
285  setObjectName( QStringLiteral( "panningWidget" ) );
286  setMinimumSize( 5, 5 );
287  setAttribute( Qt::WA_NoSystemBackground );
288 }
289 
290 void QgsPanningWidget::setPolygon( const QPolygon &p )
291 {
292  if ( p == mPoly ) return;
293  mPoly = p;
294 
295  //ensure polygon is closed
296  if ( mPoly.at( 0 ) != mPoly.at( mPoly.length() - 1 ) )
297  mPoly.append( mPoly.at( 0 ) );
298 
299  QRect rect = p.boundingRect() + QMargins( 1, 1, 1, 1 );
300  setGeometry( rect );
301  update();
302 }
303 
304 void QgsPanningWidget::paintEvent( QPaintEvent *pe )
305 {
306  Q_UNUSED( pe )
307 
308  QPainter p;
309 
310  p.begin( this );
311  QPolygonF t = mPoly.translated( -mPoly.boundingRect().left() + 1, -mPoly.boundingRect().top() + 1 );
312 
313  // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
314  // instead of rectangles! (Same cause as #13343)
315  QPainterPath path;
316  path.addPolygon( t );
317 
318  QPen pen;
319  pen.setJoinStyle( Qt::MiterJoin );
320  pen.setColor( Qt::white );
321  pen.setWidth( 3 );
322  p.setPen( pen );
323  p.drawPath( path );
324  pen.setColor( Qt::red );
325  pen.setWidth( 1 );
326  p.setPen( pen );
327  p.drawPath( path );
328 
329  p.end();
330 }
331 
332 
333 
QgsMapSettings::setDestinationCrs
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
Definition: qgsmapsettings.cpp:309
QgsMapOverviewCanvas::resizeEvent
void resizeEvent(QResizeEvent *e) override
Overridden resize event.
Definition: qgsmapoverviewcanvas.cpp:51
QgsMapCanvas::transformContextChanged
void transformContextChanged()
Emitted when the canvas transform context is changed.
QgsMapCanvas::extent
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Definition: qgsmapcanvas.cpp:865
QgsMapCanvas::refresh
void refresh()
Repaints the canvas map.
Definition: qgsmapcanvas.cpp:508
QgsMapSettings::setFlag
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsmapsettings.cpp:341
QgsMapCanvas::destinationCrsChanged
void destinationCrsChanged()
Emitted when map CRS has changed.
QgsMapOverviewCanvas::updatePanningWidget
void updatePanningWidget(QPoint pos)
called when panning to reflect mouse movement
Definition: qgsmapoverviewcanvas.cpp:154
qgsmapcanvas.h
QgsMapOverviewCanvas::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
Definition: qgsmapoverviewcanvas.cpp:126
qgsmaptopixel.h
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:380
QgsMapRendererQImageJob::renderedImage
virtual QImage renderedImage()=0
Gets a preview/resulting image.
QgsMapSettings::hasValidSettings
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
Definition: qgsmapsettings.cpp:365
QgsMapOverviewCanvas::showEvent
void showEvent(QShowEvent *e) override
Overridden show event.
Definition: qgsmapoverviewcanvas.cpp:64
QgsMapCanvas
Definition: qgsmapcanvas.h:78
QgsMapSettings::fullExtent
QgsRectangle fullExtent() const
returns current extent of layer set
Definition: qgsmapsettings.cpp:550
QgsMapOverviewCanvas::mJob
QgsMapRendererQImageJob * mJob
for rendering overview
Definition: qgsmapoverviewcanvas.h:117
QgsMapCanvas::fullExtent
QgsRectangle fullExtent() const
Returns the combined extent for all layers on the map canvas.
Definition: qgsmapcanvas.cpp:870
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsMapToPixel::toMapCoordinates
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
Definition: qgsmaptopixel.cpp:108
QgsMapOverviewCanvas::layers
QList< QgsMapLayer * > layers() const
Returns list of layers visible in the overview.
Definition: qgsmapoverviewcanvas.cpp:274
QgsMapOverviewCanvas::layerRepaintRequested
void layerRepaintRequested(bool deferred=false)
Triggered when a layer in the overview requests a repaint.
Definition: qgsmapoverviewcanvas.cpp:211
QgsMapOverviewCanvas::setBackgroundColor
void setBackgroundColor(const QColor &color)
changes background color
Definition: qgsmapoverviewcanvas.cpp:218
QgsRectangle
Definition: qgsrectangle.h:41
QgsMapOverviewCanvas::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
Definition: qgsmapoverviewcanvas.cpp:144
QgsMapSettings::DrawLabeling
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition: qgsmapsettings.h:305
QgsRectangle::scale
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
Definition: qgsrectangle.h:235
QgsMapSettings::setBackgroundColor
void setBackgroundColor(const QColor &color)
Sets the background color of the map.
Definition: qgsmapsettings.h:289
QgsMapOverviewCanvas::mPanningWidget
QgsPanningWidget * mPanningWidget
widget for panning map in overview
Definition: qgsmapoverviewcanvas.h:102
QgsMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgsmapsettings.cpp:400
QgsMapOverviewCanvas::mMapCanvas
QgsMapCanvas * mMapCanvas
main map canvas - used to get/set extent
Definition: qgsmapoverviewcanvas.h:108
QgsMapLayer::repaintRequested
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
QgsMapOverviewCanvas::QgsMapOverviewCanvas
QgsMapOverviewCanvas(QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr)
Definition: qgsmapoverviewcanvas.cpp:34
qgsmaplayer.h
QgsMapCanvas::extentsChanged
void extentsChanged()
Emitted when the extents of the map change.
QgsMapSettings::visiblePolygon
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
Definition: qgsmapsettings.cpp:375
QgsMapSettings::backgroundColor
QColor backgroundColor() const
Gets the background color of the map.
Definition: qgsmapsettings.h:291
QgsMapOverviewCanvas::mPixmap
QPixmap mPixmap
pixmap where the map is stored
Definition: qgsmapoverviewcanvas.h:111
QgsMapRendererSequentialJob
Definition: qgsmaprenderersequentialjob.h:33
QgsMapCanvas::setCenter
void setCenter(const QgsPointXY &center)
Set the center of the map canvas, in geographical coordinates.
Definition: qgsmapcanvas.cpp:945
QgsMapRendererJob::start
virtual void start()=0
Start the rendering job and immediately return.
QgsMapSettings::setTransformContext
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
Definition: qgsmapsettings.cpp:410
QgsMapOverviewCanvas::mPanningCursorOffset
QPoint mPanningCursorOffset
position of cursor inside panning widget
Definition: qgsmapoverviewcanvas.h:105
QgsMapToPixel::transform
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.cpp:217
QgsMapSettings::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Set list of layers for map rendering.
Definition: qgsmapsettings.cpp:286
QgsMapOverviewCanvas::mSettings
QgsMapSettings mSettings
map settings used for rendering of the overview map
Definition: qgsmapoverviewcanvas.h:114
QgsPointXY
Definition: qgspointxy.h:43
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Definition: qgsmapsettings.cpp:317
qgsmaprenderersequentialjob.h
QgsMapToPixel
Definition: qgsmaptopixel.h:37
QgsMapLayer
Definition: qgsmaplayer.h:80
QgsMapOverviewCanvas::transformContextChanged
void transformContextChanged()
Called when the canvas transform context is changed.
Definition: qgsmapoverviewcanvas.cpp:269
qgsmapoverviewcanvas.h
QgsMapOverviewCanvas::mousePressEvent
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
Definition: qgsmapoverviewcanvas.cpp:105
QgsMapSettings::layers
QList< QgsMapLayer * > layers() const
Gets list of layers for map rendering The layers are stored in the reverse order of how they are rend...
Definition: qgsmapsettings.cpp:281
QgsMapOverviewCanvas::mapRenderingFinished
void mapRenderingFinished()
Definition: qgsmapoverviewcanvas.cpp:199
QgsMapOverviewCanvas::paintEvent
void paintEvent(QPaintEvent *pe) override
Overridden paint event.
Definition: qgsmapoverviewcanvas.cpp:70
QgsMapSettings::setOutputSize
void setOutputSize(QSize size)
Sets the size of the resulting map image.
Definition: qgsmapsettings.cpp:239
qgslogger.h
QgsMapRendererJob::cancel
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
QgsMapSettings::visibleExtent
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
Definition: qgsmapsettings.cpp:370
QgsMapOverviewCanvas::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
updates layer set for overview
Definition: qgsmapoverviewcanvas.cpp:228
QgsMapSettings::setExtent
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
Definition: qgsmapsettings.cpp:79
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
QgsMapOverviewCanvas::destinationCrsChanged
void destinationCrsChanged()
Should be called when the canvas destination CRS is changed.
Definition: qgsmapoverviewcanvas.cpp:264
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:432
QgsMapOverviewCanvas::updateFullExtent
void updateFullExtent()
Definition: qgsmapoverviewcanvas.cpp:249
qgsproject.h
QgsMapOverviewCanvas::refresh
void refresh()
renders overview and updates panning widget
Definition: qgsmapoverviewcanvas.cpp:161
QgsMapRendererJob::finished
void finished()
emitted when asynchronous rendering is finished (or canceled).
QgsMapOverviewCanvas::drawExtentRect
void drawExtentRect()
used for overview canvas to reflect changed extent in main map canvas
Definition: qgsmapoverviewcanvas.cpp:80