mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Merge pull request #8781 from mhugent/get_atlas_print
[server][needs-docs] Get atlas print
This commit is contained in:
commit
54a5fae0b7
@ -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 );
|
||||
|
@ -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;
|
||||
|
@ -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( "/" ), "" );
|
||||
|
@ -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
|
||||
|
@ -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() ) );
|
||||
|
||||
|
@ -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 ¶meters )
|
||||
@ -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( ';' );
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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() )
|
||||
|
@ -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;
|
||||
|
@ -294,7 +294,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Project home</string>
|
||||
<string>&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&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&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&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&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>&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>&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&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&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. &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. &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&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 &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 &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>
|
||||
|
@ -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()
|
||||
|
BIN
tests/testdata/control_images/qgis_server/WMS_GetPrint_Atlas/WMS_GetPrint_Atlas.png
vendored
Normal file
BIN
tests/testdata/control_images/qgis_server/WMS_GetPrint_Atlas/WMS_GetPrint_Atlas.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 200 KiB |
@ -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="country" (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"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user