This commit is contained in:
Nyall Dawson 2017-12-16 08:16:52 +10:00
parent 662ec7a77c
commit 831732f3a3
16 changed files with 188 additions and 143 deletions

View File

@ -13,6 +13,12 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
%Docstring
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
While the raw QGraphicsScene API can be used to render the contents of a QgsLayout
to a QPainter, it is recommended to instead use a QgsLayoutExporter to handle rendering
layouts instead. QgsLayoutExporter automatically takes care of the intracacies of
preparing the layout and paint devices for correct exports, respecting various
user settings such as the layout context DPI.
.. versionadded:: 3.0
%End
@ -72,12 +78,6 @@ relations and various other bits. It is never null.
QgsLayoutModel *itemsModel();
%Docstring
Returns the items model attached to the layout.
%End
QgsLayoutExporter &exporter();
%Docstring
Returns the layout's exporter, which is used for rendering the layout and exporting
to various formats.
%End
QString name() const;
@ -182,7 +182,7 @@ z order list. This should be called after any stacking changes
which deferred z-order updates.
%End
QgsLayoutItem *itemByUuid( const QString &uuid, bool includeTemplateUuids = false );
QgsLayoutItem *itemByUuid( const QString &uuid, bool includeTemplateUuids = false ) const;
%Docstring
Returns the layout item with matching ``uuid`` unique identifier, or a None
if a matching item could not be found.
@ -387,8 +387,25 @@ Return list of keys stored in custom properties for the layout.
%End
QgsLayoutItemMap *referenceMap() const;
%Docstring
Returns the map item which will be used to generate corresponding world files when the
layout is exported. If no map was explicitly set via setReferenceMap(), the largest
map in the layout will be returned (or None if there are no maps in the layout).
.. seealso:: :py:func:`setReferenceMap()`
.. seealso:: :py:func:`generateWorldFile()`
%End
void setReferenceMap( QgsLayoutItemMap *map );
%Docstring
Sets the ``map`` item which will be used to generate corresponding world files when the
layout is exported.
.. seealso:: :py:func:`referenceMap()`
.. seealso:: :py:func:`setGenerateWorldFile()`
%End
QgsLayoutPageCollection *pageCollection();
%Docstring
@ -406,6 +423,20 @@ and other cosmetic items.
:param margin: optional marginal (in percent, e.g., 0.05 = 5% ) to add around items
:return: layout bounds, in layout units.
.. seealso:: :py:func:`pageItemBounds()`
%End
QRectF pageItemBounds( int page, bool visibleOnly = false ) const;
%Docstring
Returns the bounding box of the items contained on a specified ``page``.
A page number of 0 represents the first page in the layout.
Set ``visibleOnly`` to true to only include visible items.
The returned bounds are in layout units.
.. seealso:: :py:func:`layoutBounds()`
%End
void addLayoutItem( QgsLayoutItem *item /Transfer/ );

View File

@ -54,7 +54,6 @@ Constructor for QgsLayoutExporter, for the specified ``layout``.
QgsLayout *layout() const;
%Docstring
Returns the layout linked to this exporter.
:rtype: QgsLayout
%End
void renderPage( QPainter *painter, int page ) const;
@ -84,8 +83,8 @@ are 0 based, such that the first page in a layout is page 0.
Returns the rendered image, or a null QImage if the image does not fit into available memory.
.. seealso:: :py:func:`renderPage()`
.. seealso:: :py:func:`renderRegionToImage()`
:rtype: QImage
%End
void renderRegion( QPainter *painter, const QRectF &region ) const;
@ -94,6 +93,7 @@ Renders a ``region`` from the layout to a ``painter``. This method can be used
to render sections of pages rather than full pages.
.. seealso:: :py:func:`renderPage()`
.. seealso:: :py:func:`renderRegionToImage()`
%End
@ -112,8 +112,8 @@ to render sections of pages rather than full pages.
Returns the rendered image, or a null QImage if the image does not fit into available memory.
.. seealso:: :py:func:`renderRegion()`
.. seealso:: :py:func:`renderPageToImage()`
:rtype: QImage
%End
@ -195,7 +195,6 @@ Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Returns a result code indicating whether the export was successful or an
error was encountered. If an error code is returned, errorFile() can be called
to determine the filename for the export which encountered the error.
:rtype: ExportResult
%End
struct PdfExportSettings
@ -239,14 +238,12 @@ Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Returns a result code indicating whether the export was successful or an
error was encountered.
:rtype: ExportResult
%End
QString errorFile() const;
%Docstring
Returns the file name corresponding to the last error encountered during
an export.
:rtype: str
%End
bool georeferenceOutput( const QString &file, QgsLayoutItemMap *referenceMap = 0,
@ -265,7 +262,6 @@ Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
The function will return true if the output was successfully georeferenced.
.. seealso:: :py:func:`computeGeoTransform()`
:rtype: bool
%End
void computeWorldFileParameters( double &a, double &b, double &c, double &d, double &e, double &f, double dpi = -1 ) const;
@ -290,7 +286,6 @@ Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.
Generates the file name for a page during export.
Subclasses can override this method to customise page file naming.
:rtype: str
%End
};

View File

@ -829,15 +829,14 @@ Sets whether the item should be excluded from composer exports and prints.
also check the base class result.
.. seealso:: :py:func:`requiresRasterization()`
:rtype: bool
%End
virtual bool requiresRasterization() const;
%Docstring
Returns true if the item is drawn in such a way that forces the whole layout
to be rasterised when exporting to vector formats.
to be rasterized when exporting to vector formats.
.. seealso:: :py:func:`containsAdvancedEffects()`
:rtype: bool
%End
virtual double estimatedFrameBleed() const;
@ -920,6 +919,11 @@ Cancels the current item command and discards it.
.. seealso:: :py:func:`beginCommand()`
.. seealso:: :py:func:`endCommand()`
%End
bool shouldDrawItem() const;
%Docstring
Returns whether the item should be drawn in the current context.
%End
public slots:
@ -1161,11 +1165,6 @@ in finalizeRestoreFromXml(), not readPropertiesFromElement().
.. seealso:: :py:func:`writePropertiesToElement()`
.. seealso:: :py:func:`readXml()`
%End
bool shouldDrawItem() const;
%Docstring
Returns whether the item should be drawn in the current context.
%End
QgsLayoutSize applyDataDefinedSize( const QgsLayoutSize &size );

View File

@ -62,7 +62,6 @@ The caller takes responsibility for deleting the returned object.
virtual void setFrameStrokeWidth( const QgsLayoutMeasurement &width );
double scale() const;
%Docstring
Returns the map scale.
@ -280,10 +279,10 @@ Sets preset name for map rendering. See followVisibilityPresetName() for more de
Returns true if the map contains a WMS layer.
%End
bool containsAdvancedEffects() const;
%Docstring
Returns true if the map contains layers with blend modes or flattened layers for vectors
%End
virtual bool requiresRasterization() const;
virtual bool containsAdvancedEffects() const;
void setMapRotation( double rotation );
%Docstring

View File

@ -85,6 +85,8 @@ Returns a list of the page numbers which are visible within the specified
%Docstring
Returns whether a given ``page`` index is empty, ie, it contains no items except for the background
paper item.
.. seealso:: :py:func:`shouldExportPage()`
%End
QList< QgsLayoutItem *> itemsOnPage( int page ) const;
@ -92,6 +94,14 @@ paper item.
Returns a list of layout items on the specified ``page`` index.
%End
bool shouldExportPage( int page ) const;
%Docstring
Returns whether the specified ``page`` number should be included in exports of the layouts.
.. seealso:: :py:func:`pageIsEmpty()`
%End
void addPage( QgsLayoutItemPage *page /Transfer/ );
%Docstring
Adds a ``page`` to the collection. Ownership of the ``page`` is transferred
@ -191,6 +201,7 @@ Returns the symbol to use for drawing pages in the collection.
Should be called before changing any page item sizes, and followed by a call to
endPageSizeChange(). If page size changes are wrapped in these calls, then items
will maintain their same relative position on pages after the page sizes are updated.
.. seealso:: :py:func:`endPageSizeChange()`
%End
@ -199,6 +210,7 @@ Returns the symbol to use for drawing pages in the collection.
Should be called after changing any page item sizes, and preceded by a call to
beginPageSizeChange(). If page size changes are wrapped in these calls, then items
will maintain their same relative position on pages after the page sizes are updated.
.. seealso:: :py:func:`beginPageSizeChange()`
%End
@ -212,6 +224,16 @@ for page size/orientation change.
%Docstring
Returns the maximum width of pages in the collection. The returned value is
in layout units.
.. seealso:: :py:func:`maximumPageSize()`
%End
QSizeF maximumPageSize() const;
%Docstring
Returns the maximum size of any page in the collection, by area. The returned value
is in layout units.
.. seealso:: :py:func:`maximumPageWidth()`
%End
bool hasUniformPageSizes() const;
@ -220,7 +242,6 @@ in layout units.
This method does not consider differing units as non-uniform sizes, only the actual
physical size of the pages.
:rtype: bool
%End
int pageNumberForPoint( QPointF point ) const;

View File

@ -219,7 +219,6 @@ the a specified ``rotation`` amount.
Decodes a ``string`` representing a paper orientation and returns the
decoded orientation.
If the string was correctly decoded, ``ok`` will be set to true.
:rtype: QgsLayoutItemPage.Orientation
%End
};

View File

@ -49,7 +49,6 @@ Returns the layout view utilized by the designer.
virtual QgsMessageBar *messageBar() = 0;
%Docstring
Returns the designer's message bar.
:rtype: QgsMessageBar
%End
virtual void selectItems( const QList< QgsLayoutItem * > items ) = 0;

View File

@ -1624,7 +1624,7 @@ void QgsLayoutDesignerDialog::exportToPdf()
QApplication::setOverrideCursor( Qt::BusyCursor );
QgsLayoutExporter::PdfExportSettings pdfSettings;
pdfSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
pdfSettings.rasterizeWholeImage = mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
pdfSettings.forceVectorOutput = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool();
// force a refresh, to e.g. update data defined properties, tables, etc
@ -1843,7 +1843,7 @@ bool QgsLayoutDesignerDialog::containsAdvancedEffects() const
void QgsLayoutDesignerDialog::showRasterizationWarning()
{
if ( mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool() ||
if ( mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool() ||
mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool() )
return;
@ -1855,7 +1855,7 @@ void QgsLayoutDesignerDialog::showRasterizationWarning()
m.setCheckBoxVisible( true );
m.showMessage( true );
mLayout->setCustomProperty( QStringLiteral( "rasterise" ), m.checkBoxState() == Qt::Checked );
mLayout->setCustomProperty( QStringLiteral( "rasterize" ), m.checkBoxState() == Qt::Checked );
//make sure print as raster checkbox is updated
mLayoutPropertiesWidget->updateGui();
}

View File

@ -58,7 +58,7 @@ QgsLayoutPropertiesWidget::QgsLayoutPropertiesWidget( QWidget *parent, QgsLayout
mGenerateWorldFileCheckBox->setChecked( exportWorldFile );
connect( mGenerateWorldFileCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::worldFileToggled );
connect( mRasterizeCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::rasteriseToggled );
connect( mRasterizeCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::rasterizeToggled );
connect( mForceVectorCheckBox, &QCheckBox::toggled, this, &QgsLayoutPropertiesWidget::forceVectorToggled );
mTopMarginSpinBox->setValue( topMargin );
@ -92,13 +92,13 @@ void QgsLayoutPropertiesWidget::updateGui()
whileBlocking( mReferenceMapComboBox )->setItem( mLayout->referenceMap() );
whileBlocking( mResolutionSpinBox )->setValue( mLayout->context().dpi() );
bool rasterise = mLayout->customProperty( QStringLiteral( "rasterise" ), false ).toBool();
whileBlocking( mRasterizeCheckBox )->setChecked( rasterise );
bool rasterize = mLayout->customProperty( QStringLiteral( "rasterize" ), false ).toBool();
whileBlocking( mRasterizeCheckBox )->setChecked( rasterize );
bool forceVectors = mLayout->customProperty( QStringLiteral( "forceVector" ), false ).toBool();
whileBlocking( mForceVectorCheckBox )->setChecked( forceVectors );
if ( rasterise )
if ( rasterize )
{
mForceVectorCheckBox->setChecked( false );
mForceVectorCheckBox->setEnabled( false );
@ -208,9 +208,9 @@ void QgsLayoutPropertiesWidget::worldFileToggled()
mLayout->setCustomProperty( QStringLiteral( "exportWorldFile" ), mGenerateWorldFileCheckBox->isChecked() );
}
void QgsLayoutPropertiesWidget::rasteriseToggled()
void QgsLayoutPropertiesWidget::rasterizeToggled()
{
mLayout->setCustomProperty( QStringLiteral( "rasterise" ), mRasterizeCheckBox->isChecked() );
mLayout->setCustomProperty( QStringLiteral( "rasterize" ), mRasterizeCheckBox->isChecked() );
if ( mRasterizeCheckBox->isChecked() )
{

View File

@ -46,7 +46,7 @@ class QgsLayoutPropertiesWidget: public QgsPanelWidget, private Ui::QgsLayoutWid
void referenceMapChanged( QgsLayoutItem *item );
void dpiChanged( int value );
void worldFileToggled();
void rasteriseToggled();
void rasterizeToggled();
void forceVectorToggled();
private:

View File

@ -427,14 +427,14 @@ QgsLayoutExporter::ExportResult QgsLayoutExporter::print( QPrinter &printer )
return Success;
}
QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter, bool startNewPage, double dpi, bool rasterise )
QgsLayoutExporter::ExportResult QgsLayoutExporter::printPrivate( QPrinter &printer, QPainter &painter, bool startNewPage, double dpi, bool rasterize )
{
//layout starts page numbering at 0
int fromPage = ( printer.fromPage() < 1 ) ? 0 : printer.fromPage() - 1;
int toPage = ( printer.toPage() < 1 ) ? mLayout->pageCollection()->pageCount() - 1 : printer.toPage() - 1;
bool pageExported = false;
if ( rasterise )
if ( rasterize )
{
for ( int i = fromPage; i <= toPage; ++i )
{

View File

@ -343,6 +343,8 @@ class CORE_EXPORT QgsLayoutExporter
* \param printer QPrinter destination
* \param painter QPainter source
* \param startNewPage set to true to begin the print on a new page
* \param dpi set to a value > 0 to manually override the layout's default dpi
* \param rasterize set to true to force print as a raster image
*/
ExportResult printPrivate( QPrinter &printer, QPainter &painter, bool startNewPage = false, double dpi = -1, bool rasterize = false );

View File

@ -755,7 +755,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
/**
* Returns true if the item is drawn in such a way that forces the whole layout
* to be rasterised when exporting to vector formats.
* to be rasterized when exporting to vector formats.
* \see containsAdvancedEffects()
*/
virtual bool requiresRasterization() const;

View File

@ -834,7 +834,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
if ( containsAdvancedEffects() && ( !mLayout || !( mLayout->context().flags() & QgsLayoutContext::FlagForceVectorOutput ) ) )
{
// rasterise
// rasterize
double destinationDpi = style->matrix.m11() * 25.4;
double layoutUnitsInInches = mLayout ? mLayout->convertFromLayoutUnits( 1, QgsUnitTypes::LayoutInches ).length() : 1;
int widthInPixels = std::round( boundingRect().width() * layoutUnitsInInches * destinationDpi );

View File

@ -262,7 +262,7 @@
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="mForceVectorCheckBox">
<property name="toolTip">
<string>If checked, the layout will always be kept as vector objects when exported to a compatible format, even if the appearance of the resultant file does not match the layouts settings. If unchecked, some elements in the layout may be rasterised in order to keep their appearance intact.</string>
<string>If checked, the layout will always be kept as vector objects when exported to a compatible format, even if the appearance of the resultant file does not match the layouts settings. If unchecked, some elements in the layout may be rasterized in order to keep their appearance intact.</string>
</property>
<property name="text">
<string>Always export as vectors</string>

View File

@ -444,7 +444,7 @@ void TestQgsLayoutMap::dataDefinedStyles()
void TestQgsLayoutMap::rasterized()
{
// test a map which must be rasterised
// test a map which must be rasterized
QgsLayout l( QgsProject::instance() );
l.initializeDefaults();
@ -496,7 +496,7 @@ void TestQgsLayoutMap::rasterized()
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
// try rendering again, without requiring rasterization, for comparison
// (we can use the same test image, because CompositionMode_Darken doesn't actually have any noticable
// (we can use the same test image, because CompositionMode_Darken doesn't actually have any noticeable
// rendering differences for the black grid!)
grid->setBlendMode( QPainter::CompositionMode_SourceOver );
QVERIFY( !map->containsAdvancedEffects() );