diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp index 26dc70bf495..092b9c065bd 100644 --- a/src/core/qgspallabeling.cpp +++ b/src/core/qgspallabeling.cpp @@ -43,6 +43,7 @@ #include "qgsexpression.h" #include "qgsdatadefined.h" #include "qgslabelingenginev2.h" +#include "qgsvectorlayerlabeling.h" #include #include @@ -3610,7 +3611,6 @@ void QgsPalLabeling::clearActiveLayer( const QString &layerID ) Q_UNUSED( layerID ); } -#include "qgsvectorlayerlabeling.h" int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) { @@ -3619,7 +3619,10 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, return 0; } - QgsVectorLayerLabelProvider* lp = layer->labeling().provider( layer ); + if ( !layer->labeling() ) + return 0; + + QgsVectorLayerLabelProvider* lp = layer->labeling()->provider( layer ); if ( !lp ) return 0; diff --git a/src/core/qgsrulebasedlabeling.cpp b/src/core/qgsrulebasedlabeling.cpp index 54dc969b104..e40862aa957 100644 --- a/src/core/qgsrulebasedlabeling.cpp +++ b/src/core/qgsrulebasedlabeling.cpp @@ -139,7 +139,7 @@ QgsRuleBasedLabeling::Rule*QgsRuleBasedLabeling::Rule::create( QDomElement& rule return rule; } -QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument& doc ) +QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument& doc ) const { QDomElement ruleElem = doc.createElement( "rule" ); @@ -161,7 +161,7 @@ QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument& doc ) // ruleElem.setAttribute( "checkstate", 0 ); //ruleElem.setAttribute( "key", mRuleKey ); - for ( RuleList::iterator it = mChildren.begin(); it != mChildren.end(); ++it ) + for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it ) { Rule* rule = *it; ruleElem.appendChild( rule->save( doc ) ); @@ -265,7 +265,12 @@ QgsRuleBasedLabeling*QgsRuleBasedLabeling::create( QDomElement& element ) return rl; } -QDomElement QgsRuleBasedLabeling::save( QDomDocument& doc ) +QString QgsRuleBasedLabeling::type() const +{ + return "rule-based"; +} + +QDomElement QgsRuleBasedLabeling::save( QDomDocument& doc ) const { QDomElement elem = doc.createElement( "labeling" ); elem.setAttribute( "type", "rule-based" ); @@ -276,3 +281,8 @@ QDomElement QgsRuleBasedLabeling::save( QDomDocument& doc ) return elem; } + +QgsVectorLayerLabelProvider* QgsRuleBasedLabeling::provider( QgsVectorLayer* layer ) const +{ + return new QgsRuleBasedLabelProvider( *this, layer, false ); +} diff --git a/src/core/qgsrulebasedlabeling.h b/src/core/qgsrulebasedlabeling.h index 12394c35ae5..f3083e4984b 100644 --- a/src/core/qgsrulebasedlabeling.h +++ b/src/core/qgsrulebasedlabeling.h @@ -3,6 +3,8 @@ #include +#include "qgsvectorlayerlabeling.h" + class QDomDocument; class QDomElement; @@ -10,11 +12,9 @@ class QgsExpression; class QgsFeature; class QgsPalLayerSettings; class QgsRenderContext; -class QgsVectorLayer; -class QgsVectorLayerLabelProvider; -class CORE_EXPORT QgsRuleBasedLabeling +class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling { public: class Rule; @@ -49,7 +49,7 @@ class CORE_EXPORT QgsRuleBasedLabeling * * @return True if this rule is an else rule */ - bool isElse() { return mElseRule; } + bool isElse() const { return mElseRule; } void setLabel( QString label ) { mLabel = label; } /** @@ -93,13 +93,13 @@ class CORE_EXPORT QgsRuleBasedLabeling * * @return A list of rules */ - RuleList& children() { return mChildren; } + const RuleList& children() const { return mChildren; } /** * The parent rule * * @return Parent rule */ - Rule* parent() { return mParent; } + const Rule* parent() const { return mParent; } //! add child rule, take ownership, sets this as parent void appendChild( Rule* rule ); @@ -117,7 +117,7 @@ class CORE_EXPORT QgsRuleBasedLabeling static Rule* create( QDomElement& ruleElem ); //! store labeling info to XML element - QDomElement save( QDomDocument& doc ); + QDomElement save( QDomDocument& doc ) const; // evaluation @@ -162,13 +162,16 @@ class CORE_EXPORT QgsRuleBasedLabeling ~QgsRuleBasedLabeling(); Rule* rootRule() { return mRootRule; } + const Rule* rootRule() const { return mRootRule; } //! Create the instance from a DOM element with saved configuration static QgsRuleBasedLabeling* create( QDomElement& element ); - //! Save configuration into a DOM element - QDomElement save( QDomDocument& doc ); + // implementation of parent interface + virtual QString type() const override; + virtual QDomElement save( QDomDocument& doc ) const override; + virtual QgsVectorLayerLabelProvider* provider( QgsVectorLayer* layer ) const override; protected: Rule* mRootRule; diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index adf127fa29e..63dc039923a 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -132,7 +132,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath, , mRendererV2( NULL ) , mLabel( 0 ) , mLabelOn( false ) - , mLabeling( new QgsVectorLayerLabeling ) + , mLabeling( new QgsVectorLayerSimpleLabeling ) , mLabelFontNotFoundNotified( false ) , mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending , mLayerTransparency( 0 ) @@ -1234,6 +1234,15 @@ bool QgsVectorLayer::hasLabelsEnabled( void ) const return mLabelOn; } +void QgsVectorLayer::setLabeling( QgsAbstractVectorLayerLabeling* labeling ) +{ + if ( mLabeling == labeling ) + return; + + delete mLabeling; + mLabeling = labeling; +} + bool QgsVectorLayer::startEditing() { if ( !mDataProvider ) diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index 2508dba2211..dea955b15ba 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -63,7 +63,7 @@ class QgsSymbolV2; class QgsVectorDataProvider; class QgsVectorLayerEditBuffer; class QgsVectorLayerJoinBuffer; -class QgsVectorLayerLabeling; +class QgsAbstractVectorLayerLabeling; class QgsPointV2; typedef QList QgsAttributeList; @@ -1262,10 +1262,15 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer */ Q_DECL_DEPRECATED bool hasLabelsEnabled() const; - /** Access to labeling configuration + /** Access to labeling configuration. * @note added in 2.12 */ - QgsVectorLayerLabeling& labeling() { return *mLabeling; } + const QgsAbstractVectorLayerLabeling* labeling() const { return mLabeling; } + + /** Set labeling configuration. Takes ownership of the object. + * @note added in 2.12 + */ + void setLabeling( QgsAbstractVectorLayerLabeling* labeling ); /** Returns true if the provider is in editing mode */ virtual bool isEditable() const override; @@ -2092,7 +2097,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer bool mLabelOn; /** Labeling configuration */ - QgsVectorLayerLabeling* mLabeling; + QgsAbstractVectorLayerLabeling* mLabeling; /** Whether 'labeling font not found' has be shown for this layer (only show once in QgsMessageBar, on first rendering) */ bool mLabelFontNotFoundNotified; diff --git a/src/core/qgsvectorlayerlabeling.cpp b/src/core/qgsvectorlayerlabeling.cpp index c6966048c86..c5fee2a96b4 100644 --- a/src/core/qgsvectorlayerlabeling.cpp +++ b/src/core/qgsvectorlayerlabeling.cpp @@ -4,72 +4,28 @@ #include "qgsrulebasedlabeling.h" #include "qgsvectorlayer.h" -QgsVectorLayerLabeling::QgsVectorLayerLabeling() - : mMode( SimpleLabels ) - //, mSimpleLabeling( 0 ) - , mRuleBasedLabeling( 0 ) -{ +QgsAbstractVectorLayerLabeling::~QgsAbstractVectorLayerLabeling() +{ } -QgsVectorLayerLabeling::~QgsVectorLayerLabeling() +QgsVectorLayerLabelProvider* QgsVectorLayerSimpleLabeling::provider( QgsVectorLayer* layer ) const { - //delete mSimpleLabeling; - delete mRuleBasedLabeling; -} + if ( layer->customProperty( "labeling" ).toString() == QString( "pal" ) && layer->labelsEnabled() ) + return new QgsVectorLayerLabelProvider( layer, false ); -//QgsPalLayerSettings QgsVectorLayerLabeling::simpleLabeling() -//{ -//} - -//void QgsVectorLayerLabeling::setSimpleLabeling(QgsPalLayerSettings* settings) -//{ -// delete mSimpleLabeling; -// mSimpleLabeling = settings; -//} - -void QgsVectorLayerLabeling::setRuleBasedLabeling( QgsRuleBasedLabeling* settings ) -{ - delete mRuleBasedLabeling; - mRuleBasedLabeling = settings; -} - -QgsVectorLayerLabelProvider* QgsVectorLayerLabeling::provider( QgsVectorLayer* layer ) -{ - if ( mMode == SimpleLabels ) - { - if ( layer->customProperty( "labeling" ).toString() == QString( "pal" ) && layer->labelsEnabled() ) - return new QgsVectorLayerLabelProvider( layer, false ); - } - else // rule-based - { - if ( mRuleBasedLabeling ) - return new QgsRuleBasedLabelProvider( *mRuleBasedLabeling, layer, false ); - } return 0; } -/* -QgsAbstractLabelProvider* QgsVectorLayerLabeling::addProviderToEngine( QgsVectorLayer* layer, QgsLabelingEngineV2* engine, QgsRenderContext& context ) +QString QgsVectorLayerSimpleLabeling::type() const { - if ( mMode == SimpleLabels ) - { - QgsVectorLayerLabelProvider* provider = 0; - if ( layer->labelsEnabled() ) - { - provider = new QgsVectorLayerLabelProvider( layer, false ); - engine->addProvider( provider ); - if ( !provider->prepare( context, attributeNames ) ) - { - engine->removeProvider( provider ); - provider = 0; // deleted by engine - } - } - } - else // rule-based - { - return 0; // TODO - } - + return "simple"; +} + +QDomElement QgsVectorLayerSimpleLabeling::save( QDomDocument& doc ) const +{ + // all configuration is kept in layer custom properties (for compatibility) + QDomElement elem = doc.createElement( "labeling" ); + elem.setAttribute( "type", "simple" ); + return elem; } -*/ diff --git a/src/core/qgsvectorlayerlabeling.h b/src/core/qgsvectorlayerlabeling.h index e54f15360ef..51c6e240fed 100644 --- a/src/core/qgsvectorlayerlabeling.h +++ b/src/core/qgsvectorlayerlabeling.h @@ -1,49 +1,48 @@ #ifndef QGSVECTORLAYERLABELING_H #define QGSVECTORLAYERLABELING_H +class QDomDocument; +class QDomElement; +class QString; -class QgsPalLayerSettings; -class QgsRuleBasedLabeling; class QgsVectorLayer; class QgsVectorLayerLabelProvider; -class CORE_EXPORT QgsVectorLayerLabeling +/** + * Abstract base class - its implementations define different approaches to the labeling of a vector layer. + * + * @note added in 2.12 + */ +class CORE_EXPORT QgsAbstractVectorLayerLabeling { public: - enum Mode - { - //NoLabels, //!< the layer does not participate in labeling - //Obstacles, //!< no labels are shown, but layer's features act as obstacles for other labels - SimpleLabels, //!< the layer is labelled with one style - RuleBasedLabels //!< the layer is labelled with multiple styles defined with rules - }; - //! Defaults to no labels - QgsVectorLayerLabeling(); - ~QgsVectorLayerLabeling(); + virtual ~QgsAbstractVectorLayerLabeling(); - Mode mode() const { return mMode; } - void setMode( Mode m ) { mMode = m; } + //! Unique type string of the labeling configuration implementation + virtual QString type() const = 0; - //QgsPalLayerSettings simpleLabeling(); - - //QgsPalLayerSettings* simpleLabeling() const { return mSimpleLabeling; } - //! Assign simple labeling configuration (takes ownership) - //void setSimpleLabeling( QgsPalLayerSettings* settings ); - - QgsRuleBasedLabeling* ruleBasedLabeling() const { return mRuleBasedLabeling; } - //! Assign rule-based labeling configuration (takes ownership) - void setRuleBasedLabeling( QgsRuleBasedLabeling* settings ); - - //! Factory for label provider implementation - according to the current mode - QgsVectorLayerLabelProvider* provider( QgsVectorLayer* layer ); - - protected: - Mode mMode; - //QgsPalLayerSettings* mSimpleLabeling; - QgsRuleBasedLabeling* mRuleBasedLabeling; + //! Factory for label provider implementation + virtual QgsVectorLayerLabelProvider* provider( QgsVectorLayer* layer ) const = 0; + //! Return labeling configuration as XML element + virtual QDomElement save( QDomDocument& doc ) const = 0; }; +/** + * Basic implementation of the labeling interface. + * + * The configuration is kept in layer's custom properties for backward compatibility. + * + * @note added in 2.12 + */ +class CORE_EXPORT QgsVectorLayerSimpleLabeling : public QgsAbstractVectorLayerLabeling +{ + public: + + virtual QString type() const override; + virtual QgsVectorLayerLabelProvider* provider( QgsVectorLayer* layer ) const override; + virtual QDomElement save( QDomDocument& doc ) const override; +}; #endif // QGSVECTORLAYERLABELING_H diff --git a/src/core/qgsvectorlayerlabelprovider.h b/src/core/qgsvectorlayerlabelprovider.h index 36c68d63d9b..44faa77faee 100644 --- a/src/core/qgsvectorlayerlabelprovider.h +++ b/src/core/qgsvectorlayerlabelprovider.h @@ -23,7 +23,7 @@ class QgsAbstractFeatureSource; /** * @brief The QgsVectorLayerLabelProvider class implements a label provider * for vector layers. Parameters for the labeling are taken from the layer's - * custom properties. + * custom properties or from the given settings. * * @note added in QGIS 2.12 */ diff --git a/src/core/qgsvectorlayerrenderer.cpp b/src/core/qgsvectorlayerrenderer.cpp index bbf57750607..d1c9b7bd02c 100644 --- a/src/core/qgsvectorlayerrenderer.cpp +++ b/src/core/qgsvectorlayerrenderer.cpp @@ -495,28 +495,19 @@ void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList { if ( QgsLabelingEngineV2* engine2 = mContext.labelingEngineV2() ) { - mLabelProvider = layer->labeling().provider( layer ); - if ( mLabelProvider ) + if ( layer->labeling() ) { - engine2->addProvider( mLabelProvider ); - if ( !mLabelProvider->prepare( mContext, attributeNames ) ) + mLabelProvider = layer->labeling()->provider( layer ); + if ( mLabelProvider ) { - engine2->removeProvider( mLabelProvider ); - mLabelProvider = 0; // deleted by engine + engine2->addProvider( mLabelProvider ); + if ( !mLabelProvider->prepare( mContext, attributeNames ) ) + { + engine2->removeProvider( mLabelProvider ); + mLabelProvider = 0; // deleted by engine + } } } - - //mLabelProvider = layer->labeling().addProviderToEngine( layer, engine2, mContext ); - /*if ( layer->labelsEnabled() ) - { - mLabelProvider = new QgsVectorLayerLabelProvider( layer, false ); - engine2->addProvider( mLabelProvider ); - if ( !mLabelProvider->prepare( mContext, attributeNames ) ) - { - engine2->removeProvider( mLabelProvider ); - mLabelProvider = 0; // deleted by engine - } - }*/ } return; } diff --git a/tests/src/core/testqgslabelingenginev2.cpp b/tests/src/core/testqgslabelingenginev2.cpp index 0bef19c234b..d2032b71c3e 100644 --- a/tests/src/core/testqgslabelingenginev2.cpp +++ b/tests/src/core/testqgslabelingenginev2.cpp @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include class TestQgsLabelingEngineV2 : public QObject @@ -140,8 +142,6 @@ void TestQgsLabelingEngineV2::testDiagrams() vl->loadDefaultStyle( res ); } -#include "qgsvectorlayerlabeling.h" -#include "qgsrulebasedlabeling.h" void TestQgsLabelingEngineV2::testRuleBased() { @@ -170,8 +170,7 @@ void TestQgsLabelingEngineV2::testRuleBased() s2.textColor = Qt::red; root->appendChild( new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( s2 ), 0, 0, "Class = 'Jet'" ) ); - vl->labeling().setMode( QgsVectorLayerLabeling::RuleBasedLabels ); - vl->labeling().setRuleBasedLabeling( new QgsRuleBasedLabeling( root ) ); + vl->setLabeling( new QgsRuleBasedLabeling( root ) ); QgsMapRendererSequentialJob job( mapSettings ); job.start(); @@ -182,7 +181,7 @@ void TestQgsLabelingEngineV2::testRuleBased() // test read/write rules QDomDocument doc, doc2, doc3; - QDomElement e = vl->labeling().ruleBasedLabeling()->save( doc ); + QDomElement e = vl->labeling()->save( doc ); doc.appendChild( e ); // read saved rules doc2.setContent( doc.toString() ); @@ -194,7 +193,7 @@ void TestQgsLabelingEngineV2::testRuleBased() doc3.appendChild( e3 ); QCOMPARE( doc.toString(), doc3.toString() ); - vl->labeling().setMode( QgsVectorLayerLabeling::SimpleLabels ); + vl->setLabeling( new QgsVectorLayerSimpleLabeling ); /* QPainter p( &img );