QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 <QPainterPath>
28 #include <QPaintEvent>
29 #include <QResizeEvent>
30 #include <QMouseEvent>
31 #include "qgslogger.h"
32 #include <limits>
33 
34 
36  : QWidget( parent )
37  , mMapCanvas( mapCanvas )
38 
39 {
40  setAutoFillBackground( true );
41  setObjectName( QStringLiteral( "theOverviewCanvas" ) );
42  mPanningWidget = new QgsPanningWidget( this );
43 
46 
50 }
51 
52 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent *e )
53 {
54  mPixmap = QPixmap();
55 
56  mSettings.setOutputSize( e->size() );
57 
59 
60  refresh();
61 
62  QWidget::resizeEvent( e );
63 }
64 
65 void QgsMapOverviewCanvas::showEvent( QShowEvent *e )
66 {
67  refresh();
68  QWidget::showEvent( e );
69 }
70 
71 void QgsMapOverviewCanvas::paintEvent( QPaintEvent *pe )
72 {
73  if ( !mPixmap.isNull() )
74  {
75  QPainter paint( this );
76  paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() );
77  }
78 }
79 
80 
82 {
83  if ( !mMapCanvas ) return;
84 
85  const QgsRectangle &extent = mMapCanvas->extent();
86 
87  // show only when valid extent is set
88  if ( extent.isEmpty() || mSettings.visibleExtent().isEmpty() )
89  {
90  mPanningWidget->hide();
91  return;
92  }
93 
94  const QPolygonF &vPoly = mMapCanvas->mapSettings().visiblePolygon();
95  const QgsMapToPixel &cXf = mSettings.mapToPixel();
96  QVector< QPoint > pts;
97  pts.push_back( cXf.transform( QgsPointXY( vPoly[0] ) ).toQPointF().toPoint() );
98  pts.push_back( cXf.transform( QgsPointXY( vPoly[1] ) ).toQPointF().toPoint() );
99  pts.push_back( cXf.transform( QgsPointXY( vPoly[2] ) ).toQPointF().toPoint() );
100  pts.push_back( cXf.transform( QgsPointXY( vPoly[3] ) ).toQPointF().toPoint() );
101  mPanningWidget->setPolygon( QPolygon( pts ) );
102  mPanningWidget->show(); // show if hidden
103 }
104 
105 
107 {
108 // if (mPanningWidget->isHidden())
109 // return;
110 
111  // set offset in panning widget if inside it
112  // for better experience with panning :)
113  if ( mPanningWidget->geometry().contains( e->pos() ) )
114  {
115  mPanningCursorOffset = e->pos() - mPanningWidget->pos();
116  }
117  else
118  {
119  // use center of the panning widget if outside
120  QSize s = mPanningWidget->size();
121  mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 );
122  }
123  updatePanningWidget( e->pos() );
124 }
125 
126 
128 {
129 // if (mPanningWidget->isHidden())
130 // return;
131 
132  if ( e->button() == Qt::LeftButton )
133  {
134  // set new extent
135  const QgsMapToPixel &cXf = mSettings.mapToPixel();
136  QRect rect = mPanningWidget->geometry();
137 
138  QgsPointXY center = cXf.toMapCoordinates( rect.center() );
139  mMapCanvas->setCenter( center );
140  mMapCanvas->refresh();
141  }
142 }
143 
144 
146 {
147  // move with panning widget if tracking cursor
148  if ( ( e->buttons() & Qt::LeftButton ) == Qt::LeftButton )
149  {
150  updatePanningWidget( e->pos() );
151  }
152 }
153 
154 
156 {
157 // if (mPanningWidget->isHidden())
158 // return;
159  mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() );
160 }
161 
163 {
164  if ( !isVisible() )
165  return;
166 
168 
169  if ( !mSettings.hasValidSettings() )
170  {
171  mPixmap = QPixmap();
172  update();
173  return; // makes no sense to render anything
174  }
175 
176  if ( mJob )
177  {
178  QgsDebugMsg( QStringLiteral( "oveview - canceling old" ) );
179  mJob->cancel();
180  QgsDebugMsg( QStringLiteral( "oveview - deleting old" ) );
181  delete mJob; // get rid of previous job (if any)
182  }
183 
184  QgsDebugMsg( QStringLiteral( "oveview - starting new" ) );
185 
186  // TODO: setup overview mode
189  mJob->start();
190 
192 
193  // schedule repaint
194  update();
195 
196  // update panning widget
197  drawExtentRect();
198 }
199 
201 {
202  QgsDebugMsg( QStringLiteral( "overview - finished" ) );
203  mPixmap = QPixmap::fromImage( mJob->renderedImage() );
204 
205  delete mJob;
206  mJob = nullptr;
207 
208  // schedule repaint
209  update();
210 }
211 
213 {
214  if ( !deferred )
215  refresh();
216 }
217 
218 
219 void QgsMapOverviewCanvas::setBackgroundColor( const QColor &color )
220 {
221  mSettings.setBackgroundColor( color );
222 
223  // set erase color
224  QPalette palette;
225  palette.setColor( backgroundRole(), color );
226  setPalette( palette );
227 }
228 
229 void QgsMapOverviewCanvas::setLayers( const QList<QgsMapLayer *> &layers )
230 {
231  const auto oldLayers = mSettings.layers();
232  for ( QgsMapLayer *ml : oldLayers )
233  {
235  }
236 
238 
239  const auto newLayers = mSettings.layers();
240  for ( QgsMapLayer *ml : newLayers )
241  {
243  }
244 
246 
247  refresh();
248 }
249 
251 {
252  QgsRectangle rect;
253  if ( mSettings.hasValidSettings() )
254  rect = mSettings.fullExtent();
255  else
256  rect = mMapCanvas->fullExtent();
257 
258  // expand a bit to keep features on margin
259  rect.scale( 1.1 );
260 
261  mSettings.setExtent( rect );
262  drawExtentRect();
263 }
264 
266 {
268 }
269 
271 {
273 }
274 
275 QList<QgsMapLayer *> QgsMapOverviewCanvas::layers() const
276 {
277  return mSettings.layers();
278 }
279 
280 
282 
283 QgsPanningWidget::QgsPanningWidget( QWidget *parent )
284  : QWidget( parent )
285 {
286  setObjectName( QStringLiteral( "panningWidget" ) );
287  setMinimumSize( 5, 5 );
288  setAttribute( Qt::WA_NoSystemBackground );
289 }
290 
291 void QgsPanningWidget::setPolygon( const QPolygon &p )
292 {
293  if ( p == mPoly ) return;
294  mPoly = p;
295 
296  //ensure polygon is closed
297  if ( mPoly.at( 0 ) != mPoly.at( mPoly.length() - 1 ) )
298  mPoly.append( mPoly.at( 0 ) );
299 
300  QRect rect = p.boundingRect() + QMargins( 1, 1, 1, 1 );
301  setGeometry( rect );
302  update();
303 }
304 
305 void QgsPanningWidget::paintEvent( QPaintEvent *pe )
306 {
307  Q_UNUSED( pe )
308 
309  QPainter p;
310 
311  p.begin( this );
312  QPolygonF t = mPoly.translated( -mPoly.boundingRect().left() + 1, -mPoly.boundingRect().top() + 1 );
313 
314  // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
315  // instead of rectangles! (Same cause as #13343)
316  QPainterPath path;
317  path.addPolygon( t );
318 
319  QPen pen;
320  pen.setJoinStyle( Qt::MiterJoin );
321  pen.setColor( Qt::white );
322  pen.setWidth( 3 );
323  p.setPen( pen );
324  p.drawPath( path );
325  pen.setColor( Qt::red );
326  pen.setWidth( 1 );
327  p.setPen( pen );
328  p.drawPath( path );
329 
330  p.end();
331 }
332 
333 
334 
QgsMapSettings::setDestinationCrs
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
Definition: qgsmapsettings.cpp:310
QgsMapOverviewCanvas::resizeEvent
void resizeEvent(QResizeEvent *e) override
Overridden resize event.
Definition: qgsmapoverviewcanvas.cpp:52
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:1056
QgsMapCanvas::refresh
void refresh()
Repaints the canvas map.
Definition: qgsmapcanvas.cpp:525
QgsMapSettings::setFlag
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsmapsettings.cpp:342
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:155
qgsmapcanvas.h
QgsMapOverviewCanvas::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
Definition: qgsmapoverviewcanvas.cpp:127
qgsmaptopixel.h
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:391
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:366
QgsMapOverviewCanvas::showEvent
void showEvent(QShowEvent *e) override
Overridden show event.
Definition: qgsmapoverviewcanvas.cpp:65
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
QgsMapSettings::fullExtent
QgsRectangle fullExtent() const
returns current extent of layer set
Definition: qgsmapsettings.cpp:592
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:1061
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:275
QgsMapOverviewCanvas::layerRepaintRequested
void layerRepaintRequested(bool deferred=false)
Triggered when a layer in the overview requests a repaint.
Definition: qgsmapoverviewcanvas.cpp:212
QgsMapOverviewCanvas::setBackgroundColor
void setBackgroundColor(const QColor &color)
changes background color
Definition: qgsmapoverviewcanvas.cpp:219
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsMapOverviewCanvas::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
Definition: qgsmapoverviewcanvas.cpp:145
QgsMapSettings::DrawLabeling
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition: qgsmapsettings.h:307
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:291
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:401
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:35
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:376
QgsMapSettings::backgroundColor
QColor backgroundColor() const
Gets the background color of the map.
Definition: qgsmapsettings.h:293
QgsMapOverviewCanvas::mPixmap
QPixmap mPixmap
pixmap where the map is stored
Definition: qgsmapoverviewcanvas.h:111
QgsMapRendererSequentialJob
Job implementation that renders everything sequentially in one thread.
Definition: qgsmaprenderersequentialjob.h:34
QgsMapCanvas::setCenter
void setCenter(const QgsPointXY &center)
Set the center of the map canvas, in geographical coordinates.
Definition: qgsmapcanvas.cpp:1150
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:411
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:287
QgsMapOverviewCanvas::mSettings
QgsMapSettings mSettings
map settings used for rendering of the overview map
Definition: qgsmapoverviewcanvas.h:114
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Definition: qgsmapsettings.cpp:318
qgsmaprenderersequentialjob.h
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsMapOverviewCanvas::transformContextChanged
void transformContextChanged()
Called when the canvas transform context is changed.
Definition: qgsmapoverviewcanvas.cpp:270
qgsmapoverviewcanvas.h
QgsMapOverviewCanvas::mousePressEvent
void mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
Definition: qgsmapoverviewcanvas.cpp:106
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:282
QgsMapOverviewCanvas::mapRenderingFinished
void mapRenderingFinished()
Definition: qgsmapoverviewcanvas.cpp:200
QgsMapOverviewCanvas::paintEvent
void paintEvent(QPaintEvent *pe) override
Overridden paint event.
Definition: qgsmapoverviewcanvas.cpp:71
QgsMapSettings::setOutputSize
void setOutputSize(QSize size)
Sets the size of the resulting map image.
Definition: qgsmapsettings.cpp:240
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:371
QgsMapOverviewCanvas::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
updates layer set for overview
Definition: qgsmapoverviewcanvas.cpp:229
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:265
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:436
QgsMapOverviewCanvas::updateFullExtent
void updateFullExtent()
Definition: qgsmapoverviewcanvas.cpp:250
qgsproject.h
QgsMapOverviewCanvas::refresh
void refresh()
renders overview and updates panning widget
Definition: qgsmapoverviewcanvas.cpp:162
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:81