Skip to content

Commit 1e4ad28

Browse files
committed
[FEATURE][composer] Data defined page size, orientation and number of pages for compositions. Funded by Canton of Neuchâtel, Switzerland
1 parent a914d43 commit 1e4ad28

9 files changed

+511
-111
lines changed

python/core/composer/qgscomposition.sip

+13-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ class QgsComposition : QGraphicsScene
3434
ZValueAbove
3535
};
3636

37+
enum PaperOrientation
38+
{
39+
Portrait,
40+
Landscape
41+
};
42+
3743
//! @deprecated since 2.4 - use the constructor with QgsMapSettings
3844
QgsComposition( QgsMapRenderer* mapRenderer ) /Deprecated/;
3945
explicit QgsComposition( const QgsMapSettings& mapSettings );
@@ -403,8 +409,13 @@ class QgsComposition : QGraphicsScene
403409
void beginPrint( QPrinter& printer );
404410
/** Prepare the printer for printing in a PDF */
405411
void beginPrintAsPDF( QPrinter& printer, const QString& file );
406-
/** Print on a preconfigured printer */
407-
void doPrint( QPrinter& printer, QPainter& painter );
412+
413+
/**Print on a preconfigured printer
414+
* @param printer QPrinter destination
415+
* @painter QPainter source
416+
* @startNewPage set to true to begin the print on a new page
417+
*/
418+
void doPrint( QPrinter& printer, QPainter& painter, bool startNewPage = false );
408419

409420
/**Convenience function that prepares the printer and prints
410421
* @returns true if print was successful

src/app/composer/qgscomposer.cpp

+4-10
Original file line numberDiff line numberDiff line change
@@ -1467,11 +1467,8 @@ void QgsComposer::exportCompositionAsPDF( QgsComposer::OutputMode mode )
14671467
}
14681468
else
14691469
{
1470-
if ( featureI > 0 )
1471-
{
1472-
printer.newPage();
1473-
}
1474-
mComposition->doPrint( printer, painter );
1470+
//start print on a new page if we're not on the first feature
1471+
mComposition->doPrint( printer, painter, featureI > 0 );
14751472
}
14761473
}
14771474
atlasMap->endRender();
@@ -1604,11 +1601,8 @@ void QgsComposer::printComposition( QgsComposer::OutputMode mode )
16041601
return;
16051602
}
16061603

1607-
if ( i > 0 )
1608-
{
1609-
mPrinter.newPage();
1610-
}
1611-
mComposition->doPrint( mPrinter, painter );
1604+
//start print on a new page if we're not on the first feature
1605+
mComposition->doPrint( mPrinter, painter, i > 0 );
16121606
}
16131607
atlasMap->endRender();
16141608
painter.end();

src/app/composer/qgscompositionwidget.cpp

+123
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,33 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c )
8585
mGridResolutionSpinBox->setValue( mComposition->snapGridResolution() );
8686
mOffsetXSpinBox->setValue( mComposition->snapGridOffsetX() );
8787
mOffsetYSpinBox->setValue( mComposition->snapGridOffsetY() );
88+
89+
QgsAtlasComposition* atlas = &mComposition->atlasComposition();
90+
if ( atlas )
91+
{
92+
// repopulate data defined buttons if atlas layer changes
93+
connect( atlas, SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
94+
this, SLOT( populateDataDefinedButtons() ) );
95+
connect( atlas, SIGNAL( toggled( bool ) ), this, SLOT( populateDataDefinedButtons() ) );
96+
}
8897
}
98+
99+
connect( mPaperSizeDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
100+
connect( mPaperSizeDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
101+
connect( mPaperSizeDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mPaperSizeComboBox, SLOT( setDisabled( bool ) ) );
102+
connect( mPaperWidthDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
103+
connect( mPaperWidthDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
104+
connect( mPaperWidthDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mPaperWidthDoubleSpinBox, SLOT( setDisabled( bool ) ) );
105+
connect( mPaperHeightDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
106+
connect( mPaperHeightDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
107+
connect( mPaperHeightDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mPaperHeightDoubleSpinBox, SLOT( setDisabled( bool ) ) );
108+
connect( mNumPagesDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
109+
connect( mNumPagesDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
110+
connect( mNumPagesDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mNumPagesSpinBox, SLOT( setDisabled( bool ) ) );
111+
connect( mPaperOrientationDDBtn, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty( ) ) );
112+
connect( mPaperOrientationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty( ) ) );
113+
connect( mPaperOrientationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mPaperOrientationComboBox, SLOT( setDisabled( bool ) ) );
114+
89115
blockSignals( false );
90116
}
91117

@@ -99,6 +125,103 @@ QgsCompositionWidget::~QgsCompositionWidget()
99125

100126
}
101127

128+
void QgsCompositionWidget::populateDataDefinedButtons()
129+
{
130+
if ( !mComposition )
131+
{
132+
return;
133+
}
134+
135+
QgsVectorLayer* vl = 0;
136+
QgsAtlasComposition* atlas = &mComposition->atlasComposition();
137+
138+
if ( atlas && atlas->enabled() )
139+
{
140+
vl = atlas->coverageLayer();
141+
}
142+
143+
mPaperSizeDDBtn->blockSignals( true );
144+
mPaperWidthDDBtn->blockSignals( true );
145+
mPaperHeightDDBtn->blockSignals( true );
146+
mNumPagesDDBtn->blockSignals( true );
147+
mPaperOrientationDDBtn->blockSignals( true );
148+
149+
mPaperSizeDDBtn->init( vl, mComposition->dataDefinedProperty( QgsComposerItem::PresetPaperSize ),
150+
QgsDataDefinedButton::String, QgsDataDefinedButton::paperSizeDesc() );
151+
mPaperWidthDDBtn->init( vl, mComposition->dataDefinedProperty( QgsComposerItem::PaperWidth ),
152+
QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() );
153+
mPaperHeightDDBtn->init( vl, mComposition->dataDefinedProperty( QgsComposerItem::PaperHeight ),
154+
QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() );
155+
mNumPagesDDBtn->init( vl, mComposition->dataDefinedProperty( QgsComposerItem::NumPages ),
156+
QgsDataDefinedButton::Int, QgsDataDefinedButton::intPosOneDesc() );
157+
mPaperOrientationDDBtn->init( vl, mComposition->dataDefinedProperty( QgsComposerItem::PaperOrientation ),
158+
QgsDataDefinedButton::String, QgsDataDefinedButton::paperOrientationDesc() );
159+
160+
//initial state of controls - disable related controls when dd buttons are active
161+
mPaperSizeComboBox->setEnabled( !mPaperSizeDDBtn->isActive() );
162+
163+
mPaperSizeDDBtn->blockSignals( false );
164+
mPaperWidthDDBtn->blockSignals( false );
165+
mPaperHeightDDBtn->blockSignals( false );
166+
mNumPagesDDBtn->blockSignals( false );
167+
mPaperOrientationDDBtn->blockSignals( false );
168+
}
169+
170+
void QgsCompositionWidget::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn, QgsComposerItem::DataDefinedProperty property )
171+
{
172+
if ( !mComposition )
173+
{
174+
return;
175+
}
176+
177+
const QMap< QString, QString >& map = ddBtn->definedProperty();
178+
mComposition->setDataDefinedProperty( property, map.value( "active" ).toInt(), map.value( "useexpr" ).toInt(), map.value( "expression" ), map.value( "field" ) );
179+
}
180+
181+
QgsComposerItem::DataDefinedProperty QgsCompositionWidget::ddPropertyForWidget( QgsDataDefinedButton *widget )
182+
{
183+
if ( widget == mPaperSizeDDBtn )
184+
{
185+
return QgsComposerItem::PresetPaperSize;
186+
}
187+
else if ( widget == mPaperWidthDDBtn )
188+
{
189+
return QgsComposerItem::PaperWidth;
190+
}
191+
else if ( widget == mPaperHeightDDBtn )
192+
{
193+
return QgsComposerItem::PaperHeight;
194+
}
195+
else if ( widget == mNumPagesDDBtn )
196+
{
197+
return QgsComposerItem::NumPages;
198+
}
199+
else if ( widget == mPaperOrientationDDBtn )
200+
{
201+
return QgsComposerItem::PaperOrientation;
202+
}
203+
204+
return QgsComposerItem::NoProperty;
205+
}
206+
207+
void QgsCompositionWidget::updateDataDefinedProperty()
208+
{
209+
QgsDataDefinedButton* ddButton = dynamic_cast<QgsDataDefinedButton*>( sender() );
210+
if ( !ddButton || !mComposition )
211+
{
212+
return;
213+
}
214+
215+
QgsComposerItem::DataDefinedProperty property = ddPropertyForWidget( ddButton );
216+
if ( property == QgsComposerItem::NoProperty )
217+
{
218+
return;
219+
}
220+
221+
setDataDefinedProperty( ddButton, property );
222+
mComposition->refreshDataDefinedProperty( property );
223+
}
224+
102225
void QgsCompositionWidget::createPaperEntries()
103226
{
104227
QList<QgsCompositionPaper> formats;

src/app/composer/qgscompositionwidget.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
***************************************************************************/
1616

1717
#include "ui_qgscompositionwidgetbase.h"
18+
#include "qgscomposeritem.h"
1819

1920
class QgsComposition;
2021
class QgsComposerMap;
21-
class QgsComposerItem;
22+
class QgsDataDefinedButton;
2223

2324
/** \ingroup MapComposer
2425
* Struct to hold map composer paper properties.
@@ -76,6 +77,12 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
7677
/* when a map is deleted */
7778
void onItemRemoved( QgsComposerItem* );
7879

80+
/**Must be called when a data defined button changes*/
81+
void updateDataDefinedProperty();
82+
83+
/**Initializes data defined buttons to current atlas coverage layer*/
84+
void populateDataDefinedButtons();
85+
7986
private:
8087
QgsComposition* mComposition;
8188
QMap<QString, QgsCompositionPaper> mPaperMap;
@@ -99,4 +106,11 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
99106
void setSize( QDoubleSpinBox *spin, double v );
100107
/**Blocks / unblocks the signals of all items*/
101108
void blockSignals( bool block );
109+
110+
/**Sets a data defined property for the item from its current data defined button settings*/
111+
void setDataDefinedProperty( const QgsDataDefinedButton *ddBtn, QgsComposerItem::DataDefinedProperty property );
112+
113+
/**Returns the data defined property corresponding to a data defined button widget*/
114+
virtual QgsComposerItem::DataDefinedProperty ddPropertyForWidget( QgsDataDefinedButton* widget );
115+
102116
};

0 commit comments

Comments
 (0)