Merge pull request #8781 from mhugent/get_atlas_print

[server][needs-docs] Get atlas print
This commit is contained in:
mhugent 2019-01-07 10:42:23 +01:00 committed by GitHub
commit 54a5fae0b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 515 additions and 245 deletions

View File

@ -152,6 +152,15 @@ Returns the quality for WMS images defined in a QGIS project.
:param project: the QGIS project
:return: quality if defined in project, -1 otherwise.
%End
int wmsMaxAtlasFeatures( const QgsProject &project );
%Docstring
Returns the maximum number of atlas features which can be printed in a request
:param project: the QGIS project
:return: the number of atlas features
%End
bool wmsUseLayerIds( const QgsProject &project );

View File

@ -637,6 +637,8 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa
mWMSImageQualitySpinBox->setValue( imageQuality );
}
mWMSMaxAtlasFeaturesSpinBox->setValue( QgsProject::instance()->readNumEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), 1 ) );
mWMTSUrlLineEdit->setText( QgsProject::instance()->readEntry( QStringLiteral( "WMTSUrl" ), QStringLiteral( "/" ), QString() ) );
mWMTSMinScaleLineEdit->setValue( QgsProject::instance()->readNumEntry( QStringLiteral( "WMTSMinScale" ), QStringLiteral( "/" ), 5000 ) );
@ -1260,6 +1262,9 @@ void QgsProjectProperties::apply()
QgsProject::instance()->writeEntry( QStringLiteral( "WMSImageQuality" ), QStringLiteral( "/" ), imageQualityValue );
}
int maxAtlasFeatures = mWMSMaxAtlasFeaturesSpinBox->value();
QgsProject::instance()->writeEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), maxAtlasFeatures );
QgsProject::instance()->writeEntry( QStringLiteral( "WMTSUrl" ), QStringLiteral( "/" ), mWMTSUrlLineEdit->text() );
QgsProject::instance()->writeEntry( QStringLiteral( "WMTSMinScale" ), QStringLiteral( "/" ), mWMTSMinScaleLineEdit->value() );
bool wmtsProject = false;

View File

@ -111,6 +111,11 @@ int QgsServerProjectUtils::wmsImageQuality( const QgsProject &project )
return project.readNumEntry( QStringLiteral( "WMSImageQuality" ), QStringLiteral( "/" ), -1 );
}
int QgsServerProjectUtils::wmsMaxAtlasFeatures( const QgsProject &project )
{
return project.readNumEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), 1 );
}
bool QgsServerProjectUtils::wmsInfoFormatSia2045( const QgsProject &project )
{
QString sia2045 = project.readEntry( QStringLiteral( "WMSInfoFormatSIA2045" ), QStringLiteral( "/" ), "" );

View File

@ -147,6 +147,13 @@ namespace QgsServerProjectUtils
*/
SERVER_EXPORT int wmsImageQuality( const QgsProject &project );
/**
* Returns the maximum number of atlas features which can be printed in a request
* \param project the QGIS project
* \return the number of atlas features
*/
SERVER_EXPORT int wmsMaxAtlasFeatures( const QgsProject &project );
/**
* Returns if layer ids are used as name in WMS.
* \param project the QGIS project

View File

@ -23,6 +23,7 @@
#include "qgsserverprojectutils.h"
#include "qgslayoutmanager.h"
#include "qgslayoutatlas.h"
#include "qgsprintlayout.h"
#include "qgslayoutitemmap.h"
#include "qgslayoutitemlabel.h"
@ -680,6 +681,27 @@ namespace QgsWms
composerTemplateElem.setAttribute( QStringLiteral( "width" ), width.length() );
composerTemplateElem.setAttribute( QStringLiteral( "height" ), height.length() );
//atlas enabled and atlas covering layer
QgsLayoutAtlas *atlas = layout->atlas();
if ( atlas && atlas->enabled() )
{
composerTemplateElem.setAttribute( QStringLiteral( "atlasEnabled" ), QStringLiteral( "1" ) );
QgsVectorLayer *cLayer = atlas->coverageLayer();
if ( cLayer )
{
QString layerName = cLayer->shortName();
if ( QgsServerProjectUtils::wmsUseLayerIds( *project ) )
{
layerName = cLayer->id();
}
else if ( layerName.isEmpty() )
{
layerName = cLayer->name();
}
composerTemplateElem.setAttribute( QStringLiteral( "atlasCoverageLayer" ), layerName );
}
}
//add available composer maps and their size in mm
QList<QgsLayoutItemMap *> layoutMapList;
layout->layoutItems<QgsLayoutItemMap>( layoutMapList );
@ -1739,6 +1761,22 @@ namespace QgsWms
//displayfield
layerElem.setAttribute( QStringLiteral( "displayField" ), displayField );
//primary key
QgsAttributeList pkAttributes = vLayer->primaryKeyAttributes();
if ( pkAttributes.size() > 0 )
{
QDomElement pkElem = doc.createElement( QStringLiteral( "PrimaryKey" ) );
QgsAttributeList::const_iterator pkIt = pkAttributes.constBegin();
for ( ; pkIt != pkAttributes.constEnd(); ++pkIt )
{
QDomElement pkAttributeElem = doc.createElement( QStringLiteral( "PrimaryKeyAttribute" ) );
QDomText pkAttName = doc.createTextNode( layerFields.at( *pkIt ).name() );
pkAttributeElem.appendChild( pkAttName );
pkElem.appendChild( pkAttributeElem );
}
layerElem.appendChild( pkElem );
}
//geometry type
layerElem.setAttribute( QStringLiteral( "geometryType" ), QgsWkbTypes::displayString( vLayer->wkbType() ) );

View File

@ -498,6 +498,10 @@ namespace QgsWms
const QgsWmsParameter pWmtver( QgsWmsParameter::WMTVER );
save( pWmtver );
const QgsWmsParameter pAtlasPk( QgsWmsParameter::ATLAS_PK,
QVariant::StringList );
save( pAtlasPk );
}
QgsWmsParameters::QgsWmsParameters( const QgsServerParameters &parameters )
@ -1134,6 +1138,11 @@ namespace QgsWms
return label;
}
QStringList QgsWmsParameters::atlasPk() const
{
return mWmsParameters[ QgsWmsParameter::ATLAS_PK ].toStringList();
}
QStringList QgsWmsParameters::highlightLabelString() const
{
return mWmsParameters[ QgsWmsParameter::HIGHLIGHT_LABELSTRING ].toStringList( ';' );

View File

@ -168,7 +168,8 @@ namespace QgsWms
GRID_INTERVAL_Y,
WITH_GEOMETRY,
WITH_MAPTIP,
WMTVER
WMTVER,
ATLAS_PK
};
Q_ENUM( Name )
@ -1148,6 +1149,13 @@ namespace QgsWms
*/
QString layoutParameter( const QString &id, bool &ok ) const;
/**
* Returns the ATLAS_PK parameter
* \returns The ATLAS_PK parameter
* \since QGIS 3.6
*/
QStringList atlasPk() const;
private:
bool loadParameter( const QString &name, const QString &value ) override;

View File

@ -76,6 +76,7 @@
#include <QDir>
//for printing
#include "qgslayoutatlas.h"
#include "qgslayoutmanager.h"
#include "qgslayoutexporter.h"
#include "qgslayoutsize.h"
@ -375,7 +376,103 @@ namespace QgsWms
std::unique_ptr<QgsPrintLayout> layout( sourceLayout->clone() );
configurePrintLayout( layout.get(), mapSettings );
//atlas print?
QgsLayoutAtlas *atlas = 0;
QStringList atlasPk = mWmsParameters.atlasPk();
if ( !atlasPk.isEmpty() ) //atlas print requested?
{
atlas = layout->atlas();
if ( !atlas || !atlas->enabled() )
{
//error
throw QgsBadRequestException( QStringLiteral( "NoAtlas" ),
QStringLiteral( "The template has no atlas enabled" ) );
}
QgsVectorLayer *cLayer = atlas->coverageLayer();
if ( !cLayer )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "The atlas has no coverage layer" ) );
}
int maxAtlasFeatures = QgsServerProjectUtils::wmsMaxAtlasFeatures( *mProject );
if ( atlasPk.size() == 1 && atlasPk.at( 0 ) == QStringLiteral( "*" ) )
{
atlas->setFilterFeatures( false );
atlas->updateFeatures();
if ( atlas->count() > maxAtlasFeatures )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QString( "The project configuration allows printing maximum %1 atlas features at a time" ).arg( maxAtlasFeatures ) );
}
}
else
{
QgsAttributeList pkIndexes = cLayer->primaryKeyAttributes();
if ( pkIndexes.size() < 1 )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "An error occurred during the Atlas print" ) );
}
QStringList pkAttributeNames;
for ( int i = 0; i < pkIndexes.size(); ++i )
{
pkAttributeNames.append( cLayer->fields()[pkIndexes.at( i )].name() );
}
int nAtlasFeatures = atlasPk.size() / pkIndexes.size();
if ( nAtlasFeatures * pkIndexes.size() != atlasPk.size() ) //Test is atlasPk.size() is a multiple of pkIndexes.size(). Bail out if not
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "Wrong number of ATLAS_PK parameters" ) );
}
//number of atlas features might be restricted
if ( nAtlasFeatures > maxAtlasFeatures )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QString( "%1 atlas features have been requestet, but the project configuration only allows printing %2 atlas features at a time" )
.arg( nAtlasFeatures ).arg( maxAtlasFeatures ) );
}
QString filterString;
int currentAtlasPk = 0;
for ( int i = 0; i < nAtlasFeatures; ++i )
{
if ( i > 0 )
{
filterString.append( " OR " );
}
filterString.append( "( " );
for ( int j = 0; j < pkIndexes.size(); ++j )
{
if ( j > 0 )
{
filterString.append( " AND " );
}
filterString.append( QString( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ) ).arg( atlasPk.at( currentAtlasPk ) ) );
++currentAtlasPk;
}
filterString.append( " )" );
}
atlas->setFilterFeatures( true );
QString errorString;
atlas->setFilterExpression( filterString, errorString );
if ( !errorString.isEmpty() )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "An error occurred during the Atlas print" ) );
}
}
}
configurePrintLayout( layout.get(), mapSettings, atlas );
// Get the temporary output file
QTemporaryFile tempOutputFile( QDir::tempPath() + '/' + QStringLiteral( "XXXXXX.%1" ).arg( formatString.toLower() ) );
@ -385,6 +482,7 @@ namespace QgsWms
}
QString exportError;
if ( formatString.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
{
// Settings for the layout exporter
@ -398,8 +496,21 @@ namespace QgsWms
}
// Draw selections
exportSettings.flags |= QgsLayoutRenderContext::FlagDrawSelection;
QgsLayoutExporter exporter( layout.get() );
exporter.exportToSvg( tempOutputFile.fileName(), exportSettings );
if ( atlas )
{
//export first page of atlas
atlas->beginRender();
if ( atlas->next() )
{
QgsLayoutExporter atlasSvgExport( atlas->layout() );
atlasSvgExport.exportToSvg( tempOutputFile.fileName(), exportSettings );
}
}
else
{
QgsLayoutExporter exporter( layout.get() );
exporter.exportToSvg( tempOutputFile.fileName(), exportSettings );
}
}
else if ( formatString.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 || formatString.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0 )
{
@ -424,8 +535,21 @@ namespace QgsWms
exportSettings.imageSize = QSize( static_cast<int>( width.length() * dpi / 25.4 ), static_cast<int>( height.length() * dpi / 25.4 ) );
// Export first page only (unless it's a pdf, see below)
exportSettings.pages.append( 0 );
QgsLayoutExporter exporter( layout.get() );
exporter.exportToImage( tempOutputFile.fileName(), exportSettings );
if ( atlas )
{
//only can give back one page in server rendering
atlas->beginRender();
if ( atlas->next() )
{
QgsLayoutExporter atlasPngExport( atlas->layout() );
atlasPngExport.exportToImage( tempOutputFile.fileName(), exportSettings );
}
}
else
{
QgsLayoutExporter exporter( layout.get() );
exporter.exportToImage( tempOutputFile.fileName(), exportSettings );
}
}
else if ( formatString.compare( QLatin1String( "pdf" ), Qt::CaseInsensitive ) == 0 )
{
@ -443,7 +567,14 @@ namespace QgsWms
exportSettings.flags |= QgsLayoutRenderContext::FlagDrawSelection;
// Export all pages
QgsLayoutExporter exporter( layout.get() );
exporter.exportToPdf( tempOutputFile.fileName(), exportSettings );
if ( atlas )
{
exporter.exportToPdf( atlas, tempOutputFile.fileName(), exportSettings, exportError );
}
else
{
exporter.exportToPdf( tempOutputFile.fileName(), exportSettings );
}
}
else //unknown format
{
@ -454,7 +585,7 @@ namespace QgsWms
return tempOutputFile.readAll();
}
bool QgsRenderer::configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings )
bool QgsRenderer::configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint )
{
c->renderContext().setSelectionColor( mapSettings.selectionColor() );
// Maps are configured first
@ -463,42 +594,46 @@ namespace QgsWms
// Layout maps now use a string UUID as "id", let's assume that the first map
// has id 0 and so on ...
int mapId = 0;
for ( const auto &map : qgis::as_const( maps ) )
{
QgsWmsParametersComposerMap cMapParams = mWmsParameters.composerMapParameters( mapId );
mapId++;
//map extent is mandatory
if ( !cMapParams.mHasExtent )
if ( !atlasPrint || !map->atlasDriven() ) //No need to extent, scal, rotation set with atlas feature
{
//remove map from composition if not referenced by the request
c->removeLayoutItem( map );
continue;
}
// Change CRS of map set to "project CRS" to match requested CRS
// (if map has a valid preset crs then we keep this crs and don't use the
// requested crs for this map item)
if ( mapSettings.destinationCrs().isValid() && !map->presetCrs().isValid() )
map->setCrs( mapSettings.destinationCrs() );
//map extent is mandatory
if ( !cMapParams.mHasExtent )
{
//remove map from composition if not referenced by the request
c->removeLayoutItem( map );
continue;
}
// Change CRS of map set to "project CRS" to match requested CRS
// (if map has a valid preset crs then we keep this crs and don't use the
// requested crs for this map item)
if ( mapSettings.destinationCrs().isValid() && !map->presetCrs().isValid() )
map->setCrs( mapSettings.destinationCrs() );
QgsRectangle r( cMapParams.mExtent );
if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) &&
mapSettings.destinationCrs().hasAxisInverted() )
{
r.invert();
}
map->setExtent( r );
QgsRectangle r( cMapParams.mExtent );
if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) &&
mapSettings.destinationCrs().hasAxisInverted() )
{
r.invert();
}
map->setExtent( r );
// scale
if ( cMapParams.mScale > 0 )
{
map->setScale( cMapParams.mScale );
}
// scale
if ( cMapParams.mScale > 0 )
{
map->setScale( cMapParams.mScale );
}
// rotation
if ( cMapParams.mRotation )
{
map->setMapRotation( cMapParams.mRotation );
// rotation
if ( cMapParams.mRotation )
{
map->setMapRotation( cMapParams.mRotation );
}
}
if ( !map->keepLayerSet() )

View File

@ -282,8 +282,14 @@ namespace QgsWms
//! Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)
QgsRectangle featureInfoSearchRect( QgsVectorLayer *ml, const QgsMapSettings &ms, const QgsRenderContext &rct, const QgsPointXY &infoPoint ) const;
//! configure the print layout for the GetPrint request
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings );
/*
* Configures the print layout for the GetPrint request
*\param c the print layout
*\param mapSettings the map settings
*\param atlasPrint true if atlas is used for printing
*\returns true in case of success
* */
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint = false );
//! Creates external WMS layer. Caller takes ownership
QgsMapLayer *createExternalWMSLayer( const QString &externalLayerId ) const;

View File

@ -294,7 +294,7 @@
</sizepolicy>
</property>
<property name="text">
<string>Project home</string>
<string>&amp;Project home</string>
</property>
<property name="buddy">
<cstring>titleEdit</cstring>
@ -310,7 +310,7 @@
</sizepolicy>
</property>
<property name="text">
<string>Save paths</string>
<string>Sa&amp;ve paths</string>
</property>
<property name="buddy">
<cstring>cbxAbsolutePath</cstring>
@ -394,7 +394,7 @@
</sizepolicy>
</property>
<property name="text">
<string>Project file</string>
<string>Pro&amp;ject file</string>
</property>
<property name="buddy">
<cstring>titleEdit</cstring>
@ -454,7 +454,7 @@
</sizepolicy>
</property>
<property name="text">
<string>Background color</string>
<string>Back&amp;ground color</string>
</property>
<property name="buddy">
<cstring>pbnCanvasColor</cstring>
@ -645,7 +645,7 @@
<string>Automatically sets the number of decimal places to use when displaying coordinates</string>
</property>
<property name="text">
<string>Automatic</string>
<string>A&amp;utomatic</string>
</property>
<property name="checked">
<bool>true</bool>
@ -1528,7 +1528,7 @@
<item>
<widget class="QGroupBox" name="grpPythonMacros">
<property name="title">
<string>Python Macros</string>
<string>&amp;Python Macros</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -1638,7 +1638,7 @@
<item row="4" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Person</string>
<string>&amp;Person</string>
</property>
<property name="buddy">
<cstring>mWMSContactPerson</cstring>
@ -1755,7 +1755,7 @@
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Organization</string>
<string>Or&amp;ganization</string>
</property>
<property name="buddy">
<cstring>mWMSContactOrganization</cstring>
@ -1845,10 +1845,10 @@
<string notr="true">projowsserver</string>
</property>
<layout class="QGridLayout" name="gridLayout_13">
<item row="1" column="0">
<item row="0" column="0">
<widget class="QgsCollapsibleGroupBox" name="grpWMSExt">
<property name="title">
<string>Advertised extent</string>
<string>Ad&amp;vertised extent</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -1866,7 +1866,7 @@
<item row="0" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Min. X</string>
<string>Min. &amp;X</string>
</property>
<property name="buddy">
<cstring>mWMSExtMinX</cstring>
@ -1883,7 +1883,7 @@
<item row="1" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Min. Y</string>
<string>Min. &amp;Y</string>
</property>
<property name="buddy">
<cstring>mWMSExtMinY</cstring>
@ -1954,10 +1954,66 @@
</layout>
</widget>
</item>
<item row="2" column="0">
<item row="0" column="1">
<widget class="QgsCollapsibleGroupBox" name="grpWMSList">
<property name="title">
<string>CRS restrictions</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="1" column="0">
<widget class="QToolButton" name="pbnWMSAddSRS">
<property name="toolTip">
<string>Add new CRS</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QListWidget" name="mWMSList"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pbnWMSSetUsedSRS">
<property name="toolTip">
<string>Fetch all CRS's from layers</string>
</property>
<property name="text">
<string>Used</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="pbnWMSRemoveSRS">
<property name="toolTip">
<string>Remove selected CRS</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QgsCollapsibleGroupBox" name="mWMSPrintLayoutGroupBox">
<property name="title">
<string>Exclude layouts</string>
<string>Excl&amp;ude layouts</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2019,7 +2075,7 @@
</layout>
</widget>
</item>
<item row="2" column="1">
<item row="1" column="1">
<widget class="QgsCollapsibleGroupBox" name="mLayerRestrictionsGroupBox">
<property name="title">
<string>Exclude layers</string>
@ -2084,189 +2140,7 @@
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsCollapsibleGroupBox" name="grpWMSList">
<property name="title">
<string>CRS restrictions</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="1" column="0">
<widget class="QToolButton" name="pbnWMSAddSRS">
<property name="toolTip">
<string>Add new CRS</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QListWidget" name="mWMSList"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pbnWMSSetUsedSRS">
<property name="toolTip">
<string>Fetch all CRS's from layers</string>
</property>
<property name="text">
<string>Used</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="pbnWMSRemoveSRS">
<property name="toolTip">
<string>Remove selected CRS</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="mWmsUseLayerIDs">
<property name="text">
<string>Use layer ids as names</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="mWMSImageQualityLabel">
<property name="text">
<string>Quality for JPEG images ( 10 : smaller image - 100 : best quality )</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mWMSImageQualitySpinBox">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>90</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="mAddWktGeometryCheckBox">
<property name="text">
<string>Add geometry to feature response</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QLabel" name="mMaxWidthLabel">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>6</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="4">
<widget class="QLineEdit" name="mMaxHeightLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="mMaxWidthLineEdit"/>
</item>
<item row="1" column="3">
<widget class="QLabel" name="mMaxHeightLabel">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="5">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Maximums for GetMap request</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="9" column="0" colspan="2">
<layout class="QHBoxLayout" name="grpWMSPrecision">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>GetFeatureInfo geometry precision (decimal places)</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mWMSPrecisionSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>17</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="mWMSUrlLabel">
<property name="text">
<string>Advertised URL</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mWMSUrlLineEdit"/>
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<item row="2" column="0" colspan="2">
<widget class="QgsCollapsibleGroupBox" name="mWMSInspire">
<property name="title">
<string>INSPIRE (European directive)</string>
@ -2298,7 +2172,7 @@
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="mWMSInspireScenario2">
<property name="title">
<string>Scenario 2 - INSPIRE related fields using embedded service metadata</string>
<string>Scenario &amp;2 - INSPIRE related fields using embedded service metadata</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2347,7 +2221,7 @@
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="mWMSInspireScenario1">
<property name="title">
<string>Scenario 1 - INSPIRE related fields using referenced external service metadata</string>
<string>Scenario &amp;1 - INSPIRE related fields using referenced external service metadata</string>
</property>
<property name="checkable">
<bool>true</bool>
@ -2398,19 +2272,166 @@
</layout>
</widget>
</item>
<item row="8" column="0">
<item row="3" column="0">
<widget class="QCheckBox" name="mWmsUseLayerIDs">
<property name="text">
<string>Use layer ids as names</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="mAddWktGeometryCheckBox">
<property name="text">
<string>Add geometry to feature response</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="mAllowRequestDefinedDataSourcesBox">
<property name="text">
<string>Allow defining datasources in server requests</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="mSegmentizeFeatureInfoGeometryCheckBox">
<property name="text">
<string>Segmentize feature info geometry</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="mAllowRequestDefinedDataSourcesBox">
<property name="text">
<string>Allow defining datasources in server requests</string>
</property>
</widget>
<item row="7" column="0" colspan="2">
<layout class="QHBoxLayout" name="grpWMSPrecision">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>GetFeatureInfo geometry precision (decimal places)</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mWMSPrecisionSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>17</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="8" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="mWMSUrlLabel">
<property name="text">
<string>Advertised URL</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mWMSUrlLineEdit"/>
</item>
</layout>
</item>
<item row="9" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QLabel" name="mMaxWidthLabel">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>6</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="4">
<widget class="QLineEdit" name="mMaxHeightLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="mMaxWidthLineEdit"/>
</item>
<item row="1" column="3">
<widget class="QLabel" name="mMaxHeightLabel">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="5">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Maximums for GetMap request</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="mWMSImageQualityLabel">
<property name="text">
<string>Quality for JPEG images ( 10 : smaller image - 100 : best quality )</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mWMSImageQualitySpinBox">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>90</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="11" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QLabel" name="mWMSMaxAtlasFeaturesLabel">
<property name="text">
<string>Maximum features for Atlas print requests</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mWMSMaxAtlasFeaturesSpinBox">
<property name="maximum">
<number>9999999</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -412,6 +412,32 @@ class TestQgsServerWMSGetPrint(QgsServerTestBase):
r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_TwoMaps")
def test_wms_getprint_atlas(self):
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.3.0",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"FORMAT": "png",
"CRS": "EPSG:3857",
"ATLAS_PK": "3",
"map0:LAYERS": "Country,Hello",
}.items())])
r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_Atlas")
def test_wms_getprint_atlas_getProjectSettings(self):
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.3.0",
"REQUEST": "GetProjectSettings",
}.items())])
r, h = self._result(self._execute_request(qs))
self.assertTrue('atlasEnabled="1"' in str(r))
self.assertTrue('<PrimaryKeyAttribute>' in str(r))
if __name__ == '__main__':
unittest.main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

View File

@ -3438,6 +3438,7 @@ def my_form_open(dialog, layer, feature):
<Annotations/>
<Layouts>
<Layout worldFileMap="" name="layoutA4" units="mm" printResolution="300">
<Atlas enabled="1" coverageLayer="country20131022151106556" pageNameExpression="" sortFeatures="0" filterFeatures="0" coverageLayerProvider="spatialite" filenamePattern="'output_'||@atlas_featurenumber" coverageLayerSource="dbname='./helloworld.db' table=&quot;country&quot; (geom) sql=" coverageLayerName="Country" hideCoverage="0"/>
<Snapper tolerance="5" snapToGuides="1" snapToGrid="0" snapToItems="1"/>
<Grid offsetX="0" offsetUnits="mm" resolution="10" resUnits="mm" offsetY="0"/>
<PageCollection>
@ -3582,7 +3583,7 @@ def my_form_open(dialog, layer, feature):
</markerStyle>
<annotationFontProperties description=",11,-1,5,50,0,0,0,0,0" style=""/>
</ComposerMapGrid>
<AtlasMap atlasDriven="0" margin="0.10000000000000001" scalingMode="2"/>
<AtlasMap atlasDriven="1" margin="0.10000000000000001" scalingMode="2"/>
</LayoutItem>
<LayoutItem size="64.3016,11.0626,mm" frame="false" frameJoinStyle="miter" position="213.302,161.791,mm" itemRotation="0" referencePoint="0" opacity="1" positionLock="false" outlineWidthM="0.3,mm" marginX="1" halign="1" marginY="1" id="" uuid="{b3f8da1e-352d-4ea6-b8c1-c2464bfdd050}" blendMode="0" visibility="1" labelText="Welcome to our world...." positionOnPage="213.302,161.791,mm" groupUuid="" zValue="2" excludeFromExports="0" type="65641" valign="32" background="false" templateUuid="{b3f8da1e-352d-4ea6-b8c1-c2464bfdd050}" htmlState="0">
<FrameColor alpha="255" red="0" blue="0" green="0"/>