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