Skip to content

Commit 1556185

Browse files
author
Hugo Mercier
committedJun 17, 2013
Add autocentering of overview
Work funded by Tuscany Region - SITA. Contract "Support to the use of GFOSS (Geographic Free and Open Source Software) Desktop tools" (CIG Z3B06FA6D7).
1 parent bdd61d5 commit 1556185

File tree

5 files changed

+126
-34
lines changed

5 files changed

+126
-34
lines changed
 

‎src/app/composer/qgscomposermapwidget.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ void QgsComposerMapWidget::updateGuiElements()
303303
mOverviewBlendModeComboBox->setBlendMode( mComposerMap->overviewBlendMode() );
304304
//overview inverted
305305
mOverviewInvertCheckbox->setChecked( mComposerMap->overviewInverted() );
306+
//center overview
307+
mOverviewCenterCheckbox->setChecked( mComposerMap->overviewCentered() );
306308

307309
//grid
308310
if ( mComposerMap->gridEnabled() )
@@ -452,6 +454,7 @@ void QgsComposerMapWidget::blockAllSignals( bool b )
452454
mOverviewFrameStyleButton->blockSignals( b );
453455
mOverviewBlendModeComboBox->blockSignals( b );
454456
mOverviewInvertCheckbox->blockSignals( b );
457+
mOverviewCenterCheckbox->blockSignals( b );
455458
}
456459

457460
void QgsComposerMapWidget::on_mUpdatePreviewButton_clicked()
@@ -591,6 +594,14 @@ void QgsComposerMapWidget::on_mOverviewInvertCheckbox_toggled( bool state )
591594
}
592595
}
593596

597+
void QgsComposerMapWidget::on_mOverviewCenterCheckbox_toggled( bool state )
598+
{
599+
if ( mComposerMap )
600+
{
601+
mComposerMap->setOverviewCentered( state );
602+
}
603+
}
604+
594605
void QgsComposerMapWidget::on_mGridCheckBox_toggled( bool state )
595606
{
596607
if ( !mComposerMap )

‎src/app/composer/qgscomposermapwidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
4646
void on_mOverviewFrameStyleButton_clicked();
4747
void on_mOverviewBlendModeComboBox_currentIndexChanged( int index );
4848
void on_mOverviewInvertCheckbox_toggled( bool state );
49+
void on_mOverviewCenterCheckbox_toggled( bool state );
4950

5051
void on_mXMinLineEdit_editingFinished();
5152
void on_mXMaxLineEdit_editingFinished();

‎src/core/composer/qgscomposermap.cpp

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141

4242
QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int width, int height )
4343
: QgsComposerItem( x, y, width, height, composition ), mKeepLayerSet( false ),
44-
mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
44+
mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false ),
45+
mGridEnabled( false ), mGridStyle( Solid ),
4546
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
4647
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
4748
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
@@ -86,7 +87,8 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int w
8687

8788
QgsComposerMap::QgsComposerMap( QgsComposition *composition )
8889
: QgsComposerItem( 0, 0, 10, 10, composition ), mKeepLayerSet( false ), mOverviewFrameMapId( -1 ),
89-
mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
90+
mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false ),
91+
mGridEnabled( false ), mGridStyle( Solid ),
9092
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
9193
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
9294
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
@@ -116,6 +118,28 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition )
116118
initGridAnnotationFormatFromProject();
117119
}
118120

121+
void QgsComposerMap::extentCenteredOnOverview( QgsRectangle& extent ) const
122+
{
123+
extent = mExtent;
124+
if ( ! mOverviewCentered ) {
125+
return;
126+
}
127+
128+
if ( mOverviewFrameMapId != -1 ) {
129+
const QgsComposerMap* overviewFrameMap = mComposition->getComposerMapById( mOverviewFrameMapId );
130+
QgsRectangle otherExtent = overviewFrameMap->extent();
131+
132+
if ( ! mExtent.contains( otherExtent ) ) {
133+
QgsPoint center = otherExtent.center();
134+
QgsRectangle movedExtent( center.x() - mExtent.width() / 2,
135+
center.y() - mExtent.height() / 2,
136+
center.x() - mExtent.width() / 2 + mExtent.width(),
137+
center.y() - mExtent.height() / 2 + mExtent.height() );
138+
extent = movedExtent;
139+
}
140+
}
141+
}
142+
119143
QgsComposerMap::~QgsComposerMap()
120144
{
121145
delete mOverviewFrameMapSymbol;
@@ -297,6 +321,10 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
297321

298322
QgsRectangle requestRectangle;
299323
requestedExtent( requestRectangle );
324+
325+
QgsRectangle cExtent;
326+
extentCenteredOnOverview( cExtent );
327+
300328
double horizontalVScaleFactor = horizontalViewScaleFactor();
301329
if ( horizontalVScaleFactor < 0 )
302330
{
@@ -305,15 +333,15 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
305333

306334
double imagePixelWidth = mExtent.width() / requestRectangle.width() * mCacheImage.width() ; //how many pixels of the image are for the map extent?
307335
double scale = rect().width() / imagePixelWidth;
308-
QgsPoint rotationPoint = QgsPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
336+
QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );
309337

310338
//shift such that rotation point is at 0/0 point in the coordinate system
311339
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
312340
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
313341

314342
//shift such that top left point of the extent at point 0/0 in item coordinate system
315-
double xTopLeftShift = ( rotationPoint.x() - mExtent.xMinimum() ) * mapUnitsToMM();
316-
double yTopLeftShift = ( mExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
343+
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
344+
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
317345

318346
painter->save();
319347

@@ -351,16 +379,20 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
351379
QgsRectangle requestRectangle;
352380
requestedExtent( requestRectangle );
353381

382+
QgsRectangle cExtent;
383+
extentCenteredOnOverview( cExtent );
384+
354385
QSizeF theSize( requestRectangle.width() * mapUnitsToMM(), requestRectangle.height() * mapUnitsToMM() );
355-
QgsPoint rotationPoint = QgsPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
386+
387+
QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );
356388

357389
//shift such that rotation point is at 0/0 point in the coordinate system
358390
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
359391
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
360392

361393
//shift such that top left point of the extent at point 0/0 in item coordinate system
362-
double xTopLeftShift = ( rotationPoint.x() - mExtent.xMinimum() ) * mapUnitsToMM();
363-
double yTopLeftShift = ( mExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
394+
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
395+
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
364396
painter->save();
365397
painter->translate( mXOffset, mYOffset );
366398
painter->translate( xTopLeftShift, yTopLeftShift );
@@ -757,6 +789,9 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
757789
{
758790
overviewFrameElem.setAttribute( "overviewInverted", "false" );
759791
}
792+
793+
overviewFrameElem.setAttribute( "overviewCentered", mOverviewCentered ? "true" : "false" );
794+
760795
QDomElement overviewFrameStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mOverviewFrameMapSymbol, doc );
761796
overviewFrameElem.appendChild( overviewFrameStyleElem );
762797
composerMapElem.appendChild( overviewFrameElem );
@@ -874,6 +909,15 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
874909
setOverviewInverted( false );
875910
}
876911

912+
if ( overviewFrameElem.attribute( "overviewCentered" ).compare( "true", Qt::CaseInsensitive ) == 0 )
913+
{
914+
setOverviewCentered( true );
915+
}
916+
else
917+
{
918+
setOverviewCentered( false );
919+
}
920+
877921
QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( "symbol" );
878922
if ( !overviewFrameSymbolElem.isNull() )
879923
{
@@ -1727,63 +1771,70 @@ double QgsComposerMap::maxExtension() const
17271771
return maxExtension + mAnnotationFrameDistance + gridFrameDist;
17281772
}
17291773

1730-
void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
1774+
void QgsComposerMap::mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const
17311775
{
17321776
poly.clear();
17331777
if ( mRotation == 0 )
17341778
{
1735-
poly << QPointF( mExtent.xMinimum(), mExtent.yMaximum() );
1736-
poly << QPointF( mExtent.xMaximum(), mExtent.yMaximum() );
1737-
poly << QPointF( mExtent.xMaximum(), mExtent.yMinimum() );
1738-
poly << QPointF( mExtent.xMinimum(), mExtent.yMinimum() );
1779+
poly << QPointF( extent.xMinimum(), extent.yMaximum() );
1780+
poly << QPointF( extent.xMaximum(), extent.yMaximum() );
1781+
poly << QPointF( extent.xMaximum(), extent.yMinimum() );
1782+
poly << QPointF( extent.xMinimum(), extent.yMinimum() );
17391783
return;
17401784
}
17411785

17421786
//there is rotation
1743-
QgsPoint rotationPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
1787+
QgsPoint rotationPoint(( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
17441788
double dx, dy; //x-, y- shift from rotation point to corner point
17451789

17461790
//top left point
1747-
dx = rotationPoint.x() - mExtent.xMinimum();
1748-
dy = rotationPoint.y() - mExtent.yMaximum();
1791+
dx = rotationPoint.x() - extent.xMinimum();
1792+
dy = rotationPoint.y() - extent.yMaximum();
17491793
rotate( mRotation, dx, dy );
17501794
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17511795

17521796
//top right point
1753-
dx = rotationPoint.x() - mExtent.xMaximum();
1754-
dy = rotationPoint.y() - mExtent.yMaximum();
1797+
dx = rotationPoint.x() - extent.xMaximum();
1798+
dy = rotationPoint.y() - extent.yMaximum();
17551799
rotate( mRotation, dx, dy );
17561800
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17571801

17581802
//bottom right point
1759-
dx = rotationPoint.x() - mExtent.xMaximum();
1760-
dy = rotationPoint.y() - mExtent.yMinimum();
1803+
dx = rotationPoint.x() - extent.xMaximum();
1804+
dy = rotationPoint.y() - extent.yMinimum();
17611805
rotate( mRotation, dx, dy );
17621806
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17631807

17641808
//bottom left point
1765-
dx = rotationPoint.x() - mExtent.xMinimum();
1766-
dy = rotationPoint.y() - mExtent.yMinimum();
1809+
dx = rotationPoint.x() - extent.xMinimum();
1810+
dy = rotationPoint.y() - extent.yMinimum();
17671811
rotate( mRotation, dx, dy );
17681812
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17691813
}
17701814

1815+
void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
1816+
{
1817+
return mapPolygon( mExtent, poly );
1818+
}
1819+
17711820
void QgsComposerMap::requestedExtent( QgsRectangle& extent ) const
17721821
{
1822+
QgsRectangle newExtent;
1823+
extentCenteredOnOverview( newExtent );
17731824
if ( mRotation == 0 )
17741825
{
1775-
extent = mExtent;
1776-
return;
1826+
extent = newExtent;
1827+
}
1828+
else
1829+
{
1830+
QPolygonF poly;
1831+
mapPolygon( newExtent, poly );
1832+
QRectF bRect = poly.boundingRect();
1833+
extent.setXMinimum( bRect.left() );
1834+
extent.setXMaximum( bRect.right() );
1835+
extent.setYMinimum( bRect.top() );
1836+
extent.setYMaximum( bRect.bottom() );
17771837
}
1778-
1779-
QPolygonF poly;
1780-
mapPolygon( poly );
1781-
QRectF bRect = poly.boundingRect();
1782-
extent.setXMinimum( bRect.left() );
1783-
extent.setXMaximum( bRect.right() );
1784-
extent.setYMinimum( bRect.top() );
1785-
extent.setYMaximum( bRect.bottom() );
1786-
return;
17871838
}
17881839

17891840
double QgsComposerMap::mapUnitsToMM() const
@@ -1836,6 +1887,12 @@ void QgsComposerMap::setOverviewInverted( bool inverted )
18361887
update();
18371888
}
18381889

1890+
void QgsComposerMap::setOverviewCentered( bool centered )
1891+
{
1892+
mOverviewCentered = centered;
1893+
update();
1894+
}
1895+
18391896
void QgsComposerMap::setGridLineSymbol( QgsLineSymbolV2* symbol )
18401897
{
18411898
delete mGridLineSymbol;
@@ -2165,7 +2222,8 @@ void QgsComposerMap::drawOverviewMapExtent( QPainter* p )
21652222
}
21662223

21672224
QgsRectangle otherExtent = overviewFrameMap->extent();
2168-
QgsRectangle thisExtent = extent();
2225+
QgsRectangle thisExtent;
2226+
extentCenteredOnOverview( thisExtent );
21692227
QgsRectangle intersectRect = thisExtent.intersect( &otherExtent );
21702228

21712229
QgsRenderContext context;

‎src/core/composer/qgscomposermap.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
332332
/** Sets the overview's inversion mode*/
333333
void setOverviewInverted( bool inverted );
334334

335+
/** Returns true if the extent is forced to center on the overview when the overview is outside the extent */
336+
bool overviewCentered() const { return mOverviewCentered; }
337+
/** Set the overview's centering mode */
338+
void setOverviewCentered( bool centered );
339+
335340
void setGridLineSymbol( QgsLineSymbolV2* symbol );
336341
QgsLineSymbolV2* gridLineSymbol() { return mGridLineSymbol; }
337342

@@ -408,6 +413,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
408413
/**Blend mode for overview*/
409414
QPainter::CompositionMode mOverviewBlendMode;
410415
bool mOverviewInverted;
416+
/** Centering mode for overview */
417+
bool mOverviewCentered;
411418

412419
/**Establishes signal/slot connection for update in case of layer change*/
413420
void connectUpdateSlot();
@@ -503,6 +510,9 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
503510
@param poly out: the result polygon with the four corner points. The points are clockwise, starting at the top-left point
504511
@return true in case of success*/
505512
void mapPolygon( QPolygonF& poly ) const;
513+
/** mapPolygon variant using a given extent */
514+
void mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const;
515+
506516
/**Calculates the extent to request and the yShift of the top-left point in case of rotation.*/
507517
void requestedExtent( QgsRectangle& extent ) const;
508518
/**Scales a composer map shift (in MM) and rotates it by mRotation
@@ -525,6 +535,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
525535
void createDefaultOverviewFrameSymbol();
526536
void createDefaultGridLineSymbol();
527537
void initGridAnnotationFormatFromProject();
538+
539+
/**
540+
* Returns the extent, centered on the overview frame, if needed (when the overview frame is not visible)
541+
*/
542+
void extentCenteredOnOverview( QgsRectangle& extent ) const;
528543
};
529544

530545
#endif

‎src/ui/qgscomposermapwidgetbase.ui

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,13 @@
697697
</property>
698698
</widget>
699699
</item>
700+
<item row="4" column="0">
701+
<widget class="QCheckBox" name="mOverviewCenterCheckbox">
702+
<property name="text">
703+
<string>Center on overview when needed</string>
704+
</property>
705+
</widget>
706+
</item>
700707
</layout>
701708
</widget>
702709
</item>

0 commit comments

Comments
 (0)
Please sign in to comment.