mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE][AFS] Create labels when settings provied by server
This commit is contained in:
parent
cf0442dac6
commit
22a66ef390
@ -52,6 +52,7 @@ of feature and attribute information from a spatial datasource.
|
||||
WriteLayerMetadata,
|
||||
CancelSupport,
|
||||
CreateRenderer,
|
||||
CreateLabeling,
|
||||
};
|
||||
|
||||
typedef QFlags<QgsVectorDataProvider::Capability> Capabilities;
|
||||
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -41,6 +41,7 @@ class QgsFeatureIterator;
|
||||
class QgsTransaction;
|
||||
class QgsFeedback;
|
||||
class QgsFeatureRenderer;
|
||||
class QgsAbstractVectorLayerLabeling;
|
||||
|
||||
#include "qgsfeaturerequest.h"
|
||||
|
||||
@ -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 )
|
||||
@ -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 );
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
@ -263,6 +264,10 @@ QgsVectorDataProvider::Capabilities QgsAfsProvider::capabilities() const
|
||||
{
|
||||
c = c | QgsVectorDataProvider::CreateRenderer;
|
||||
}
|
||||
if ( !mLabelingDataList.empty() )
|
||||
{
|
||||
c = c | QgsVectorDataProvider::CreateLabeling;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
@ -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;
|
||||
@ -80,6 +81,7 @@ class QgsAfsProvider : public QgsVectorDataProvider
|
||||
QString mLayerDescription;
|
||||
QgsLayerMetadata mLayerMetadata;
|
||||
QVariantMap mRendererDataMap;
|
||||
QVariantList mLabelingDataList;
|
||||
};
|
||||
|
||||
#endif // QGSAFSPROVIDER_H
|
||||
|
@ -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"
|
||||
@ -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>
|
||||
@ -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();
|
||||
|
@ -24,6 +24,7 @@ class QNetworkReply;
|
||||
class QgsNetworkAccessManager;
|
||||
class QgsFields;
|
||||
class QgsAbstractGeometry;
|
||||
class QgsAbstractVectorLayerLabeling;
|
||||
class QgsCoordinateReferenceSystem;
|
||||
class QgsFeedback;
|
||||
class QgsSymbol;
|
||||
@ -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 );
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgslinesymbollayer.h"
|
||||
#include "qgsfillsymbollayer.h"
|
||||
#include "qgsmarkersymbollayer.h"
|
||||
#include "qgsrulebasedlabeling.h"
|
||||
#include "qgssinglesymbolrenderer.h"
|
||||
#include "qgscategorizedsymbolrenderer.h"
|
||||
#include <QObject>
|
||||
@ -49,6 +50,7 @@ class TestQgsArcGisRestUtils : public QObject
|
||||
void testParsePictureFillSymbol();
|
||||
void testParseRendererSimple();
|
||||
void testParseRendererCategorized();
|
||||
void testParseLabeling();
|
||||
|
||||
private:
|
||||
|
||||
@ -454,6 +456,107 @@ void TestQgsArcGisRestUtils::testParseRendererCategorized()
|
||||
QVERIFY( catRenderer->categories().at( 1 ).symbol() );
|
||||
}
|
||||
|
||||
void TestQgsArcGisRestUtils::testParseLabeling()
|
||||
{
|
||||
QVariantMap map = jsonStringToMap( "{"
|
||||
"\"labelingInfo\": ["
|
||||
"{"
|
||||
"\"labelPlacement\": \"esriServerPointLabelPlacementAboveRight\","
|
||||
"\"where\": \"1=1\","
|
||||
"\"labelExpression\": \"[Name]\","
|
||||
"\"useCodedValues\": true,"
|
||||
"\"symbol\": {"
|
||||
"\"type\": \"esriTS\","
|
||||
"\"color\": ["
|
||||
"255,"
|
||||
"0,"
|
||||
"0,"
|
||||
"255"
|
||||
"],"
|
||||
"\"backgroundColor\": null,"
|
||||
"\"borderLineColor\": null,"
|
||||
"\"borderLineSize\": null,"
|
||||
"\"verticalAlignment\": \"bottom\","
|
||||
"\"horizontalAlignment\": \"center\","
|
||||
"\"rightToLeft\": false,"
|
||||
"\"angle\": 0,"
|
||||
"\"xoffset\": 0,"
|
||||
"\"yoffset\": 0,"
|
||||
"\"haloColor\": null,"
|
||||
"\"haloSize\": null,"
|
||||
"\"font\": {"
|
||||
"\"family\": \"Arial\","
|
||||
"\"size\": 8,"
|
||||
"\"style\": \"normal\","
|
||||
"\"weight\": \"bold\","
|
||||
"\"decoration\": \"none\""
|
||||
"}"
|
||||
"},"
|
||||
"\"minScale\": 200000,"
|
||||
"\"maxScale\": 0"
|
||||
"},{"
|
||||
"\"labelPlacement\": \"esriServerPointLabelPlacementAboveRight\","
|
||||
"\"where\": \"1_testing broken where string\","
|
||||
"\"labelExpression\": \"[Name]\","
|
||||
"\"useCodedValues\": true,"
|
||||
"\"symbol\": {"
|
||||
"\"type\": \"esriTS\","
|
||||
"\"color\": ["
|
||||
"255,"
|
||||
"0,"
|
||||
"0,"
|
||||
"255"
|
||||
"],"
|
||||
"\"backgroundColor\": null,"
|
||||
"\"borderLineColor\": null,"
|
||||
"\"borderLineSize\": null,"
|
||||
"\"verticalAlignment\": \"bottom\","
|
||||
"\"horizontalAlignment\": \"center\","
|
||||
"\"rightToLeft\": false,"
|
||||
"\"angle\": 0,"
|
||||
"\"xoffset\": 0,"
|
||||
"\"yoffset\": 0,"
|
||||
"\"haloColor\": null,"
|
||||
"\"haloSize\": null,"
|
||||
"\"font\": {"
|
||||
"\"family\": \"Arial\","
|
||||
"\"size\": 8,"
|
||||
"\"style\": \"normal\","
|
||||
"\"weight\": \"bold\","
|
||||
"\"decoration\": \"none\""
|
||||
"}"
|
||||
"},"
|
||||
"\"minScale\": 200000,"
|
||||
"\"maxScale\": 0"
|
||||
"}"
|
||||
"]"
|
||||
"}" );
|
||||
std::unique_ptr< QgsAbstractVectorLayerLabeling > labeling( QgsArcGisRestUtils::parseEsriLabeling( map.value( QStringLiteral( "labelingInfo" ) ).toList() ) );
|
||||
QVERIFY( labeling );
|
||||
QgsRuleBasedLabeling *rules = dynamic_cast< QgsRuleBasedLabeling *>( labeling.get() );
|
||||
QVERIFY( rules );
|
||||
QgsRuleBasedLabeling::Rule *root = rules->rootRule();
|
||||
QVERIFY( root );
|
||||
|
||||
QgsRuleBasedLabeling::RuleList children = root->children();
|
||||
QCOMPARE( children.count(), 2 );
|
||||
//checking filter expression from valid where string
|
||||
QCOMPARE( children.at( 0 )->filterExpression(), QStringLiteral( "1=1" ) );
|
||||
//checking empty filter expression from invalid where string
|
||||
QCOMPARE( children.at( 1 )->filterExpression(), QString( "" ) );
|
||||
QCOMPARE( children.at( 0 )->minimumScale(), 200000.0 );
|
||||
QCOMPARE( children.at( 0 )->maximumScale(), 0.0 );
|
||||
|
||||
QgsPalLayerSettings *settings = children.at( 0 )->settings();
|
||||
QVERIFY( settings );
|
||||
QCOMPARE( settings->placement, QgsPalLayerSettings::OverPoint );
|
||||
QCOMPARE( settings->quadOffset, QgsPalLayerSettings::QuadrantAboveRight );
|
||||
|
||||
QgsTextFormat textFormat = settings->format();
|
||||
QCOMPARE( textFormat.color(), QColor( 255, 0, 0 ) );
|
||||
QCOMPARE( textFormat.size(), 8.0 );
|
||||
}
|
||||
|
||||
QVariantMap TestQgsArcGisRestUtils::jsonStringToMap( const QString &string ) const
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson( string.toUtf8() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user