38 #include <QRegularExpression> 
   43   if ( esriFieldType == QLatin1String( 
"esriFieldTypeInteger" ) )
 
   44     return QVariant::LongLong;
 
   45   if ( esriFieldType == QLatin1String( 
"esriFieldTypeSmallInteger" ) )
 
   47   if ( esriFieldType == QLatin1String( 
"esriFieldTypeDouble" ) )
 
   48     return QVariant::Double;
 
   49   if ( esriFieldType == QLatin1String( 
"esriFieldTypeSingle" ) )
 
   50     return QVariant::Double;
 
   51   if ( esriFieldType == QLatin1String( 
"esriFieldTypeString" ) )
 
   52     return QVariant::String;
 
   53   if ( esriFieldType == QLatin1String( 
"esriFieldTypeDate" ) )
 
   54     return QVariant::DateTime;
 
   55   if ( esriFieldType == QLatin1String( 
"esriFieldTypeGeometry" ) )
 
   56     return QVariant::Invalid; 
 
   57   if ( esriFieldType == QLatin1String( 
"esriFieldTypeOID" ) )
 
   58     return QVariant::LongLong;
 
   59   if ( esriFieldType == QLatin1String( 
"esriFieldTypeBlob" ) )
 
   60     return QVariant::ByteArray;
 
   61   if ( esriFieldType == QLatin1String( 
"esriFieldTypeGlobalID" ) )
 
   62     return QVariant::String;
 
   63   if ( esriFieldType == QLatin1String( 
"esriFieldTypeRaster" ) )
 
   64     return QVariant::ByteArray;
 
   65   if ( esriFieldType == QLatin1String( 
"esriFieldTypeGUID" ) )
 
   66     return QVariant::String;
 
   67   if ( esriFieldType == QLatin1String( 
"esriFieldTypeXML" ) )
 
   68     return QVariant::String;
 
   69   return QVariant::Invalid;
 
   75   if ( esriGeometryType == QLatin1String( 
"esriGeometryNull" ) )
 
   77   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPoint" ) )
 
   79   else if ( esriGeometryType == QLatin1String( 
"esriGeometryMultipoint" ) )
 
   81   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPolyline" ) )
 
   83   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPolygon" ) )
 
   85   else if ( esriGeometryType == QLatin1String( 
"esriGeometryEnvelope" ) )
 
  105 std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint( 
const QVariantList &coordList, 
QgsWkbTypes::Type pointType )
 
  107   int nCoords = coordList.size();
 
  110   bool xok = 
false, yok = 
false;
 
  111   double x = coordList[0].toDouble( &xok );
 
  112   double y = coordList[1].toDouble( &yok );
 
  115   double z = nCoords >= 3 ? coordList[2].toDouble() : 0;
 
  116   double m = nCoords >= 4 ? coordList[3].toDouble() : 0;
 
  117   return qgis::make_unique< QgsPoint >( pointType, x, y, z, m );
 
  120 std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString( 
const QVariantMap &curveData, 
QgsWkbTypes::Type pointType, 
const QgsPoint &startPoint )
 
  122   const QVariantList coordsList = curveData[QStringLiteral( 
"c" )].toList();
 
  123   if ( coordsList.isEmpty() )
 
  125   QVector<QgsPoint> points;
 
  126   points.append( startPoint );
 
  127   for ( 
const QVariant &coordData : coordsList )
 
  129     std::unique_ptr< QgsPoint > point( convertPoint( coordData.toList(), pointType ) );
 
  134     points.append( *point );
 
  136   std::unique_ptr< QgsCircularString > curve = qgis::make_unique< QgsCircularString> ();
 
  137   curve->setPoints( points );
 
  141 std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve( 
const QVariantList &curvesList, 
QgsWkbTypes::Type pointType )
 
  144   std::unique_ptr< QgsCompoundCurve > compoundCurve = qgis::make_unique< QgsCompoundCurve >();
 
  146   compoundCurve->addCurve( lineString );
 
  147   for ( 
const QVariant &curveData : curvesList )
 
  149     if ( curveData.type() == QVariant::List )
 
  151       std::unique_ptr< QgsPoint > point( convertPoint( curveData.toList(), pointType ) );
 
  158     else if ( curveData.type() == QVariant::Map )
 
  161       std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lineString->
endPoint() ) );
 
  162       if ( !circularString )
 
  168       if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
 
  169         compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
 
  171       const QgsPoint endPointCircularString = circularString->endPoint();
 
  172       compoundCurve->addCurve( circularString.release() );
 
  176       compoundCurve->addCurve( lineString );
 
  177       lineString->
addVertex( endPointCircularString );
 
  180   return compoundCurve;
 
  183 std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint( 
const QVariantMap &geometryData, 
QgsWkbTypes::Type pointType )
 
  186   bool xok = 
false, yok = 
false;
 
  187   double x = geometryData[QStringLiteral( 
"x" )].toDouble( &xok );
 
  188   double y = geometryData[QStringLiteral( 
"y" )].toDouble( &yok );
 
  191   double z = geometryData[QStringLiteral( 
"z" )].toDouble();
 
  192   double m = geometryData[QStringLiteral( 
"m" )].toDouble();
 
  193   return qgis::make_unique< QgsPoint >( pointType, x, y, z, m );
 
  196 std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint( 
const QVariantMap &geometryData, 
QgsWkbTypes::Type pointType )
 
  199   const QVariantList coordsList = geometryData[QStringLiteral( 
"points" )].toList();
 
  201   std::unique_ptr< QgsMultiPoint > multiPoint = qgis::make_unique< QgsMultiPoint >();
 
  202   multiPoint->reserve( coordsList.size() );
 
  203   for ( 
const QVariant &coordData : coordsList )
 
  205     const QVariantList coordList = coordData.toList();
 
  206     std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
 
  211     multiPoint->addGeometry( p.release() );
 
  216   std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
 
  218     multiPoint->addGeometry( p.release() );
 
  220   if ( multiPoint->numGeometries() == 0 )
 
  228 std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline( 
const QVariantMap &geometryData, 
QgsWkbTypes::Type pointType )
 
  231   QVariantList pathsList;
 
  232   if ( geometryData[QStringLiteral( 
"paths" )].isValid() )
 
  233     pathsList = geometryData[QStringLiteral( 
"paths" )].toList();
 
  234   else if ( geometryData[QStringLiteral( 
"curvePaths" )].isValid() )
 
  235     pathsList = geometryData[QStringLiteral( 
"curvePaths" )].toList();
 
  236   if ( pathsList.isEmpty() )
 
  238   std::unique_ptr< QgsMultiCurve > multiCurve = qgis::make_unique< QgsMultiCurve >();
 
  239   multiCurve->reserve( pathsList.size() );
 
  240   for ( 
const QVariant &pathData : qgis::as_const( pathsList ) )
 
  242     std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
 
  247     multiCurve->addGeometry( curve.release() );
 
  252 std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon( 
const QVariantMap &geometryData, 
QgsWkbTypes::Type pointType )
 
  255   QVariantList ringsList;
 
  256   if ( geometryData[QStringLiteral( 
"rings" )].isValid() )
 
  257     ringsList = geometryData[QStringLiteral( 
"rings" )].toList();
 
  258   else if ( geometryData[QStringLiteral( 
"ringPaths" )].isValid() )
 
  259     ringsList = geometryData[QStringLiteral( 
"ringPaths" )].toList();
 
  260   if ( ringsList.isEmpty() )
 
  263   QList< QgsCompoundCurve * > curves;
 
  264   for ( 
int i = 0, n = ringsList.size(); i < n; ++i )
 
  266     std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
 
  271     curves.append( curve.release() );
 
  273   if ( curves.count() == 0 )
 
  276   std::sort( curves.begin(), curves.end(), []( 
const QgsCompoundCurve * a, 
const QgsCompoundCurve * b )->bool{ double a_area = 0.0; double b_area = 0.0; a->sumUpArea( a_area ); b->sumUpArea( b_area ); return std::abs( a_area ) > std::abs( b_area ); } );
 
  277   std::unique_ptr< QgsMultiSurface > result = qgis::make_unique< QgsMultiSurface >();
 
  278   result->reserve( curves.size() );
 
  279   while ( !curves.isEmpty() )
 
  285     engine->prepareGeometry();
 
  287     QMutableListIterator< QgsCompoundCurve * > it( curves );
 
  288     while ( it.hasNext() )
 
  295         if ( engine->contains( &point ) )
 
  300           engine->prepareGeometry();
 
  304     result->addGeometry( newPolygon );
 
  306   if ( result->numGeometries() == 0 )
 
  312 std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope( 
const QVariantMap &geometryData )
 
  315   bool xminOk = 
false, yminOk = 
false, xmaxOk = 
false, ymaxOk = 
false;
 
  316   double xmin = geometryData[QStringLiteral( 
"xmin" )].toDouble( &xminOk );
 
  317   double ymin = geometryData[QStringLiteral( 
"ymin" )].toDouble( &yminOk );
 
  318   double xmax = geometryData[QStringLiteral( 
"xmax" )].toDouble( &xmaxOk );
 
  319   double ymax = geometryData[QStringLiteral( 
"ymax" )].toDouble( &ymaxOk );
 
  320   if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
 
  322   std::unique_ptr< QgsLineString > ext = qgis::make_unique< QgsLineString> ();
 
  323   ext->addVertex( 
QgsPoint( xmin, ymin ) );
 
  324   ext->addVertex( 
QgsPoint( xmax, ymin ) );
 
  325   ext->addVertex( 
QgsPoint( xmax, ymax ) );
 
  326   ext->addVertex( 
QgsPoint( xmin, ymax ) );
 
  327   ext->addVertex( 
QgsPoint( xmin, ymin ) );
 
  328   std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >();
 
  329   poly->setExteriorRing( ext.release() );
 
  342   if ( esriGeometryType == QLatin1String( 
"esriGeometryNull" ) )
 
  344   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPoint" ) )
 
  345     return convertGeometryPoint( geometryData, pointType ).release();
 
  346   else if ( esriGeometryType == QLatin1String( 
"esriGeometryMultipoint" ) )
 
  347     return convertMultiPoint( geometryData, pointType ).release();
 
  348   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPolyline" ) )
 
  349     return convertGeometryPolyline( geometryData, pointType ).release();
 
  350   else if ( esriGeometryType == QLatin1String( 
"esriGeometryPolygon" ) )
 
  351     return convertGeometryPolygon( geometryData, pointType ).release();
 
  352   else if ( esriGeometryType == QLatin1String( 
"esriGeometryEnvelope" ) )
 
  353     return convertEnvelope( geometryData ).release();
 
  374   QString spatialReference = spatialReferenceMap[QStringLiteral( 
"latestWkid" )].toString();
 
  375   if ( spatialReference.isEmpty() )
 
  376     spatialReference = spatialReferenceMap[QStringLiteral( 
"wkid" )].toString();
 
  377   if ( spatialReference.isEmpty() )
 
  378     spatialReference = spatialReferenceMap[QStringLiteral( 
"wkt" )].toString();
 
  380     spatialReference = QStringLiteral( 
"EPSG:%1" ).arg( spatialReference );
 
  393   const QString type = symbolData.value( QStringLiteral( 
"type" ) ).toString();
 
  394   if ( type == QLatin1String( 
"esriSMS" ) )
 
  397     return parseEsriMarkerSymbolJson( symbolData ).release();
 
  399   else if ( type == QLatin1String( 
"esriSLS" ) )
 
  402     return parseEsriLineSymbolJson( symbolData ).release();
 
  404   else if ( type == QLatin1String( 
"esriSFS" ) )
 
  407     return parseEsriFillSymbolJson( symbolData ).release();
 
  409   else if ( type == QLatin1String( 
"esriPFS" ) )
 
  411     return parseEsriPictureFillSymbolJson( symbolData ).release();
 
  413   else if ( type == QLatin1String( 
"esriPMS" ) )
 
  416     return parseEsriPictureMarkerSymbolJson( symbolData ).release();
 
  418   else if ( type == QLatin1String( 
"esriTS" ) )
 
  426 std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson( 
const QVariantMap &symbolData )
 
  428   QColor lineColor = 
convertColor( symbolData.value( QStringLiteral( 
"color" ) ) );
 
  429   if ( !lineColor.isValid() )
 
  433   double widthInPoints = symbolData.value( QStringLiteral( 
"width" ) ).toDouble( &ok );
 
  438   Qt::PenStyle penStyle = 
convertLineStyle( symbolData.value( QStringLiteral( 
"style" ) ).toString() );
 
  439   std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = qgis::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
 
  441   layers.append( lineLayer.release() );
 
  443   std::unique_ptr< QgsLineSymbol > symbol = qgis::make_unique< QgsLineSymbol >( layers );
 
  447 std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson( 
const QVariantMap &symbolData )
 
  449   QColor fillColor = 
convertColor( symbolData.value( QStringLiteral( 
"color" ) ) );
 
  450   Qt::BrushStyle brushStyle = 
convertFillStyle( symbolData.value( QStringLiteral( 
"style" ) ).toString() );
 
  452   const QVariantMap outlineData = symbolData.value( QStringLiteral( 
"outline" ) ).toMap();
 
  453   QColor lineColor = 
convertColor( outlineData.value( QStringLiteral( 
"color" ) ) );
 
  454   Qt::PenStyle penStyle = 
convertLineStyle( outlineData.value( QStringLiteral( 
"style" ) ).toString() );
 
  456   double penWidthInPoints = outlineData.value( QStringLiteral( 
"width" ) ).toDouble( &ok );
 
  459   std::unique_ptr< QgsSimpleFillSymbolLayer > fillLayer = qgis::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
 
  461   layers.append( fillLayer.release() );
 
  463   std::unique_ptr< QgsFillSymbol > symbol = qgis::make_unique< QgsFillSymbol >( layers );
 
  467 std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson( 
const QVariantMap &symbolData )
 
  471   double widthInPixels = symbolData.value( QStringLiteral( 
"width" ) ).toInt( &ok );
 
  475   const double xScale = symbolData.value( QStringLiteral( 
"xscale" ) ).toDouble( &ok );
 
  477     widthInPixels *= xScale;
 
  479   const double angleCCW = symbolData.value( QStringLiteral( 
"angle" ) ).toDouble( &ok );
 
  484   const double xOffset = symbolData.value( QStringLiteral( 
"xoffset" ) ).toDouble();
 
  485   const double yOffset = symbolData.value( QStringLiteral( 
"yoffset" ) ).toDouble();
 
  487   QString symbolPath( symbolData.value( QStringLiteral( 
"imageData" ) ).toString() );
 
  488   symbolPath.prepend( QLatin1String( 
"base64:" ) );
 
  491   std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = qgis::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
 
  492   fillLayer->setWidth( widthInPixels );
 
  493   fillLayer->setAngle( angleCW );
 
  495   fillLayer->setOffset( QPointF( xOffset, yOffset ) );
 
  497   layers.append( fillLayer.release() );
 
  499   const QVariantMap outlineData = symbolData.value( QStringLiteral( 
"outline" ) ).toMap();
 
  500   QColor lineColor = 
convertColor( outlineData.value( QStringLiteral( 
"color" ) ) );
 
  501   Qt::PenStyle penStyle = 
convertLineStyle( outlineData.value( QStringLiteral( 
"style" ) ).toString() );
 
  502   double penWidthInPoints = outlineData.value( QStringLiteral( 
"width" ) ).toDouble( &ok );
 
  504   std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = qgis::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
 
  506   layers.append( lineLayer.release() );
 
  508   std::unique_ptr< QgsFillSymbol > symbol = qgis::make_unique< QgsFillSymbol >( layers );
 
  514   if ( style == QLatin1String( 
"esriSMSCircle" ) )
 
  516   else if ( style == QLatin1String( 
"esriSMSCross" ) )
 
  518   else if ( style == QLatin1String( 
"esriSMSDiamond" ) )
 
  520   else if ( style == QLatin1String( 
"esriSMSSquare" ) )
 
  522   else if ( style == QLatin1String( 
"esriSMSX" ) )
 
  524   else if ( style == QLatin1String( 
"esriSMSTriangle" ) )
 
  530 std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson( 
const QVariantMap &symbolData )
 
  532   QColor fillColor = 
convertColor( symbolData.value( QStringLiteral( 
"color" ) ) );
 
  534   const double sizeInPoints = symbolData.value( QStringLiteral( 
"size" ) ).toDouble( &ok );
 
  537   const double angleCCW = symbolData.value( QStringLiteral( 
"angle" ) ).toDouble( &ok );
 
  544   const double xOffset = symbolData.value( QStringLiteral( 
"xoffset" ) ).toDouble();
 
  545   const double yOffset = symbolData.value( QStringLiteral( 
"yoffset" ) ).toDouble();
 
  547   const QVariantMap outlineData = symbolData.value( QStringLiteral( 
"outline" ) ).toMap();
 
  548   QColor lineColor = 
convertColor( outlineData.value( QStringLiteral( 
"color" ) ) );
 
  549   Qt::PenStyle penStyle = 
convertLineStyle( outlineData.value( QStringLiteral( 
"style" ) ).toString() );
 
  550   double penWidthInPoints = outlineData.value( QStringLiteral( 
"width" ) ).toDouble( &ok );
 
  553   std::unique_ptr< QgsSimpleMarkerSymbolLayer > markerLayer = qgis::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW, 
QgsSymbol::ScaleArea, fillColor, lineColor );
 
  556   markerLayer->setStrokeStyle( penStyle );
 
  557   markerLayer->setStrokeWidth( penWidthInPoints );
 
  558   markerLayer->setOffset( QPointF( xOffset, yOffset ) );
 
  560   layers.append( markerLayer.release() );
 
  562   std::unique_ptr< QgsMarkerSymbol > symbol = qgis::make_unique< QgsMarkerSymbol >( layers );
 
  566 std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson( 
const QVariantMap &symbolData )
 
  569   const double widthInPixels = symbolData.value( QStringLiteral( 
"width" ) ).toInt( &ok );
 
  572   const double heightInPixels = symbolData.value( QStringLiteral( 
"height" ) ).toInt( &ok );
 
  576   const double angleCCW = symbolData.value( QStringLiteral( 
"angle" ) ).toDouble( &ok );
 
  581   const double xOffset = symbolData.value( QStringLiteral( 
"xoffset" ) ).toDouble();
 
  582   const double yOffset = symbolData.value( QStringLiteral( 
"yoffset" ) ).toDouble();
 
  586   QString symbolPath( symbolData.value( QStringLiteral( 
"imageData" ) ).toString() );
 
  587   symbolPath.prepend( QLatin1String( 
"base64:" ) );
 
  590   std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = qgis::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW, 
QgsSymbol::ScaleArea );
 
  594   if ( !
qgsDoubleNear( 
static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
 
  595     markerLayer->setFixedAspectRatio( 
static_cast< double >( heightInPixels ) / widthInPixels );
 
  597   markerLayer->setOffset( QPointF( xOffset, yOffset ) );
 
  599   layers.append( markerLayer.release() );
 
  601   std::unique_ptr< QgsMarkerSymbol > symbol = qgis::make_unique< QgsMarkerSymbol >( layers );
 
  607   if ( labelingData.empty() )
 
  614   for ( 
const QVariant &lbl : labelingData )
 
  616     const QVariantMap labeling = lbl.toMap();
 
  621     const QString placement = labeling.value( QStringLiteral( 
"labelPlacement" ) ).toString();
 
  622     if ( placement == QLatin1String( 
"esriServerPointLabelPlacementAboveCenter" ) )
 
  627     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementBelowCenter" ) )
 
  632     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementCenterCenter" ) )
 
  637     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementAboveLeft" ) )
 
  642     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementBelowLeft" ) )
 
  647     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementCenterLeft" ) )
 
  652     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementAboveRight" ) )
 
  657     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementBelowRight" ) )
 
  662     else if ( placement == QLatin1String( 
"esriServerPointLabelPlacementCenterRight" ) )
 
  667     else if ( placement == QLatin1String( 
"esriServerLinePlacementAboveAfter" ) ||
 
  668               placement == QLatin1String( 
"esriServerLinePlacementAboveStart" ) ||
 
  669               placement == QLatin1String( 
"esriServerLinePlacementAboveAlong" ) )
 
  674     else if ( placement == QLatin1String( 
"esriServerLinePlacementBelowAfter" ) ||
 
  675               placement == QLatin1String( 
"esriServerLinePlacementBelowStart" ) ||
 
  676               placement == QLatin1String( 
"esriServerLinePlacementBelowAlong" ) )
 
  681     else if ( placement == QLatin1String( 
"esriServerLinePlacementCenterAfter" ) ||
 
  682               placement == QLatin1String( 
"esriServerLinePlacementCenterStart" ) ||
 
  683               placement == QLatin1String( 
"esriServerLinePlacementCenterAlong" ) )
 
  688     else if ( placement == QLatin1String( 
"esriServerPolygonPlacementAlwaysHorizontal" ) )
 
  693     const double minScale = labeling.value( QStringLiteral( 
"minScale" ) ).toDouble();
 
  694     const double maxScale = labeling.value( QStringLiteral( 
"maxScale" ) ).toDouble();
 
  696     QVariantMap symbol = labeling.value( QStringLiteral( 
"symbol" ) ).toMap();
 
  698     const double haloSize = symbol.value( QStringLiteral( 
"haloSize" ) ).toDouble();
 
  709     const QString fontFamily = symbol.value( QStringLiteral( 
"font" ) ).toMap().value( QStringLiteral( 
"family" ) ).toString();
 
  710     const QString fontStyle = symbol.value( QStringLiteral( 
"font" ) ).toMap().value( QStringLiteral( 
"style" ) ).toString();
 
  711     const QString fontWeight = symbol.value( QStringLiteral( 
"font" ) ).toMap().value( QStringLiteral( 
"weight" ) ).toString();
 
  712     const int fontSize = symbol.value( QStringLiteral( 
"font" ) ).toMap().value( QStringLiteral( 
"size" ) ).toInt();
 
  713     QFont font( fontFamily, fontSize );
 
  714     font.setStyleName( fontStyle );
 
  715     font.setWeight( fontWeight == QLatin1String( 
"bold" ) ? QFont::Bold : QFont::Normal );
 
  723     QString where = labeling.value( QStringLiteral( 
"where" ) ).toString();
 
  742   const QString type = rendererData.value( QStringLiteral( 
"type" ) ).toString();
 
  743   if ( type == QLatin1String( 
"simple" ) )
 
  745     const QVariantMap symbolProps = rendererData.value( QStringLiteral( 
"symbol" ) ).toMap();
 
  746     std::unique_ptr< QgsSymbol > symbol( 
convertSymbol( symbolProps ) );
 
  752   else if ( type == QLatin1String( 
"uniqueValue" ) )
 
  754     const QString field1 = rendererData.value( QStringLiteral( 
"field1" ) ).toString();
 
  755     const QString field2 = rendererData.value( QStringLiteral( 
"field2" ) ).toString();
 
  756     const QString field3 = rendererData.value( QStringLiteral( 
"field3" ) ).toString();
 
  758     if ( !field2.isEmpty() || !field3.isEmpty() )
 
  760       const QString delimiter = rendererData.value( QStringLiteral( 
"fieldDelimiter" ) ).toString();
 
  761       if ( !field3.isEmpty() )
 
  763         attribute = QStringLiteral( 
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
 
  767         attribute = QStringLiteral( 
"concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
 
  775     const QVariantList categories = rendererData.value( QStringLiteral( 
"uniqueValueInfos" ) ).toList();
 
  777     for ( 
const QVariant &category : categories )
 
  779       const QVariantMap categoryData = category.toMap();
 
  780       const QString value = categoryData.value( QStringLiteral( 
"value" ) ).toString();
 
  781       const QString label = categoryData.value( QStringLiteral( 
"label" ) ).toString();
 
  789     std::unique_ptr< QgsSymbol > defaultSymbol( 
convertSymbol( rendererData.value( QStringLiteral( 
"defaultSymbol" ) ).toMap() ) );
 
  792       categoryList.append( 
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral( 
"defaultLabel" ) ).toString() ) );
 
  795     if ( categoryList.empty() )
 
  800   else if ( type == QLatin1String( 
"classBreaks" ) )
 
  805   else if ( type == QLatin1String( 
"heatmap" ) )
 
  810   else if ( type == QLatin1String( 
"vectorField" ) )
 
  820   QString expression = string;
 
  823   expression = expression.replace( QRegularExpression( 
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ), QStringLiteral( 
"\\4||\\5" ) );
 
  824   expression = expression.replace( QRegularExpression( 
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ), QStringLiteral( 
"\\4'\\n'\\5" ) );
 
  827   expression = expression.replace( QRegularExpression( 
"\"(.*?(?<!\\\\))\"" ), QStringLiteral( 
"'\\1'" ) );
 
  828   expression = expression.replace( QRegularExpression( 
"\\\\\"" ), QStringLiteral( 
"\"" ) );
 
  831   expression = expression.replace( QRegularExpression( 
"\\[([^]]*)\\]" ), QStringLiteral( 
"\"\\1\"" ) );
 
  838   const QVariantList colorParts = colorData.toList();
 
  839   if ( colorParts.count() < 4 )
 
  842   int red = colorParts.at( 0 ).toInt();
 
  843   int green = colorParts.at( 1 ).toInt();
 
  844   int blue = colorParts.at( 2 ).toInt();
 
  845   int alpha = colorParts.at( 3 ).toInt();
 
  846   return QColor( red, green, blue, alpha );
 
  851   if ( style == QLatin1String( 
"esriSLSSolid" ) )
 
  852     return Qt::SolidLine;
 
  853   else if ( style == QLatin1String( 
"esriSLSDash" ) )
 
  855   else if ( style == QLatin1String( 
"esriSLSDashDot" ) )
 
  856     return Qt::DashDotLine;
 
  857   else if ( style == QLatin1String( 
"esriSLSDashDotDot" ) )
 
  858     return Qt::DashDotDotLine;
 
  859   else if ( style == QLatin1String( 
"esriSLSDot" ) )
 
  861   else if ( style == QLatin1String( 
"esriSLSNull" ) )
 
  864     return Qt::SolidLine;
 
  869   if ( style == QLatin1String( 
"esriSFSBackwardDiagonal" ) )
 
  870     return Qt::BDiagPattern;
 
  871   else if ( style == QLatin1String( 
"esriSFSCross" ) )
 
  872     return Qt::CrossPattern;
 
  873   else if ( style == QLatin1String( 
"esriSFSDiagonalCross" ) )
 
  874     return Qt::DiagCrossPattern;
 
  875   else if ( style == QLatin1String( 
"esriSFSForwardDiagonal" ) )
 
  876     return Qt::FDiagPattern;
 
  877   else if ( style == QLatin1String( 
"esriSFSHorizontal" ) )
 
  878     return Qt::HorPattern;
 
  879   else if ( style == QLatin1String( 
"esriSFSNull" ) )
 
  881   else if ( style == QLatin1String( 
"esriSFSSolid" ) )
 
  882     return Qt::SolidPattern;
 
  883   else if ( style == QLatin1String( 
"esriSFSVertical" ) )
 
  884     return Qt::VerPattern;
 
  886     return Qt::SolidPattern;
 
  891   if ( value.isNull() )
 
  894   QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
 
  897     QgsDebugMsg( QStringLiteral( 
"Invalid value %1 for datetime" ).arg( value.toString() ) );
 
Abstract base class for all geometries.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
static QgsCoordinateReferenceSystem convertSpatialReference(const QVariantMap &spatialReferenceMap)
Converts a spatial reference JSON definition to a QgsCoordinateReferenceSystem value.
static QDateTime convertDateTime(const QVariant &value)
Converts a date time value to a QDateTime.
static QString convertLabelingExpression(const QString &string)
Converts an ESRI labeling expression to a QGIS expression string.
static QgsSymbol * convertSymbol(const QVariantMap &definition)
Converts a symbol JSON definition to a QgsSymbol.
static QgsAbstractGeometry * convertGeometry(const QVariantMap &geometry, const QString &esriGeometryType, bool hasM, bool hasZ, QgsCoordinateReferenceSystem *crs=nullptr)
Converts an ESRI REST geometry JSON definition to a QgsAbstractGeometry.
static Qt::PenStyle convertLineStyle(const QString &style)
Converts an ESRI line style to a Qt pen style.
static QgsFeatureRenderer * convertRenderer(const QVariantMap &rendererData)
Converts renderer JSON data to an equivalent QgsFeatureRenderer.
static Qt::BrushStyle convertFillStyle(const QString &style)
Converts an ESRI fill style to a Qt brush style.
static QVariant::Type convertFieldType(const QString &type)
Converts an ESRI REST field type to a QVariant type.
static QgsWkbTypes::Type convertGeometryType(const QString &type)
Converts an ESRI REST geometry type to a WKB type.
static QgsAbstractVectorLayerLabeling * convertLabeling(const QVariantList &data)
Converts labeling JSON data to an equivalent QGIS vector labeling.
static QColor convertColor(const QVariant &data)
Converts ESRI JSON color data to a QColor object.
Compound curve geometry type.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
Curve polygon geometry type.
virtual void setExteriorRing(QgsCurve *ring)
Sets the exterior ring of the polygon.
virtual void addInteriorRing(QgsCurve *ring)
Adds an interior ring to the geometry (takes ownership)
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool isValid() const
Checks if this expression is valid.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
void setPlacementFlags(QgsLabeling::LinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
Line string geometry type, with support for z-dimension and m-values.
QgsPoint endPoint() const override SIP_HOLDGIL
Returns the end point of the curve.
void addVertex(const QgsPoint &pt)
Adds a new vertex to the end of the line string.
Contains settings for how a map layer will be labeled.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
QuadrantPosition quadOffset
Sets the quadrant in which to offset labels from feature.
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
QString fieldName
Name of field (or an expression) to use for label text.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
A child rule for QgsRuleBasedLabeling.
void setActive(bool state)
Sets if this rule is active.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
Rule based labeling for a vector layer.
Shape
Marker symbol shapes.
@ Cross2
Rotated cross (lines only), "x" shape.
@ Cross
Cross (lines only)
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Abstract base class for all rendered symbols.
@ ScaleArea
Calculate scale by the area.
Container for settings relating to a text buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
@ RenderPoints
Points (e.g., for font sizes)
Type
The WKB type describes the number of dimensions a geometry has.
static Type zmType(Type type, bool hasZ, bool hasM) SIP_HOLDGIL
Returns the modified input geometry type according to hasZ / hasM.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsRendererCategory > QgsCategoryList
QList< QgsSymbolLayer * > QgsSymbolLayerList
const QgsCoordinateReferenceSystem & crs