Navigation Menu

Skip to content

Commit

Permalink
[FEATURE][AFS] Create labels when settings provied by server
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Dec 10, 2018
1 parent cf0442d commit 22a66ef
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 0 deletions.
18 changes: 18 additions & 0 deletions python/core/auto_generated/qgsvectordataprovider.sip.in
Expand Up @@ -52,6 +52,7 @@ of feature and attribute information from a spatial datasource.
WriteLayerMetadata,
CancelSupport,
CreateRenderer,
CreateLabeling,
};

typedef QFlags<QgsVectorDataProvider::Capability> Capabilities;
Expand Down Expand Up @@ -518,6 +519,23 @@ Only providers which report the CreateRenderer capability will return a feature
providers will return None.

.. versionadded:: 3.2
%End

virtual QgsAbstractVectorLayerLabeling *createLabeling( const QVariantMap &configuration = QVariantMap() ) const /Factory/;
%Docstring
Creates labeling settings, using provider backend specific information.

The ``configuration`` map can be used to pass provider-specific configuration maps to the provider to
allow customization of the returned labeling object. Support and format of ``configuration`` varies by provider.

When called with an empty ``configuration`` map the provider's default labeling settings will be returned.

This method returns a new labeling settings and the caller takes ownership of the returned object.

Only providers which report the CreateLabeling capability will return labeling settings. Other
providers will return None.

.. versionadded:: 3.6
%End

static QVariant convertValue( QVariant::Type type, const QString &value );
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Expand Up @@ -699,6 +699,11 @@ QgsFeatureRenderer *QgsVectorDataProvider::createRenderer( const QVariantMap & )
return nullptr;
}

QgsAbstractVectorLayerLabeling *QgsVectorDataProvider::createLabeling( const QVariantMap & ) const
{
return nullptr;
}

void QgsVectorDataProvider::pushError( const QString &msg ) const
{
QgsDebugMsg( msg );
Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsvectordataprovider.h
Expand Up @@ -41,6 +41,7 @@ class QgsFeatureIterator;
class QgsTransaction;
class QgsFeedback;
class QgsFeatureRenderer;
class QgsAbstractVectorLayerLabeling;

#include "qgsfeaturerequest.h"

Expand Down Expand Up @@ -93,6 +94,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
WriteLayerMetadata = 1 << 22, //!< Provider can write layer metadata to the data store. Since QGIS 3.0. See QgsDataProvider::writeLayerMetadata()
CancelSupport = 1 << 23, //!< Supports interruption of pending queries from a separated thread. Since QGIS 3.2
CreateRenderer = 1 << 24, //!< Provider can create feature renderers using backend-specific formatting information. Since QGIS 3.2. See QgsVectorDataProvider::createRenderer().
CreateLabeling = 1 << 25, //!< Provider can set labeling settings using backend-specific formatting information. Since QGIS 3.6. See QgsVectorDataProvider::createLabeling().
};

Q_DECLARE_FLAGS( Capabilities, Capability )
Expand Down Expand Up @@ -520,6 +522,23 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
*/
virtual QgsFeatureRenderer *createRenderer( const QVariantMap &configuration = QVariantMap() ) const SIP_FACTORY;

/**
* Creates labeling settings, using provider backend specific information.
*
* The \a configuration map can be used to pass provider-specific configuration maps to the provider to
* allow customization of the returned labeling object. Support and format of \a configuration varies by provider.
*
* When called with an empty \a configuration map the provider's default labeling settings will be returned.
*
* This method returns a new labeling settings and the caller takes ownership of the returned object.
*
* Only providers which report the CreateLabeling capability will return labeling settings. Other
* providers will return nullptr.
*
* \since QGIS 3.6
*/
virtual QgsAbstractVectorLayerLabeling *createLabeling( const QVariantMap &configuration = QVariantMap() ) const SIP_FACTORY;

static QVariant convertValue( QVariant::Type type, const QString &value );

/**
Expand Down
10 changes: 10 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -1531,6 +1531,16 @@ void QgsVectorLayer::setDataSource( const QString &dataSource, const QString &ba
}

setLegend( QgsMapLayerLegend::defaultVectorLegend( this ) );

if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
{
std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
if ( defaultLabeling )
{
setLabeling( defaultLabeling.release() );
setLabelsEnabled( true );
}
}
}

emit dataSourceChanged();
Expand Down
9 changes: 9 additions & 0 deletions src/providers/arcgisrest/qgsafsprovider.cpp
Expand Up @@ -222,6 +222,7 @@ QgsAfsProvider::QgsAfsProvider( const QString &uri, const ProviderOptions &optio

// renderer
mRendererDataMap = layerData.value( QStringLiteral( "drawingInfo" ) ).toMap().value( QStringLiteral( "renderer" ) ).toMap();
mLabelingDataList = layerData.value( QStringLiteral( "drawingInfo" ) ).toMap().value( QStringLiteral( "labelingInfo" ) ).toList();

mValid = true;
}
Expand Down Expand Up @@ -263,6 +264,10 @@ QgsVectorDataProvider::Capabilities QgsAfsProvider::capabilities() const
{
c = c | QgsVectorDataProvider::CreateRenderer;
}
if ( !mLabelingDataList.empty() )
{
c = c | QgsVectorDataProvider::CreateLabeling;
}
return c;
}

Expand Down Expand Up @@ -307,6 +312,10 @@ QgsFeatureRenderer *QgsAfsProvider::createRenderer( const QVariantMap & ) const
return QgsArcGisRestUtils::parseEsriRenderer( mRendererDataMap );
}

QgsAbstractVectorLayerLabeling *QgsAfsProvider::createLabeling( const QVariantMap & ) const
{
return QgsArcGisRestUtils::parseEsriLabeling( mLabelingDataList );
}

#ifdef HAVE_GUI

Expand Down
2 changes: 2 additions & 0 deletions src/providers/arcgisrest/qgsafsprovider.h
Expand Up @@ -71,6 +71,7 @@ class QgsAfsProvider : public QgsVectorDataProvider
QString dataComment() const override;
void reloadData() override;
QgsFeatureRenderer *createRenderer( const QVariantMap &configuration = QVariantMap() ) const override;
QgsAbstractVectorLayerLabeling *createLabeling( const QVariantMap &configuration = QVariantMap() ) const override;

private:
bool mValid = false;
Expand All @@ -80,6 +81,7 @@ class QgsAfsProvider : public QgsVectorDataProvider
QString mLayerDescription;
QgsLayerMetadata mLayerMetadata;
QVariantMap mRendererDataMap;
QVariantList mLabelingDataList;
};

#endif // QGSAFSPROVIDER_H
130 changes: 130 additions & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -28,6 +28,7 @@
#include "geometry/qgspolygon.h"
#include "geometry/qgspoint.h"
#include "qgsfeedback.h"
#include "qgspallabeling.h"
#include "qgssymbol.h"
#include "qgssymbollayer.h"
#include "qgsauthmanager.h"
Expand All @@ -36,8 +37,11 @@
#include "qgsfillsymbollayer.h"
#include "qgsmarkersymbollayer.h"
#include "qgsrenderer.h"
#include "qgsrulebasedlabeling.h"
#include "qgssinglesymbolrenderer.h"
#include "qgscategorizedsymbolrenderer.h"
#include "qgsvectorlayerlabeling.h"

#include <QEventLoop>
#include <QNetworkRequest>
#include <QNetworkReply>
Expand Down Expand Up @@ -765,6 +769,132 @@ std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbo
return symbol;
}

QgsAbstractVectorLayerLabeling *QgsArcGisRestUtils::parseEsriLabeling( const QVariantList &labelingData )
{
if ( labelingData.empty() )
return nullptr;

QgsRuleBasedLabeling::Rule *root = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings(), 0, 0, QString(), QString(), false );
root->setActive( true );

int i = 1;
for ( const QVariant &lbl : labelingData )
{
const QVariantMap labeling = lbl.toMap();

QgsPalLayerSettings *settings = new QgsPalLayerSettings();
QgsTextFormat format;

const QString placement = labeling.value( QStringLiteral( "labelPlacement" ) ).toString();
if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveCenter" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantAbove;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowCenter" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantBelow;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterCenter" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantOver;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveLeft" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantAboveLeft;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowLeft" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantBelowLeft;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterLeft" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantLeft;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveRight" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantAboveRight;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowRight" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantBelowRight;
}
else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterRight" ) )
{
settings->placement = QgsPalLayerSettings::OverPoint;
settings->quadOffset = QgsPalLayerSettings::QuadrantRight;
}
else if ( placement == QLatin1String( "esriServerLinePlacementAboveAfter" ) ||
placement == QLatin1String( "esriServerLinePlacementAboveStart" ) ||
placement == QLatin1String( "esriServerLinePlacementAboveAlong" ) )
{
settings->placement = QgsPalLayerSettings::Line;
settings->placementFlags = QgsPalLayerSettings::AboveLine | QgsPalLayerSettings::MapOrientation;
}
else if ( placement == QLatin1String( "esriServerLinePlacementBelowAfter" ) ||
placement == QLatin1String( "esriServerLinePlacementBelowStart" ) ||
placement == QLatin1String( "esriServerLinePlacementBelowAlong" ) )
{
settings->placement = QgsPalLayerSettings::Line;
settings->placementFlags = QgsPalLayerSettings::BelowLine | QgsPalLayerSettings::MapOrientation;
}
else if ( placement == QLatin1String( "esriServerLinePlacementCenterAfter" ) ||
placement == QLatin1String( "esriServerLinePlacementCenterStart" ) ||
placement == QLatin1String( "esriServerLinePlacementCenterAlong" ) )
{
settings->placement = QgsPalLayerSettings::Line;
settings->placementFlags = QgsPalLayerSettings::OnLine | QgsPalLayerSettings::MapOrientation;
}
else if ( placement == QLatin1String( "esriServerPolygonPlacementAlwaysHorizontal" ) )
{
settings->placement = QgsPalLayerSettings::Horizontal;
}

const double minScale = labeling.value( QStringLiteral( "minScale" ) ).toDouble();
const double maxScale = labeling.value( QStringLiteral( "maxScale" ) ).toDouble();

QVariantMap symbol = labeling.value( QStringLiteral( "symbol" ) ).toMap();
format.setColor( parseEsriColorJson( symbol.value( QStringLiteral( "color" ) ) ) );

const QString fontFamily = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "family" ) ).toString();
const QString fontStyle = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "style" ) ).toString();
const QString fontWeight = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "weight" ) ).toString();
const int fontSize = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "size" ) ).toInt();
QFont font( fontFamily, fontSize );
font.setStyleName( fontStyle );
font.setWeight( fontWeight == QLatin1String( "bold" ) ? QFont::Bold : QFont::Normal );

format.setFont( font );
format.setSize( fontSize );
format.setSizeUnit( QgsUnitTypes::RenderPoints );

settings->setFormat( format );

QString where = labeling.value( QStringLiteral( "where" ) ).toString();
QgsExpression exp( where );
// If the where clause isn't parsed as valid, don't use its
if ( !exp.isValid() )
where.clear();

QString expression = labeling.value( QStringLiteral( "labelExpression" ) ).toString();
settings->fieldName = expression.replace( '[', '"' ).replace( ']', '"' );
settings->isExpression = true;

QgsRuleBasedLabeling::Rule *child = new QgsRuleBasedLabeling::Rule( settings, maxScale, minScale, where, QObject::tr( "ASF label %1" ).arg( i++ ), false );
child->setActive( true );
root->appendChild( child );
}

return new QgsRuleBasedLabeling( root );
}

QgsFeatureRenderer *QgsArcGisRestUtils::parseEsriRenderer( const QVariantMap &rendererData )
{
const QString type = rendererData.value( QStringLiteral( "type" ) ).toString();
Expand Down
2 changes: 2 additions & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.h
Expand Up @@ -24,6 +24,7 @@ class QNetworkReply;
class QgsNetworkAccessManager;
class QgsFields;
class QgsAbstractGeometry;
class QgsAbstractVectorLayerLabeling;
class QgsCoordinateReferenceSystem;
class QgsFeedback;
class QgsSymbol;
Expand Down Expand Up @@ -58,6 +59,7 @@ class QgsArcGisRestUtils
static std::unique_ptr< QgsMarkerSymbol > parseEsriMarkerSymbolJson( const QVariantMap &symbolData );
static std::unique_ptr< QgsMarkerSymbol > parseEsriPictureMarkerSymbolJson( const QVariantMap &symbolData );
static QgsFeatureRenderer *parseEsriRenderer( const QVariantMap &rendererData );
static QgsAbstractVectorLayerLabeling *parseEsriLabeling( const QVariantList &labelingData );

static QColor parseEsriColorJson( const QVariant &colorData );
static Qt::PenStyle parseEsriLineStyle( const QString &style );
Expand Down

0 comments on commit 22a66ef

Please sign in to comment.