Skip to content

Commit 084fa89

Browse files
Hugo Merciernyalldawson
Hugo Mercier
authored andcommitted
[FEATURE][composer] Add a 'predefined scales' mode to atlas maps, which sets an atlas maps' extent to the largest predefined scale which fits the atlas feature. Scales are taken from the project's predefined scales, or the global predefined scales.
1 parent 2476a52 commit 084fa89

15 files changed

+379
-93
lines changed

python/core/composer/qgsatlascomposition.sip

+9
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ public:
131131
int sortKeyAttributeIndex() const /Deprecated/;
132132
void setSortKeyAttributeIndex( int idx ) /Deprecated/;
133133

134+
/** Returns the current list of predefined scales
135+
@returns a vector of doubles representing predefined scales
136+
*/
137+
const QVector<double>& predefinedScales() const;
138+
/** Sets the predefined scales
139+
@param scales a vector of doubles representing predefined scales
140+
*/
141+
void setPredefinedScales( const QVector<double>& scales );
142+
134143
/** Begins the rendering. Returns true if successful, false if no matching atlas
135144
features found.*/
136145
bool beginRender();

python/core/composer/qgscomposermap.sip

+31-4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ class QgsComposerMap : QgsComposerItem
7070
Top
7171
};
7272

73+
/** Scaling modes used for the serial rendering (atlas)
74+
*/
75+
enum AtlasScalingMode
76+
{
77+
Fixed, /*< The current scale of the map is used for each feature of the atlas */
78+
Predefined, /*< A scale is chosen from the predefined scales
79+
@see QgsAtlasComposition::setPredefinedScales.
80+
The smallest scale from the list of scales where the atlas feature
81+
is fully visible is chosen.
82+
*/
83+
Auto /*< The extent is adjusted so that each feature is fully visible.
84+
A margin is applied around the center @see setAtlasMargin */
85+
};
86+
7387
/** \brief Draw to paint device
7488
@param painter painter
7589
@param extent map extent
@@ -394,10 +408,23 @@ class QgsComposerMap : QgsComposerItem
394408
/** Set to true if the map extents should be set by the current atlas feature */
395409
void setAtlasDriven( bool enabled );
396410

397-
/** Returns true if the map uses a fixed scale when in atlas mode */
398-
bool atlasFixedScale() const;
399-
/** Set to true if the map should use a fixed scale when in atlas mode */
400-
void setAtlasFixedScale( bool fixed );
411+
/** Returns true if the map uses a fixed scale when in atlas mode
412+
@deprecated since 2.4 Use atlasScalingMode() instead
413+
*/
414+
bool atlasFixedScale() const /Deprecated/;
415+
/** Set to true if the map should use a fixed scale when in atlas mode
416+
@deprecated since 2.4 Use setAtlasScalingMode() instead
417+
*/
418+
void setAtlasFixedScale( bool fixed ) /Deprecated/;
419+
420+
/** Returns the current atlas scaling mode
421+
@returns the current scaling mode
422+
*/
423+
AtlasScalingMode atlasScalingMode();
424+
/** Sets the current atlas scaling mode
425+
@param mode atlas scaling mode to set
426+
*/
427+
void setAtlasScalingMode( AtlasScalingMode mode );
401428

402429
/** Returns the margin size (percentage) used when the map is in atlas mode */
403430
double atlasMargin() const;

src/app/composer/qgscomposer.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,7 @@ void QgsComposer::on_mActionAtlasPreview_triggered( bool checked )
929929

930930
if ( checked )
931931
{
932+
loadAtlasPredefinedScalesFromProject();
932933
atlasMap->firstFeature();
933934
emit( atlasPreviewFeatureChanged() );
934935
}
@@ -1333,6 +1334,7 @@ void QgsComposer::exportCompositionAsPDF( QgsComposer::OutputMode mode )
13331334

13341335
try
13351336
{
1337+
loadAtlasPredefinedScalesFromProject();
13361338
atlasMap->beginRender();
13371339
}
13381340
catch ( std::exception& e )
@@ -1487,6 +1489,7 @@ void QgsComposer::printComposition( QgsComposer::OutputMode mode )
14871489
QPainter painter( &mPrinter );
14881490
try
14891491
{
1492+
loadAtlasPredefinedScalesFromProject();
14901493
atlasMap->beginRender();
14911494
}
14921495
catch ( std::exception& e )
@@ -1748,6 +1751,7 @@ void QgsComposer::exportCompositionAsImage( QgsComposer::OutputMode mode )
17481751

17491752
try
17501753
{
1754+
loadAtlasPredefinedScalesFromProject();
17511755
atlasMap->beginRender();
17521756
}
17531757
catch ( std::exception& e )
@@ -2015,6 +2019,7 @@ void QgsComposer::exportCompositionAsSVG( QgsComposer::OutputMode mode )
20152019
{
20162020
try
20172021
{
2022+
loadAtlasPredefinedScalesFromProject();
20182023
atlasMap->beginRender();
20192024
}
20202025
catch ( std::exception& e )
@@ -3470,3 +3475,32 @@ void QgsComposer::updateAtlasMapLayerAction( bool atlasEnabled )
34703475
}
34713476
}
34723477

3478+
void QgsComposer::loadAtlasPredefinedScalesFromProject()
3479+
{
3480+
if ( !mComposition ) {
3481+
return;
3482+
}
3483+
QgsAtlasComposition& atlasMap = mComposition->atlasComposition();
3484+
QVector<double> pScales;
3485+
// first look at project's scales
3486+
QStringList scales( QgsProject::instance()->readListEntry( "Scales", "/ScalesList" ) );
3487+
bool hasProjectScales( QgsProject::instance()->readBoolEntry( "Scales", "/useProjectScales" ) );
3488+
if ( !hasProjectScales || scales.isEmpty() )
3489+
{
3490+
// default to global map tool scales
3491+
QSettings settings;
3492+
QString scalesStr( settings.value( "Map/scales", PROJECT_SCALES ).toString() );
3493+
scales = scalesStr.split( "," );
3494+
}
3495+
3496+
for ( QStringList::const_iterator scaleIt = scales.constBegin(); scaleIt != scales.constEnd(); ++scaleIt )
3497+
{
3498+
QStringList parts(scaleIt->split(':'));
3499+
if (parts.size() == 2)
3500+
{
3501+
pScales.push_back( parts[1].toDouble() );
3502+
}
3503+
}
3504+
atlasMap.setPredefinedScales( pScales );
3505+
}
3506+

src/app/composer/qgscomposer.h

+3
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
484484
//! Set default settings for printer page settings based on composition paper size
485485
void setPrinterPageDefaults();
486486

487+
//! Load predefined scales from the project's properties
488+
void loadAtlasPredefinedScalesFromProject();
489+
487490
/**Composer title*/
488491
QString mTitle;
489492

src/app/composer/qgscomposermapwidget.cpp

+90-44
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "qgscomposershape.h"
3333
#include "qgspaperitem.h"
3434
#include "qgsexpressionbuilderdialog.h"
35+
#include "qgsproject.h"
3536
#include <QColorDialog>
3637
#include <QFontDialog>
3738
#include <QMessageBox>
@@ -92,8 +93,6 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap ): QWidg
9293
connect( mGridCheckBox, SIGNAL( toggled( bool ) ),
9394
mDrawAnnotationCheckableGroupBox, SLOT( setEnabled( bool ) ) );
9495

95-
connect( mAtlasCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( atlasToggled( bool ) ) );
96-
9796
if ( composerMap )
9897
{
9998
connect( composerMap, SIGNAL( itemChanged() ), this, SLOT( setGuiElementValues() ) );
@@ -133,27 +132,16 @@ void QgsComposerMapWidget::compositionAtlasToggled( bool atlasEnabled )
133132
}
134133
}
135134

136-
void QgsComposerMapWidget::atlasToggled( bool checked )
135+
void QgsComposerMapWidget::on_mAtlasCheckBox_toggled( bool checked )
137136
{
138-
if ( checked && mComposerMap )
139-
{
140-
//check atlas coverage layer type
141-
QgsComposition* composition = mComposerMap->composition();
142-
if ( composition )
143-
{
144-
toggleAtlasMarginByLayerType();
145-
}
146-
else
147-
{
148-
mAtlasMarginRadio->setEnabled( false );
149-
}
150-
}
151-
else
137+
if ( !mComposerMap )
152138
{
153-
mAtlasMarginRadio->setEnabled( false );
139+
return;
154140
}
155141

156142
mAtlasFixedScaleRadio->setEnabled( checked );
143+
mAtlasMarginRadio->setEnabled( checked );
144+
157145
if ( mAtlasMarginRadio->isEnabled() && mAtlasMarginRadio->isChecked() )
158146
{
159147
mAtlasMarginSpinBox->setEnabled( true );
@@ -162,14 +150,23 @@ void QgsComposerMapWidget::atlasToggled( bool checked )
162150
{
163151
mAtlasMarginSpinBox->setEnabled( false );
164152
}
165-
}
166153

154+
mAtlasPredefinedScaleRadio->setEnabled( checked );
167155

168-
void QgsComposerMapWidget::on_mAtlasCheckBox_toggled( bool checked )
169-
{
170-
if ( !mComposerMap )
156+
if ( checked )
171157
{
172-
return;
158+
//check atlas coverage layer type
159+
QgsComposition* composition = mComposerMap->composition();
160+
if ( composition )
161+
{
162+
toggleAtlasScalingOptionsByLayerType();
163+
}
164+
}
165+
166+
// disable predefined scales if none are defined
167+
if ( !hasPredefinedScales() )
168+
{
169+
mAtlasPredefinedScaleRadio->setEnabled( false );
173170
}
174171

175172
mComposerMap->setAtlasDriven( checked );
@@ -201,6 +198,12 @@ void QgsComposerMapWidget::updateMapForAtlas()
201198
void QgsComposerMapWidget::on_mAtlasMarginRadio_toggled( bool checked )
202199
{
203200
mAtlasMarginSpinBox->setEnabled( checked );
201+
202+
if (checked && mComposerMap)
203+
{
204+
mComposerMap->setAtlasScalingMode( QgsComposerMap::Auto );
205+
updateMapForAtlas();
206+
}
204207
}
205208

206209
void QgsComposerMapWidget::on_mAtlasMarginSpinBox_valueChanged( int value )
@@ -221,8 +224,36 @@ void QgsComposerMapWidget::on_mAtlasFixedScaleRadio_toggled( bool checked )
221224
return;
222225
}
223226

224-
mComposerMap->setAtlasFixedScale( checked );
225-
updateMapForAtlas();
227+
if (checked)
228+
{
229+
mComposerMap->setAtlasScalingMode( QgsComposerMap::Fixed );
230+
updateMapForAtlas();
231+
}
232+
}
233+
234+
void QgsComposerMapWidget::on_mAtlasPredefinedScaleRadio_toggled( bool checked )
235+
{
236+
if ( !mComposerMap )
237+
{
238+
return;
239+
}
240+
241+
if ( hasPredefinedScales() )
242+
{
243+
if ( checked )
244+
{
245+
mComposerMap->setAtlasScalingMode( QgsComposerMap::Predefined );
246+
updateMapForAtlas();
247+
}
248+
}
249+
else
250+
{
251+
// restore to fixed scale if no predefined scales exist
252+
mAtlasFixedScaleRadio->blockSignals( true );
253+
mAtlasFixedScaleRadio->setChecked( Qt::Checked );
254+
mAtlasFixedScaleRadio->blockSignals( false );
255+
mComposerMap->setAtlasScalingMode( QgsComposerMap::Fixed );
256+
}
226257
}
227258

228259
void QgsComposerMapWidget::on_mPreviewModeComboBox_activated( int i )
@@ -536,33 +567,30 @@ void QgsComposerMapWidget::updateGuiElements()
536567
//atlas controls
537568
mAtlasCheckBox->setChecked( mComposerMap->atlasDriven() );
538569
mAtlasMarginSpinBox->setValue( static_cast<int>( mComposerMap->atlasMargin() * 100 ) );
539-
if ( mComposerMap->atlasFixedScale() )
540-
{
541-
mAtlasFixedScaleRadio->setChecked( true );
542-
mAtlasMarginSpinBox->setEnabled( false );
543-
}
544-
else
545-
{
546-
mAtlasMarginRadio->setChecked( true );
547-
mAtlasMarginSpinBox->setEnabled( true );
548-
}
549-
if ( !mComposerMap->atlasDriven() )
570+
571+
mAtlasFixedScaleRadio->setEnabled( mComposerMap->atlasDriven() );
572+
mAtlasFixedScaleRadio->setChecked( mComposerMap->atlasScalingMode() == QgsComposerMap::Fixed );
573+
mAtlasMarginSpinBox->setEnabled( mComposerMap->atlasScalingMode() == QgsComposerMap::Auto );
574+
mAtlasMarginRadio->setEnabled( mComposerMap->atlasDriven() );
575+
mAtlasMarginRadio->setChecked( mComposerMap->atlasScalingMode() == QgsComposerMap::Auto );
576+
mAtlasPredefinedScaleRadio->setEnabled( mComposerMap->atlasDriven() );
577+
mAtlasPredefinedScaleRadio->setChecked( mComposerMap->atlasScalingMode() == QgsComposerMap::Predefined );
578+
579+
if ( mComposerMap->atlasDriven() )
550580
{
551-
mAtlasMarginSpinBox->setEnabled( false );
552-
mAtlasMarginRadio->setEnabled( false );
553-
mAtlasFixedScaleRadio->setEnabled( false );
581+
toggleAtlasScalingOptionsByLayerType();
554582
}
555-
else
583+
// disable predefined scales if none are defined
584+
if ( !hasPredefinedScales() )
556585
{
557-
mAtlasFixedScaleRadio->setEnabled( true );
558-
toggleAtlasMarginByLayerType();
586+
mAtlasPredefinedScaleRadio->setEnabled( false );
559587
}
560588

561589
blockAllSignals( false );
562590
}
563591
}
564592

565-
void QgsComposerMapWidget::toggleAtlasMarginByLayerType()
593+
void QgsComposerMapWidget::toggleAtlasScalingOptionsByLayerType()
566594
{
567595
if ( !mComposerMap )
568596
{
@@ -593,10 +621,12 @@ void QgsComposerMapWidget::toggleAtlasMarginByLayerType()
593621
//For point layers buffer setting makes no sense, so set "fixed scale" on and disable margin control
594622
mAtlasFixedScaleRadio->setChecked( true );
595623
mAtlasMarginRadio->setEnabled( false );
624+
mAtlasPredefinedScaleRadio->setEnabled( false );
596625
break;
597626
default:
598627
//Not a point layer, so enable changes to fixed scale control
599628
mAtlasMarginRadio->setEnabled( true );
629+
mAtlasPredefinedScaleRadio->setEnabled( true );
600630
}
601631
}
602632

@@ -1396,5 +1426,21 @@ void QgsComposerMapWidget::atlasLayerChanged( QgsVectorLayer* layer )
13961426
return;
13971427
}
13981428

1399-
toggleAtlasMarginByLayerType();
1429+
toggleAtlasScalingOptionsByLayerType();
1430+
}
1431+
1432+
bool QgsComposerMapWidget::hasPredefinedScales() const
1433+
{
1434+
// first look at project's scales
1435+
QStringList scales( QgsProject::instance()->readListEntry( "Scales", "/ScalesList" ) );
1436+
bool hasProjectScales( QgsProject::instance()->readBoolEntry( "Scales", "/useProjectScales" ) );
1437+
if ( !hasProjectScales || scales.isEmpty() )
1438+
{
1439+
// default to global map tool scales
1440+
QSettings settings;
1441+
QString scalesStr( settings.value( "Map/scales", PROJECT_SCALES ).toString() );
1442+
QStringList myScalesList = scalesStr.split( "," );
1443+
return myScalesList.size() > 0 && myScalesList[0] != "";
1444+
}
1445+
return true;
14001446
}

src/app/composer/qgscomposermapwidget.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
9191
void on_mGridFrameFill1ColorButton_colorChanged( const QColor& newColor );
9292
void on_mGridFrameFill2ColorButton_colorChanged( const QColor& newColor );
9393

94-
void atlasToggled( bool checked );
9594
void on_mAtlasMarginRadio_toggled( bool checked );
9695

9796
void on_mAtlasCheckBox_toggled( bool checked );
9897
void on_mAtlasMarginSpinBox_valueChanged( int value );
9998
void on_mAtlasFixedScaleRadio_toggled( bool checked );
99+
void on_mAtlasPredefinedScaleRadio_toggled( bool checked );
100100

101101
protected:
102102
void showEvent( QShowEvent * event );
@@ -144,12 +144,15 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
144144
/**Enables/disables grid frame related controls*/
145145
void toggleFrameControls( bool frameEnabled );
146146

147-
/**Enables or disables the atlas margin radio depending on the atlas coverage layer type*/
148-
void toggleAtlasMarginByLayerType();
147+
/**Enables or disables the atlas margin and predefined scales radio depending on the atlas coverage layer type*/
148+
void toggleAtlasScalingOptionsByLayerType();
149149

150150
/**Recalculates the bounds for an atlas map when atlas properties change*/
151151
void updateMapForAtlas();
152152

153+
/**Is there some predefined scales, globally or as project's options ?*/
154+
bool hasPredefinedScales() const;
155+
153156
};
154157

155158
#endif

0 commit comments

Comments
 (0)