|
QGIS API Documentation
master-3f58142
|
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 updateFullExtent(); 00099 mNewSize = QSize(); 00100 refresh(); 00101 } 00102 00103 QPainter paint( this ); 00104 paint.drawPixmap( pe->rect().topLeft(), mPixmap, pe->rect() ); 00105 } 00106 00107 00108 void QgsMapOverviewCanvas::drawExtentRect() 00109 { 00110 if ( !mMapCanvas || !mMapRenderer ) return; 00111 00112 const QgsRectangle& extent = mMapCanvas->extent(); 00113 00114 // show only when valid extent is set 00115 if ( extent.isEmpty() || mMapRenderer->extent().isEmpty() ) 00116 { 00117 mPanningWidget->hide(); 00118 return; 00119 } 00120 00121 const QgsMapToPixel* cXf = mMapRenderer->coordinateTransform(); 00122 QgsPoint ll( extent.xMinimum(), extent.yMinimum() ); 00123 QgsPoint ur( extent.xMaximum(), extent.yMaximum() ); 00124 if ( cXf ) 00125 { 00126 // transform the points before drawing 00127 cXf->transform( &ll ); 00128 cXf->transform( &ur ); 00129 } 00130 00131 #if 0 00132 // test whether panning widget should be drawn 00133 bool show = false; 00134 if ( ur.x() >= 0 && ur.x() < width() ) 00135 show = true; 00136 if ( ll.x() >= 0 && ll.x() < width() ) 00137 show = true; 00138 if ( ur.y() >= 0 && ur.y() < height() ) 00139 show = true; 00140 if ( ll.y() >= 0 && ll.y() < height() ) 00141 show = true; 00142 if ( !show ) 00143 { 00144 QgsDebugMsg( "panning: extent out of overview area" ); 00145 mPanningWidget->hide(); 00146 return; 00147 } 00148 #endif 00149 00150 // round values 00151 int x1 = static_cast<int>( ur.x() + 0.5 ), x2 = static_cast<int>( ll.x() + 0.5 ); 00152 int y1 = static_cast<int>( ur.y() + 0.5 ), y2 = static_cast<int>( ll.y() + 0.5 ); 00153 00154 if ( x1 > x2 ) 00155 std::swap( x1, x2 ); 00156 if ( y1 > y2 ) 00157 std::swap( y1, y2 ); 00158 00159 #ifdef Q_WS_MAC 00160 // setGeometry (Qt 4.2) is causing Mac window corruption (decorations 00161 // are drawn at odd locations) if both coords are at limit. This may 00162 // have something to do with Qt calculating dimensions as x2 - x1 + 1. 00163 // (INT_MAX - INT_MIN + 1 is UINT_MAX + 1) 00164 if ( x1 == INT_MIN && x2 == INT_MAX ) 00165 x1 += 1; // x2 -= 1 works too 00166 if ( y1 == INT_MIN && y2 == INT_MAX ) 00167 y1 += 1; 00168 #endif 00169 00170 QRect r( x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); 00171 00172 // allow for 5 pixel minimum widget size 00173 if ( r.width() < 5 && x1 > INT_MIN + 2 ) // make sure no underflow occurs (2 is largest adjustment) 00174 { 00175 r.setX( r.x() - (( 5 - r.width() ) / 2 ) ); // adjust x by 1/2 the difference of calculated and min. width 00176 r.setWidth( 5 ); 00177 } 00178 if ( r.height() < 5 && y1 > INT_MIN + 2 ) 00179 { 00180 r.setY( r.y() - (( 5 - r.height() ) / 2 ) ); // adjust y 00181 r.setHeight( 5 ); 00182 } 00183 00184 QgsDebugMsg( QString( "panning: extent to widget: [%1,%2] [%3x%4]" ).arg( x1 ).arg( y1 ).arg( r.width() ).arg( r.height() ) ); 00185 00186 mPanningWidget->setGeometry( r ); 00187 mPanningWidget->show(); // show if hidden 00188 } 00189 00190 00191 void QgsMapOverviewCanvas::mousePressEvent( QMouseEvent * e ) 00192 { 00193 // if (mPanningWidget->isHidden()) 00194 // return; 00195 00196 // set offset in panning widget if inside it 00197 // for better experience with panning :) 00198 if ( mPanningWidget->geometry().contains( e->pos() ) ) 00199 { 00200 mPanningCursorOffset = e->pos() - mPanningWidget->pos(); 00201 } 00202 else 00203 { 00204 // use center of the panning widget if outside 00205 QSize s = mPanningWidget->size(); 00206 mPanningCursorOffset = QPoint( s.width() / 2, s.height() / 2 ); 00207 } 00208 updatePanningWidget( e->pos() ); 00209 } 00210 00211 00212 void QgsMapOverviewCanvas::mouseReleaseEvent( QMouseEvent * e ) 00213 { 00214 // if (mPanningWidget->isHidden()) 00215 // return; 00216 00217 if ( e->button() == Qt::LeftButton ) 00218 { 00219 // set new extent 00220 const QgsMapToPixel* cXf = mMapRenderer->coordinateTransform(); 00221 QRect rect = mPanningWidget->geometry(); 00222 00223 QgsPoint center = cXf->toMapCoordinates( rect.center() ); 00224 QgsRectangle oldExtent = mMapCanvas->extent(); 00225 QgsRectangle ext; 00226 ext.setXMinimum( center.x() - oldExtent.width() / 2 ); 00227 ext.setXMaximum( center.x() + oldExtent.width() / 2 ); 00228 ext.setYMinimum( center.y() - oldExtent.height() / 2 ); 00229 ext.setYMaximum( center.y() + oldExtent.height() / 2 ); 00230 00231 QgsDebugMsg( QString( "panning: new position: [%1,%2] [%3x%4]" ).arg( rect.left() ).arg( rect.top() ).arg( rect.width() ).arg( rect.height() ) ); 00232 00233 mMapCanvas->setExtent( ext ); 00234 mMapCanvas->refresh(); 00235 } 00236 } 00237 00238 00239 void QgsMapOverviewCanvas::mouseMoveEvent( QMouseEvent * e ) 00240 { 00241 // move with panning widget if tracking cursor 00242 if (( e->buttons() & Qt::LeftButton ) == Qt::LeftButton ) 00243 { 00244 updatePanningWidget( e->pos() ); 00245 } 00246 } 00247 00248 00249 void QgsMapOverviewCanvas::updatePanningWidget( const QPoint& pos ) 00250 { 00251 // if (mPanningWidget->isHidden()) 00252 // return; 00253 mPanningWidget->move( pos.x() - mPanningCursorOffset.x(), pos.y() - mPanningCursorOffset.y() ); 00254 } 00255 00256 00257 void QgsMapOverviewCanvas::refresh() 00258 { 00259 if ( mPixmap.isNull() || mPixmap.paintingActive() ) 00260 return; 00261 00262 mPixmap.fill( mBgColor ); //palette().color(backgroundRole()); 00263 00264 QPainter painter; 00265 painter.begin( &mPixmap ); 00266 00267 // antialiasing 00268 if ( mAntiAliasing ) 00269 painter.setRenderHint( QPainter::Antialiasing ); 00270 00271 // render image 00272 mMapRenderer->render( &painter ); 00273 00274 painter.end(); 00275 00276 // schedule repaint 00277 update(); 00278 00279 // update panning widget 00280 drawExtentRect(); 00281 } 00282 00283 00284 void QgsMapOverviewCanvas::setBackgroundColor( const QColor& color ) 00285 { 00286 mBgColor = color; 00287 00288 // set erase color 00289 QPalette palette; 00290 palette.setColor( backgroundRole(), color ); 00291 setPalette( palette ); 00292 } 00293 00294 void QgsMapOverviewCanvas::setLayerSet( const QStringList& layerSet ) 00295 { 00296 QgsDebugMsg( "layerSet: " + layerSet.join( ", " ) ); 00297 if ( !mMapRenderer ) return; 00298 mMapRenderer->setLayerSet( layerSet ); 00299 mMapRenderer->updateFullExtent(); 00300 updateFullExtent(); 00301 } 00302 00303 void QgsMapOverviewCanvas::updateFullExtent() 00304 { 00305 if ( !mMapRenderer ) return; 00306 QgsRectangle rect; 00307 if ( !mMapRenderer->layerSet().isEmpty() ) 00308 { 00309 rect = mMapRenderer->fullExtent(); 00310 // expand a bit to keep features on margin 00311 rect.scale( 1.1 ); 00312 } 00313 mMapRenderer->setExtent( rect ); 00314 drawExtentRect(); 00315 } 00316 00317 void QgsMapOverviewCanvas::hasCrsTransformEnabled( bool flag ) 00318 { 00319 mMapRenderer->setProjectionsEnabled( flag ); 00320 } 00321 00322 void QgsMapOverviewCanvas::destinationSrsChanged() 00323 { 00324 const QgsCoordinateReferenceSystem& srs = mMapCanvas->mapRenderer()->destinationCrs(); 00325 mMapRenderer->setDestinationCrs( srs ); 00326 } 00327 00328 QStringList& QgsMapOverviewCanvas::layerSet() 00329 { 00330 return mMapRenderer->layerSet(); 00331 }