Skip to content

Commit 135ef36

Browse files
committed
Merge pull request #665 from Oslandia/overview_centering
[2.1] Overview centering
2 parents 1aa5daf + 00041e6 commit 135ef36

File tree

9 files changed

+181
-38
lines changed

9 files changed

+181
-38
lines changed

python/core/composer/qgscomposermap.sip

+6-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,12 @@ class QgsComposerMap : QgsComposerItem
300300
/**Sets flag if overview frame should be inverted
301301
@note this function was added in version 1.9*/
302302
void setOverviewInverted( bool inverted );
303-
bool overviewInverted() const;
303+
bool overviewInverted() const;
304+
305+
/** Returns true if the extent is forced to center on the overview */
306+
bool overviewCentered() const;
307+
/** Set the overview's centering mode */
308+
void setOverviewCentered( bool centered );
304309

305310
/**Sets mId to a number not yet used in the composition. mId is kept if it is not in use.
306311
Usually, this function is called before adding the composer map to the composition*/

src/app/composer/qgscomposermapwidget.cpp

+15
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,18 @@ 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+
mComposerMap->beginCommand( tr( "Overview centering mode changed" ) );
604+
mComposerMap->cache();
605+
mComposerMap->update();
606+
mComposerMap->endCommand();
607+
}
608+
594609
void QgsComposerMapWidget::on_mGridCheckBox_toggled( bool state )
595610
{
596611
if ( !mComposerMap )

src/app/composer/qgscomposermapwidget.h

+1
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

+90-34
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,26 @@ 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+
QgsPoint center = otherExtent.center();
133+
QgsRectangle movedExtent( center.x() - mExtent.width() / 2,
134+
center.y() - mExtent.height() / 2,
135+
center.x() - mExtent.width() / 2 + mExtent.width(),
136+
center.y() - mExtent.height() / 2 + mExtent.height() );
137+
extent = movedExtent;
138+
}
139+
}
140+
119141
QgsComposerMap::~QgsComposerMap()
120142
{
121143
delete mOverviewFrameMapSymbol;
@@ -297,6 +319,10 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
297319

298320
QgsRectangle requestRectangle;
299321
requestedExtent( requestRectangle );
322+
323+
QgsRectangle cExtent;
324+
extentCenteredOnOverview( cExtent );
325+
300326
double horizontalVScaleFactor = horizontalViewScaleFactor();
301327
if ( horizontalVScaleFactor < 0 )
302328
{
@@ -305,15 +331,15 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
305331

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

310336
//shift such that rotation point is at 0/0 point in the coordinate system
311337
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
312338
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
313339

314340
//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();
341+
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
342+
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
317343

318344
painter->save();
319345

@@ -351,16 +377,20 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
351377
QgsRectangle requestRectangle;
352378
requestedExtent( requestRectangle );
353379

380+
QgsRectangle cExtent;
381+
extentCenteredOnOverview( cExtent );
382+
354383
QSizeF theSize( requestRectangle.width() * mapUnitsToMM(), requestRectangle.height() * mapUnitsToMM() );
355-
QgsPoint rotationPoint = QgsPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
384+
385+
QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );
356386

357387
//shift such that rotation point is at 0/0 point in the coordinate system
358388
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
359389
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();
360390

361391
//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();
392+
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
393+
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
364394
painter->save();
365395
painter->translate( mXOffset, mYOffset );
366396
painter->translate( xTopLeftShift, yTopLeftShift );
@@ -757,6 +787,9 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
757787
{
758788
overviewFrameElem.setAttribute( "overviewInverted", "false" );
759789
}
790+
791+
overviewFrameElem.setAttribute( "overviewCentered", mOverviewCentered ? "true" : "false" );
792+
760793
QDomElement overviewFrameStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mOverviewFrameMapSymbol, doc );
761794
overviewFrameElem.appendChild( overviewFrameStyleElem );
762795
composerMapElem.appendChild( overviewFrameElem );
@@ -874,6 +907,15 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
874907
setOverviewInverted( false );
875908
}
876909

910+
if ( overviewFrameElem.attribute( "overviewCentered" ).compare( "true", Qt::CaseInsensitive ) == 0 )
911+
{
912+
setOverviewCentered( true );
913+
}
914+
else
915+
{
916+
setOverviewCentered( false );
917+
}
918+
877919
QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( "symbol" );
878920
if ( !overviewFrameSymbolElem.isNull() )
879921
{
@@ -1727,63 +1769,70 @@ double QgsComposerMap::maxExtension() const
17271769
return maxExtension + mAnnotationFrameDistance + gridFrameDist;
17281770
}
17291771

1730-
void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
1772+
void QgsComposerMap::mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const
17311773
{
17321774
poly.clear();
17331775
if ( mRotation == 0 )
17341776
{
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() );
1777+
poly << QPointF( extent.xMinimum(), extent.yMaximum() );
1778+
poly << QPointF( extent.xMaximum(), extent.yMaximum() );
1779+
poly << QPointF( extent.xMaximum(), extent.yMinimum() );
1780+
poly << QPointF( extent.xMinimum(), extent.yMinimum() );
17391781
return;
17401782
}
17411783

17421784
//there is rotation
1743-
QgsPoint rotationPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
1785+
QgsPoint rotationPoint(( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
17441786
double dx, dy; //x-, y- shift from rotation point to corner point
17451787

17461788
//top left point
1747-
dx = rotationPoint.x() - mExtent.xMinimum();
1748-
dy = rotationPoint.y() - mExtent.yMaximum();
1789+
dx = rotationPoint.x() - extent.xMinimum();
1790+
dy = rotationPoint.y() - extent.yMaximum();
17491791
rotate( mRotation, dx, dy );
17501792
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17511793

17521794
//top right point
1753-
dx = rotationPoint.x() - mExtent.xMaximum();
1754-
dy = rotationPoint.y() - mExtent.yMaximum();
1795+
dx = rotationPoint.x() - extent.xMaximum();
1796+
dy = rotationPoint.y() - extent.yMaximum();
17551797
rotate( mRotation, dx, dy );
17561798
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17571799

17581800
//bottom right point
1759-
dx = rotationPoint.x() - mExtent.xMaximum();
1760-
dy = rotationPoint.y() - mExtent.yMinimum();
1801+
dx = rotationPoint.x() - extent.xMaximum();
1802+
dy = rotationPoint.y() - extent.yMinimum();
17611803
rotate( mRotation, dx, dy );
17621804
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17631805

17641806
//bottom left point
1765-
dx = rotationPoint.x() - mExtent.xMinimum();
1766-
dy = rotationPoint.y() - mExtent.yMinimum();
1807+
dx = rotationPoint.x() - extent.xMinimum();
1808+
dy = rotationPoint.y() - extent.yMinimum();
17671809
rotate( mRotation, dx, dy );
17681810
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
17691811
}
17701812

1813+
void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
1814+
{
1815+
return mapPolygon( mExtent, poly );
1816+
}
1817+
17711818
void QgsComposerMap::requestedExtent( QgsRectangle& extent ) const
17721819
{
1820+
QgsRectangle newExtent;
1821+
extentCenteredOnOverview( newExtent );
17731822
if ( mRotation == 0 )
17741823
{
1775-
extent = mExtent;
1776-
return;
1824+
extent = newExtent;
1825+
}
1826+
else
1827+
{
1828+
QPolygonF poly;
1829+
mapPolygon( newExtent, poly );
1830+
QRectF bRect = poly.boundingRect();
1831+
extent.setXMinimum( bRect.left() );
1832+
extent.setXMaximum( bRect.right() );
1833+
extent.setYMinimum( bRect.top() );
1834+
extent.setYMaximum( bRect.bottom() );
17771835
}
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;
17871836
}
17881837

17891838
double QgsComposerMap::mapUnitsToMM() const
@@ -1836,6 +1885,12 @@ void QgsComposerMap::setOverviewInverted( bool inverted )
18361885
update();
18371886
}
18381887

1888+
void QgsComposerMap::setOverviewCentered( bool centered )
1889+
{
1890+
mOverviewCentered = centered;
1891+
update();
1892+
}
1893+
18391894
void QgsComposerMap::setGridLineSymbol( QgsLineSymbolV2* symbol )
18401895
{
18411896
delete mGridLineSymbol;
@@ -2165,7 +2220,8 @@ void QgsComposerMap::drawOverviewMapExtent( QPainter* p )
21652220
}
21662221

21672222
QgsRectangle otherExtent = overviewFrameMap->extent();
2168-
QgsRectangle thisExtent = extent();
2223+
QgsRectangle thisExtent;
2224+
extentCenteredOnOverview( thisExtent );
21692225
QgsRectangle intersectRect = thisExtent.intersect( &otherExtent );
21702226

21712227
QgsRenderContext context;

src/core/composer/qgscomposermap.h

+15
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 */
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
541+
*/
542+
void extentCenteredOnOverview( QgsRectangle& extent ) const;
528543
};
529544

530545
#endif

src/ui/qgscomposermapwidgetbase.ui

+10-3
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@
5454
<property name="geometry">
5555
<rect>
5656
<x>0</x>
57-
<y>0</y>
58-
<width>438</width>
59-
<height>1454</height>
57+
<y>-376</y>
58+
<width>439</width>
59+
<height>1439</height>
6060
</rect>
6161
</property>
6262
<property name="sizePolicy">
@@ -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</string>
704+
</property>
705+
</widget>
706+
</item>
700707
</layout>
701708
</widget>
702709
</item>

0 commit comments

Comments
 (0)