Performance optimizations

- avoid container detachments
- use QStringLiteral
This commit is contained in:
Nyall Dawson 2017-09-05 14:51:12 +10:00
parent b1745b0fea
commit 5b092aeb8d
6 changed files with 124 additions and 117 deletions

View File

@ -36,7 +36,7 @@ Destructor
%End
void setConnName( const QString &connName );
QgsDataSourceUri uri();
QgsDataSourceUri uri() const;
%Docstring
:rtype: QgsDataSourceUri
%End

View File

@ -42,11 +42,17 @@ class QgsGeoNodeRequest : QObject
#include "qgsgeonoderequest.h"
%End
public:
explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = 0 );
QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent = 0 );
%Docstring
Constructor for QgsGeoNodeRequest.
If ``forceRefresh`` is false, then cached copies of the request may be reused.
%End
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = 0 );
virtual ~QgsGeoNodeRequest();
bool request( QString endPoint );
bool request( const QString &endPoint );
%Docstring
:rtype: bool
%End
@ -56,28 +62,30 @@ class QgsGeoNodeRequest : QObject
:rtype: list of QgsServiceLayerDetail
%End
QList<QgsGeoNodeStyle> getStyles( QString layerName );
QList<QgsGeoNodeStyle> getStyles( const QString &layerName );
%Docstring
:rtype: list of QgsGeoNodeStyle
%End
QgsGeoNodeStyle getDefaultStyle( QString layerName );
QgsGeoNodeStyle getDefaultStyle( const QString &layerName );
%Docstring
:rtype: QgsGeoNodeStyle
%End
QgsGeoNodeStyle getStyle( QString styleID );
QgsGeoNodeStyle getStyle( const QString &styleID );
%Docstring
:rtype: QgsGeoNodeStyle
%End
QStringList serviceUrls( QString serviceType );
QStringList serviceUrls( const QString &serviceType );
%Docstring
Obtain list of unique URLs in the geonode
:rtype: list of str
%End
QgsStringMap serviceUrlData( QString serviceType );
QgsStringMap serviceUrlData( const QString &serviceType );
%Docstring
Obtain map of layer name and url for a service type
:rtype: QgsStringMap
%End

View File

@ -28,23 +28,21 @@ QgsGeoNodeConnection::QgsGeoNodeConnection( const QString &connName )
// settings.Section
QString key = "qgis/connections-geonode/" + mConnName;
QString credentialsKey = "qgis/geonode/" + mConnName;
QString key = sPathGeoNodeConnection + QStringLiteral( "/" ) + mConnName;
QString credentialsKey = sPathGeoNodeConnectionDetails + QStringLiteral( "/" ) + mConnName;
QStringList connStringParts;
mUri.setParam( QStringLiteral( "url" ), settings.value( key + "/url", "", QgsSettings::Providers ).toString() );
mUri.setParam( QStringLiteral( "url" ), settings.value( key + QStringLiteral( "/url" ), QString(), QgsSettings::Providers ).toString() );
// Check for credentials and prepend to the connection info
QString username = settings.value( credentialsKey + "/username", "", QgsSettings::Providers ).toString();
QString password = settings.value( credentialsKey + "/password", "", QgsSettings::Providers ).toString();
QString username = settings.value( credentialsKey + QStringLiteral( "/username" ), QString(), QgsSettings::Providers ).toString();
QString password = settings.value( credentialsKey + QStringLiteral( "/password" ), QString(), QgsSettings::Providers ).toString();
if ( !username.isEmpty() )
{
mUri.setParam( QStringLiteral( "username" ), username );
mUri.setParam( QStringLiteral( "password" ), password );
}
QString authcfg = settings.value( credentialsKey + "/authcfg", "", QgsSettings::Providers ).toString();
QString authcfg = settings.value( credentialsKey + QStringLiteral( "/authcfg" ), QString(), QgsSettings::Providers ).toString();
if ( !authcfg.isEmpty() )
{
mUri.setParam( QStringLiteral( "authcfg" ), authcfg );
@ -58,7 +56,7 @@ QgsGeoNodeConnection::~QgsGeoNodeConnection()
}
QgsDataSourceUri QgsGeoNodeConnection::uri()
QgsDataSourceUri QgsGeoNodeConnection::uri() const
{
return mUri;
}
@ -67,7 +65,7 @@ QStringList QgsGeoNodeConnection::connectionList()
{
QgsSettings settings;
// Add Section manually
settings.beginGroup( "providers/qgis/connections-geonode" );
settings.beginGroup( QStringLiteral( "providers/qgis/connections-geonode" ) );
return settings.childGroups();
}
@ -75,20 +73,20 @@ void QgsGeoNodeConnection::deleteConnection( const QString &name )
{
QgsSettings settings;
// Add Section manually
settings.remove( "providers/qgis/connections-geonode/" + name );
settings.remove( "providers/qgis/geonode/" + name );
settings.remove( QStringLiteral( "providers/qgis/connections-geonode/" ) + name );
settings.remove( QStringLiteral( "providers/qgis/geonode/" ) + name );
}
QString QgsGeoNodeConnection::selectedConnection()
{
QgsSettings settings;
return settings.value( "qgis/connections-geonode/selected", "", QgsSettings::Providers ).toString();
return settings.value( QStringLiteral( "qgis/connections-geonode/selected" ), QString(), QgsSettings::Providers ).toString();
}
void QgsGeoNodeConnection::setSelectedConnection( const QString &name )
{
QgsSettings settings;
settings.setValue( "qgis/connections-geonode/selected", name, QgsSettings::Providers );
settings.setValue( QStringLiteral( "qgis/connections-geonode/selected" ), name, QgsSettings::Providers );
}
QString QgsGeoNodeConnection::pathGeoNodeConnection()

View File

@ -37,7 +37,7 @@ class CORE_EXPORT QgsGeoNodeConnection : public QObject
QString connName() const;
void setConnName( const QString &connName );
QgsDataSourceUri uri();
QgsDataSourceUri uri() const;
void setUri( const QgsDataSourceUri &uri );
//! Retrieve all geonode connection

View File

@ -34,7 +34,7 @@ QgsGeoNodeRequest::QgsGeoNodeRequest( bool forceRefresh, QObject *parent )
}
QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent )
QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent )
: QObject( parent )
, mBaseUrl( baseUrl )
, mForceRefresh( forceRefresh )
@ -77,14 +77,14 @@ QgsGeoNodeStyle QgsGeoNodeRequest::getDefaultStyle( const QString &layerName )
return defaultStyle;
}
QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
QJsonObject jsonObject = jsonDocument.object();
QList<QVariant> layers = jsonObject.toVariantMap()["objects"].toList();
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
const QJsonObject jsonObject = jsonDocument.object();
const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
if ( layers.count() < 1 )
{
return defaultStyle;
}
QString defaultStyleUrl = layers[0].toMap()["default_style"].toString();
QString defaultStyleUrl = layers.at( 0 ).toMap().value( QStringLiteral( "default_style" ) ).toString();
defaultStyle = retrieveStyle( defaultStyleUrl );
@ -101,14 +101,14 @@ QList<QgsGeoNodeStyle> QgsGeoNodeRequest::getStyles( const QString &layerName )
return geoNodeStyles;
}
QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
QJsonObject jsobObject = jsonDocument.object();
QList<QVariant> styles = jsobObject.toVariantMap()["objects"].toList();
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
const QJsonObject jsobObject = jsonDocument.object();
const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
Q_FOREACH ( QVariant style, styles )
for ( const QVariant &style : styles )
{
QVariantMap styleMap = style.toMap();
QString styleUrl = styleMap["resource_uri"].toString();
const QVariantMap styleMap = style.toMap();
QString styleUrl = styleMap.value( QStringLiteral( "resource_uri" ) ).toString();
QgsGeoNodeStyle geoNodeStyle = retrieveStyle( styleUrl );
if ( !geoNodeStyle.name.isEmpty() )
{
@ -125,13 +125,12 @@ QgsGeoNodeStyle QgsGeoNodeRequest::getStyle( const QString &styleID )
QString endPoint = QStringLiteral( "/api/styles/" ) + styleID;
return retrieveStyle( endPoint );
}
void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
{
QString msg = tr( "%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral( "unknown number of" ) : QString::number( bytesTotal ) );
QgsMessageLog::logMessage( msg, tr( "GeoNode" ) );
QgsDebugMsgLevel( msg, 3 );
emit statusChanged( msg );
}
@ -147,7 +146,7 @@ void QgsGeoNodeRequest::setProtocol( const QString &protocol )
void QgsGeoNodeRequest::replyFinished()
{
QgsMessageLog::logMessage( QStringLiteral( "Reply finished" ), tr( "GeoNode" ) );
QgsDebugMsg( "Reply finished" );
if ( !mIsAborted && mGeoNodeReply )
{
if ( mGeoNodeReply->error() == QNetworkReply::NoError )
@ -177,7 +176,7 @@ void QgsGeoNodeRequest::replyFinished()
mGeoNodeReply->deleteLater();
mGeoNodeReply = nullptr;
QgsDebugMsg( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
QgsDebugMsgLevel( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ), 3 );
mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
@ -196,7 +195,7 @@ void QgsGeoNodeRequest::replyFinished()
QNetworkCacheMetaData::RawHeaderList hl;
Q_FOREACH ( const QNetworkCacheMetaData::RawHeader &h, cmd.rawHeaders() )
{
if ( h.first != "Cache-Control" )
if ( h.first != QStringLiteral( "Cache-Control" ) )
hl.append( h );
}
cmd.setRawHeaders( hl );
@ -249,17 +248,17 @@ QList<QgsServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &l
return layers;
}
QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
QJsonObject jsonObject = jsonDocument.object();
QVariantMap jsonVariantMap = jsonObject.toVariantMap();
QVariantList layerList = jsonVariantMap["objects"].toList();
const QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
const QJsonObject jsonObject = jsonDocument.object();
const QVariantMap jsonVariantMap = jsonObject.toVariantMap();
const QVariantList layerList = jsonVariantMap.value( QStringLiteral( "objects" ) ).toList();
qint16 majorVersion;
qint16 minorVersion;
if ( jsonVariantMap.contains( QStringLiteral( "geonode_version" ) ) )
{
QStringList geonodeVersionSplit = jsonVariantMap["geonode_version"].toString().split( "." );
majorVersion = geonodeVersionSplit[0].toInt();
minorVersion = geonodeVersionSplit[1].toInt();
const QStringList geonodeVersionSplit = jsonVariantMap.value( QStringLiteral( "geonode_version" ) ).toString().split( '.' );
majorVersion = geonodeVersionSplit.at( 0 ).toInt();
minorVersion = geonodeVersionSplit.at( 1 ).toInt();
}
else
{
@ -269,38 +268,38 @@ QList<QgsServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &l
if ( majorVersion == 2 && minorVersion == 6 )
{
Q_FOREACH ( QVariant layer, layerList )
for ( const QVariant &layer : qgsAsConst( layerList ) )
{
QgsServiceLayerDetail layerStruct;
QVariantMap layerMap = layer.toMap();
const QVariantMap layerMap = layer.toMap();
// Find WMS and WFS. XYZ is not available
// Trick to get layer's typename from distribution_url or detail_url
QString layerTypeName = layerMap["detail_url"].toString().split( "/" ).last();
if ( layerTypeName.length() == 0 )
QString layerTypeName = layerMap.value( QStringLiteral( "detail_url" ) ).toString().split( '/' ).last();
if ( layerTypeName.isEmpty() )
{
layerTypeName = layerMap["distribution_url"].toString().split( "/" ).last();
layerTypeName = layerMap.value( QStringLiteral( "distribution_url" ) ).toString().split( '/' ).last();
}
// On this step, layerTypeName is in WORKSPACE%3ALAYERNAME or WORKSPACE:LAYERNAME format
if ( layerTypeName.contains( "%3A" ) )
if ( layerTypeName.contains( QStringLiteral( "%3A" ) ) )
{
layerTypeName.replace( "%3A", ":" );
layerTypeName.replace( QStringLiteral( "%3A" ), QStringLiteral( ":" ) );
}
// On this step, layerTypeName is in WORKSPACE:LAYERNAME format
QStringList splitURL = layerTypeName.split( ":" );
QString layerWorkspace = splitURL[0];
QString layerName = splitURL[1];
const QStringList splitURL = layerTypeName.split( ':' );
QString layerWorkspace = splitURL.at( 0 );
QString layerName = splitURL.at( 1 );
layerStruct.name = layerName;
layerStruct.typeName = layerTypeName;
layerStruct.uuid = layerMap["uuid"].toString();
layerStruct.title = layerMap["title"].toString();;
layerStruct.uuid = layerMap.value( QStringLiteral( "uuid" ) ).toString();
layerStruct.title = layerMap.value( QStringLiteral( "title" ) ).toString();
// WMS url : BASE_URI/geoserver/WORKSPACE/wms
layerStruct.wmsURL = mBaseUrl + "/geoserver/" + layerWorkspace + "/wms";
layerStruct.wmsURL = mBaseUrl + QStringLiteral( "/geoserver/" ) + layerWorkspace + QStringLiteral( "/wms" );
// WFS url : BASE_URI/geoserver/WORKSPACE/wfs
layerStruct.wfsURL = mBaseUrl + "/geoserver/" + layerWorkspace + "/wfs";
layerStruct.wfsURL = mBaseUrl + QStringLiteral( "/geoserver/" ) + layerWorkspace + QStringLiteral( "/wfs" );
// XYZ url : set to empty string
layerStruct.xyzURL = "";
layerStruct.xyzURL.clear();
layers.append( layerStruct );
}
@ -308,46 +307,43 @@ QList<QgsServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &l
// Geonode version 2.7 or newer
else if ( ( majorVersion == 2 && minorVersion >= 7 ) || ( majorVersion >= 3 ) )
{
Q_FOREACH ( QVariant layer, layerList )
for ( const QVariant &layer : qgsAsConst( layerList ) )
{
QgsServiceLayerDetail layerStruct;
QVariantMap layerMap = layer.toMap();
const QVariantMap layerMap = layer.toMap();
// Find WMS, WFS, and XYZ link
QVariantList layerLinks = layerMap["links"].toList();
layerStruct.wmsURL = QStringLiteral( "" );
layerStruct.wfsURL = QStringLiteral( "" );
layerStruct.xyzURL = QStringLiteral( "" );
Q_FOREACH ( QVariant link, layerLinks )
const QVariantList layerLinks = layerMap.value( QStringLiteral( "links" ) ).toList();
for ( const QVariant &link : layerLinks )
{
QVariantMap linkMap = link.toMap();
if ( linkMap.contains( "link_type" ) )
const QVariantMap linkMap = link.toMap();
if ( linkMap.contains( QStringLiteral( "link_type" ) ) )
{
if ( linkMap["link_type"] == "OGC:WMS" )
if ( linkMap.value( QStringLiteral( "link_type" ) ) == QStringLiteral( "OGC:WMS" ) )
{
layerStruct.wmsURL = linkMap["url"].toString();
layerStruct.wmsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
}
if ( linkMap["link_type"] == "OGC:WFS" )
else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QStringLiteral( "OGC:WFS" ) )
{
layerStruct.wfsURL = linkMap["url"].toString();
layerStruct.wfsURL = linkMap.value( QStringLiteral( "url" ) ).toString();
}
if ( linkMap["link_type"] == "image" )
else if ( linkMap.value( QStringLiteral( "link_type" ) ) == QStringLiteral( "image" ) )
{
if ( linkMap.contains( "name" ) && linkMap["name"] == "Tiles" )
if ( linkMap.contains( QStringLiteral( "name" ) ) && linkMap.value( QStringLiteral( "name" ) ) == QStringLiteral( "Tiles" ) )
{
layerStruct.xyzURL = linkMap["url"].toString();
layerStruct.xyzURL = linkMap.value( QStringLiteral( "url" ) ).toString();
}
}
}
}
if ( layerMap["typename"].toString().length() == 0 )
if ( layerMap.value( QStringLiteral( "typename" ) ).toString().isEmpty() )
{
QStringList splitURL = layerMap["detail_url"].toString().split( "/" );
layerStruct.typeName = splitURL[ splitURL.length() - 1];
const QStringList splitURL = layerMap.value( QStringLiteral( "detail_url" ) ).toString().split( '/' );
layerStruct.typeName = splitURL.at( splitURL.length() - 1 );
}
layerStruct.uuid = layerMap["uuid"].toString();
layerStruct.name = layerMap["name"].toString();
layerStruct.typeName = layerMap["typename"].toString();
layerStruct.title = layerMap["title"].toString();
layerStruct.uuid = layerMap.value( QStringLiteral( "uuid" ) ).toString();
layerStruct.name = layerMap.value( QStringLiteral( "name" ) ).toString();
layerStruct.typeName = layerMap.value( QStringLiteral( "typename" ) ).toString();
layerStruct.title = layerMap.value( QStringLiteral( "title" ) ).toString();
layers.append( layerStruct );
}
}
@ -363,13 +359,14 @@ QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
{
return geoNodeStyle;
}
QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
QJsonObject jsonObject = jsonDocument.object();
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
const QJsonObject jsonObject = jsonDocument.object();
geoNodeStyle.id = jsonObject.toVariantMap()["id"].toString();
geoNodeStyle.name = jsonObject.toVariantMap()["name"].toString();
geoNodeStyle.title = jsonObject.toVariantMap()["title"].toString();
geoNodeStyle.styleUrl = jsonObject.toVariantMap()["style_url"].toString();
const QVariantMap jsonMap = jsonObject.toVariantMap();
geoNodeStyle.id = jsonMap.value( QStringLiteral( "id" ) ).toString();
geoNodeStyle.name = jsonMap.value( QStringLiteral( "name" ) ).toString();
geoNodeStyle.title = jsonMap.value( QStringLiteral( "title" ) ).toString();
geoNodeStyle.styleUrl = jsonMap.value( QStringLiteral( "style_url" ) ).toString();
success = request( geoNodeStyle.styleUrl );
if ( !success )
@ -390,38 +387,37 @@ QStringList QgsGeoNodeRequest::serviceUrls( const QString &serviceType )
{
QStringList urls;
QList<QgsServiceLayerDetail> layers = getLayers();
const QList<QgsServiceLayerDetail> layers = getLayers();
if ( layers.empty() )
{
return urls;
}
Q_FOREACH ( QgsServiceLayerDetail layer, layers )
for ( const QgsServiceLayerDetail &layer : layers )
{
QString url;
if ( serviceType.toLower() == "wms" )
if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.wmsURL;
}
else if ( serviceType.toLower() == "wfs" )
else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.wfsURL;
}
else if ( serviceType.toLower() == "xyz" )
else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.xyzURL;
}
else
{
url = "";
}
if ( !url.contains( QLatin1String( "://" ) ) && url.length() > 0 )
if ( url.isEmpty() )
continue;
if ( !url.contains( QLatin1String( "://" ) ) )
{
url.prepend( getProtocol() );
}
if ( !urls.contains( url ) && url.length() > 0 )
if ( !urls.contains( url ) )
{
urls.append( url );
}
@ -434,40 +430,39 @@ QgsStringMap QgsGeoNodeRequest::serviceUrlData( const QString &serviceType )
{
QgsStringMap urls;
QList<QgsServiceLayerDetail> layers = getLayers();
const QList<QgsServiceLayerDetail> layers = getLayers();
if ( layers.empty() )
{
return urls;
}
Q_FOREACH ( QgsServiceLayerDetail layer, layers )
for ( const QgsServiceLayerDetail &layer : layers )
{
QString url;
if ( serviceType.toLower() == "wms" )
if ( QString::compare( serviceType, QStringLiteral( "wms" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.wmsURL;
}
else if ( serviceType.toLower() == "wfs" )
else if ( QString::compare( serviceType, QStringLiteral( "wfs" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.wfsURL;
}
else if ( serviceType.toLower() == "xyz" )
else if ( QString::compare( serviceType, QStringLiteral( "xyz" ), Qt::CaseInsensitive ) == 0 )
{
url = layer.xyzURL;
}
else
{
url = "";
}
if ( url.isEmpty() )
continue;
QString layerName = layer.name;
if ( !url.contains( QLatin1String( "://" ) ) && url.length() > 0 )
if ( !url.contains( QLatin1String( "://" ) ) )
{
url.prepend( getProtocol() );
}
if ( !urls.contains( url ) && url.length() > 0 )
if ( !urls.contains( url ) )
{
urls.insert( layerName, url );
}
@ -482,8 +477,8 @@ bool QgsGeoNodeRequest::request( const QString &endPoint )
mIsAborted = false;
// Handle case where the endpoint is full url
QString url = endPoint.startsWith( mBaseUrl ) ? endPoint : mBaseUrl + endPoint;
QgsMessageLog::logMessage( "Requesting to " + url, tr( "GeoNode" ) );
setProtocol( url.split( "://" )[0] );
QgsDebugMsg( "Requesting to " + url );
setProtocol( url.split( QStringLiteral( "://" ) ).at( 0 ) );
QUrl layerUrl( url );
layerUrl.setScheme( getProtocol() );

View File

@ -58,8 +58,14 @@ class CORE_EXPORT QgsGeoNodeRequest : public QObject
{
Q_OBJECT
public:
/**
* Constructor for QgsGeoNodeRequest.
*
* If \a forceRefresh is false, then cached copies of the request may be reused.
*/
explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = nullptr );
QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent = nullptr );
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = nullptr );
virtual ~QgsGeoNodeRequest();
bool request( const QString &endPoint );
@ -72,10 +78,10 @@ class CORE_EXPORT QgsGeoNodeRequest : public QObject
QgsGeoNodeStyle getStyle( const QString &styleID );
// Obtain list of unique URL in the geonode
//! Obtain list of unique URLs in the geonode
QStringList serviceUrls( const QString &serviceType );
// Obtain map of layer name and url for a service type
//! Obtain map of layer name and url for a service type
QgsStringMap serviceUrlData( const QString &serviceType );
QString lastError() const { return mError; }