QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
33 
35  : QWidget( parent )
36  , mMapCanvas( mapCanvas )
37  , mJob( nullptr )
38 {
39  setAutoFillBackground( true );
40  setObjectName( "theOverviewCanvas" );
41  mPanningWidget = new QgsPanningWidget( this );
42 
44 
45  connect( mMapCanvas, SIGNAL( extentsChanged() ), this, SLOT( drawExtentRect() ) );
46 }
47 
49 {
50 }
51 
53 {
54  mPixmap = QPixmap();
55 
57 
59 
60  refresh();
61 
63 }
64 
66 {
67  refresh();
68  QWidget::showEvent( e );
69 }
70 
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();
97  pts.push_back( cXf.transform( QgsPoint( vPoly[0] ) ).toQPointF().toPoint() );
98  pts.push_back( cXf.transform( QgsPoint( vPoly[1] ) ).toQPointF().toPoint() );
99  pts.push_back( cXf.transform( QgsPoint( vPoly[2] ) ).toQPointF().toPoint() );
100  pts.push_back( cXf.transform( QgsPoint( 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  QgsPoint 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( "oveview - cancelling old" );
179  mJob->cancel();
180  QgsDebugMsg( "oveview - deleting old" );
181  delete mJob; // get rid of previous job (if any)
182  }
183 
184  QgsDebugMsg( "oveview - starting new" );
185 
186  // TODO: setup overview mode
188  connect( mJob, SIGNAL( finished() ), this, SLOT( mapRenderingFinished() ) );
189  mJob->start();
190 
192 
193  // schedule repaint
194  update();
195 
196  // update panning widget
197  drawExtentRect();
198 }
199 
201 {
202  QgsDebugMsg( "overview - finished" );
204 
205  delete mJob;
206  mJob = nullptr;
207 
208  // schedule repaint
209  update();
210 }
211 
213 {
214  refresh();
215 }
216 
217 
219 {
220  mSettings.setBackgroundColor( color );
221 
222  // set erase color
224  palette.setColor( backgroundRole(), color );
225  setPalette( palette );
226 }
227 
229 {
230  QgsDebugMsg( "layerSet: " + layerSet.join( ", " ) );
231 
232  Q_FOREACH ( const QString& layerID, mSettings.layers() )
233  {
234  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
235  disconnect( ml, SIGNAL( repaintRequested() ), this, SLOT( layerRepaintRequested() ) );
236  }
237 
238  mSettings.setLayers( layerSet );
239 
240  Q_FOREACH ( const QString& layerID, mSettings.layers() )
241  {
242  if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
243  connect( ml, SIGNAL( repaintRequested() ), this, SLOT( layerRepaintRequested() ) );
244  }
245 
247 }
248 
250 {
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 
275 {
276  return mSettings.layers();
277 }
278 
279 
281 
282 QgsPanningWidget::QgsPanningWidget( QWidget* parent )
283  : QWidget( parent )
284 {
285  setObjectName( "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.size() - 1 ) )
297  mPoly.append( mPoly.at( 0 ) );
298 
299  setGeometry( p.boundingRect() );
300  update();
301 }
302 
303 void QgsPanningWidget::paintEvent( QPaintEvent* pe )
304 {
305  Q_UNUSED( pe );
306 
307  QPainter p;
308  p.begin( this );
309  p.setPen( Qt::red );
310  QPolygonF t = mPoly.translated( -mPoly.boundingRect().left(), -mPoly.boundingRect().top() );
311 
312  // drawPolygon causes issues on windows - corners of path may be missing resulting in triangles being drawn
313  // instead of rectangles! (Same cause as #13343)
314  QPainterPath path;
315  path.addPolygon( t );
316  p.drawPath( path );
317 
318  p.end();
319 }
320 
321 
322 
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
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
const QPalette & palette() const
int width() const
bool end()
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspoint.cpp:129
void append(const T &value)
void setColor(ColorGroup group, ColorRole role, const QColor &color)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QRect boundingRect() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QgsMapCanvas * mMapCanvas
main map canvas - used to get/set extent
QgsMapRendererQImageJob * mJob
for rendering overview
QColor backgroundColor() const
Get the background color of the map.
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
QPolygonF translated(qreal dx, qreal dy) const
bool isVisible() const
void updatePanningWidget(QPoint pos)
called when panning to reflect mouse movement
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QgsPoint toMapCoordinates(int x, int y) const
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
void refresh()
Repaints the canvas map.
QString join(const QString &separator) const
Qt::MouseButtons buttons() const
void setBackgroundColor(const QColor &color)
changes background color
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
virtual QImage renderedImage()=0
Get a preview/resulting image.
QgsRectangle visibleExtent() const
Return the actual extent derived from requested extent that takes takes output image size into accoun...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:109
void update()
Enable drawing of labels on top of the map.
int x() const
int y() const
void setGeometry(int x, int y, int w, int h)
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
const QRect & rect() const
void setMinimumSize(const QSize &)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
virtual void showEvent(QShowEvent *event)
void setOutputSize(QSize size)
Set the size of the resulting map image.
void showEvent(QShowEvent *e) override
Overridden show event.
void addPolygon(const QPolygonF &polygon)
QgsPanningWidget * mPanningWidget
widget for panning map in overview
bool isEmpty() const
test if rectangle is empty.
void setPen(const QColor &color)
Qt::MouseButton button() const
QgsMapSettings mSettings
map settings used for rendering of the overview map
QPalette::ColorRole backgroundRole() const
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
void setObjectName(const QString &name)
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
void mouseMoveEvent(QMouseEvent *e) override
Overridden mouse move event.
QPoint pos() const
QPoint center() const
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QgsMapOverviewCanvas(QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr)
void refresh()
renders overview and updates panning widget
A class to represent a point.
Definition: qgspoint.h:117
const QgsMapToPixel & mapToPixel() const
QRect rect() const
const QSize & size() const
bool isNull() const
virtual void start()=0
Start the rendering job and immediately return.
void hasCrsTransformEnabled(bool flag)
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
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.
QStringList layerSet() const
QPixmap mPixmap
pixmap where the map is stored
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void drawPath(const QPainterPath &path)
QPoint toPoint() const
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
QgsRectangle fullExtent() const
returns current extent of layer set
QWidget(QWidget *parent, QFlags< Qt::WindowType > f)
QgsRectangle fullExtent() const
Returns the combined exent for all layers on the map canvas.
int height() const
QPoint topLeft() const
void push_back(const T &value)
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.
void resizeEvent(QResizeEvent *e) override
Overridden resize event.
void setAutoFillBackground(bool enabled)
QPolygonF visiblePolygon() const
Return the visible area as a polygon (may be rotated)
const QPoint & pos() const
virtual void resizeEvent(QResizeEvent *event)
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 mousePressEvent(QMouseEvent *e) override
Overridden mouse press event.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
bool begin(QPaintDevice *device)
void mouseReleaseEvent(QMouseEvent *e) override
Overridden mouse release event.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
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