QGIS API Documentation  master-59fd5e0
src/gui/qgsmapoverviewcanvas.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines