[QGIS Commit] r14973 - trunk/qgis/src/mapserver
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Fri Dec 24 09:11:13 EST 2010
Author: mhugent
Date: 2010-12-24 06:11:13 -0800 (Fri, 24 Dec 2010)
New Revision: 14973
Modified:
trunk/qgis/src/mapserver/qgis_map_serv.cpp
trunk/qgis/src/mapserver/qgsconfigparser.cpp
trunk/qgis/src/mapserver/qgsconfigparser.h
trunk/qgis/src/mapserver/qgsgetrequesthandler.cpp
trunk/qgis/src/mapserver/qgsgetrequesthandler.h
trunk/qgis/src/mapserver/qgsmslayercache.cpp
trunk/qgis/src/mapserver/qgsprojectparser.cpp
trunk/qgis/src/mapserver/qgsprojectparser.h
trunk/qgis/src/mapserver/qgsrequesthandler.h
trunk/qgis/src/mapserver/qgssldparser.cpp
trunk/qgis/src/mapserver/qgssldparser.h
trunk/qgis/src/mapserver/qgssoaprequesthandler.cpp
trunk/qgis/src/mapserver/qgssoaprequesthandler.h
trunk/qgis/src/mapserver/qgswmsserver.cpp
trunk/qgis/src/mapserver/qgswmsserver.h
Log:
[FEATURE]: initial support for wms printing with GetPrint-Request
Modified: trunk/qgis/src/mapserver/qgis_map_serv.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgis_map_serv.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgis_map_serv.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -382,6 +382,28 @@
continue;
}
+ else if ( requestIt->second == "GetPrint" )
+ {
+ QByteArray* printOutput = 0;
+ QString formatString;
+ try
+ {
+ printOutput = theServer->getPrint( formatString );
+ }
+ catch ( QgsMapServiceException& ex )
+ {
+ theRequestHandler->sendServiceException( ex );
+ }
+
+ if ( printOutput )
+ {
+ theRequestHandler->sendGetPrintResponse( printOutput, formatString );
+ }
+ delete printOutput;
+ delete theRequestHandler;
+ delete theServer;
+ continue;
+ }
else//unknown request
{
QgsMapServiceException e( "OperationNotSupported", "Operation " + requestIt->second + " not supported" );
Modified: trunk/qgis/src/mapserver/qgsconfigparser.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgsconfigparser.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsconfigparser.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -17,6 +17,8 @@
#include "qgsconfigparser.h"
#include "qgsapplication.h"
+#include "qgscomposermap.h"
+#include "qgscomposition.h"
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
#include <sqlite3.h>
@@ -269,3 +271,108 @@
layerElement.appendChild( crsElement );
}
}
+
+QgsComposition* QgsConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const
+{
+ QList<QgsComposerMap*> composerMaps;
+ QList<QgsComposerLabel*> composerLabels;
+
+ QgsComposition* c = initComposition( composerTemplate, mapRenderer, composerMaps, composerLabels );
+ if ( !c )
+ {
+ return 0;
+ }
+
+ QMap< QString, QString >::const_iterator dpiIt = parameterMap.find( "DPI" );
+ if ( dpiIt != parameterMap.constEnd() )
+ {
+ c->setPrintResolution( dpiIt.value().toInt() );
+ }
+
+ //replace composer map parameters
+ QList<QgsComposerMap*>::iterator mapIt = composerMaps.begin();
+ QgsComposerMap* currentMap = 0;
+ for ( ; mapIt != composerMaps.end(); ++mapIt )
+ {
+ currentMap = *mapIt;
+ if ( !currentMap )
+ {
+ continue;
+ }
+
+ //search composer map title in parameter map-> string
+ QMap< QString, QString >::const_iterator titleIt = parameterMap.find( "MAP" + QString::number( currentMap->id() ) );
+ if ( titleIt == parameterMap.constEnd() )
+ {
+ continue;
+ }
+ QString replaceString = titleIt.value();
+ QStringList replacementList = replaceString.split( "/" );
+
+ //get map extent from string
+ if ( replacementList.size() > 0 )
+ {
+ QStringList coordList = replacementList.at( 0 ).split( "," );
+ if ( coordList.size() > 3 )
+ {
+ 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 )
+ {
+ currentMap->setNewExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
+ }
+ }
+ }
+
+ //get rotation from string
+ if ( replacementList.size() > 1 )
+ {
+ bool rotationOk;
+ double rotation = replacementList.at( 1 ).toDouble( &rotationOk );
+ if ( rotationOk )
+ {
+ currentMap->setMapRotation( rotation );
+ }
+ }
+
+ //get layer list from string
+ if ( replacementList.size() > 2 )
+ {
+ QStringList layerSet;
+ QStringList wmsLayerList = replacementList.at( 2 ).split( "," );
+ QStringList wmsStyleList;
+ if ( replacementList.size() > 3 )
+ {
+ wmsStyleList = replacementList.at( 3 ).split( "," );
+ }
+
+ for ( int i = 0; i < wmsLayerList.size(); ++i )
+ {
+ QString styleName;
+ if ( wmsStyleList.size() > i )
+ {
+ styleName = wmsStyleList.at( i );
+ }
+ QList<QgsMapLayer*> layerList = mapLayerFromStyle( wmsLayerList.at( i ), styleName );
+ QList<QgsMapLayer*>::const_iterator mapIdIt = layerList.constBegin();
+ for ( ; mapIdIt != layerList.constEnd(); ++mapIdIt )
+ {
+ if ( *mapIdIt )
+ {
+ layerSet.push_back(( *mapIdIt )->getLayerID() );
+ }
+ }
+ }
+
+ currentMap->setLayerSet( layerSet );
+ currentMap->setKeepLayerSet( true );
+ }
+ }
+
+ //replace composer label text
+
+ return c; //soon...
+}
Modified: trunk/qgis/src/mapserver/qgsconfigparser.h
===================================================================
--- trunk/qgis/src/mapserver/qgsconfigparser.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsconfigparser.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -24,6 +24,9 @@
#include <QList>
#include <QSet>
+class QgsComposition;
+class QgsComposerLabel;
+class QgsComposerMap;
class QDomElement;
/**Interface class for configuration parsing, e.g. SLD configuration or QGIS project file*/
@@ -56,6 +59,7 @@
/**Sets fallback parser (does not take ownership)*/
void setFallbackParser( QgsConfigParser* p );
+ const QgsConfigParser* fallbackParser() { return mFallbackParser; }
void setScaleDenominator( double denom ) {mScaleDenominator = denom;}
@@ -88,6 +92,15 @@
/**Returns information about vector attributes with hidden edit type. Key is layer id, value is a set containing the names of the hidden attributes*/
virtual QMap< QString, QSet<QString> > hiddenAttributes() const { return QMap< QString, QSet<QString> >(); }
+ /**Creates a print composition, usually for a GetPrint request. Replaces map and label parameters*/
+ 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 ) const = 0;
+
+ /**Adds print capabilities to xml document. ParentElem usually is the <Capabilities> element*/
+ virtual void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0;
+
protected:
/**Parser to forward not resolved requests (e.g. SLD parser based on user request might have a fallback parser with admin configuration)*/
QgsConfigParser* mFallbackParser;
Modified: trunk/qgis/src/mapserver/qgsgetrequesthandler.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgsgetrequesthandler.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsgetrequesthandler.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -107,10 +107,6 @@
{
formatString = "PNG";
}
- else
- {
- throw QgsMapServiceException( "InvalidFormat", "Invalid format, only jpg and png are supported" );
- }
mFormat = formatString;
}
}
@@ -301,3 +297,8 @@
QByteArray ba = exceptionDoc.toByteArray();
sendHttpResponse( &ba, "text/xml" );
}
+
+void QgsGetRequestHandler::sendGetPrintResponse( QByteArray* ba, const QString& formatString ) const
+{
+ sendHttpResponse( ba, formatString );
+}
Modified: trunk/qgis/src/mapserver/qgsgetrequesthandler.h
===================================================================
--- trunk/qgis/src/mapserver/qgsgetrequesthandler.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsgetrequesthandler.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -29,4 +29,5 @@
void sendGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) const;
void sendServiceException( const QgsMapServiceException& ex ) const;
void sendGetStyleResponse( const QDomDocument& doc ) const;
+ void sendGetPrintResponse( QByteArray* ba, const QString& formatString ) const;
};
Modified: trunk/qgis/src/mapserver/qgsmslayercache.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgsmslayercache.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsmslayercache.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -79,6 +79,7 @@
QMap<QPair<QString, QString>, QgsMSLayerCacheEntry>::iterator it = mEntries.find( urlNamePair );
if ( it == mEntries.end() )
{
+ QgsMSDebugMsg( "Layer not found in cache" )
return 0;
}
else
@@ -92,6 +93,7 @@
vl->removeOverlay( "diagram" );
}
#endif //DIAGRAMSERVER
+ QgsMSDebugMsg( "Layer found in cache" )
return it->layerPointer;
}
}
Modified: trunk/qgis/src/mapserver/qgsprojectparser.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgsprojectparser.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsprojectparser.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -22,6 +22,16 @@
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
+#include "qgscomposition.h"
+#include "qgscomposerarrow.h"
+#include "qgscomposerattributetable.h"
+#include "qgscomposerlabel.h"
+#include "qgscomposerlegend.h"
+#include "qgscomposermap.h"
+#include "qgscomposerpicture.h"
+#include "qgscomposerscalebar.h"
+#include "qgscomposershape.h"
+
QgsProjectParser::QgsProjectParser( QDomDocument* xmlDoc ): QgsConfigParser(), mXMLDoc( xmlDoc )
{
mOutputUnits = QgsMapRenderer::Millimeters;
@@ -814,3 +824,161 @@
return legendLayerFileList.at( 0 ).toElement().attribute( "layerid" );
}
+QgsComposition* QgsProjectParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* > labelList ) const
+{
+ //Create composition from xml
+ QDomElement composerElem = composerByName( composerTemplate );
+ if ( composerElem.isNull() )
+ {
+ return 0;
+ }
+
+ QDomElement compositionElem = composerElem.firstChildElement( "Composition" );
+ if ( compositionElem.isNull() )
+ {
+ return 0;
+ }
+
+ QgsComposition* composition = new QgsComposition( mapRenderer ); //set resolution, paper size from composer element attributes
+ if ( !composition->readXML( compositionElem, *mXMLDoc ) )
+ {
+ delete composition;
+ return 0;
+ }
+
+ QList<QDomElement> scaleBarElemList;
+
+ //go through all the item elements and add them to the composition (and to the lists)
+ QDomNodeList itemNodes = composerElem.childNodes();
+ for ( int i = 0; i < itemNodes.size(); ++i )
+ {
+ QDomElement currentElem = itemNodes.at( i ).toElement();
+ QString elemName = currentElem.tagName();
+ if ( elemName == "ComposerMap" )
+ {
+ QgsComposerMap* map = new QgsComposerMap( composition );
+ map->readXML( currentElem, *mXMLDoc );
+ composition->addItem( map );
+ mapList.push_back( map );
+ }
+ else if ( elemName == "ComposerLabel" )
+ {
+ QgsComposerLabel* label = new QgsComposerLabel( composition );
+ label->readXML( currentElem, *mXMLDoc );
+ composition->addItem( label );
+ labelList.push_back( label );
+ }
+ else if ( elemName == "ComposerLegend" )
+ {
+ QgsComposerLegend* legend = new QgsComposerLegend( composition );
+ legend->readXML( currentElem, *mXMLDoc );
+ composition->addItem( legend );
+ }
+ else if ( elemName == "ComposerPicture" )
+ {
+ QgsComposerPicture* picture = new QgsComposerPicture( composition );
+ picture->readXML( currentElem, *mXMLDoc );
+ composition->addItem( picture );
+ }
+ else if ( elemName == "ComposerScaleBar" )
+ {
+ //scalebars need to be loaded after the composer maps
+ scaleBarElemList.push_back( currentElem );
+ }
+ else if ( elemName == "ComposerShape" )
+ {
+ QgsComposerShape* shape = new QgsComposerShape( composition );
+ shape->readXML( currentElem, *mXMLDoc );
+ composition->addItem( shape );
+ }
+ else if ( elemName == "ComposerArrow" )
+ {
+ QgsComposerArrow* arrow = new QgsComposerArrow( composition );
+ arrow->readXML( currentElem, *mXMLDoc );
+ composition->addItem( arrow );
+ }
+ else if ( elemName == "ComposerAttributeTable" )
+ {
+ QgsComposerAttributeTable* table = new QgsComposerAttributeTable( composition );
+ table->readXML( currentElem, *mXMLDoc );
+ composition->addItem( table );
+ }
+ }
+
+ //scalebars need to be loaded after the composer maps to receive the correct size
+ QList<QDomElement>::const_iterator scaleBarIt = scaleBarElemList.constBegin();
+ for ( ; scaleBarIt != scaleBarElemList.constEnd(); ++scaleBarIt )
+ {
+ QgsComposerScaleBar* bar = new QgsComposerScaleBar( composition );
+ bar->readXML( *scaleBarIt, *mXMLDoc );
+ composition->addItem( bar );
+ }
+
+ return composition;
+}
+
+void QgsProjectParser::printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const
+{
+ if ( !mXMLDoc )
+ {
+ return;
+ }
+
+ QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );
+ for ( int i = 0; i < composerNodeList.size(); ++i )
+ {
+ QDomElement composerTemplateElem = doc.createElement( "ComposerTemplate" );
+ QDomElement currentComposerElem = composerNodeList.at( i ).toElement();
+ if ( currentComposerElem.isNull() )
+ {
+ continue;
+ }
+
+ composerTemplateElem.setAttribute( "name", currentComposerElem.attribute( "title" ) );
+ composerTemplateElem.setAttribute( "xmlns:wms", "http://www.opengis.net/wms" );
+ composerTemplateElem.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
+ composerTemplateElem.setAttribute( "xsi:type", "wms:_ExtendedCapabilities" );
+
+ //add available composer maps and their size in mm
+ QDomNodeList composerMapList = currentComposerElem.elementsByTagName( "ComposerMap" );
+ for ( int j = 0; j < composerMapList.size(); ++j )
+ {
+ QDomElement cmap = composerMapList.at( j ).toElement();
+ QDomElement citem = cmap.firstChildElement( "ComposerItem" );
+ if ( citem.isNull() )
+ {
+ continue;
+ }
+
+ QDomElement composerMapElem = doc.createElement( "ComposerMap" );
+ composerMapElem.setAttribute( "name", "map" + cmap.attribute( "id" ) );
+ composerMapElem.setAttribute( "width", citem.attribute( "width" ) );
+ composerMapElem.setAttribute( "height", citem.attribute( "height" ) );
+ composerTemplateElem.appendChild( composerMapElem );
+ }
+
+ parentElement.appendChild( composerTemplateElem );
+ }
+}
+
+QDomElement QgsProjectParser::composerByName( const QString& composerName ) const
+{
+ QDomElement composerElem;
+ if ( !mXMLDoc )
+ {
+ return composerElem;
+ }
+
+ QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );
+ for ( int i = 0; i < composerNodeList.size(); ++i )
+ {
+ QDomElement currentComposerElem = composerNodeList.at( i ).toElement();
+ if ( currentComposerElem.attribute( "title" ) == composerName )
+ {
+ return currentComposerElem;
+ }
+ }
+
+ return composerElem;
+}
+
Modified: trunk/qgis/src/mapserver/qgsprojectparser.h
===================================================================
--- trunk/qgis/src/mapserver/qgsprojectparser.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsprojectparser.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -85,6 +85,14 @@
/**Return project title*/
QString projectTitle() const;
+ const QDomDocument* xmlDoc() const { return mXMLDoc; }
+
+ /**Creates a composition from the project file (probably delegated to the fallback parser)*/
+ QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* > labelList ) const;
+
+ /**Adds print capabilities to xml document. ParentElem usually is the <Capabilities> element*/
+ void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
+
private:
/**Content of project file*/
QDomDocument* mXMLDoc;
@@ -118,6 +126,9 @@
const QStringList &nonIdentifiableLayers,
const QgsRectangle &mapExtent,
const QgsCoordinateReferenceSystem &mapCRS ) const;
+
+ /**Returns dom element of composer (identified by composer title) or a null element in case of error*/
+ QDomElement composerByName( const QString& composerName ) const;
};
#endif // QGSPROJECTPARSER_H
Modified: trunk/qgis/src/mapserver/qgsrequesthandler.h
===================================================================
--- trunk/qgis/src/mapserver/qgsrequesthandler.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgsrequesthandler.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -40,6 +40,7 @@
virtual void sendGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) const = 0;
virtual void sendServiceException( const QgsMapServiceException& ex ) const = 0;
virtual void sendGetStyleResponse( const QDomDocument& doc ) const = 0;
+ virtual void sendGetPrintResponse( QByteArray* ba, const QString& formatString ) const = 0;
protected:
/**This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG')*/
QString mFormat;
Modified: trunk/qgis/src/mapserver/qgssldparser.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgssldparser.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgssldparser.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -1539,6 +1539,23 @@
}
}
+QgsComposition* QgsSLDParser::initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* > labelList ) const
+{
+ if ( mFallbackParser )
+ {
+ return mFallbackParser->initComposition( composerTemplate, mapRenderer, mapList, labelList );
+ }
+ return 0;
+}
+
+void QgsSLDParser::printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const
+{
+ if ( mFallbackParser )
+ {
+ mFallbackParser->printCapabilities( parentElement, doc );
+ }
+}
+
#ifdef DIAGRAMSERVER
int QgsSLDParser::overlaysFromUserStyle( const QDomElement& userStyleElement, QgsVectorLayer* vec ) const
{
Modified: trunk/qgis/src/mapserver/qgssldparser.h
===================================================================
--- trunk/qgis/src/mapserver/qgssldparser.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgssldparser.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -68,6 +68,12 @@
virtual void setParameterMap( const std::map<QString, QString>& parameterMap ) { mParameterMap = parameterMap; }
+ /**Creates a composition from the project file (delegated to the fallback parser)*/
+ QgsComposition* initComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, QList< QgsComposerMap*>& mapList, QList< QgsComposerLabel* > labelList ) const;
+
+ /**Adds print capabilities to xml document. Delegated to fallback parser*/
+ void printCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
+
private:
/**Don't use the default constructor*/
QgsSLDParser();
Modified: trunk/qgis/src/mapserver/qgssoaprequesthandler.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgssoaprequesthandler.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgssoaprequesthandler.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -469,8 +469,11 @@
sendHttpResponse( &ba, "text/xml" );
}
+void QgsSOAPRequestHandler::sendGetPrintResponse( QByteArray* ba, const QString& formatString ) const
+{
+ //soon...
+}
-
void QgsSOAPRequestHandler::sendServiceException( const QgsMapServiceException& ex ) const
{
//create response document
Modified: trunk/qgis/src/mapserver/qgssoaprequesthandler.h
===================================================================
--- trunk/qgis/src/mapserver/qgssoaprequesthandler.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgssoaprequesthandler.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -34,6 +34,7 @@
void sendGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) const;
void sendServiceException( const QgsMapServiceException& ex ) const;
void sendGetStyleResponse( const QDomDocument& doc ) const;
+ void sendGetPrintResponse( QByteArray* ba, const QString& formatString ) const;
private:
/**Parses the xml of a getMap request and fills the parameters into the map. Returns 0 in case of success*/
int parseGetMapElement( std::map<QString, QString>& parameterMap, const QDomElement& getMapElement ) const;
Modified: trunk/qgis/src/mapserver/qgswmsserver.cpp
===================================================================
--- trunk/qgis/src/mapserver/qgswmsserver.cpp 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgswmsserver.cpp 2010-12-24 14:11:13 UTC (rev 14973)
@@ -45,6 +45,12 @@
#include <QTextStream>
#include <QDir>
+//for printing
+#include "qgscomposition.h"
+#include <QBuffer>
+#include <QPrinter>
+#include <QSvgGenerator>
+
QgsWMSServer::QgsWMSServer( std::map<QString, QString> parameters, QgsMapRenderer* renderer )
: mParameterMap( parameters )
, mConfigParser( 0 )
@@ -208,18 +214,27 @@
exceptionElement.appendChild( exFormatElement );
capabilityElement.appendChild( exceptionElement );
+ //Insert <ComposerTemplate> elements derived from wms:_ExtendedCapabilities
+ if ( mConfigParser )
+ {
+ mConfigParser->printCapabilities( capabilityElement, doc );
+ }
+
//add the xml content for the individual layers/styles
QgsMSDebugMsg( "calling layersAndStylesCapabilities" )
- mConfigParser->layersAndStylesCapabilities( capabilityElement, doc );
+ if ( mConfigParser )
+ {
+ mConfigParser->layersAndStylesCapabilities( capabilityElement, doc );
+ }
QgsMSDebugMsg( "layersAndStylesCapabilities returned" )
//for debugging: save the document to disk
- QFile capabilitiesFile( QDir::tempPath() + "/capabilities.txt" );
+ /*QFile capabilitiesFile( QDir::tempPath() + "/capabilities.txt" );
if ( capabilitiesFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
{
QTextStream capabilitiesStream( &capabilitiesFile );
doc.save( capabilitiesStream, 4 );
- }
+ }*/
return doc;
}
@@ -340,81 +355,104 @@
return mConfigParser->getStyle( styleName, layerName );
}
-QImage* QgsWMSServer::getMap()
+QByteArray* QgsWMSServer::getPrint( QString& formatString )
{
- QgsMSDebugMsg( "Entering" )
- if ( !mConfigParser )
+ QStringList layersList, stylesList, layerIdList;
+ QImage* theImage = initializeRendering( layersList, stylesList, layerIdList, formatString );
+ if ( !theImage )
{
- QgsMSDebugMsg( "Error: mSLDParser is 0" )
return 0;
}
+ delete theImage;
- if ( !mMapRenderer )
+ //GetPrint request needs a template parameter
+ std::map<QString, QString>::const_iterator templateIt = mParameterMap.find( "TEMPLATE" );
+ if ( templateIt == mParameterMap.end() )
{
- QgsMSDebugMsg( "Error: mMapRenderer is 0" )
return 0;
}
- QStringList layersList, stylesList;
- QString formatString;
-
- if ( readLayersAndStyles( layersList, stylesList ) != 0 )
+ QgsComposition* c = mConfigParser->createPrintComposition( templateIt->second, mMapRenderer, QMap<QString, QString>( mParameterMap ) );
+ if ( !c )
{
- QgsMSDebugMsg( "error reading layers and styles" )
return 0;
}
- if ( initializeSLDParser( layersList, stylesList ) != 0 )
+ QByteArray* ba = 0;
+ c->setPlotStyle( QgsComposition::Print );
+
+ //SVG export without a running X-Server is a problem. See e.g. http://developer.qt.nokia.com/forums/viewthread/2038
+ if ( formatString.compare( "svg", Qt::CaseInsensitive ) == 0 )
{
- return 0;
+ c->setPlotStyle( QgsComposition::Print );
+
+ QSvgGenerator generator;
+ ba = new QByteArray();
+ QBuffer svgBuffer( ba );
+ generator.setOutputDevice( &svgBuffer );
+ int width = ( int )( c->paperWidth() * c->printResolution() / 25.4 ); //width in pixel
+ int height = ( int )( c->paperHeight() * c->printResolution() / 25.4 ); //height in pixel
+ generator.setSize( QSize( width, height ) );
+ generator.setResolution( c->printResolution() ); //because the rendering is done in mm, convert the dpi
+
+ QPainter p( &generator );
+ QRectF sourceArea( 0, 0, c->paperWidth(), c->paperHeight() );
+ QRectF targetArea( 0, 0, width, height );
+ c->render( &p, targetArea, sourceArea );
+ p.end();
}
-
- //pass external GML to the SLD parser.
- std::map<QString, QString>::const_iterator gmlIt = mParameterMap.find( "GML" );
- if ( gmlIt != mParameterMap.end() )
+ else if ( formatString.compare( "png", Qt::CaseInsensitive ) == 0 )
{
- QDomDocument* gmlDoc = new QDomDocument();
- if ( gmlDoc->setContent( gmlIt->second, true ) )
+ int width = ( int )( c->paperWidth() * c->printResolution() / 25.4 ); //width in pixel
+ int height = ( int )( c->paperHeight() * c->printResolution() / 25.4 ); //height in pixel
+ QImage image( QSize( width, height ), QImage::Format_ARGB32 );
+ image.setDotsPerMeterX( c->printResolution() / 25.4 * 1000 );
+ image.setDotsPerMeterY( c->printResolution() / 25.4 * 1000 );
+ image.fill( 0 );
+ QPainter p( &image );
+ QRectF sourceArea( 0, 0, c->paperWidth(), c->paperHeight() );
+ QRectF targetArea( 0, 0, width, height );
+ c->render( &p, targetArea, sourceArea );
+ p.end();
+ ba = new QByteArray();
+ QBuffer buffer( ba );
+ buffer.open( QIODevice::WriteOnly );
+ image.save( &buffer, "png", -1 );
+ }
+ else if ( formatString.compare( "pdf", Qt::CaseInsensitive ) == 0 )
+ {
+ QTemporaryFile tempFile;
+ if ( !tempFile.open() )
{
- QString layerName = gmlDoc->documentElement().attribute( "layerName" );
- QgsMSDebugMsg( "Adding entry with key: " + layerName + " to external GML data" )
- mConfigParser->addExternalGMLData( layerName, gmlDoc );
+ delete c;
+ return 0;
}
- else
- {
- QgsMSDebugMsg( "Error, could not add external GML to QgsSLDParser" )
- delete gmlDoc;
- }
- }
- //get output format
- std::map<QString, QString>::const_iterator outIt = mParameterMap.find( "FORMAT" );
- if ( outIt == mParameterMap.end() )
- {
- QgsMSDebugMsg( "Error, no parameter FORMAT found" )
- return 0; //output format parameter also mandatory
- }
+ QPrinter printer;
+ printer.setOutputFormat( QPrinter::PdfFormat );
+ printer.setOutputFileName( tempFile.fileName() );
+ printer.setPaperSize( QSizeF( c->paperWidth(), c->paperHeight() ), QPrinter::Millimeter );
+ printer.setResolution( c->printResolution() );
- QImage* theImage = createImage();
- if ( !theImage )
- {
- return 0;
- }
+ QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
+ QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
+ QPainter p( &printer );
+ c->render( &p, paperRectPixel, paperRectMM );
+ p.end();
- if ( configureMapRender( theImage ) != 0 )
- {
- return 0;
+ ba = new QByteArray();
+ *ba = tempFile.readAll();
}
- mMapRenderer->setLabelingEngine( new QgsPalLabeling() );
- //find out the current scale denominater and set it to the SLD parser
- QgsScaleCalculator scaleCalc(( theImage->logicalDpiX() + theImage->logicalDpiY() ) / 2 , mMapRenderer->destinationSrs().mapUnits() );
- QgsRectangle mapExtent = mMapRenderer->extent();
- mConfigParser->setScaleDenominator( scaleCalc.calculate( mapExtent, theImage->width() ) );
+ delete c;
+ return ba;
+}
- //create objects for qgis rendering
- QStringList theLayers = layerSet( layersList, stylesList, mMapRenderer->destinationSrs() );
- mMapRenderer->setLayerSet( theLayers );
+QImage* QgsWMSServer::getMap()
+{
+ QStringList layersList, stylesList, layerIdList;
+ QString outputFormat;
+ QImage* theImage = initializeRendering( layersList, stylesList, layerIdList, outputFormat );
QPainter thePainter( theImage );
thePainter.setRenderHint( QPainter::Antialiasing ); //make it look nicer
@@ -610,6 +648,82 @@
return 0;
}
+QImage* QgsWMSServer::initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList, QString& outputFormat )
+{
+ if ( !mConfigParser )
+ {
+ QgsMSDebugMsg( "Error: mSLDParser is 0" )
+ return 0;
+ }
+
+ if ( !mMapRenderer )
+ {
+ QgsMSDebugMsg( "Error: mMapRenderer is 0" )
+ return 0;
+ }
+
+ if ( readLayersAndStyles( layersList, stylesList ) != 0 )
+ {
+ QgsMSDebugMsg( "error reading layers and styles" )
+ return 0;
+ }
+
+ if ( initializeSLDParser( layersList, stylesList ) != 0 )
+ {
+ return 0;
+ }
+
+ //pass external GML to the SLD parser.
+ std::map<QString, QString>::const_iterator gmlIt = mParameterMap.find( "GML" );
+ if ( gmlIt != mParameterMap.end() )
+ {
+ QDomDocument* gmlDoc = new QDomDocument();
+ if ( gmlDoc->setContent( gmlIt->second, true ) )
+ {
+ QString layerName = gmlDoc->documentElement().attribute( "layerName" );
+ QgsMSDebugMsg( "Adding entry with key: " + layerName + " to external GML data" )
+ mConfigParser->addExternalGMLData( layerName, gmlDoc );
+ }
+ else
+ {
+ QgsMSDebugMsg( "Error, could not add external GML to QgsSLDParser" )
+ delete gmlDoc;
+ }
+ }
+
+ //get output format
+ std::map<QString, QString>::const_iterator outIt = mParameterMap.find( "FORMAT" );
+ if ( outIt == mParameterMap.end() )
+ {
+ QgsMSDebugMsg( "Error, no parameter FORMAT found" )
+ return 0; //output format parameter also mandatory
+ }
+ outputFormat = outIt->second;
+
+ QImage* theImage = createImage();
+ if ( !theImage )
+ {
+ return 0;
+ }
+
+ if ( configureMapRender( theImage ) != 0 )
+ {
+ delete theImage;
+ return 0;
+ }
+ mMapRenderer->setLabelingEngine( new QgsPalLabeling() );
+
+ //find out the current scale denominater and set it to the SLD parser
+ QgsScaleCalculator scaleCalc(( theImage->logicalDpiX() + theImage->logicalDpiY() ) / 2 , mMapRenderer->destinationSrs().mapUnits() );
+ QgsRectangle mapExtent = mMapRenderer->extent();
+ mConfigParser->setScaleDenominator( scaleCalc.calculate( mapExtent, theImage->width() ) );
+
+ //create objects for qgis rendering
+ QStringList theLayers = layerSet( layersList, stylesList, mMapRenderer->destinationSrs() );
+ mMapRenderer->setLayerSet( theLayers );
+ return theImage;
+}
+
QImage* QgsWMSServer::createImage( int width, int height ) const
{
bool conversionSuccess;
@@ -619,12 +733,12 @@
std::map<QString, QString>::const_iterator wit = mParameterMap.find( "WIDTH" );
if ( wit == mParameterMap.end() )
{
- return 0; //width parameter is mandatory
+ width = 0; //width parameter is mandatory
}
width = wit->second.toInt( &conversionSuccess );
if ( !conversionSuccess )
{
- return 0;
+ width = 0;
}
}
@@ -633,12 +747,12 @@
std::map<QString, QString>::const_iterator hit = mParameterMap.find( "HEIGHT" );
if ( hit == mParameterMap.end() )
{
- return 0; //height parameter is mandatory
+ height = 0; //height parameter is mandatory
}
height = hit->second.toInt( &conversionSuccess );
if ( !conversionSuccess )
{
- return 0;
+ height = 0;
}
}
@@ -718,23 +832,27 @@
std::map<QString, QString>::const_iterator bbIt = mParameterMap.find( "BBOX" );
if ( bbIt == mParameterMap.end() )
{
- return 2;
+ //GetPrint request is allowed to have missing BBOX parameter
+ minx = 0; miny = 0; maxx = 0; maxy = 0;
}
- bool bboxOk = true;
- QString bbString = bbIt->second;
- minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess ) {bboxOk = false;}
- miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess ) {bboxOk = false;}
- maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess ) {bboxOk = false;}
- maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess ) {bboxOk = false;}
+ else
+ {
+ bool bboxOk = true;
+ QString bbString = bbIt->second;
+ minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess ) {bboxOk = false;}
+ miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess ) {bboxOk = false;}
+ maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess ) {bboxOk = false;}
+ maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess ) {bboxOk = false;}
- if ( !bboxOk )
- {
- //throw a service exception
- throw QgsMapServiceException( "InvalidParameterValue", "Invalid BBOX parameter" );
+ if ( !bboxOk )
+ {
+ //throw a service exception
+ throw QgsMapServiceException( "InvalidParameterValue", "Invalid BBOX parameter" );
+ }
}
QGis::UnitType mapUnits = QGis::Degrees;
Modified: trunk/qgis/src/mapserver/qgswmsserver.h
===================================================================
--- trunk/qgis/src/mapserver/qgswmsserver.h 2010-12-24 07:14:58 UTC (rev 14972)
+++ trunk/qgis/src/mapserver/qgswmsserver.h 2010-12-24 14:11:13 UTC (rev 14973)
@@ -60,6 +60,11 @@
/**Returns an SLD file with the style of the requested layer. Exception is raised in case of troubles :-)*/
QDomDocument getStyle();
+ /**Returns printed page as binary
+ @param formatString out: format of the print output (e.g. pdf, svg, png, ...)
+ @return printed page as binary or 0 in case of error*/
+ QByteArray* getPrint( QString& formatString );
+
/**Creates an xml document that describes the result of the getFeatureInfo request.
@return 0 in case of success*/
int getFeatureInfo( QDomDocument& result );
@@ -70,6 +75,15 @@
private:
/**Don't use the default constructor*/
QgsWMSServer();
+
+ /**Initializes WMS layers and configures mMapRendering.
+ @param layersList out: list with WMS layer names
+ @param stylesList out: list with WMS style names
+ @param layerIdList out: list with QGIS layer ids
+ @param outputFormat out: name of requested output format
+ @return image configured together with mMapRenderer (or 0 in case of error). The calling function takes ownership of the image*/
+ QImage* initializeRendering( QStringList& layersList, QStringList& stylesList, QStringList& layerIdList, QString& outputFormat );
+
/**Creates a QImage from the HEIGHT and WIDTH parameters
@param width image width (or -1 if width should be taken from WIDTH wms parameter)
@param height image height (or -1 if height should be taken from HEIGHT wms parameter)
More information about the QGIS-commit
mailing list