Skip to content

Commit

Permalink
Merge pull request #3942 from pblottiere/qgsserverprojectutils
Browse files Browse the repository at this point in the history
[server] WIP clean project parsing by using QgsProject
  • Loading branch information
rldhont committed Jan 30, 2017
2 parents 8ba609e + 83f4c99 commit 50319b1
Show file tree
Hide file tree
Showing 68 changed files with 1,110 additions and 385 deletions.
4 changes: 0 additions & 4 deletions python/server/qgsserverprojectparser.sip
Expand Up @@ -86,10 +86,6 @@ class QgsServerProjectParser
@return name or a null string in case of error*/
QString layerName( const QDomElement& layerElem ) const;

QString serviceUrl() const;
QString wfsServiceUrl() const;
QString wcsServiceUrl() const;

QStringList wfsLayers() const;
QStringList wcsLayers() const;

Expand Down
58 changes: 58 additions & 0 deletions python/server/qgsserverprojectutils.sip
@@ -0,0 +1,58 @@
/***************************************************************************
qgsserverprojectutils.sip
-------------------------
begin : December 19, 2016
copyright : (C) 2016 by Paul Blottiere
email : paul dot blottiere at oslandia dot com
***************************************************************************/

/***************************************************************************
* *
* 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. *
* *
***************************************************************************/

%ModuleHeaderCode
#include "qgsserverprojectutils.h"
%End

/** \ingroup server
* The QgsServerProjectUtils namespace provides a way to retrieve specific
* entries from a QgsProject.
* @note added in QGIS 3.0
*/
namespace QgsServerProjectUtils
{
/** Returns the maximum width for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return width if defined in project, -1 otherwise.
*/
int wmsMaxWidth( const QgsProject& project );

/** Returns the maximum height for WMS images defined in a QGIS project.
* @param project the QGIS project
* @return height if defined in project, -1 otherwise.
*/
int wmsMaxHeight( const QgsProject& project );

/** Returns the WMS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
QString wmsServiceUrl( const QgsProject& project );

/** Returns the WFS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
QString wfsServiceUrl( const QgsProject& project );

/** Returns the WCS service url defined in a QGIS project.
* @param project the QGIS project
* @return url if defined in project, an empty string otherwise.
*/
QString wcsServiceUrl( const QgsProject& project );
};
2 changes: 1 addition & 1 deletion python/server/qgsservice.sip
Expand Up @@ -64,6 +64,6 @@ class QgsService
* Execute the requests and set result in QgsServerRequest
*/
virtual void executeRequest( const QgsServerRequest& request, QgsServerResponse& response,
QgsProject* project = nullptr ) = 0;
const QgsProject* project ) = 0;
};

2 changes: 0 additions & 2 deletions python/server/qgswcsprojectparser.sip
Expand Up @@ -27,8 +27,6 @@ class QgsWCSProjectParser
~QgsWCSProjectParser();

void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString wcsServiceUrl() const;
QString serviceUrl() const;
void wcsContentMetadata( QDomElement& parentElement, QDomDocument& doc ) const;
QStringList wcsLayers() const;
void describeCoverage( const QString& aCoveName, QDomElement& parentElement, QDomDocument& doc ) const;
Expand Down
2 changes: 0 additions & 2 deletions python/server/qgswfsprojectparser.sip
Expand Up @@ -28,8 +28,6 @@ class QgsWfsProjectParser
~QgsWfsProjectParser();

void serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const;
QString serviceUrl() const;
QString wfsServiceUrl() const;
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const;

void describeFeatureType( const QString& aTypeName, QDomElement& parentElement, QDomDocument& doc ) const;
Expand Down
8 changes: 2 additions & 6 deletions python/server/qgswmsconfigparser.sip
Expand Up @@ -27,7 +27,7 @@ class 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;
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const = 0;

/** Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned*/
virtual QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const = 0;
Expand All @@ -42,7 +42,7 @@ class QgsWmsConfigParser
virtual QDomDocument getStyles( QStringList& layerList ) const = 0;

/** Returns the xml fragment of layers styles description*/
virtual QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const = 0;
virtual QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const = 0;

/** Returns if output are MM or PIXEL*/
virtual QgsUnitTypes::RenderUnit outputUnits() const = 0;
Expand Down Expand Up @@ -74,8 +74,6 @@ class QgsWmsConfigParser
/** Load PAL engine settings into global project instance*/
virtual void loadLabelSettings() const = 0;

virtual QString serviceUrl() const = 0;

virtual QStringList wfsLayerNames() const = 0;

virtual void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const = 0;
Expand All @@ -91,8 +89,6 @@ class QgsWmsConfigParser
virtual QFont legendLayerFont() const = 0;
virtual QFont legendItemFont() const = 0;

virtual double maxWidth() const = 0;
virtual double maxHeight() const = 0;
virtual double imageQuality() const = 0;

// WMS GetFeatureInfo precision (decimal places)
Expand Down
8 changes: 2 additions & 6 deletions python/server/qgswmsprojectparser.sip
Expand Up @@ -28,12 +28,10 @@ class QgsWmsProjectParser : public 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)*/
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings = false ) const /*override*/ ;
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, const QString& serviceUrl, bool fullProjectSettings = false ) const /*override*/ ;

QList<QgsMapLayer*> mapLayerFromStyle( const QString& lName, const QString& styleName, bool useCache = true ) const /*override*/ ;

QString serviceUrl() const /*override*/ ;

QStringList wfsLayerNames() const /*override*/ ;

void owsGeneralAndResourceList( QDomElement& parentElement, QDomDocument& doc, const QString& strHref ) const /*override*/ ;
Expand All @@ -49,8 +47,6 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
QFont legendLayerFont() const /*override*/ ;
QFont legendItemFont() const /*override*/ ;

double maxWidth() const /*override*/ ;
double maxHeight() const /*override*/ ;
double imageQuality() const /*override*/ ;
int wmsPrecision() const /*override*/ ;

Expand All @@ -75,7 +71,7 @@ class QgsWmsProjectParser : public QgsWmsConfigParser
QDomDocument getStyles( QStringList& layerList ) const /*override*/ ;

/** Returns the xml fragment of layers styles description*/
QDomDocument describeLayer( QStringList& layerList, const QString& hrefString ) const /*override*/ ;
QDomDocument describeLayer( QStringList& layerList, const QString& wfsHrefString, const QString& wcsHrefString ) const /*override*/ ;

/** Returns if output are MM or PIXEL*/
QgsUnitTypes::RenderUnit outputUnits() const /*override*/ ;
Expand Down
1 change: 1 addition & 0 deletions python/server/server.sip
Expand Up @@ -27,6 +27,7 @@
%Include qgswfsprojectparser.sip
%Include qgsconfigcache.sip
%Include qgsserversettings.sip
%Include qgsserverprojectutils.sip
%Include qgsserver.sip

%Include qgsserverrequest.sip
Expand Down
24 changes: 15 additions & 9 deletions src/core/qgsmaplayer.cpp
Expand Up @@ -155,6 +155,12 @@ QPainter::CompositionMode QgsMapLayer::blendMode() const


bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
{
return readLayerXml( layerElement, QgsProject::instance() );
}


bool QgsMapLayer::readLayerXml( const QDomElement& layerElement, const QgsProject *project )
{
bool layerError;

Expand Down Expand Up @@ -185,19 +191,19 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
if ( provider == QLatin1String( "spatialite" ) )
{
QgsDataSourceUri uri( mDataSource );
uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
uri.setDatabase( project->readPath( uri.database() ) );
mDataSource = uri.uri();
}
else if ( provider == QLatin1String( "ogr" ) )
{
QStringList theURIParts = mDataSource.split( '|' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = project->readPath( theURIParts[0] );
mDataSource = theURIParts.join( QStringLiteral( "|" ) );
}
else if ( provider == QLatin1String( "gpx" ) )
{
QStringList theURIParts = mDataSource.split( '?' );
theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
theURIParts[0] = project->readPath( theURIParts[0] );
mDataSource = theURIParts.join( QStringLiteral( "?" ) );
}
else if ( provider == QLatin1String( "delimitedtext" ) )
Expand All @@ -211,7 +217,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
urlSource.setPath( file.path() );
}

QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
QUrl urlDest = QUrl::fromLocalFile( project->readPath( urlSource.toLocalFile() ) );
urlDest.setQueryItems( urlSource.queryItems() );
mDataSource = QString::fromAscii( urlDest.toEncoded() );
}
Expand Down Expand Up @@ -309,7 +315,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "NETCDF:\"" + project->readPath( filename ) + "\":" + r.cap( 2 );
handled = true;
}
}
Expand All @@ -323,7 +329,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 2 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 3 );
mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + project->readPath( filename ) + "\":" + r.cap( 3 );
handled = true;
}
}
Expand All @@ -337,7 +343,7 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QString filename = r.cap( 1 );
if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
filename = filename.mid( 1, filename.length() - 2 );
mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename ) + "\":" + r.cap( 2 );
mDataSource = "HDF5:\"" + project->readPath( filename ) + "\":" + r.cap( 2 );
handled = true;
}
}
Expand All @@ -348,14 +354,14 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement )
QRegExp r( "([^:]+):([^:]+):(.+)" );
if ( r.exactMatch( mDataSource ) )
{
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ) );
mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + project->readPath( r.cap( 3 ) );
handled = true;
}
}
}

if ( !handled )
mDataSource = QgsProject::instance()->readPath( mDataSource );
mDataSource = project->readPath( mDataSource );
}

// Set the CRS from project file, asking the user if necessary.
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsmaplayer.h
Expand Up @@ -38,6 +38,7 @@
class QgsMapLayerLegend;
class QgsMapLayerRenderer;
class QgsMapLayerStyleManager;
class QgsProject;

class QDomDocument;
class QKeyEvent;
Expand Down Expand Up @@ -364,6 +365,13 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool readLayerXml( const QDomElement& layerElement );

/** Sets state from Dom document for a specific project.
* @param layerElement The Dom element corresponding to ``maplayer'' tag
* @param project
* @returns true if successful
*/
bool readLayerXml( const QDomElement& layerElement, const QgsProject *project );


/** Stores state in Dom node
* @param layerElement is a Dom element corresponding to ``maplayer'' tag
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsproject.cpp
Expand Up @@ -733,7 +733,7 @@ bool QgsProject::addLayer( const QDomElement &layerElem, QList<QDomNode> &broken
Q_CHECK_PTR( mapLayer );

// have the layer restore state that is stored in Dom node
if ( mapLayer->readLayerXml( layerElem ) && mapLayer->isValid() )
if ( mapLayer->readLayerXml( layerElem, this ) && mapLayer->isValid() )
{
// postpone readMapLayer signal for vector layers with joins
QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer*>( mapLayer );
Expand Down
1 change: 1 addition & 0 deletions src/server/CMakeLists.txt
Expand Up @@ -39,6 +39,7 @@ SET(qgis_mapserv_SRCS
qgswmsconfigparser.cpp
qgswmsprojectparser.cpp
qgsserverprojectparser.cpp
qgsserverprojectutils.cpp
qgssldconfigparser.cpp
qgsconfigparserutils.cpp
qgsserver.cpp
Expand Down
20 changes: 19 additions & 1 deletion src/server/qgsserver.cpp
Expand Up @@ -39,6 +39,7 @@
#include "qgsbufferserverresponse.h"
#include "qgsfilterresponsedecorator.h"
#include "qgsservice.h"
#include "qgsserverprojectutils.h"

#include <QDomDocument>
#include <QNetworkDiskCache>
Expand Down Expand Up @@ -351,6 +352,23 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res
//Config file path
QString configFilePath = configPath( *sConfigFilePath, parameterMap );

// load the project if needed and not empty
auto projectIt = mProjectRegistry.find( configFilePath );
if ( projectIt == mProjectRegistry.constEnd() )
{
// load the project
QgsProject* project = new QgsProject();
project->setFileName( configFilePath );
if ( project->read() )
{
projectIt = mProjectRegistry.insert( configFilePath, project );
}
else
{
throw QgsServerException( QStringLiteral( "Project file error" ) );
}
}

sServerInterface->setConfigFilePath( configFilePath );

//Service parameter
Expand Down Expand Up @@ -379,7 +397,7 @@ void QgsServer::handleRequest( QgsServerRequest& request, QgsServerResponse& res
QgsService* service = sServiceRegistry.getService( serviceString, versionString );
if ( service )
{
service->executeRequest( request, theResponse );
service->executeRequest( request, theResponse, projectIt.value() );
}
else
{
Expand Down
4 changes: 4 additions & 0 deletions src/server/qgsserver.h
Expand Up @@ -43,6 +43,7 @@

class QgsServerRequest;
class QgsServerResponse;
class QgsProject;

/** \ingroup server
* The QgsServer class provides OGC web services.
Expand Down Expand Up @@ -130,6 +131,9 @@ class SERVER_EXPORT QgsServer
static QgsServiceRegistry sServiceRegistry;

static QgsServerSettings sSettings;

// map of QgsProject
QMap<QString, const QgsProject*> mProjectRegistry;
};
#endif // QGSSERVER_H

0 comments on commit 50319b1

Please sign in to comment.