QGIS API Documentation  2.2.0-Valmiera
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 "qgsmaprenderer.h"
21 #include "qgsmapoverviewcanvas.h"
22 #include "qgsmaptopixel.h"
23 
24 #include <QPainter>
25 #include <QPaintEvent>
26 #include <QResizeEvent>
27 #include <QMouseEvent>
28 #include "qgslogger.h"
29 #include <limits.h>
30 
32 class QgsPanningWidget : public QWidget
33 {
34  public:
35  QgsPanningWidget( QWidget* parent )
36  : QWidget( parent )
37  {
38  setObjectName( "panningWidget" );
39  setMinimumSize( 5, 5 );
40  setAttribute( Qt::WA_NoSystemBackground );
41  }
42 
43  void resizeEvent( QResizeEvent* r )
44  {
45  QSize s = r->size();
46  QRegion reg( 0, 0, s.width(), s.height() );
47  QRegion reg2( 2, 2, s.width() - 4, s.height() - 4 );
48  QRegion reg3 = reg.subtract( reg2 );
49  setMask( reg3 );
50  }
51 
52 
53  void paintEvent( QPaintEvent* pe )
54  {
55  Q_UNUSED( pe );
56 
57  QRect r( QPoint( 0, 0 ), size() );
58  QPainter p;
59  p.begin( this );
60  p.setPen( Qt::red );
61  p.setBrush( Qt::red );
62  p.drawRect( r );
63  p.end();
64  }
65 
66 };
67 
68 
69 
71  : QWidget( parent ), mMapCanvas( mapCanvas )
72 {
73  setObjectName( "theOverviewCanvas" );
74  mPanningWidget = new QgsPanningWidget( this );
75 
78 
79  setBackgroundColor( palette().window().color() );
80 }
81 
83 {
84  delete mMapRenderer;
85 }
86 
87 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent* e )
88 {
89  mNewSize = e->size();
90 }
91 
92 void QgsMapOverviewCanvas::paintEvent( QPaintEvent* pe )
93 {
94  if ( mNewSize.isValid() )
95  {
96  mPixmap = QPixmap( mNewSize );
97  mMapRenderer->setOutputSize( mNewSize, mPixmap.logicalDpiX() );
99  mNewSize = QSize();
100  refresh();
101  }
102 
103  QPainter paint( this );
104  paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() );
105 }
106 
107 
109 {
110  if ( !mMapCanvas || !mMapRenderer ) return;
111 
112  const QgsRectangle& extent = mMapCanvas->extent();
113 
114  // show only when valid extent is set
115  if ( extent.isEmpty() || mMapRenderer->extent().isEmpty() )
116  {
117  mPanningWidget->hide();
118  return;
119  }
120 
122  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
123  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
124  if ( cXf )
125  {
126  // transform the points before drawing
127  cXf->transform( &ll );
128  cXf->transform( &ur );
129  }
130 
131 #if 0
132  // test whether panning widget should be drawn
133  bool show = false;
134  if ( ur.x() >= 0 && ur.x() < width() )
135  show = true;
136  if ( ll.x() >= 0 && ll.x() < width() )
137  show = true;
138  if ( ur.y() >= 0 && ur.y() < height() )
139  show = true;
140  if ( ll.y() >= 0 && ll.y() < height() )
141  show = true;
142  if ( !show )
143  {
144  QgsDebugMsg( "panning: extent out of overview area" );
145  mPanningWidget->hide();
146  return;
147  }
148 #endif
149 
150  // round values
151  int x1 = static_cast<int>( ur.x() + 0.5 ), x2 = static_cast<int>( ll.x() + 0.5 );
152  int y1 = static_cast<int>( ur.y() + 0.5 ), y2 = static_cast<int>( ll.y() + 0.5 );
153 
154  if ( x1 > x2 )
155  std::swap( x1, x2 );
156  if ( y1 > y2 )
157  std::swap( y1, y2 );
158 
159 #ifdef Q_WS_MAC
160  // setGeometry (Qt 4.2) is causing Mac window corruption (decorations
161  // are drawn at odd locations) if both coords are at limit. This may
162  // have something to do with Qt calculating dimensions as x2 - x1 + 1.
163  // (INT_MAX - INT_MIN + 1 is UINT_MAX + 1)
164  if ( x1 == INT_MIN && x2 == INT_MAX )
165  x1 += 1; // x2 -= 1 works too
166  if ( y1 == INT_MIN && y2 == INT_MAX )
167  y1 += 1;
168 #endif
169 
170  QRect r( x1, y1, x2 - x1 + 1, y2 - y1 + 1 );
171 
172  // allow for 5 pixel minimum widget size
173  if ( r.width() < 5 && x1 > INT_MIN + 2 ) // make sure no underflow occurs (2 is largest adjustment)
174  {
175  r.setX( r.x() - (( 5 - r.width() ) / 2 ) ); // adjust x by 1/2 the difference of calculated and min. width
176  r.setWidth( 5 );
177  }
178  if ( r.height() < 5 && y1 > INT_MIN + 2 )
179  {
180  r.setY( r.y() - (( 5 - r.height() ) / 2 ) ); // adjust y
181  r.setHeight( 5 );
182  }
183 
184  QgsDebugMsg( QString( "panning: extent to widget: [%1,%2] [%3x%4]" ).arg( x1 ).arg( y1 ).arg( r.width() ).arg( r.height() ) );
185 
186  mPanningWidget->setGeometry( r );
187  mPanningWidget->show(); // show if hidden
188 }
189 
190 
192 {
193 // if (mPanningWidget->isHidden())
194 // return;
195 
196  // set offset in panning widget if inside it
197  // for better experience with panning :)
198  if ( mPanningWidget->geometry().contains( e->pos() ) )
199  {
200  mPanningCursorOffset = e->pos() - mPanningWidget->pos();
201  }
202  else
203  {
204  // use center of the panning widget if outside
205  QSize s = mPanningWidget->size();
206  mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 );
207  }
208  updatePanningWidget( e->pos() );
209 }
210 
211 
213 {
214 // if (mPanningWidget->isHidden())
215 // return;
216 
217  if ( e->button() == Qt::LeftButton )
218  {
219  // set new extent
221  QRect rect = mPanningWidget->geometry();
222 
223  QgsPoint center = cXf->toMapCoordinates( rect.center() );
224  QgsRectangle oldExtent = mMapCanvas->extent();
225  QgsRectangle ext;
226  ext.setXMinimum( center.x() - oldExtent.width() / 2 );
227  ext.setXMaximum( center.x() + oldExtent.width() / 2 );
228  ext.setYMinimum( center.y() - oldExtent.height() / 2 );
229  ext.setYMaximum( center.y() + oldExtent.height() / 2 );
230 
231  QgsDebugMsg( QString( "panning: new position: [%1,%2] [%3x%4]" ).arg( rect.left() ).arg( rect.top() ).arg( rect.width() ).arg( rect.height() ) );
232 
233  mMapCanvas->setExtent( ext );
234  mMapCanvas->refresh();
235  }
236 }
237 
238 
240 {
241  // move with panning widget if tracking cursor
242  if (( e->buttons() & Qt::LeftButton ) == Qt::LeftButton )
243  {
244  updatePanningWidget( e->pos() );
245  }
246 }
247 
248 
250 {
251 // if (mPanningWidget->isHidden())
252 // return;
253  mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() );
254 }
255 
256 
258 {
259  if ( mPixmap.isNull() || mPixmap.paintingActive() )
260  return;
261 
262  mPixmap.fill( mBgColor ); //palette().color(backgroundRole());
263 
264  QPainter painter;
265  painter.begin( &mPixmap );
266 
267  // antialiasing
268  if ( mAntiAliasing )
269  painter.setRenderHint( QPainter::Antialiasing );
270 
271  // render image
272  mMapRenderer->render( &painter );
273 
274  painter.end();
275 
276  // schedule repaint
277  update();
278 
279  // update panning widget
280  drawExtentRect();
281 }
282 
283 
284 void QgsMapOverviewCanvas::setBackgroundColor( const QColor& color )
285 {
286  mBgColor = color;
287 
288  // set erase color
289  QPalette palette;
290  palette.setColor( backgroundRole(), color );
291  setPalette( palette );
292 }
293 
294 void QgsMapOverviewCanvas::setLayerSet( const QStringList& layerSet )
295 {
296  QgsDebugMsg( "layerSet: " + layerSet.join( ", " ) );
297  if ( !mMapRenderer ) return;
298  mMapRenderer->setLayerSet( layerSet );
301 }
302 
304 {
305  if ( !mMapRenderer ) return;
306  QgsRectangle rect;
307  if ( !mMapRenderer->layerSet().isEmpty() )
308  {
309  rect = mMapRenderer->fullExtent();
310  // expand a bit to keep features on margin
311  rect.scale( 1.1 );
312  }
313  mMapRenderer->setExtent( rect );
314  drawExtentRect();
315 }
316 
318 {
320 }
321 
323 {
326 }
327 
329 {
330  return mMapRenderer->layerSet();
331 }
QSize mNewSize
resized canvas size
const QgsMapToPixel * coordinateTransform()
QPoint mPanningCursorOffset
position of cursor inside panning widget
A rectangle specified with double values.
Definition: qgsrectangle.h:35
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 mouseMoveEvent(QMouseEvent *e)
Overridden mouse move event.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:164
bool mAntiAliasing
indicates whether antialiasing will be used for rendering
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:189
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void resizeEvent(QResizeEvent *r)
QgsRectangle extent() const
returns current extent
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
QgsMapCanvas * mMapCanvas
main map canvas - used to get/set extent
QgsPoint transform(const QgsPoint &p) const
void refresh()
Repaints the canvas map.
void resizeEvent(QResizeEvent *e)
Overridden resize event.
QColor mBgColor
background color
void setProjectionsEnabled(bool enabled)
sets whether to use projections for this layer set
void enableOverviewMode(bool isOverview=true)
sets whether map image will be for overview
void setLayerSet(const QStringList &layers)
change current layer set
A non GUI class for rendering a map layer set onto a QPainter.
void setBackgroundColor(const QColor &color)
changes background color
widget that serves as rectangle showing current extent in overview
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:99
double x() const
Definition: qgspoint.h:110
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
void paintEvent(QPaintEvent *pe)
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:194
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:179
QgsPanningWidget * mPanningWidget
widget for panning map in overview
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:169
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
QgsPanningWidget(QWidget *parent)
void paintEvent(QPaintEvent *pe)
Overridden paint event.
void setOutputSize(QSize size, int dpi)
void refresh()
renders overview and updates panning widget
A class to represent a point geometry.
Definition: qgspoint.h:63
void updateFullExtent()
updates extent of the layer set
void hasCrsTransformEnabled(bool flag)
QgsPoint toMapCoordinates(int x, int y) const
QgsRectangle fullExtent()
returns current extent of layer set
QPixmap mPixmap
pixmap where the map is stored
void setLayerSet(const QStringList &layerSet)
updates layer set for overview
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:174
void mouseReleaseEvent(QMouseEvent *e)
Overridden mouse release event.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs, bool refreshCoordinateTransformInfo=true)
sets destination coordinate reference system
QgsMapRenderer * mapRenderer()
Class for storing a coordinate reference system (CRS)
double y() const
Definition: qgspoint.h:118
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
QgsMapOverviewCanvas(QWidget *parent=0, QgsMapCanvas *mapCanvas=NULL)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:199
QgsMapRenderer * mMapRenderer
for rendering overview
double size
Definition: qgssvgcache.cpp:77
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:184
QStringList & layerSet()
returns current layer set
void updatePanningWidget(const QPoint &pos)
called when panning to reflect mouse movement
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:159
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:204
void drawExtentRect()
used for overview canvas to reflect changed extent in main map canvas
void mousePressEvent(QMouseEvent *e)
Overridden mouse press event.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.