Quantum GIS API Documentation
1.7.4
|
00001 /*************************************************************************** 00002 qgsmapoverviewcanvas.cpp 00003 Map canvas subclassed for overview 00004 ------------------- 00005 begin : 09/14/2005 00006 copyright : (C) 2005 by Martin Dobias 00007 email : won.der at centrum.sk 00008 ***************************************************************************/ 00009 00010 /*************************************************************************** 00011 * * 00012 * This program is free software; you can redistribute it and/or modify * 00013 * it under the terms of the GNU General Public License as published by * 00014 * the Free Software Foundation; either version 2 of the License, or * 00015 * (at your option) any later version. * 00016 * * 00017 ***************************************************************************/ 00018 /* $Id$ */ 00019 00020 #include "qgsmapcanvas.h" 00021 #include "qgsmaprenderer.h" 00022 #include "qgsmapoverviewcanvas.h" 00023 #include "qgsmaptopixel.h" 00024 00025 #include <QPainter> 00026 #include <QPaintEvent> 00027 #include <QResizeEvent> 00028 #include <QMouseEvent> 00029 #include "qgslogger.h" 00030 #include <limits.h> 00031 00033 class QgsPanningWidget : public QWidget 00034 { 00035 public: 00036 QgsPanningWidget( QWidget* parent ) 00037 : QWidget( parent ) 00038 { 00039 setObjectName( "panningWidget" ); 00040 setMinimumSize( 5, 5 ); 00041 setAttribute( Qt::WA_NoSystemBackground ); 00042 } 00043 00044 void resizeEvent( QResizeEvent* r ) 00045 { 00046 QSize s = r->size(); 00047 QRegion reg( 0, 0, s.width(), s.height() ); 00048 QRegion reg2( 2, 2, s.width() - 4, s.height() - 4 ); 00049 QRegion reg3 = reg.subtract( reg2 ); 00050 setMask( reg3 ); 00051 } 00052 00053 00054 void paintEvent( QPaintEvent* pe ) 00055 { 00056 QRect r( QPoint( 0, 0 ), size() ); 00057 QPainter p; 00058 p.begin( this ); 00059 p.setPen( Qt::red ); 00060 p.setBrush( Qt::red ); 00061 p.drawRect( r ); 00062 p.end(); 00063 } 00064 00065 }; 00066 00067 00068 00069 QgsMapOverviewCanvas::QgsMapOverviewCanvas( QWidget * parent, QgsMapCanvas* mapCanvas ) 00070 : QWidget( parent ), mMapCanvas( mapCanvas ) 00071 { 00072 setObjectName( "theOverviewCanvas" ); 00073 mPanningWidget = new QgsPanningWidget( this ); 00074 00075 mMapRenderer = new QgsMapRenderer; 00076 mMapRenderer->enableOverviewMode(); 00077 00078 setBackgroundColor( palette().window().color() ); 00079 } 00080 00081 QgsMapOverviewCanvas::~QgsMapOverviewCanvas() 00082 { 00083 delete mMapRenderer; 00084 } 00085 00086 void QgsMapOverviewCanvas::resizeEvent( QResizeEvent* e ) 00087 { 00088 mNewSize = e->size(); 00089 } 00090 00091 void QgsMapOverviewCanvas::paintEvent( QPaintEvent* pe ) 00092 { 00093 if ( mNewSize.isValid() ) 00094 { 00095 mPixmap = QPixmap( mNewSize ); 00096 mMapRenderer->setOutputSize( mNewSize, mPixmap.logicalDpiX() ); 00097 mNewSize = QSize(); 00098 refresh(); 00099 } 00100 00101 QPainter paint( this ); 00102 paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() ); 00103 } 00104 00105 00106 void QgsMapOverviewCanvas::drawExtentRect() 00107 { 00108 const QgsRectangle& extent = mMapCanvas->extent(); 00109 00110 // show only when valid extent is set 00111 if ( extent.isEmpty() ) 00112 { 00113 mPanningWidget->hide(); 00114 return; 00115 } 00116 00117 const QgsMapToPixel* cXf = mMapRenderer->coordinateTransform(); 00118 QgsPoint ll( extent.xMinimum(), extent.yMinimum() ); 00119 QgsPoint ur( extent.xMaximum(), extent.yMaximum() ); 00120 if ( cXf ) 00121 { 00122 // transform the points before drawing 00123 cXf->transform( &ll ); 00124 cXf->transform( &ur ); 00125 } 00126 00127 #if 0 00128 // test whether panning widget should be drawn 00129 bool show = false; 00130 if ( ur.x() >= 0 && ur.x() < width() ) show = true; 00131 if ( ll.x() >= 0 && ll.x() < width() ) show = true; 00132 if ( ur.y() >= 0 && ur.y() < height() ) show = true; 00133 if ( ll.y() >= 0 && ll.y() < height() ) show = true; 00134 if ( !show ) 00135 { 00136 QgsDebugMsg( "panning: extent out of overview area" ); 00137 mPanningWidget->hide(); 00138 return; 00139 } 00140 #endif 00141 00142 // round values 00143 int x1 = static_cast<int>( ur.x() + 0.5 ), x2 = static_cast<int>( ll.x() + 0.5 ); 00144 int y1 = static_cast<int>( ur.y() + 0.5 ), y2 = static_cast<int>( ll.y() + 0.5 ); 00145 00146 if ( x1 > x2 ) 00147 std::swap( x1, x2 ); 00148 if ( y1 > y2 ) 00149 std::swap( y1, y2 ); 00150 00151 #ifdef Q_WS_MAC 00152 // setGeometry (Qt 4.2) is causing Mac window corruption (decorations 00153 // are drawn at odd locations) if both coords are at limit. This may 00154 // have something to do with Qt calculating dimensions as x2 - x1 + 1. 00155 // (INT_MAX - INT_MIN + 1 is UINT_MAX + 1) 00156 if ( x1 == INT_MIN && x2 == INT_MAX ) x1 += 1; // x2 -= 1 works too 00157 if ( y1 == INT_MIN && y2 == INT_MAX ) y1 += 1; 00158 #endif 00159 00160 QRect r( x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); 00161 00162 // allow for 5 pixel minimum widget size 00163 if ( r.width() < 5 && x1 > INT_MIN + 2 ) // make sure no underflow occurs (2 is largest adjustment) 00164 { 00165 r.setX( r.x() - (( 5 - r.width() ) / 2 ) ); // adjust x by 1/2 the difference of calculated and min. width 00166 r.setWidth( 5 ); 00167 } 00168 if ( r.height() < 5 && y1 > INT_MIN + 2 ) 00169 { 00170 r.setY( r.y() - (( 5 - r.height() ) / 2 ) ); // adjust y 00171 r.setHeight( 5 ); 00172 } 00173 00174 QgsDebugMsg( QString( "panning: extent to widget: [%1,%2] [%3x%4]" ).arg( x1 ).arg( y1 ).arg( r.width() ).arg( r.height() ) ); 00175 00176 mPanningWidget->setGeometry( r ); 00177 mPanningWidget->show(); // show if hidden 00178 } 00179 00180 00181 void QgsMapOverviewCanvas::mousePressEvent( QMouseEvent * e ) 00182 { 00183 // if (mPanningWidget->isHidden()) 00184 // return; 00185 00186 // set offset in panning widget if inside it 00187 // for better experience with panning :) 00188 if ( mPanningWidget->geometry().contains( e->pos() ) ) 00189 { 00190 mPanningCursorOffset = e->pos() - mPanningWidget->pos(); 00191 } 00192 else 00193 { 00194 // use center of the panning widget if outside 00195 QSize s = mPanningWidget->size(); 00196 mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 ); 00197 } 00198 updatePanningWidget( e->pos() ); 00199 } 00200 00201 00202 void QgsMapOverviewCanvas::mouseReleaseEvent( QMouseEvent * e ) 00203 { 00204 // if (mPanningWidget->isHidden()) 00205 // return; 00206 00207 if ( e->button() == Qt::LeftButton ) 00208 { 00209 // set new extent 00210 const QgsMapToPixel* cXf = mMapRenderer->coordinateTransform(); 00211 QRect rect = mPanningWidget->geometry(); 00212 00213 QgsPoint center = cXf->toMapCoordinates( rect.center() ); 00214 QgsRectangle oldExtent = mMapCanvas->extent(); 00215 QgsRectangle ext; 00216 ext.setXMinimum( center.x() - oldExtent.width() / 2 ); 00217 ext.setXMaximum( center.x() + oldExtent.width() / 2 ); 00218 ext.setYMinimum( center.y() - oldExtent.height() / 2 ); 00219 ext.setYMaximum( center.y() + oldExtent.height() / 2 ); 00220 00221 QgsDebugMsg( QString( "panning: new position: [%1,%2] [%3x%4]" ).arg( rect.left() ).arg( rect.top() ).arg( rect.width() ).arg( rect.height() ) ); 00222 00223 mMapCanvas->setExtent( ext ); 00224 mMapCanvas->refresh(); 00225 } 00226 } 00227 00228 00229 void QgsMapOverviewCanvas::mouseMoveEvent( QMouseEvent * e ) 00230 { 00231 // move with panning widget if tracking cursor 00232 if (( e->buttons() & Qt::LeftButton ) == Qt::LeftButton ) 00233 { 00234 updatePanningWidget( e->pos() ); 00235 } 00236 } 00237 00238 00239 void QgsMapOverviewCanvas::updatePanningWidget( const QPoint& pos ) 00240 { 00241 // if (mPanningWidget->isHidden()) 00242 // return; 00243 mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() ); 00244 } 00245 00246 00247 void QgsMapOverviewCanvas::refresh() 00248 { 00249 if ( mPixmap.isNull() || mPixmap.paintingActive() ) 00250 return; 00251 00252 mPixmap.fill( mBgColor ); //palette().color(backgroundRole()); 00253 00254 QPainter painter; 00255 painter.begin( &mPixmap ); 00256 00257 // antialiasing 00258 if ( mAntiAliasing ) 00259 painter.setRenderHint( QPainter::Antialiasing ); 00260 00261 // render image 00262 mMapRenderer->render( &painter ); 00263 00264 painter.end(); 00265 00266 // schedule repaint 00267 update(); 00268 00269 // update panning widget 00270 drawExtentRect(); 00271 } 00272 00273 00274 void QgsMapOverviewCanvas::setBackgroundColor( const QColor& color ) 00275 { 00276 mBgColor = color; 00277 00278 // set erase color 00279 QPalette palette; 00280 palette.setColor( backgroundRole(), color ); 00281 setPalette( palette ); 00282 } 00283 00284 void QgsMapOverviewCanvas::setLayerSet( const QStringList& layerSet ) 00285 { 00286 mMapRenderer->setLayerSet( layerSet ); 00287 } 00288 00289 void QgsMapOverviewCanvas::updateFullExtent( const QgsRectangle& rect ) 00290 { 00291 mMapRenderer->setExtent( rect ); 00292 drawExtentRect(); 00293 } 00294 00295 void QgsMapOverviewCanvas::hasCrsTransformEnabled( bool flag ) 00296 { 00297 mMapRenderer->setProjectionsEnabled( flag ); 00298 } 00299 00300 void QgsMapOverviewCanvas::destinationSrsChanged() 00301 { 00302 const QgsCoordinateReferenceSystem& srs = mMapCanvas->mapRenderer()->destinationCrs(); 00303 mMapRenderer->setDestinationCrs( srs ); 00304 } 00305 00306 QStringList& QgsMapOverviewCanvas::layerSet() 00307 { 00308 return mMapRenderer->layerSet(); 00309 }