Skip to content

Commit

Permalink
[layouts][needs-docs] Add control for whether pages should be
Browse files Browse the repository at this point in the history
exported, including data defined setting

This replaces the 2.x data-defined "number of pages" setting.
Instead of requiring users to develop an expression to return
the number of pages, instead we allow individual pages to have
a data defined control of whether that page should be included
in the export.

This is more flexible, and works correctly with the mixed page
size model for layouts.
  • Loading branch information
nyalldawson committed Dec 17, 2017
1 parent 3704c48 commit f649f1f
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 38 deletions.
3 changes: 0 additions & 3 deletions python/core/layout/qgslayout.sip
Expand Up @@ -580,9 +580,6 @@ Emitted when the layout's name is changed.


}; };





/************************************************************************ /************************************************************************
* This file has been generated automatically from * * This file has been generated automatically from *
* * * *
Expand Down
6 changes: 6 additions & 0 deletions src/app/layout/qgslayoutdesignerdialog.cpp
Expand Up @@ -1511,6 +1511,9 @@ void QgsLayoutDesignerDialog::exportToRaster()
mView->setPaintingEnabled( false ); mView->setPaintingEnabled( false );
QApplication::setOverrideCursor( Qt::BusyCursor ); QApplication::setOverrideCursor( Qt::BusyCursor );


// force a refresh, to e.g. update data defined properties, tables, etc
mLayout->refresh();

QgsLayoutExporter exporter( mLayout ); QgsLayoutExporter exporter( mLayout );


QgsLayoutExporter::ImageExportSettings settings; QgsLayoutExporter::ImageExportSettings settings;
Expand Down Expand Up @@ -1624,6 +1627,9 @@ void QgsLayoutDesignerDialog::exportToPdf()
pdfSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool(); pdfSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
pdfSettings.forceVectorOutput = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool(); pdfSettings.forceVectorOutput = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool();


// force a refresh, to e.g. update data defined properties, tables, etc
mLayout->refresh();

QgsLayoutExporter exporter( mLayout ); QgsLayoutExporter exporter( mLayout );
switch ( exporter.exportToPdf( outputFileName, pdfSettings ) ) switch ( exporter.exportToPdf( outputFileName, pdfSettings ) )
{ {
Expand Down
11 changes: 11 additions & 0 deletions src/app/layout/qgslayoutpagepropertieswidget.cpp
Expand Up @@ -39,6 +39,7 @@ QgsLayoutPagePropertiesWidget::QgsLayoutPagePropertiesWidget( QWidget *parent, Q
mWidthSpin->setValue( mPage->pageSize().width() ); mWidthSpin->setValue( mPage->pageSize().width() );
mHeightSpin->setValue( mPage->pageSize().height() ); mHeightSpin->setValue( mPage->pageSize().height() );
mSizeUnitsComboBox->setUnit( mPage->pageSize().units() ); mSizeUnitsComboBox->setUnit( mPage->pageSize().units() );
mExcludePageCheckBox->setChecked( mPage->excludeFromExports() );


mPageOrientationComboBox->setCurrentIndex( mPageOrientationComboBox->findData( mPage->orientation() ) ); mPageOrientationComboBox->setCurrentIndex( mPageOrientationComboBox->findData( mPage->orientation() ) );


Expand All @@ -59,11 +60,14 @@ QgsLayoutPagePropertiesWidget::QgsLayoutPagePropertiesWidget( QWidget *parent, Q
connect( mHeightSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::updatePageSize ); connect( mHeightSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::updatePageSize );
connect( mWidthSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::setToCustomSize ); connect( mWidthSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::setToCustomSize );
connect( mHeightSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::setToCustomSize ); connect( mHeightSpin, static_cast< void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutPagePropertiesWidget::setToCustomSize );
connect( mExcludePageCheckBox, &QCheckBox::toggled, this, &QgsLayoutPagePropertiesWidget::excludeExportsToggled );


connect( mSymbolButton, &QgsSymbolButton::changed, this, &QgsLayoutPagePropertiesWidget::symbolChanged ); connect( mSymbolButton, &QgsSymbolButton::changed, this, &QgsLayoutPagePropertiesWidget::symbolChanged );
registerDataDefinedButton( mPaperSizeDDBtn, QgsLayoutObject::PresetPaperSize ); registerDataDefinedButton( mPaperSizeDDBtn, QgsLayoutObject::PresetPaperSize );
registerDataDefinedButton( mWidthDDBtn, QgsLayoutObject::ItemWidth ); registerDataDefinedButton( mWidthDDBtn, QgsLayoutObject::ItemWidth );
registerDataDefinedButton( mHeightDDBtn, QgsLayoutObject::ItemHeight ); registerDataDefinedButton( mHeightDDBtn, QgsLayoutObject::ItemHeight );
registerDataDefinedButton( mExcludePageDDBtn, QgsLayoutObject::ExcludeFromExports );
mExcludePageDDBtn->registerEnabledWidget( mExcludePageCheckBox, false );


showCurrentPageSize(); showCurrentPageSize();
} }
Expand Down Expand Up @@ -155,6 +159,13 @@ void QgsLayoutPagePropertiesWidget::symbolChanged()
mPage->layout()->undoStack()->endCommand(); mPage->layout()->undoStack()->endCommand();
} }


void QgsLayoutPagePropertiesWidget::excludeExportsToggled( bool checked )
{
mPage->beginCommand( !checked ? tr( "Include Page in Exports" ) : tr( "Exclude Page from Exports" ) );
mPage->setExcludeFromExports( checked );
mPage->endCommand();
}

void QgsLayoutPagePropertiesWidget::showCurrentPageSize() void QgsLayoutPagePropertiesWidget::showCurrentPageSize()
{ {
QgsLayoutSize paperSize = mPage->pageSize(); QgsLayoutSize paperSize = mPage->pageSize();
Expand Down
1 change: 1 addition & 0 deletions src/app/layout/qgslayoutpagepropertieswidget.h
Expand Up @@ -48,6 +48,7 @@ class QgsLayoutPagePropertiesWidget : public QgsLayoutItemBaseWidget, private Ui
void updatePageSize(); void updatePageSize();
void setToCustomSize(); void setToCustomSize();
void symbolChanged(); void symbolChanged();
void excludeExportsToggled( bool checked );


private: private:


Expand Down
3 changes: 0 additions & 3 deletions src/core/layout/qgslayout.h
Expand Up @@ -672,6 +672,3 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext
}; };


#endif //QGSLAYOUT_H #endif //QGSLAYOUT_H



3 changes: 2 additions & 1 deletion src/core/layout/qgslayoutcontext.h
Expand Up @@ -236,7 +236,8 @@ class CORE_EXPORT QgsLayoutContext : public QObject
bool mPagesVisible = true; bool mPagesVisible = true;


friend class QgsLayoutExporter; friend class QgsLayoutExporter;
friend class LayoutItemCacheSettingRestorer; friend class TestQgsLayout;
friend class LayoutContextPreviewSettingRestorer;




}; };
Expand Down
43 changes: 39 additions & 4 deletions src/core/layout/qgslayoutexporter.cpp
Expand Up @@ -26,6 +26,30 @@
#include "gdal.h" #include "gdal.h"
#include "cpl_conv.h" #include "cpl_conv.h"


///@cond PRIVATE
class LayoutContextPreviewSettingRestorer
{
public:

LayoutContextPreviewSettingRestorer( QgsLayout *layout )
: mLayout( layout )
, mPreviousSetting( layout->context().mIsPreviewRender )
{
mLayout->context().mIsPreviewRender = false;
}

~LayoutContextPreviewSettingRestorer()
{
mLayout->context().mIsPreviewRender = mPreviousSetting;
}

private:
QgsLayout *mLayout = nullptr;
bool mPreviousSetting = false;
};

///@endcond PRIVATE

QgsLayoutExporter::QgsLayoutExporter( QgsLayout *layout ) QgsLayoutExporter::QgsLayoutExporter( QgsLayout *layout )
: mLayout( layout ) : mLayout( layout )
{ {
Expand Down Expand Up @@ -53,6 +77,9 @@ void QgsLayoutExporter::renderPage( QPainter *painter, int page ) const
return; return;
} }


LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;

QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() ); QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
renderRegion( painter, paperRect ); renderRegion( painter, paperRect );
} }
Expand All @@ -73,6 +100,9 @@ QImage QgsLayoutExporter::renderPageToImage( int page, QSize imageSize, double d
return QImage(); return QImage();
} }


LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;

QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() ); QRectF paperRect = QRectF( pageItem->pos().x(), pageItem->pos().y(), pageItem->rect().width(), pageItem->rect().height() );
return renderRegionToImage( paperRect, imageSize, dpi ); return renderRegionToImage( paperRect, imageSize, dpi );
} }
Expand All @@ -85,8 +115,6 @@ class LayoutItemCacheSettingRestorer
LayoutItemCacheSettingRestorer( QgsLayout *layout ) LayoutItemCacheSettingRestorer( QgsLayout *layout )
: mLayout( layout ) : mLayout( layout )
{ {
mLayout->context().mIsPreviewRender = false;

const QList< QGraphicsItem * > items = mLayout->items(); const QList< QGraphicsItem * > items = mLayout->items();
for ( QGraphicsItem *item : items ) for ( QGraphicsItem *item : items )
{ {
Expand All @@ -101,8 +129,6 @@ class LayoutItemCacheSettingRestorer
{ {
it.key()->setCacheMode( it.value() ); it.key()->setCacheMode( it.value() );
} }

mLayout->context().mIsPreviewRender = true;
} }


private: private:
Expand All @@ -122,6 +148,8 @@ void QgsLayoutExporter::renderRegion( QPainter *painter, const QRectF &region )


LayoutItemCacheSettingRestorer cacheRestorer( mLayout ); LayoutItemCacheSettingRestorer cacheRestorer( mLayout );
( void )cacheRestorer; ( void )cacheRestorer;
LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;


#if 0 //TODO #if 0 //TODO
setSnapLinesVisible( false ); setSnapLinesVisible( false );
Expand All @@ -138,6 +166,9 @@ void QgsLayoutExporter::renderRegion( QPainter *painter, const QRectF &region )


QImage QgsLayoutExporter::renderRegionToImage( const QRectF &region, QSize imageSize, double dpi ) const QImage QgsLayoutExporter::renderRegionToImage( const QRectF &region, QSize imageSize, double dpi ) const
{ {
LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;

double resolution = mLayout->context().dpi(); double resolution = mLayout->context().dpi();
double oneInchInLayoutUnits = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( 1, QgsUnitTypes::LayoutInches ) ); double oneInchInLayoutUnits = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( 1, QgsUnitTypes::LayoutInches ) );
if ( imageSize.isValid() ) if ( imageSize.isValid() )
Expand Down Expand Up @@ -219,6 +250,8 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToImage( const QString
pageDetails.baseName = fi.baseName(); pageDetails.baseName = fi.baseName();
pageDetails.extension = fi.completeSuffix(); pageDetails.extension = fi.completeSuffix();


LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;
LayoutContextSettingsRestorer dpiRestorer( mLayout ); LayoutContextSettingsRestorer dpiRestorer( mLayout );
( void )dpiRestorer; ( void )dpiRestorer;
mLayout->context().setDpi( settings.dpi ); mLayout->context().setDpi( settings.dpi );
Expand Down Expand Up @@ -303,6 +336,8 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::exportToPdf( const QString &f


mErrorFileName.clear(); mErrorFileName.clear();


LayoutContextPreviewSettingRestorer restorer( mLayout );
( void )restorer;
LayoutContextSettingsRestorer contextRestorer( mLayout ); LayoutContextSettingsRestorer contextRestorer( mLayout );
( void )contextRestorer; ( void )contextRestorer;
mLayout->context().setDpi( settings.dpi ); mLayout->context().setDpi( settings.dpi );
Expand Down
10 changes: 5 additions & 5 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -831,6 +831,11 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/ */
void cancelCommand(); void cancelCommand();


/**
* Returns whether the item should be drawn in the current context.
*/
bool shouldDrawItem() const;

public slots: public slots:


/** /**
Expand Down Expand Up @@ -1049,11 +1054,6 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/ */
virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ); virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );


/**
* Returns whether the item should be drawn in the current context.
*/
bool shouldDrawItem() const;

/** /**
* Applies any present data defined size overrides to the specified layout \a size. * Applies any present data defined size overrides to the specified layout \a size.
*/ */
Expand Down
4 changes: 4 additions & 0 deletions src/core/layout/qgslayoutpagecollection.cpp
Expand Up @@ -482,6 +482,10 @@ bool QgsLayoutPageCollection::shouldExportPage( int page ) const
return false; return false;
} }


QgsLayoutItemPage *pageItem = mPages.at( page );
if ( !pageItem->shouldDrawItem() )
return false;

//check all frame items on page //check all frame items on page
QList<QgsLayoutFrame *> frames; QList<QgsLayoutFrame *> frames;
itemsOnPage( frames, page ); itemsOnPage( frames, page );
Expand Down
82 changes: 61 additions & 21 deletions src/ui/layout/qgslayoutpagepropertieswidget.ui
Expand Up @@ -14,27 +14,7 @@
<string>New Item Properties</string> <string>New Item Properties</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="3" column="0"> <item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Background</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsSymbolButton" name="mSymbolButton"> <widget class="QgsSymbolButton" name="mSymbolButton">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
Expand All @@ -56,6 +36,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Background</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
Expand Down Expand Up @@ -204,6 +191,56 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="mExcludePageCheckBox">
<property name="toolTip">
<string>If checked, this page will not be included when exporting the layout</string>
</property>
<property name="text">
<string>Exclude page from exports</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QgsPropertyOverrideButton" name="mExcludePageDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
Expand Down Expand Up @@ -244,6 +281,9 @@
<tabstop>mHeightSpin</tabstop> <tabstop>mHeightSpin</tabstop>
<tabstop>mHeightDDBtn</tabstop> <tabstop>mHeightDDBtn</tabstop>
<tabstop>mSizeUnitsComboBox</tabstop> <tabstop>mSizeUnitsComboBox</tabstop>
<tabstop>mExcludePageCheckBox</tabstop>
<tabstop>mExcludePageDDBtn</tabstop>
<tabstop>mSymbolButton</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>
Expand Down
2 changes: 1 addition & 1 deletion src/ui/qgisapp.ui
Expand Up @@ -17,7 +17,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1018</width> <width>1018</width>
<height>20</height> <height>25</height>
</rect> </rect>
</property> </property>
<property name="toolTip"> <property name="toolTip">
Expand Down
28 changes: 28 additions & 0 deletions tests/src/core/testqgslayout.cpp
Expand Up @@ -613,6 +613,7 @@ void TestQgsLayout::shouldExportPage()
QgsLayoutItemPage *page2 = new QgsLayoutItemPage( &l ); QgsLayoutItemPage *page2 = new QgsLayoutItemPage( &l );
page2->setPageSize( "A4" ); page2->setPageSize( "A4" );
l.pageCollection()->addPage( page2 ); l.pageCollection()->addPage( page2 );
l.context().mIsPreviewRender = false;


QgsLayoutItemHtml *htmlItem = new QgsLayoutItemHtml( &l ); QgsLayoutItemHtml *htmlItem = new QgsLayoutItemHtml( &l );
//frame on page 1 //frame on page 1
Expand Down Expand Up @@ -645,6 +646,33 @@ void TestQgsLayout::shouldExportPage()


QVERIFY( l.pageCollection()->shouldExportPage( 0 ) ); QVERIFY( l.pageCollection()->shouldExportPage( 0 ) );
QVERIFY( !l.pageCollection()->shouldExportPage( 1 ) ); QVERIFY( !l.pageCollection()->shouldExportPage( 1 ) );

// get rid of frames
l.removeItem( frame1 );
l.removeItem( frame2 );
l.removeMultiFrame( htmlItem );
delete htmlItem;
QgsApplication::sendPostedEvents( nullptr, QEvent::DeferredDelete );

QVERIFY( l.pageCollection()->shouldExportPage( 0 ) );
QVERIFY( l.pageCollection()->shouldExportPage( 1 ) );

// explicitly set exclude from exports
l.pageCollection()->page( 0 )->setExcludeFromExports( true );
QVERIFY( !l.pageCollection()->shouldExportPage( 0 ) );
QVERIFY( l.pageCollection()->shouldExportPage( 1 ) );

l.pageCollection()->page( 0 )->setExcludeFromExports( false );
l.pageCollection()->page( 1 )->setExcludeFromExports( true );
QVERIFY( l.pageCollection()->shouldExportPage( 0 ) );
QVERIFY( !l.pageCollection()->shouldExportPage( 1 ) );

l.pageCollection()->page( 1 )->setExcludeFromExports( false );
l.pageCollection()->page( 0 )->dataDefinedProperties().setProperty( QgsLayoutObject::ExcludeFromExports, QgsProperty::fromExpression( "1" ) );
l.pageCollection()->page( 1 )->dataDefinedProperties().setProperty( QgsLayoutObject::ExcludeFromExports, QgsProperty::fromValue( true ) );
l.refresh();
QVERIFY( !l.pageCollection()->shouldExportPage( 0 ) );
QVERIFY( !l.pageCollection()->shouldExportPage( 1 ) );
} }


void TestQgsLayout::pageIsEmpty() void TestQgsLayout::pageIsEmpty()
Expand Down

0 comments on commit f649f1f

Please sign in to comment.