One common class for labeling configurations (QgsAbstractVectorLayerLabeling)

This is +/- equivalent of QgsFeatureRendererV2 for vector layer labels

This code has been funded by Tuscany Region (Italy) - SITA (CIG: 63526840AE) and commissioned to Gis3W s.a.s.
This commit is contained in:
Martin Dobias 2015-09-23 16:23:46 +08:00
parent 44ae0b8cea
commit 249c87822f
10 changed files with 110 additions and 135 deletions

View File

@ -43,6 +43,7 @@
#include "qgsexpression.h"
#include "qgsdatadefined.h"
#include "qgslabelingenginev2.h"
#include "qgsvectorlayerlabeling.h"
#include <qgslogger.h>
#include <qgsvectorlayer.h>
@ -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;

View File

@ -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 );
}

View File

@ -3,6 +3,8 @@
#include <QStringList>
#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;

View File

@ -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 )

View File

@ -63,7 +63,7 @@ class QgsSymbolV2;
class QgsVectorDataProvider;
class QgsVectorLayerEditBuffer;
class QgsVectorLayerJoinBuffer;
class QgsVectorLayerLabeling;
class QgsAbstractVectorLayerLabeling;
class QgsPointV2;
typedef QList<int> 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;

View File

@ -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;
}
*/

View File

@ -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

View File

@ -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
*/

View File

@ -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;
}

View File

@ -19,8 +19,10 @@
#include <qgslabelingenginev2.h>
#include <qgsmaplayerregistry.h>
#include <qgsmaprenderersequentialjob.h>
#include <qgsrulebasedlabeling.h>
#include <qgsvectorlayer.h>
#include <qgsvectorlayerdiagramprovider.h>
#include <qgsvectorlayerlabeling.h>
#include <qgsvectorlayerlabelprovider.h>
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 );