Skip to content

Commit

Permalink
Re-add wms based printing
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Apr 1, 2014
1 parent e7d0433 commit db87e4d
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/mapserver/CMakeLists.txt
Expand Up @@ -42,6 +42,7 @@ SET ( qgis_mapserv_SRCS
qgsmsutils.cpp
qgswcsprojectparser.cpp
qgswfsprojectparser.cpp
qgswmsconfigparser.cpp
qgswmsprojectparser.cpp
qgsserverprojectparser.cpp
qgssldconfigparser.cpp
Expand Down
4 changes: 2 additions & 2 deletions src/mapserver/qgssldconfigparser.cpp
Expand Up @@ -54,8 +54,8 @@
#define TO8(x) (x).toLocal8Bit().constData()
#endif

QgsSLDConfigParser::QgsSLDConfigParser( QDomDocument* doc, const QMap<QString, QString>& parameters ): mXMLDoc( doc ),
mParameterMap( parameters ), mFallbackParser( 0 )
QgsSLDConfigParser::QgsSLDConfigParser( QDomDocument* doc, const QMap<QString, QString>& parameters ):
QgsWMSConfigParser(), mXMLDoc( doc ), mParameterMap( parameters ), mFallbackParser( 0 )
{
mSLDNamespace = "http://www.opengis.net/sld";

Expand Down
212 changes: 212 additions & 0 deletions src/mapserver/qgswmsconfigparser.cpp
@@ -0,0 +1,212 @@
/***************************************************************************
qgswmsconfigparser.cpp
----------------------
begin : March 25, 2014
copyright : (C) 2014 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgswmsconfigparser.h"
#include "qgsmaplayer.h"

#include "qgscomposerlabel.h"
#include "qgscomposermap.h"
#include "qgscomposerhtml.h"
#include "qgscomposerframe.h"
#include "qgscomposition.h"

QgsWMSConfigParser::QgsWMSConfigParser()
{

}

QgsWMSConfigParser::~QgsWMSConfigParser()
{

}

QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const
{
QList<QgsComposerMap*> composerMaps;
QList<QgsComposerLabel*> composerLabels;
QList<const QgsComposerHtml*> composerHtmls;

QgsComposition* c = initComposition( composerTemplate, mapRenderer, composerMaps, composerLabels, composerHtmls );
if ( !c )
{
return 0;
}

QString dpi = parameterMap.value( "DPI" );
if ( !dpi.isEmpty() )
{
c->setPrintResolution( dpi.toInt() );
}

//replace composer map parameters
foreach ( QgsComposerMap* currentMap, composerMaps )
{
if ( !currentMap )
{
continue;
}

QString mapId = "MAP" + QString::number( currentMap->id() );

QString extent = parameterMap.value( mapId + ":EXTENT" );
if ( extent.isEmpty() ) //map extent is mandatory
{
//remove map from composition if not referenced by the request
c->removeItem( currentMap ); delete currentMap; continue;
}

QStringList coordList = extent.split( "," );
if ( coordList.size() < 4 )
{
c->removeItem( currentMap ); delete currentMap; continue; //need at least four coordinates
}

bool xMinOk, yMinOk, xMaxOk, yMaxOk;
double xmin = coordList.at( 0 ).toDouble( &xMinOk );
double ymin = coordList.at( 1 ).toDouble( &yMinOk );
double xmax = coordList.at( 2 ).toDouble( &xMaxOk );
double ymax = coordList.at( 3 ).toDouble( &yMaxOk );
if ( !xMinOk || !yMinOk || !xMaxOk || !yMaxOk )
{
c->removeItem( currentMap ); delete currentMap; continue;
}

QgsRectangle r( xmin, ymin, xmax, ymax );

//Change x- and y- of extent for WMS 1.3.0 if axis inverted
QString version = parameterMap.value( "VERSION" );
if ( version == "1.3.0" && mapRenderer && mapRenderer->destinationCrs().axisInverted() )
{
r.invert();
}
currentMap->setNewExtent( r );

//scale
QString scaleString = parameterMap.value( mapId + ":SCALE" );
if ( !scaleString.isEmpty() )
{
bool scaleOk;
double scale = scaleString.toDouble( &scaleOk );
if ( scaleOk )
{
currentMap->setNewScale( scale );
}
}

//rotation
QString rotationString = parameterMap.value( mapId + ":ROTATION" );
if ( !rotationString.isEmpty() )
{
bool rotationOk;
double rotation = rotationString.toDouble( &rotationOk );
if ( rotationOk )
{
currentMap->setMapRotation( rotation );
}
}

//layers / styles
QString layers = parameterMap.value( mapId + ":LAYERS" );
QString styles = parameterMap.value( mapId + ":STYLES" );
if ( !layers.isEmpty() )
{
QStringList layerSet;
QStringList wmsLayerList = layers.split( "," );
QStringList wmsStyleList;

if ( !styles.isEmpty() )
{
wmsStyleList = styles.split( "," );
}

for ( int i = 0; i < wmsLayerList.size(); ++i )
{
QString styleName;
if ( wmsStyleList.size() > i )
{
styleName = wmsStyleList.at( i );
}

foreach ( QgsMapLayer *layer, mapLayerFromStyle( wmsLayerList.at( i ), styleName ) )
{
if ( layer )
{
layerSet.push_back( layer->id() );
}
}
}

currentMap->setLayerSet( layerSet );
currentMap->setKeepLayerSet( true );
}

//grid space x / y
currentMap->setGridIntervalX( parameterMap.value( mapId + ":GRID_INTERVAL_X" ).toDouble() );
currentMap->setGridIntervalY( parameterMap.value( mapId + ":GRID_INTERVAL_Y" ).toDouble() );
}

//replace label text
foreach ( QgsComposerLabel *currentLabel, composerLabels )
{
QString title = parameterMap.value( currentLabel->id().toUpper() );

if ( title.isEmpty() )
{
//remove exported labels referenced in the request
//but with empty string
if ( parameterMap.contains( currentLabel->id().toUpper() ) )
{
c->removeItem( currentLabel );
delete currentLabel;
}
continue;
}

currentLabel->setText( title );
}

//replace html url
foreach ( const QgsComposerHtml *currentHtml, composerHtmls )
{
QgsComposerHtml * html = const_cast<QgsComposerHtml *>( currentHtml );
QgsComposerFrame *htmlFrame = html->frame( 0 );
QString htmlId = htmlFrame->id();
QString url = parameterMap.value( htmlId.toUpper() );

if ( url.isEmpty() )
{
//remove exported Htmls referenced in the request
//but with empty string
if ( parameterMap.contains( htmlId.toUpper() ) )
{
c->removeMultiFrame( html );
delete currentHtml;
}
else
{
html->update();
}
continue;
}

QUrl newUrl( url );
html->setUrl( newUrl );
html->update();
}

return c;
}
5 changes: 4 additions & 1 deletion src/mapserver/qgswmsconfigparser.h
Expand Up @@ -24,6 +24,9 @@ class QgsWMSConfigParser
{
public:

QgsWMSConfigParser();
virtual ~QgsWMSConfigParser();

/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.
@param fullProjectInformation If true: add extended project information (does not validate against WMS schema)*/
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const = 0;
Expand Down Expand Up @@ -90,7 +93,7 @@ class QgsWMSConfigParser
//printing

/**Creates a print composition, usually for a GetPrint request. Replaces map and label parameters*/
virtual QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const = 0;
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const;

/**Creates a composition from the project file (probably delegated to the fallback parser)*/
virtual QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const = 0;
Expand Down
99 changes: 92 additions & 7 deletions src/mapserver/qgswmsprojectparser.cpp
Expand Up @@ -22,9 +22,20 @@
#include "qgsmapserviceexception.h"
#include "qgsvectorlayer.h"

#include "qgscomposition.h"
#include "qgscomposerarrow.h"
#include "qgscomposerattributetable.h"
#include "qgscomposerlabel.h"
#include "qgscomposerlegend.h"
#include "qgscomposermap.h"
#include "qgscomposerhtml.h"
#include "qgscomposerpicture.h"
#include "qgscomposerscalebar.h"
#include "qgscomposershape.h"

#include <QFileInfo>

QgsWMSProjectParser::QgsWMSProjectParser( QDomDocument* xmlDoc, const QString& filePath ):
QgsWMSProjectParser::QgsWMSProjectParser( QDomDocument* xmlDoc, const QString& filePath ): QgsWMSConfigParser(),
mProjectParser( xmlDoc, filePath )
{
mLegendLayerFont.fromString( mProjectParser.firstComposerLegendElement().attribute( "layerFont" ) );
Expand Down Expand Up @@ -293,14 +304,66 @@ double QgsWMSProjectParser::maxHeight() const
return maxHeight;
}

QgsComposition* QgsWMSProjectParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const
QgsComposition* QgsWMSProjectParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlList ) const
{
return 0; //todo: fixme
}
//Create composition from xml
QDomElement composerElem = composerByName( composerTemplate );
if ( composerElem.isNull() )
{
throw QgsMapServiceException( "Error", "Composer template not found" );
}

QgsComposition* QgsWMSProjectParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const
{
return 0; //todo: fixme
QDomElement compositionElem = composerElem.firstChildElement( "Composition" );
if ( compositionElem.isNull() )
{
return 0;
}

QgsComposition* composition = new QgsComposition( mapRenderer->mapSettings() ); //set resolution, paper size from composer element attributes
if ( !composition->readXML( compositionElem, *( mProjectParser.xmlDocument() ) ) )
{
delete composition;
return 0;
}

composition->addItemsFromXML( compositionElem, *( mProjectParser.xmlDocument() ) );

labelList.clear();
mapList.clear();
htmlList.clear();

QList<QgsComposerItem* > itemList;
composition->composerItems( itemList );
QList<QgsComposerItem *>::iterator itemIt = itemList.begin();
for ( ; itemIt != itemList.end(); ++itemIt )
{
QgsComposerLabel* label = dynamic_cast< QgsComposerLabel *>( *itemIt );
if ( label )
{
labelList.push_back( label );
continue;
}
QgsComposerMap* map = dynamic_cast< QgsComposerMap *>( *itemIt );
if ( map )
{
mapList.push_back( map );
continue;
}
QgsComposerPicture* pic = dynamic_cast< QgsComposerPicture *>( *itemIt );
if ( pic )
{
pic->setPictureFile( mProjectParser.convertToAbsolutePath(( pic )->pictureFile() ) );
continue;
}
const QgsComposerHtml* html = composition->getComposerHtmlByItem( *itemIt );
if ( html )
{
htmlList.push_back( html );
continue;
}
}

return composition;
}

void QgsWMSProjectParser::printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const
Expand Down Expand Up @@ -1584,3 +1647,25 @@ void QgsWMSProjectParser::drawOverlays( QPainter* p, int dpi, int width, int hei
}
#endif //0
}

QDomElement QgsWMSProjectParser::composerByName( const QString& composerName ) const
{
QDomElement composerElem;
if ( !mProjectParser.xmlDocument() )
{
return composerElem;
}

QList<QDomElement> composerElemList = mProjectParser.publishedComposerElements();
QList<QDomElement>::const_iterator composerIt = composerElemList.constBegin();
for ( ; composerIt != composerElemList.constEnd(); ++composerIt )
{
QDomElement currentComposerElem = *composerIt;
if ( currentComposerElem.attribute( "title" ) == composerName )
{
return currentComposerElem;
}
}

return composerElem;
}
4 changes: 2 additions & 2 deletions src/mapserver/qgswmsprojectparser.h
Expand Up @@ -54,8 +54,6 @@ class QgsWMSProjectParser: public QgsWMSConfigParser
double maxHeight() const;

//printing
QgsComposition* createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const;

QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* >& labelList, QList<const QgsComposerHtml *>& htmlFrameList ) const;

void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
Expand Down Expand Up @@ -126,6 +124,8 @@ class QgsWMSProjectParser: public QgsWMSConfigParser
void addOWSLayers( QDomDocument &doc, QDomElement &parentElem, const QDomElement &legendElem,
const QMap<QString, QgsMapLayer *> &layerMap, const QStringList &nonIdentifiableLayers,
const QString& strHref, QgsRectangle& combinedBBox, QString strGroup ) const;

QDomElement composerByName( const QString& composerName ) const;
};

#endif // QGSWMSPROJECTPARSER_H

0 comments on commit db87e4d

Please sign in to comment.