Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 /* $Id$ */
19 
20 #include "qgsmapcanvas.h"
21 #include "qgsmaprenderer.h"
22 #include "qgsmapoverviewcanvas.h"
23 #include "qgsmaptopixel.h"
24 
25 #include <QPainter>
26 #include <QPaintEvent>
27 #include <QResizeEvent>
28 #include <QMouseEvent>
29 #include "qgslogger.h"
30 #include <limits.h>
31 
33 class QgsPanningWidget : public QWidget
34 {
35  public:
36  QgsPanningWidget( QWidget* parent )
37  : QWidget( parent )
38  {
39  setObjectName( "panningWidget" );
40  setMinimumSize( 5, 5 );
41  setAttribute( Qt::WA_NoSystemBackground );
42  }
43 
44  void resizeEvent( QResizeEvent* r )
45  {
46  QSize s = r->size();
47  QRegion reg( 0, 0, s.width(), s.height() );
48  QRegion reg2( 2, 2, s.width() - 4, s.height() - 4 );
49  QRegion reg3 = reg.subtract( reg2 );
50  setMask( reg3 );
51  }
52 
53 
54  void paintEvent( QPaintEvent* pe )
55  {
56  QRect r( QPoint( 0, 0 ), size() );
57  QPainter p;
58  p.begin( this );
59  p.setPen( Qt::red );
60  p.setBrush( Qt::red );
61  p.drawRect( r );
62  p.end();
63  }
64 
65 };
66 
67 
68 
70  : QWidget( parent ), mMapCanvas( mapCanvas )
71 {
72  setObjectName( "theOverviewCanvas" );
73  mPanningWidget = new QgsPanningWidget( this );
74 
77 
78  setBackgroundColor( palette().window().color() );
79 }
80 
82 {
83  delete mMapRenderer;
84 }
85 
86 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent* e )
87 {
88  mNewSize = e->size();
89 }
90 
91 void QgsMapOverviewCanvas::paintEvent( QPaintEvent* pe )
92 {
93  if ( mNewSize.isValid() )
94  {
95  mPixmap = QPixmap( mNewSize );
96  mMapRenderer->setOutputSize( mNewSize, mPixmap.logicalDpiX() );
97  mNewSize = QSize();
98  refresh();
99  }
100 
101  QPainter paint( this );
102  paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() );
103 }
104 
105 
107 {
108  const QgsRectangle& extent = mMapCanvas->extent();
109 
110  // show only when valid extent is set
111  if ( extent.isEmpty() )
112  {
113  mPanningWidget->hide();
114  return;
115  }
116 
118  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
119  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
120  if ( cXf )
121  {
122  // transform the points before drawing
123  cXf->transform( &ll );
124  cXf->transform( &ur );
125  }
126 
127 #if 0
128  // test whether panning widget should be drawn
129  bool show = false;
130  if ( ur.x() >= 0 && ur.x() < width() ) show = true;
131  if ( ll.x() >= 0 && ll.x() < width() ) show = true;
132  if ( ur.y() >= 0 && ur.y() < height() ) show = true;
133  if ( ll.y() >= 0 && ll.y() < height() ) show = true;
134  if ( !show )
135  {
136  QgsDebugMsg( "panning: extent out of overview area" );
137  mPanningWidget->hide();
138  return;
139  }
140 #endif
141 
142  // round values
143  int x1 = static_cast<int>( ur.x() + 0.5 ), x2 = static_cast<int>( ll.x() + 0.5 );
144  int y1 = static_cast<int>( ur.y() + 0.5 ), y2 = static_cast<int>( ll.y() + 0.5 );
145 
146  if ( x1 > x2 )
147  std::swap( x1, x2 );
148  if ( y1 > y2 )
149  std::swap( y1, y2 );
150 
151 #ifdef Q_WS_MAC
152  // setGeometry (Qt 4.2) is causing Mac window corruption (decorations
153  // are drawn at odd locations) if both coords are at limit. This may
154  // have something to do with Qt calculating dimensions as x2 - x1 + 1.
155  // (INT_MAX - INT_MIN + 1 is UINT_MAX + 1)
156  if ( x1 == INT_MIN && x2 == INT_MAX ) x1 += 1; // x2 -= 1 works too
157  if ( y1 == INT_MIN && y2 == INT_MAX ) y1 += 1;
158 #endif
159 
160  QRect r( x1, y1, x2 - x1 + 1, y2 - y1 + 1 );
161 
162  // allow for 5 pixel minimum widget size
163  if ( r.width() < 5 && x1 > INT_MIN + 2 ) // make sure no underflow occurs (2 is largest adjustment)
164  {
165  r.setX( r.x() - (( 5 - r.width() ) / 2 ) ); // adjust x by 1/2 the difference of calculated and min. width
166  r.setWidth( 5 );
167  }
168  if ( r.height() < 5 && y1 > INT_MIN + 2 )
169  {
170  r.setY( r.y() - (( 5 - r.height() ) / 2 ) ); // adjust y
171  r.setHeight( 5 );
172  }
173 
174  QgsDebugMsg( QString( "panning: extent to widget: [%1,%2] [%3x%4]" ).arg( x1 ).arg( y1 ).arg( r.width() ).arg( r.height() ) );
175 
176  mPanningWidget->setGeometry( r );
177  mPanningWidget->show(); // show if hidden
178 }
179 
180 
182 {
183 // if (mPanningWidget->isHidden())
184 // return;
185 
186  // set offset in panning widget if inside it
187  // for better experience with panning :)
188  if ( mPanningWidget->geometry().contains( e->pos() ) )
189  {
190  mPanningCursorOffset = e->pos() - mPanningWidget->pos();
191  }
192  else
193  {
194  // use center of the panning widget if outside
195  QSize s = mPanningWidget->size();
196  mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 );
197  }
198  updatePanningWidget( e->pos() );
199 }
200 
201 
203 {
204 // if (mPanningWidget->isHidden())
205 // return;
206 
207  if ( e->button() == Qt::LeftButton )
208  {
209  // set new extent
211  QRect rect = mPanningWidget->geometry();
212 
213  QgsPoint center = cXf->toMapCoordinates( rect.center() );
214  QgsRectangle oldExtent = mMapCanvas->extent();
215  QgsRectangle ext;
216  ext.setXMinimum( center.x() - oldExtent.width() / 2 );
217  ext.setXMaximum( center.x() + oldExtent.width() / 2 );
218  ext.setYMinimum( center.y() - oldExtent.height() / 2 );
219  ext.setYMaximum( center.y() + oldExtent.height() / 2 );
220 
221  QgsDebugMsg( QString( "panning: new position: [%1,%2] [%3x%4]" ).arg( rect.left() ).arg( rect.top() ).arg( rect.width() ).arg( rect.height() ) );
222 
223  mMapCanvas->setExtent( ext );
224  mMapCanvas->refresh();
225  }
226 }
227 
228 
230 {
231  // move with panning widget if tracking cursor
232  if (( e->buttons() & Qt::LeftButton ) == Qt::LeftButton )
233  {
234  updatePanningWidget( e->pos() );
235  }
236 }
237 
238 
240 {
241 // if (mPanningWidget->isHidden())
242 // return;
243  mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() );
244 }
245 
246 
248 {
249  if ( mPixmap.isNull() || mPixmap.paintingActive() )
250  return;
251 
252  mPixmap.fill( mBgColor ); //palette().color(backgroundRole());
253 
254  QPainter painter;
255  painter.begin( &mPixmap );
256 
257  // antialiasing
258  if ( mAntiAliasing )
259  painter.setRenderHint( QPainter::Antialiasing );
260 
261  // render image
262  mMapRenderer->render( &painter );
263 
264  painter.end();
265 
266  // schedule repaint
267  update();
268 
269  // update panning widget
270  drawExtentRect();
271 }
272 
273 
274 void QgsMapOverviewCanvas::setBackgroundColor( const QColor& color )
275 {
276  mBgColor = color;
277 
278  // set erase color
279  QPalette palette;
280  palette.setColor( backgroundRole(), color );
281  setPalette( palette );
282 }
283 
284 void QgsMapOverviewCanvas::setLayerSet( const QStringList& layerSet )
285 {
286  mMapRenderer->setLayerSet( layerSet );
287 }
288 
290 {
291  mMapRenderer->setExtent( rect );
292  drawExtentRect();
293 }
294 
296 {
298 }
299 
301 {
304 }
305 
307 {
308  return mMapRenderer->layerSet();
309 }