diff --git a/python/core/qgsmaprenderer.sip b/python/core/qgsmaprenderer.sip index 0f62aeb1dc1..130069d6bfb 100644 --- a/python/core/qgsmaprenderer.sip +++ b/python/core/qgsmaprenderer.sip @@ -35,7 +35,7 @@ class QgsLabelingEngineInterface //! called when we're going to start with rendering //! @deprecated since 2.4 - use override with QgsMapSettings - virtual void init( QgsMapRenderer* mp ) = 0 /Deprecated/; + virtual void init( QgsMapRenderer *mp ) = 0 /Deprecated/; //! called when we're going to start with rendering virtual void init( const QgsMapSettings& mapSettings ) = 0; //! called to find out whether the layer is used for labeling @@ -48,17 +48,17 @@ class QgsLabelingEngineInterface virtual int prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) = 0; //! returns PAL layer settings for a registered layer //! @deprecated since 2.12 - if direct access to QgsPalLayerSettings is necessary, use QgsPalLayerSettings::fromLayer() - virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0 /Deprecated/; + virtual QgsPalLayerSettings &layer( const QString &layerName ) = 0 /Deprecated/; //! adds a diagram layer to the labeling engine //! @note added in QGIS 2.12 - virtual int prepareDiagramLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ); + virtual int prepareDiagramLayer( QgsVectorLayer *layer, QStringList &attrNames, QgsRenderContext &ctx ); //! adds a diagram layer to the labeling engine //! @deprecated since 2.12 - use prepareDiagramLayer() - virtual int addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLayerSettings* s ) /Deprecated/; + virtual int addDiagramLayer( QgsVectorLayer *layer, const QgsDiagramLayerSettings *s ) /Deprecated/; //! called for every feature - virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context, const QString& dxfLayer = QString::null ) = 0; + virtual void registerFeature( const QString &layerID, QgsFeature &feat, QgsRenderContext &context ) = 0; //! called for every diagram feature - virtual void registerDiagramFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ); + virtual void registerDiagramFeature( const QString &layerID, QgsFeature &feat, QgsRenderContext &context ); //! called when the map is drawn and labels should be placed virtual void drawLabeling( QgsRenderContext& context ) = 0; //! called when we're done with rendering @@ -268,7 +268,7 @@ class QgsMapRenderer : QObject //! Accessor for render context QgsRenderContext* rendererContext(); - //! Labeling engine (NULL if there's no custom engine) + //! Labeling engine (nullptr if there's no custom engine) QgsLabelingEngineInterface* labelingEngine(); //! Set labeling engine. Previous engine (if any) is deleted. diff --git a/python/core/qgspallabeling.sip b/python/core/qgspallabeling.sip index 0877730f047..0b3f813c600 100644 --- a/python/core/qgspallabeling.sip +++ b/python/core/qgspallabeling.sip @@ -551,7 +551,6 @@ class QgsPalLayerSettings * @param f feature to label * @param context render context. The QgsExpressionContext contained within the render context * must have already had the feature and fields sets prior to calling this method. - * @param dxfLayer dxfLayer name * @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available * in Python bindings. * @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry @@ -560,7 +559,7 @@ class QgsPalLayerSettings * the feature's original geometry will be used as an obstacle for labels. Not available * in Python bindings. */ - void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer ); + void registerFeature( QgsFeature& f, QgsRenderContext& context ); void readFromLayer( QgsVectorLayer* layer ); void writeToLayer( QgsVectorLayer* layer ); @@ -867,9 +866,8 @@ class QgsPalLabeling : QgsLabelingEngineInterface * @param feat feature to label * @param context render context. The QgsExpressionContext contained within the render context * must have already had the feature and fields sets prior to calling this method. - * @param dxfLayer dxfLayer name */ - virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context, const QString& dxfLayer = QString::null ); + virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ); virtual void registerDiagramFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ); //! called when the map is drawn and labels should be placed diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 92117f6ce95..a0a66878718 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -37,6 +37,11 @@ #include "qgsvectorlayer.h" #include "qgsmaplayerregistry.h" #include "qgsunittypes.h" +#include "qgstextlabelfeature.h" + +#include "pal/feature.h" +#include "pal/pointset.h" +#include "pal/labelposition.h" #include @@ -942,12 +947,32 @@ void QgsDxfExport::writeEntities() attributes << layerAttr; } - QgsDxfLabelProvider* lp = new QgsDxfLabelProvider( vl, this ); - engine.addProvider( lp ); - if ( !lp->prepare( ctx, attributes ) ) + const QgsAbstractVectorLayerLabeling *labeling = vl->labeling(); + QgsDxfLabelProvider *lp = nullptr; + QgsDxfRuleBasedLabelProvider *rblp = nullptr; + if ( dynamic_cast( labeling ) ) { - engine.removeProvider( lp ); - lp = nullptr; + const QgsRuleBasedLabeling *rbl = dynamic_cast( labeling ); + rblp = new QgsDxfRuleBasedLabelProvider( *rbl, vl, this ); + rblp->reinit( vl ); + engine.addProvider( rblp ); + + if ( !rblp->prepare( ctx, attributes ) ) + { + engine.removeProvider( rblp ); + rblp = nullptr; + } + } + else + { + lp = new QgsDxfLabelProvider( vl, this, nullptr ); + engine.addProvider( lp ); + + if ( !lp->prepare( ctx, attributes ) ) + { + engine.removeProvider( lp ); + lp = nullptr; + } } if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology && @@ -1012,6 +1037,10 @@ void QgsDxfExport::writeEntities() { lp->registerDxfFeature( fet, ctx, lName ); } + else if ( rblp ) + { + rblp->registerDxfFeature( fet, ctx, lName ); + } } } @@ -4169,3 +4198,112 @@ QString QgsDxfExport::layerName( QgsVectorLayer *vl ) const Q_ASSERT( vl ); return mLayerTitleAsName && !vl->title().isEmpty() ? vl->title() : vl->name(); } + +void QgsDxfExport::drawLabel( QString layerId, QgsRenderContext& context, pal::LabelPosition* label, const QgsPalLayerSettings &settings ) +{ + Q_UNUSED( context ); + QgsTextLabelFeature* lf = dynamic_cast( label->getFeaturePart()->feature() ); + if ( !lf ) + return; + + //label text + QString txt = lf->text( label->getPartId() ); + + //angle + double angle = label->getAlpha() * 180 / M_PI; + + QgsFeatureId fid = label->getFeaturePart()->featureId(); + QString dxfLayer = mDxfLayerNames[layerId][fid]; + + //debug: show label rectangle +#if 0 + QgsPolyline line; + for ( int i = 0; i < 4; ++i ) + { + line.append( QgsPoint( label->getX( i ), label->getY( i ) ) ); + } + writePolyline( line, dxfLayer, "CONTINUOUS", 1, 0.01, true ); +#endif + + QString wrapchr = settings.wrapChar.isEmpty() ? "\n" : settings.wrapChar; + + //add the direction symbol if needed + if ( !txt.isEmpty() && settings.placement == QgsPalLayerSettings::Line && settings.addDirectionSymbol ) + { + bool prependSymb = false; + QString symb = settings.rightDirectionSymbol; + + if ( label->getReversed() ) + { + prependSymb = true; + symb = settings.leftDirectionSymbol; + } + + if ( settings.reverseDirectionSymbol ) + { + if ( symb == settings.rightDirectionSymbol ) + { + prependSymb = true; + symb = settings.leftDirectionSymbol; + } + else + { + prependSymb = false; + symb = settings.rightDirectionSymbol; + } + } + + if ( settings.placeDirectionSymbol == QgsPalLayerSettings::SymbolAbove ) + { + prependSymb = true; + symb = symb + wrapchr; + } + else if ( settings.placeDirectionSymbol == QgsPalLayerSettings::SymbolBelow ) + { + prependSymb = false; + symb = wrapchr + symb; + } + + if ( prependSymb ) + { + txt.prepend( symb ); + } + else + { + txt.append( symb ); + } + } + + txt = txt.replace( wrapchr, "\\P" ); + + if ( settings.textFont.underline() ) + { + txt.prepend( "\\L" ).append( "\\l" ); + } + + if ( settings.textFont.overline() ) + { + txt.prepend( "\\O" ).append( "\\o" ); + } + + if ( settings.textFont.strikeOut() ) + { + txt.prepend( "\\K" ).append( "\\k" ); + } + + txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;\\W0.75;" ) + .arg( settings.textFont.family() ) + .arg( settings.textFont.italic() ? 1 : 0 ) + .arg( settings.textFont.bold() ? 1 : 0 ) + .arg( label->getHeight() / ( 1 + txt.count( "\\P" ) ) * 0.75 ) ); + + writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth() * 1.1, angle, settings.textColor ); +} + +void QgsDxfExport::registerDxfLayer( QString layerId, QgsFeatureId fid, QString layerName ) +{ + if ( !mDxfLayerNames.contains( layerId ) ) + mDxfLayerNames[ layerId ] = QMap(); + + mDxfLayerNames[layerId][fid] = layerName; +} diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index cc5c2322509..0a999f723c9 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -20,6 +20,7 @@ #include "qgsgeometry.h" #include "qgssymbolv2.h" + #include #include #include @@ -28,6 +29,12 @@ class QgsMapLayer; class QgsPoint; class QgsSymbolLayerV2; class QIODevice; +class QgsPalLayerSettings; + +namespace pal +{ + class LabelPosition; +}; class CORE_EXPORT QgsDxfExport { @@ -283,6 +290,9 @@ class CORE_EXPORT QgsDxfExport //! return list of available DXF encodings static QStringList encodings(); + void drawLabel( QString layerId, QgsRenderContext& context, pal::LabelPosition* label, const QgsPalLayerSettings &settings ); + void registerDxfLayer( QString layerId, QgsFeatureId fid, QString layer ); + private: QList< QPair > mLayers; @@ -350,6 +360,9 @@ class CORE_EXPORT QgsDxfExport QHash mBlockHandles; QString mBlockHandle; + + //! DXF layer name for each label feature + QMap< QString, QMap > mDxfLayerNames; }; #endif // QGSDXFEXPORT_H diff --git a/src/core/dxf/qgsdxfpallabeling.cpp b/src/core/dxf/qgsdxfpallabeling.cpp index 9785f47a852..928c14bc4d0 100644 --- a/src/core/dxf/qgsdxfpallabeling.cpp +++ b/src/core/dxf/qgsdxfpallabeling.cpp @@ -17,131 +17,57 @@ #include "qgsdxfpallabeling.h" #include "qgsdxfexport.h" -#include "qgstextlabelfeature.h" #include "qgspallabeling.h" #include "qgsmapsettings.h" - -#include "pal/feature.h" -#include "pal/pointset.h" -#include "pal/labelposition.h" +#include "qgslogger.h" -QgsDxfLabelProvider::QgsDxfLabelProvider( QgsVectorLayer* layer , QgsDxfExport* dxf ) - : QgsVectorLayerLabelProvider( layer, false ) +QgsDxfLabelProvider::QgsDxfLabelProvider( QgsVectorLayer* layer, QgsDxfExport* dxf, const QgsPalLayerSettings *settings ) + : QgsVectorLayerLabelProvider( layer, false, settings ) , mDxfExport( dxf ) { } void QgsDxfLabelProvider::drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const { - Q_UNUSED( context ); - - //debug: print label infos - if ( mDxfExport ) - { - QgsTextLabelFeature* lf = dynamic_cast( label->getFeaturePart()->feature() ); - if ( !lf ) - return; - - const QgsPalLayerSettings& tmpLyr = mSettings; - - //label text - QString txt = lf->text( label->getPartId() ); - - //angle - double angle = label->getAlpha() * 180 / M_PI; - - QgsFeatureId fid = label->getFeaturePart()->featureId(); - QString dxfLayer = mDxfLayerNames[fid]; - - //debug: show label rectangle -#if 0 - QgsPolyline line; - for ( int i = 0; i < 4; ++i ) - { - line.append( QgsPoint( label->getX( i ), label->getY( i ) ) ); - } - mDxfExport->writePolyline( line, dxfLayer, "CONTINUOUS", 1, 0.01, true ); -#endif - - QString wrapchr = tmpLyr.wrapChar.isEmpty() ? "\n" : tmpLyr.wrapChar; - - //add the direction symbol if needed - if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line && tmpLyr.addDirectionSymbol ) - { - bool prependSymb = false; - QString symb = tmpLyr.rightDirectionSymbol; - - if ( label->getReversed() ) - { - prependSymb = true; - symb = tmpLyr.leftDirectionSymbol; - } - - if ( tmpLyr.reverseDirectionSymbol ) - { - if ( symb == tmpLyr.rightDirectionSymbol ) - { - prependSymb = true; - symb = tmpLyr.leftDirectionSymbol; - } - else - { - prependSymb = false; - symb = tmpLyr.rightDirectionSymbol; - } - } - - if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolAbove ) - { - prependSymb = true; - symb = symb + wrapchr; - } - else if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolBelow ) - { - prependSymb = false; - symb = wrapchr + symb; - } - - if ( prependSymb ) - { - txt.prepend( symb ); - } - else - { - txt.append( symb ); - } - } - - txt = txt.replace( wrapchr, "\\P" ); - - if ( tmpLyr.textFont.underline() ) - { - txt.prepend( "\\L" ).append( "\\l" ); - } - - if ( tmpLyr.textFont.overline() ) - { - txt.prepend( "\\O" ).append( "\\o" ); - } - - if ( tmpLyr.textFont.strikeOut() ) - { - txt.prepend( "\\K" ).append( "\\k" ); - } - - txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;\\W0.75;" ) - .arg( tmpLyr.textFont.family() ) - .arg( tmpLyr.textFont.italic() ? 1 : 0 ) - .arg( tmpLyr.textFont.bold() ? 1 : 0 ) - .arg( label->getHeight() / ( 1 + txt.count( "\\P" ) ) * 0.75 ) ); - - mDxfExport->writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth() * 1.1, angle, tmpLyr.textColor ); - } + Q_ASSERT( mDxfExport ); + mDxfExport->drawLabel( layerId(), context, label, mSettings ); } void QgsDxfLabelProvider::registerDxfFeature( QgsFeature& feature, QgsRenderContext& context, const QString& dxfLayerName ) { registerFeature( feature, context ); - mDxfLayerNames[feature.id()] = dxfLayerName; + mDxfExport->registerDxfLayer( layerId(), feature.id(), dxfLayerName ); +} + +QgsDxfRuleBasedLabelProvider::QgsDxfRuleBasedLabelProvider( const QgsRuleBasedLabeling &rules, QgsVectorLayer* layer, QgsDxfExport* dxf ) + : QgsRuleBasedLabelProvider( rules, layer, false ) + , mDxfExport( dxf ) +{ +} + +void QgsDxfRuleBasedLabelProvider::reinit( QgsVectorLayer* layer ) +{ + QgsDebugMsg( "Entering." ); + mRules.rootRule()->createSubProviders( layer, mSubProviders, this ); +} + +QgsVectorLayerLabelProvider *QgsDxfRuleBasedLabelProvider::createProvider( QgsVectorLayer *layer, bool withFeatureLoop, const QgsPalLayerSettings *settings ) +{ + QgsDebugMsg( "Entering." ); + Q_UNUSED( withFeatureLoop ); + return new QgsDxfLabelProvider( layer, mDxfExport, settings ); +} + +void QgsDxfRuleBasedLabelProvider::drawLabel( QgsRenderContext &context, pal::LabelPosition *label ) const +{ + QgsDebugMsg( "Entering." ); + Q_ASSERT( mDxfExport ); + mDxfExport->drawLabel( layerId(), context, label, mSettings ); +} + +void QgsDxfRuleBasedLabelProvider::registerDxfFeature( QgsFeature &feature, QgsRenderContext &context, const QString &dxfLayerName ) +{ + registerFeature( feature, context ); + mDxfExport->registerDxfLayer( layerId(), feature.id(), dxfLayerName ); } diff --git a/src/core/dxf/qgsdxfpallabeling.h b/src/core/dxf/qgsdxfpallabeling.h index f051b500772..e48d6089d48 100644 --- a/src/core/dxf/qgsdxfpallabeling.h +++ b/src/core/dxf/qgsdxfpallabeling.h @@ -21,8 +21,11 @@ #include "qgsmaprenderer.h" #include "qgsrendercontext.h" #include "qgsvectorlayerlabelprovider.h" +#include "qgsrulebasedlabeling.h" class QgsDxfExport; +class QgsPalLayerSettings; +class QgsRuleBasedLabeling; /** Implements a derived label provider internally used for DXF export @@ -34,10 +37,10 @@ class QgsDxfLabelProvider : public QgsVectorLayerLabelProvider { public: //! construct the provider - explicit QgsDxfLabelProvider( QgsVectorLayer* layer, QgsDxfExport* dxf ); + explicit QgsDxfLabelProvider( QgsVectorLayer* layer, QgsDxfExport* dxf, const QgsPalLayerSettings *settings ); //! re-implementation that writes to DXF file instead of drawing with QPainter - virtual void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const override; + void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const override; //! registration method that keeps track of DXF layer names of individual features void registerDxfFeature( QgsFeature& feature, QgsRenderContext &context, const QString& dxfLayerName ); @@ -45,8 +48,29 @@ class QgsDxfLabelProvider : public QgsVectorLayerLabelProvider protected: //! pointer to parent DXF export where this instance is used QgsDxfExport* mDxfExport; - //! DXF layer name for each label feature - QMap mDxfLayerNames; }; +class QgsDxfRuleBasedLabelProvider : public QgsRuleBasedLabelProvider +{ + public: + //! construct the provider + explicit QgsDxfRuleBasedLabelProvider( const QgsRuleBasedLabeling &rules, QgsVectorLayer* layer, QgsDxfExport* dxf ); + + void reinit( QgsVectorLayer* layer ); + + //! re-implementation that writes to DXF file instead of drawing with QPainter + void drawLabel( QgsRenderContext &context, pal::LabelPosition *label ) const override; + + //! registration method that keeps track of DXF layer names of individual features + void registerDxfFeature( QgsFeature& feature, QgsRenderContext &context, const QString& dxfLayerName ); + + virtual QgsVectorLayerLabelProvider *createProvider( QgsVectorLayer *layer, bool withFeatureLoop, const QgsPalLayerSettings *settings ) override; + + protected: + //! pointer to parent DXF export where this instance is used + QgsDxfExport* mDxfExport; +}; + + + #endif // QGSDXFPALLABELING_H diff --git a/src/core/qgslabelfeature.cpp b/src/core/qgslabelfeature.cpp index 4f0cd624ab6..4ed75b75530 100644 --- a/src/core/qgslabelfeature.cpp +++ b/src/core/qgslabelfeature.cpp @@ -13,7 +13,6 @@ * * ***************************************************************************/ #include "qgslabelfeature.h" - #include "feature.h" diff --git a/src/core/qgsmaprenderer.h b/src/core/qgsmaprenderer.h index 15ebb875479..648a38a25b1 100644 --- a/src/core/qgsmaprenderer.h +++ b/src/core/qgsmaprenderer.h @@ -46,9 +46,10 @@ class QgsDiagramLayerSettings; class CORE_EXPORT QgsLabelPosition { public: - QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, const QString& labeltext, const QFont& labelfont, bool upside_down, bool diagram = false, bool pinned = false ): - featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), labelText( labeltext ), labelFont( labelfont ), upsideDown( upside_down ), isDiagram( diagram ), isPinned( pinned ) {} - QgsLabelPosition(): featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), labelText( "" ), labelFont( QFont() ), upsideDown( false ), isDiagram( false ), isPinned( false ) {} + QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, const QString& labeltext, const QFont& labelfont, bool upside_down, bool diagram = false, bool pinned = false ) + : featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), labelText( labeltext ), labelFont( labelfont ), upsideDown( upside_down ), isDiagram( diagram ), isPinned( pinned ) {} + QgsLabelPosition() + : featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), labelText( "" ), labelFont( QFont() ), upsideDown( false ), isDiagram( false ), isPinned( false ) {} int featureId; double rotation; QVector< QgsPoint > cornerPoints; @@ -72,7 +73,7 @@ class CORE_EXPORT QgsLabelingEngineInterface //! called when we're going to start with rendering //! @deprecated since 2.4 - use override with QgsMapSettings - Q_DECL_DEPRECATED virtual void init( QgsMapRenderer* mp ) = 0; + Q_DECL_DEPRECATED virtual void init( QgsMapRenderer *mp ) = 0; //! called when we're going to start with rendering virtual void init( const QgsMapSettings& mapSettings ) = 0; //! called to find out whether the layer is used for labeling @@ -85,19 +86,19 @@ class CORE_EXPORT QgsLabelingEngineInterface virtual int prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) = 0; //! returns PAL layer settings for a registered layer //! @deprecated since 2.12 - if direct access to QgsPalLayerSettings is necessary, use QgsPalLayerSettings::fromLayer() - Q_DECL_DEPRECATED virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0; + Q_DECL_DEPRECATED virtual QgsPalLayerSettings &layer( const QString &layerName ) = 0; //! adds a diagram layer to the labeling engine //! @note added in QGIS 2.12 - virtual int prepareDiagramLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) + virtual int prepareDiagramLayer( QgsVectorLayer *layer, QStringList &attrNames, QgsRenderContext &ctx ) { Q_UNUSED( layer ); Q_UNUSED( attrNames ); Q_UNUSED( ctx ); return 0; } //! adds a diagram layer to the labeling engine //! @deprecated since 2.12 - use prepareDiagramLayer() - Q_DECL_DEPRECATED virtual int addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLayerSettings* s ) + Q_DECL_DEPRECATED virtual int addDiagramLayer( QgsVectorLayer *layer, const QgsDiagramLayerSettings *s ) { Q_UNUSED( layer ); Q_UNUSED( s ); return 0; } //! called for every feature - virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context, const QString& dxfLayer = QString::null ) = 0; + virtual void registerFeature( const QString &layerID, QgsFeature &feat, QgsRenderContext &context ) = 0; //! called for every diagram feature - virtual void registerDiagramFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ) + virtual void registerDiagramFeature( const QString &layerID, QgsFeature &feat, QgsRenderContext &context ) { Q_UNUSED( layerID ); Q_UNUSED( feat ); Q_UNUSED( context ); } //! called when the map is drawn and labels should be placed virtual void drawLabeling( QgsRenderContext& context ) = 0; diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp index cb0562f1f1c..f1a50ab267a 100644 --- a/src/core/qgspallabeling.cpp +++ b/src/core/qgspallabeling.cpp @@ -1939,13 +1939,11 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t #endif } -void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** labelFeature , QgsGeometry* obstacleGeometry ) +void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &context, QgsLabelFeature** labelFeature , QgsGeometry* obstacleGeometry ) { // either used in QgsPalLabeling (palLayer is set) or in QgsLabelingEngineV2 (labelFeature is set) Q_ASSERT( labelFeature ); - Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider - QVariant exprVal; // value() is repeatedly nulled on data defined evaluation and replaced when successful mCurFeat = &f; @@ -1960,7 +1958,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont { if ( isObstacle ) { - registerObstacleFeature( f, context, QString(), labelFeature, obstacleGeometry ); + registerObstacleFeature( f, context, labelFeature, obstacleGeometry ); } return; } @@ -2812,10 +2810,8 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont lf->setDataDefinedValues( dataDefinedValues ); } -void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry ) +void QgsPalLayerSettings::registerObstacleFeature( QgsFeature& f, QgsRenderContext &context, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry ) { - Q_UNUSED( dxfLayer ); // now handled in QgsDxfLabelProvider - mCurFeat = &f; const QgsGeometry* geom = nullptr; @@ -3809,9 +3805,8 @@ int QgsPalLabeling::addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLaye return 0; } -void QgsPalLabeling::registerFeature( const QString& layerID, QgsFeature& f, QgsRenderContext &context, const QString& dxfLayer ) +void QgsPalLabeling::registerFeature( const QString& layerID, QgsFeature& f, QgsRenderContext &context ) { - Q_UNUSED( dxfLayer ); // now handled by QgsDxfLabelProvider if ( QgsVectorLayerLabelProvider* provider = mLabelProviders.value( layerID, nullptr ) ) provider->registerFeature( f, context ); } diff --git a/src/core/qgspallabeling.h b/src/core/qgspallabeling.h index da9e25917da..0f25764815a 100644 --- a/src/core/qgspallabeling.h +++ b/src/core/qgspallabeling.h @@ -533,7 +533,6 @@ class CORE_EXPORT QgsPalLayerSettings * @param f feature to label * @param context render context. The QgsExpressionContext contained within the render context * must have already had the feature and fields sets prior to calling this method. - * @param dxfLayer dxfLayer name * @param labelFeature if using QgsLabelingEngineV2, this will receive the label feature. Not available * in Python bindings. * @param obstacleGeometry optional obstacle geometry, if a different geometry to the feature's geometry @@ -542,7 +541,7 @@ class CORE_EXPORT QgsPalLayerSettings * the feature's original geometry will be used as an obstacle for labels. Not available * in Python bindings. */ - void registerFeature( QgsFeature& f, QgsRenderContext& context, const QString& dxfLayer, QgsLabelFeature** labelFeature = nullptr, QgsGeometry* obstacleGeometry = nullptr ); + void registerFeature( QgsFeature& f, QgsRenderContext& context, QgsLabelFeature** labelFeature = nullptr, QgsGeometry* obstacleGeometry = nullptr ); void readFromLayer( QgsVectorLayer* layer ); void writeToLayer( QgsVectorLayer* layer ); @@ -712,7 +711,7 @@ class CORE_EXPORT QgsPalLayerSettings /** Registers a feature as an obstacle only (no label rendered) */ - void registerObstacleFeature( QgsFeature &f, QgsRenderContext &context, const QString& dxfLayer, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry = nullptr ); + void registerObstacleFeature( QgsFeature &f, QgsRenderContext &context, QgsLabelFeature** obstacleFeature, QgsGeometry* obstacleGeometry = nullptr ); QMap dataDefinedValues; QgsExpression* expression; @@ -949,9 +948,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface * @param feat feature to label * @param context render context. The QgsExpressionContext contained within the render context * must have already had the feature and fields sets prior to calling this method. - * @param dxfLayer dxfLayer name */ - virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context, const QString& dxfLayer = QString::null ) override; + virtual void registerFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ) override; virtual void registerDiagramFeature( const QString& layerID, QgsFeature& feat, QgsRenderContext& context ) override; //! called when the map is drawn and labels should be placed diff --git a/src/core/qgsrulebasedlabeling.cpp b/src/core/qgsrulebasedlabeling.cpp index 54fbf21f5ed..4f89475d0ab 100644 --- a/src/core/qgsrulebasedlabeling.cpp +++ b/src/core/qgsrulebasedlabeling.cpp @@ -15,12 +15,11 @@ #include "qgsrulebasedlabeling.h" - QgsRuleBasedLabelProvider::QgsRuleBasedLabelProvider( const QgsRuleBasedLabeling& rules, QgsVectorLayer* layer, bool withFeatureLoop ) : QgsVectorLayerLabelProvider( layer, withFeatureLoop ) , mRules( rules ) { - mRules.rootRule()->createSubProviders( layer, mSubProviders ); + mRules.rootRule()->createSubProviders( layer, mSubProviders, this ); } QgsRuleBasedLabelProvider::~QgsRuleBasedLabelProvider() @@ -28,6 +27,10 @@ QgsRuleBasedLabelProvider::~QgsRuleBasedLabelProvider() // sub-providers owned by labeling engine } +QgsVectorLayerLabelProvider *QgsRuleBasedLabelProvider::createProvider( QgsVectorLayer *layer, bool withFeatureLoop, const QgsPalLayerSettings *settings ) +{ + return new QgsVectorLayerLabelProvider( layer, withFeatureLoop, settings ); +} bool QgsRuleBasedLabelProvider::prepare( const QgsRenderContext& context, QStringList& attributeNames ) { @@ -213,19 +216,20 @@ QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument& doc ) const return ruleElem; } -void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer* layer, QgsRuleBasedLabeling::RuleToProviderMap& subProviders ) +void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer* layer, QgsRuleBasedLabeling::RuleToProviderMap& subProviders, QgsRuleBasedLabelProvider *provider ) { if ( mSettings ) { // add provider! - QgsVectorLayerLabelProvider* p = new QgsVectorLayerLabelProvider( layer, false, mSettings ); + QgsVectorLayerLabelProvider *p = provider->createProvider( layer, false, mSettings ); + delete subProviders.value( this, nullptr ); subProviders[this] = p; } // call recursively Q_FOREACH ( Rule* rule, mChildren ) { - rule->createSubProviders( layer, subProviders ); + rule->createSubProviders( layer, subProviders, provider ); } } @@ -262,6 +266,8 @@ QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerF bool registered = false; + Q_ASSERT( !mSettings == subProviders.contains( this ) ); + // do we have active subprovider for the rule? if ( subProviders.contains( this ) && mIsActive ) { diff --git a/src/core/qgsrulebasedlabeling.h b/src/core/qgsrulebasedlabeling.h index ac4d0fb8721..8d39b8efd19 100644 --- a/src/core/qgsrulebasedlabeling.h +++ b/src/core/qgsrulebasedlabeling.h @@ -19,6 +19,7 @@ #include #include "qgsvectorlayerlabeling.h" +#include "qgsvectorlayerlabelprovider.h" class QDomDocument; class QDomElement; @@ -28,6 +29,7 @@ class QgsFeature; class QgsPalLayerSettings; class QgsRenderContext; class QgsGeometry; +class QgsRuleBasedLabelProvider; /** * @class QgsRuleBasedLabeling @@ -42,7 +44,6 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling typedef QList RuleList; typedef QMap RuleToProviderMap; - /** * @class QgsRuleBasedLabeling::Rule * @note not available in Python bindings @@ -214,7 +215,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling // evaluation //! add providers - void createSubProviders( QgsVectorLayer* layer, RuleToProviderMap& subProviders ); + void createSubProviders( QgsVectorLayer* layer, RuleToProviderMap& subProviders, QgsRuleBasedLabelProvider *provider ); //! call prepare() on sub-providers and populate attributeNames void prepare( const QgsRenderContext& context, QStringList& attributeNames, RuleToProviderMap& subProviders ); @@ -285,15 +286,13 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling virtual QString type() const override; virtual QDomElement save( QDomDocument& doc ) const override; - virtual QgsVectorLayerLabelProvider* provider( QgsVectorLayer* layer ) const override; + virtual QgsVectorLayerLabelProvider *provider( QgsVectorLayer* layer ) const override; protected: Rule* mRootRule; }; -#include "qgsvectorlayerlabelprovider.h" - /** * @class QgsRuleBasedLabelProvider * @note not available in Python bindings @@ -312,6 +311,7 @@ class CORE_EXPORT QgsRuleBasedLabelProvider : public QgsVectorLayerLabelProvider virtual void registerFeature( QgsFeature& feature, QgsRenderContext& context, QgsGeometry* obstacleGeometry = nullptr ) override; // new methods + virtual QgsVectorLayerLabelProvider *createProvider( QgsVectorLayer *layer, bool withFeatureLoop, const QgsPalLayerSettings *settings ); virtual QList subProviders() override; diff --git a/src/core/qgsvectorlayerlabelprovider.cpp b/src/core/qgsvectorlayerlabelprovider.cpp index fb8127816a2..a6bc3fd7f98 100644 --- a/src/core/qgsvectorlayerlabelprovider.cpp +++ b/src/core/qgsvectorlayerlabelprovider.cpp @@ -316,7 +316,7 @@ QList QgsVectorLayerLabelProvider::labelFeatures( QgsRenderCon void QgsVectorLayerLabelProvider::registerFeature( QgsFeature& feature, QgsRenderContext& context, QgsGeometry* obstacleGeometry ) { QgsLabelFeature* label = nullptr; - mSettings.registerFeature( feature, context, QString(), &label, obstacleGeometry ); + mSettings.registerFeature( feature, context, &label, obstacleGeometry ); if ( label ) mLabels << label; } diff --git a/src/core/qgsvectorlayerlabelprovider.h b/src/core/qgsvectorlayerlabelprovider.h index 3ad6049c531..fb3efafc15d 100644 --- a/src/core/qgsvectorlayerlabelprovider.h +++ b/src/core/qgsvectorlayerlabelprovider.h @@ -116,5 +116,4 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider QList mLabels; }; - #endif // QGSVECTORLAYERLABELPROVIDER_H diff --git a/tests/src/core/testqgslabelingenginev2.cpp b/tests/src/core/testqgslabelingenginev2.cpp index daea089a09b..9f70edf3c42 100644 --- a/tests/src/core/testqgslabelingenginev2.cpp +++ b/tests/src/core/testqgslabelingenginev2.cpp @@ -259,7 +259,7 @@ void TestQgsLabelingEngineV2::testRuleBased() delete rl2; - /* +#if 0 QPainter p( &img ); QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings ); context.setPainter( &p ); @@ -267,7 +267,8 @@ void TestQgsLabelingEngineV2::testRuleBased() QgsLabelingEngineV2 engine; engine.setMapSettings( mapSettings ); engine.addProvider( new QgsRuleBasedLabelProvider( , vl ) ); - engine.run( context );*/ + engine.run( context ); +#endif } void TestQgsLabelingEngineV2::zOrder()