mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
More labeling engine refactoring
- QgsPalLabeling now internally uses new engine - label/diagram providers can hook into rendering loop to avoid extra feature loops - map rendering uses the new engine instead of QgsPalLabeling This code has been funded by Tuscany Region (Italy) - SITA (CIG: 63526840AE) and commissioned to Gis3W s.a.s.
This commit is contained in:
parent
8100495df6
commit
d0fcc9557f
@ -47,9 +47,14 @@ class QgsLabelingEngineInterface
|
||||
//! called when starting rendering of a layer
|
||||
virtual int prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) = 0;
|
||||
//! returns PAL layer settings for a registered layer
|
||||
virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0;
|
||||
//! @deprecated since 2.12 - if direct access to QgsPalLayerSettings is necessary, use QgsPalLayerSettings::fromLayer()
|
||||
virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0 /Deprecated/;
|
||||
//! adds a diagram layer to the labeling engine
|
||||
virtual int addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLayerSettings* s );
|
||||
//! @note added in QGIS 2.12
|
||||
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/;
|
||||
//! called for every feature
|
||||
virtual void registerFeature( const QString& layerID, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext(), QString dxfLayer = QString::null ) = 0;
|
||||
//! called for every diagram feature
|
||||
|
@ -699,7 +699,8 @@ class QgsPalLabeling : QgsLabelingEngineInterface
|
||||
|
||||
bool isShowingCandidates() const;
|
||||
void setShowingCandidates( bool showing );
|
||||
const QList<QgsLabelCandidate>& candidates();
|
||||
//! @deprecated since 2.12
|
||||
const QList<QgsLabelCandidate>& candidates() /Deprecated/;
|
||||
|
||||
bool isShowingShadowRectangles() const;
|
||||
void setShowingShadowRectangles( bool showing );
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "qgslogger.h"
|
||||
#include "qgspalgeometry.h"
|
||||
#include "qgsproject.h"
|
||||
|
||||
#include "feature.h"
|
||||
#include "labelposition.h"
|
||||
@ -33,9 +34,8 @@ static bool _palIsCancelled( void* ctx )
|
||||
}
|
||||
|
||||
|
||||
QgsLabelingEngineV2::QgsLabelingEngineV2( const QgsMapSettings& mapSettings )
|
||||
: mMapSettings( mapSettings )
|
||||
, mFlags( RenderOutlineLabels | UsePartialCandidates )
|
||||
QgsLabelingEngineV2::QgsLabelingEngineV2()
|
||||
: mFlags( RenderOutlineLabels | UsePartialCandidates )
|
||||
, mSearchMethod( QgsPalLabeling::Chain )
|
||||
, mCandPoint( 8 )
|
||||
, mCandLine( 8 )
|
||||
@ -57,6 +57,15 @@ void QgsLabelingEngineV2::addProvider( QgsAbstractLabelProvider* provider )
|
||||
mProviders << provider;
|
||||
}
|
||||
|
||||
void QgsLabelingEngineV2::removeProvider( QgsAbstractLabelProvider* provider )
|
||||
{
|
||||
int idx = mProviders.indexOf( provider );
|
||||
if ( idx >= 0 )
|
||||
{
|
||||
delete mProviders.takeAt( idx );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingEngineV2::run( QgsRenderContext& context )
|
||||
{
|
||||
pal::Pal p;
|
||||
@ -146,7 +155,7 @@ void QgsLabelingEngineV2::run( QgsRenderContext& context )
|
||||
l->setUpsidedownLabels( upsdnlabels );
|
||||
|
||||
|
||||
QList<QgsLabelFeature*> features = provider->labelFeatures( mMapSettings, context );
|
||||
QList<QgsLabelFeature*> features = provider->labelFeatures( context );
|
||||
|
||||
foreach ( QgsLabelFeature* feature, features )
|
||||
{
|
||||
@ -286,6 +295,40 @@ QgsLabelingResults* QgsLabelingEngineV2::takeResults()
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void QgsLabelingEngineV2::readSettingsFromProject()
|
||||
{
|
||||
bool saved = false;
|
||||
QgsProject* prj = QgsProject::instance();
|
||||
mSearchMethod = ( QgsPalLabeling::Search )( prj->readNumEntry( "PAL", "/SearchMethod", ( int ) QgsPalLabeling::Chain, &saved ) );
|
||||
mCandPoint = prj->readNumEntry( "PAL", "/CandidatesPoint", 8, &saved );
|
||||
mCandLine = prj->readNumEntry( "PAL", "/CandidatesLine", 8, &saved );
|
||||
mCandPolygon = prj->readNumEntry( "PAL", "/CandidatesPolygon", 8, &saved );
|
||||
|
||||
mFlags = 0;
|
||||
if ( prj->readBoolEntry( "PAL", "/ShowingCandidates", false, &saved ) ) mFlags |= DrawCandidates;
|
||||
if ( prj->readBoolEntry( "PAL", "/DrawRectOnly", false, &saved ) ) mFlags |= DrawLabelRectOnly;
|
||||
if ( prj->readBoolEntry( "PAL", "/ShowingShadowRects", false, &saved ) ) mFlags |= DrawShadowRects;
|
||||
if ( prj->readBoolEntry( "PAL", "/ShowingAllLabels", false, &saved ) ) mFlags |= UseAllLabels;
|
||||
if ( prj->readBoolEntry( "PAL", "/ShowingPartialsLabels", true, &saved ) ) mFlags |= UsePartialCandidates;
|
||||
if ( prj->readBoolEntry( "PAL", "/DrawOutlineLabels", true, &saved ) ) mFlags |= RenderOutlineLabels;
|
||||
}
|
||||
|
||||
void QgsLabelingEngineV2::writeSettingsToProject()
|
||||
{
|
||||
QgsProject::instance()->writeEntry( "PAL", "/SearchMethod", ( int )mSearchMethod );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/CandidatesPoint", mCandPoint );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/CandidatesLine", mCandLine );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/CandidatesPolygon", mCandPolygon );
|
||||
|
||||
QgsProject::instance()->writeEntry( "PAL", "/ShowingCandidates", mFlags.testFlag( DrawCandidates ) );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/DrawRectOnly", mFlags.testFlag( DrawLabelRectOnly ) );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/ShowingShadowRects", mFlags.testFlag( DrawShadowRects ) );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/ShowingAllLabels", mFlags.testFlag( UseAllLabels ) );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/ShowingPartialsLabels", mFlags.testFlag( UsePartialCandidates ) );
|
||||
QgsProject::instance()->writeEntry( "PAL", "/DrawOutlineLabels", mFlags.testFlag( RenderOutlineLabels ) );
|
||||
}
|
||||
|
||||
QgsAbstractLabelProvider* QgsLabelingEngineV2::providerById( const QString& id )
|
||||
{
|
||||
Q_FOREACH ( QgsAbstractLabelProvider* provider, mProviders )
|
||||
|
@ -164,7 +164,7 @@ class CORE_EXPORT QgsAbstractLabelProvider
|
||||
virtual QString id() const = 0;
|
||||
|
||||
//! Return list of labels
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsMapSettings& mapSettings, const QgsRenderContext& context ) = 0;
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsRenderContext& context ) = 0;
|
||||
|
||||
//! draw this label at the position determined by the labeling engine
|
||||
virtual void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const = 0;
|
||||
@ -210,7 +210,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAbstractLabelProvider::Flags )
|
||||
class CORE_EXPORT QgsLabelingEngineV2
|
||||
{
|
||||
public:
|
||||
QgsLabelingEngineV2( const QgsMapSettings& mapSettings );
|
||||
QgsLabelingEngineV2();
|
||||
~QgsLabelingEngineV2();
|
||||
|
||||
enum Flag
|
||||
@ -224,9 +224,18 @@ class CORE_EXPORT QgsLabelingEngineV2
|
||||
};
|
||||
Q_DECLARE_FLAGS( Flags, Flag )
|
||||
|
||||
void setMapSettings( const QgsMapSettings& mapSettings ) { mMapSettings = mapSettings; }
|
||||
const QgsMapSettings& mapSettings() const { return mMapSettings; }
|
||||
|
||||
//! Add provider of label features. Takes ownership of the provider
|
||||
void addProvider( QgsAbstractLabelProvider* provider );
|
||||
|
||||
//! Remove provider if the provider's initialization failed. Provider instance is deleted.
|
||||
void removeProvider( QgsAbstractLabelProvider* provider );
|
||||
|
||||
//! Lookup provider by its ID
|
||||
QgsAbstractLabelProvider* providerById( const QString& id );
|
||||
|
||||
//! compute the labeling with given map settings and providers
|
||||
void run( QgsRenderContext& context );
|
||||
|
||||
@ -238,6 +247,8 @@ class CORE_EXPORT QgsLabelingEngineV2
|
||||
|
||||
void setFlags( Flags flags ) { mFlags = flags; }
|
||||
Flags flags() const { return mFlags; }
|
||||
bool testFlag( Flag f ) const { return mFlags.testFlag( f ); }
|
||||
void setFlag( Flag f, bool enabled ) { if ( enabled ) mFlags |= f; else mFlags &= ~f; }
|
||||
|
||||
void numCandidatePositions( int& candPoint, int& candLine, int& candPolygon ) { candPoint = mCandPoint; candLine = mCandLine; candPolygon = mCandPolygon; }
|
||||
void setNumCandidatePositions( int candPoint, int candLine, int candPolygon ) { mCandPoint = candPoint; mCandLine = candLine; mCandPolygon = candPolygon; }
|
||||
@ -245,8 +256,8 @@ class CORE_EXPORT QgsLabelingEngineV2
|
||||
void setSearchMethod( QgsPalLabeling::Search s ) { mSearchMethod = s; }
|
||||
QgsPalLabeling::Search searchMethod() const { return mSearchMethod; }
|
||||
|
||||
protected:
|
||||
QgsAbstractLabelProvider* providerById( const QString& id );
|
||||
void readSettingsFromProject();
|
||||
void writeSettingsToProject();
|
||||
|
||||
protected:
|
||||
QgsMapSettings mMapSettings;
|
||||
|
@ -84,9 +84,15 @@ class CORE_EXPORT QgsLabelingEngineInterface
|
||||
//! called when starting rendering of a layer
|
||||
virtual int prepareLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) = 0;
|
||||
//! returns PAL layer settings for a registered layer
|
||||
virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0;
|
||||
//! @deprecated since 2.12 - if direct access to QgsPalLayerSettings is necessary, use QgsPalLayerSettings::fromLayer()
|
||||
Q_DECL_DEPRECATED virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0;
|
||||
//! adds a diagram layer to the labeling engine
|
||||
virtual int addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLayerSettings* s )
|
||||
//! @note added in QGIS 2.12
|
||||
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_UNUSED( layer ); Q_UNUSED( s ); return 0; }
|
||||
//! called for every feature
|
||||
virtual void registerFeature( const QString& layerID, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext(), QString dxfLayer = QString::null ) = 0;
|
||||
|
@ -85,7 +85,9 @@ void QgsMapRendererCustomPainterJob::start()
|
||||
if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) )
|
||||
{
|
||||
#ifdef LABELING_V2
|
||||
mLabelingEngineV2 = new QgsLabelingEngineV2( mSettings );
|
||||
mLabelingEngineV2 = new QgsLabelingEngineV2();
|
||||
mLabelingEngineV2->readSettingsFromProject();
|
||||
mLabelingEngineV2->setMapSettings( mSettings );
|
||||
#else
|
||||
mLabelingEngine = new QgsPalLabeling;
|
||||
mLabelingEngine->loadEngineSettings();
|
||||
|
@ -64,7 +64,9 @@ void QgsMapRendererParallelJob::start()
|
||||
if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) )
|
||||
{
|
||||
#ifdef LABELING_V2
|
||||
mLabelingEngineV2 = new QgsLabelingEngineV2( mSettings );
|
||||
mLabelingEngineV2 = new QgsLabelingEngineV2();
|
||||
mLabelingEngineV2->readSettingsFromProject();
|
||||
mLabelingEngineV2->setMapSettings( mSettings );
|
||||
#else
|
||||
mLabelingEngine = new QgsPalLabeling;
|
||||
mLabelingEngine->loadEngineSettings();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,9 @@ class QgsCoordinateTransform;
|
||||
class QgsLabelSearchTree;
|
||||
class QgsMapSettings;
|
||||
class QgsLabelFeature;
|
||||
class QgsLabelingEngineV2;
|
||||
class QgsVectorLayerLabelProvider;
|
||||
class QgsVectorLayerDiagramProvider;
|
||||
|
||||
class CORE_EXPORT QgsPalLayerSettings
|
||||
{
|
||||
@ -781,7 +784,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
QgsPalLabeling();
|
||||
~QgsPalLabeling();
|
||||
|
||||
QgsPalLayerSettings& layer( const QString& layerName ) override;
|
||||
//! @deprecated since 2.12 - if direct access to QgsPalLayerSettings is necessary, use QgsPalLayerSettings::fromLayer()
|
||||
Q_DECL_DEPRECATED QgsPalLayerSettings& layer( const QString& layerName ) override;
|
||||
|
||||
void numCandidatePositions( int& candPoint, int& candLine, int& candPolygon );
|
||||
void setNumCandidatePositions( int candPoint, int candLine, int candPolygon );
|
||||
@ -791,29 +795,30 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
void setSearchMethod( Search s );
|
||||
Search searchMethod() const;
|
||||
|
||||
bool isShowingCandidates() const { return mShowingCandidates; }
|
||||
void setShowingCandidates( bool showing ) { mShowingCandidates = showing; }
|
||||
const QList<QgsLabelCandidate>& candidates() { return mCandidates; }
|
||||
bool isShowingCandidates() const;
|
||||
void setShowingCandidates( bool showing );
|
||||
//! @deprecated since 2.12
|
||||
Q_DECL_DEPRECATED const QList<QgsLabelCandidate>& candidates() { return mCandidates; }
|
||||
|
||||
bool isShowingShadowRectangles() const { return mShowingShadowRects; }
|
||||
void setShowingShadowRectangles( bool showing ) { mShowingShadowRects = showing; }
|
||||
bool isShowingShadowRectangles() const;
|
||||
void setShowingShadowRectangles( bool showing );
|
||||
|
||||
bool isShowingAllLabels() const { return mShowingAllLabels; }
|
||||
void setShowingAllLabels( bool showing ) { mShowingAllLabels = showing; }
|
||||
bool isShowingAllLabels() const;
|
||||
void setShowingAllLabels( bool showing );
|
||||
|
||||
bool isShowingPartialsLabels() const { return mShowingPartialsLabels; }
|
||||
void setShowingPartialsLabels( bool showing ) { mShowingPartialsLabels = showing; }
|
||||
bool isShowingPartialsLabels() const;
|
||||
void setShowingPartialsLabels( bool showing );
|
||||
|
||||
//! @note added in 2.4
|
||||
bool isDrawingOutlineLabels() const { return mDrawOutlineLabels; }
|
||||
void setDrawingOutlineLabels( bool outline ) { mDrawOutlineLabels = outline; }
|
||||
bool isDrawingOutlineLabels() const;
|
||||
void setDrawingOutlineLabels( bool outline );
|
||||
|
||||
/** Returns whether the engine will only draw the outline rectangles of labels,
|
||||
* not the label contents themselves. Used for debugging and testing purposes.
|
||||
* @see setDrawLabelRectOnly
|
||||
* @note added in QGIS 2.12
|
||||
*/
|
||||
bool drawLabelRectOnly() const { return mDrawLabelRectOnly; }
|
||||
bool drawLabelRectOnly() const;
|
||||
|
||||
/** Sets whether the engine should only draw the outline rectangles of labels,
|
||||
* not the label contents themselves. Used for debugging and testing purposes.
|
||||
@ -821,7 +826,7 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
* @see drawLabelRectOnly
|
||||
* @note added in QGIS 2.12
|
||||
*/
|
||||
void setDrawLabelRectOnly( bool drawRect ) { mDrawLabelRectOnly = drawRect; }
|
||||
void setDrawLabelRectOnly( bool drawRect );
|
||||
|
||||
// implemented methods from labeling engine interface
|
||||
|
||||
@ -845,7 +850,11 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
//! hook called when drawing layer before issuing select()
|
||||
virtual int prepareLayer( QgsVectorLayer* layer, QStringList &attrNames, QgsRenderContext& ctx ) override;
|
||||
//! adds a diagram layer to the labeling engine
|
||||
virtual int addDiagramLayer( QgsVectorLayer* layer, const QgsDiagramLayerSettings *s ) override;
|
||||
//! @note added in QGIS 2.12
|
||||
virtual int prepareDiagramLayer( QgsVectorLayer* layer, QStringList& attrNames, QgsRenderContext& ctx ) override;
|
||||
//! 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 ) override;
|
||||
|
||||
/** Register a feature for labelling.
|
||||
* @param layerID string identifying layer associated with label
|
||||
@ -976,31 +985,18 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
*/
|
||||
static bool checkMinimumSizeMM( const QgsRenderContext &context, const QgsGeometry *geom, double minSize );
|
||||
|
||||
// hashtable of layer settings, being filled during labeling (key = layer ID)
|
||||
QHash<QString, QgsPalLayerSettings> mActiveLayers;
|
||||
// hashtable of active diagram layers (key = layer ID)
|
||||
QHash<QString, QgsDiagramLayerSettings> mActiveDiagramLayers;
|
||||
//! hashtable of label providers, being filled during labeling (key = layer ID)
|
||||
QHash<QString, QgsVectorLayerLabelProvider*> mLabelProviders;
|
||||
//! hashtable of diagram providers (key = layer ID)
|
||||
QHash<QString, QgsVectorLayerDiagramProvider*> mDiagramProviders;
|
||||
QgsPalLayerSettings mInvalidLayerSettings;
|
||||
|
||||
const QgsMapSettings* mMapSettings;
|
||||
int mCandPoint, mCandLine, mCandPolygon;
|
||||
Search mSearch;
|
||||
|
||||
pal::Pal* mPal;
|
||||
//! New labeling engine to interface with PAL
|
||||
QgsLabelingEngineV2* mEngine;
|
||||
|
||||
// list of candidates from last labeling
|
||||
QList<QgsLabelCandidate> mCandidates;
|
||||
|
||||
//! Whether to only draw the label rect and not the actual label text (used for unit tests)
|
||||
bool mDrawLabelRectOnly;
|
||||
bool mShowingCandidates;
|
||||
bool mShowingAllLabels; // whether to avoid collisions or not
|
||||
bool mShowingShadowRects; // whether to show debugging rectangles for drop shadows
|
||||
bool mShowingPartialsLabels; // whether to avoid partials labels or not
|
||||
bool mDrawOutlineLabels; // whether to draw labels as text or outlines
|
||||
|
||||
QgsLabelingResults* mResults;
|
||||
|
||||
friend class QgsPalLayerSettings;
|
||||
};
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
@ -45,14 +45,14 @@ QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider(
|
||||
}
|
||||
|
||||
|
||||
QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider( QgsVectorLayer* layer )
|
||||
QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider( QgsVectorLayer* layer, bool ownFeatureLoop )
|
||||
: mSettings( *layer->diagramLayerSettings() )
|
||||
, mDiagRenderer( layer->diagramRenderer()->clone() )
|
||||
, mLayerId( layer->id() )
|
||||
, mFields( layer->fields() )
|
||||
, mLayerCrs( layer->crs() )
|
||||
, mSource( new QgsVectorLayerFeatureSource( layer ) )
|
||||
, mOwnsSource( true )
|
||||
, mSource( ownFeatureLoop ? new QgsVectorLayerFeatureSource( layer ) : 0 )
|
||||
, mOwnsSource( ownFeatureLoop )
|
||||
{
|
||||
init();
|
||||
}
|
||||
@ -81,67 +81,18 @@ QString QgsVectorLayerDiagramProvider::id() const
|
||||
return mLayerId + "d";
|
||||
}
|
||||
|
||||
QList<QgsLabelFeature*> QgsVectorLayerDiagramProvider::labelFeatures( const QgsMapSettings& mapSettings, const QgsRenderContext& context )
|
||||
QList<QgsLabelFeature*> QgsVectorLayerDiagramProvider::labelFeatures( const QgsRenderContext& context )
|
||||
{
|
||||
|
||||
QgsDiagramLayerSettings& s2 = mSettings;
|
||||
|
||||
s2.ct = 0;
|
||||
if ( mapSettings.hasCrsTransformEnabled() )
|
||||
s2.ct = new QgsCoordinateTransform( mLayerCrs, mapSettings.destinationCrs() );
|
||||
|
||||
s2.xform = &mapSettings.mapToPixel();
|
||||
|
||||
s2.fields = mFields;
|
||||
|
||||
s2.renderer = mDiagRenderer;
|
||||
|
||||
const QgsDiagramRendererV2* diagRenderer = s2.renderer;
|
||||
if ( !mSource )
|
||||
{
|
||||
// we have created the provider with "own feature loop" == false
|
||||
// so it is assumed that prepare() has been already called followed by registerFeature() calls
|
||||
return mFeatures;
|
||||
}
|
||||
|
||||
QStringList attributeNames;
|
||||
|
||||
//add attributes needed by the diagram renderer
|
||||
QList<QString> att = diagRenderer->diagramAttributes();
|
||||
QList<QString>::const_iterator attIt = att.constBegin();
|
||||
for ( ; attIt != att.constEnd(); ++attIt )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, context.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
|
||||
const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( diagRenderer );
|
||||
if ( linearlyInterpolatedDiagramRenderer != NULL )
|
||||
{
|
||||
if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), context.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name();
|
||||
if ( !attributeNames.contains( name ) )
|
||||
attributeNames << name;
|
||||
}
|
||||
}
|
||||
|
||||
//and the ones needed for data defined diagram positions
|
||||
if ( mSettings.xPosColumn != -1 )
|
||||
attributeNames << mFields.at( mSettings.xPosColumn ).name();
|
||||
if ( mSettings.yPosColumn != -1 )
|
||||
attributeNames << mFields.at( mSettings.yPosColumn ).name();
|
||||
if ( !prepare( context, attributeNames ) )
|
||||
return QList<QgsLabelFeature*>();
|
||||
|
||||
QgsRectangle layerExtent = context.extent();
|
||||
if ( mSettings.ct )
|
||||
@ -152,19 +103,17 @@ QList<QgsLabelFeature*> QgsVectorLayerDiagramProvider::labelFeatures( const QgsM
|
||||
request.setSubsetOfAttributes( attributeNames, mFields );
|
||||
QgsFeatureIterator fit = mSource->getFeatures( request );
|
||||
|
||||
QList<QgsLabelFeature*> features;
|
||||
|
||||
QgsFeature fet;
|
||||
while ( fit.nextFeature( fet ) )
|
||||
{
|
||||
QgsLabelFeature* label = registerDiagram( fet, mapSettings, context );
|
||||
if ( label )
|
||||
features << label;
|
||||
registerFeature( fet, context );
|
||||
}
|
||||
|
||||
return features;
|
||||
return mFeatures;
|
||||
}
|
||||
|
||||
|
||||
void QgsVectorLayerDiagramProvider::drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const
|
||||
{
|
||||
#if 1 // XXX strk
|
||||
@ -210,8 +159,88 @@ void QgsVectorLayerDiagramProvider::drawLabel( QgsRenderContext& context, pal::L
|
||||
}
|
||||
|
||||
|
||||
QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& feat, const QgsMapSettings& mapSettings, const QgsRenderContext& context )
|
||||
bool QgsVectorLayerDiagramProvider::prepare( const QgsRenderContext& context, QStringList& attributeNames )
|
||||
{
|
||||
QgsDiagramLayerSettings& s2 = mSettings;
|
||||
const QgsMapSettings& mapSettings = mEngine->mapSettings();
|
||||
|
||||
s2.ct = 0;
|
||||
if ( mapSettings.hasCrsTransformEnabled() )
|
||||
{
|
||||
if ( context.coordinateTransform() )
|
||||
// this is context for layer rendering - use its CT as it includes correct datum transform
|
||||
s2.ct = context.coordinateTransform()->clone();
|
||||
else
|
||||
// otherwise fall back to creating our own CT - this one may not have the correct datum transform!
|
||||
s2.ct = new QgsCoordinateTransform( mLayerCrs, mapSettings.destinationCrs() );
|
||||
}
|
||||
|
||||
s2.xform = &mapSettings.mapToPixel();
|
||||
|
||||
s2.fields = mFields;
|
||||
|
||||
s2.renderer = mDiagRenderer;
|
||||
|
||||
const QgsDiagramRendererV2* diagRenderer = s2.renderer;
|
||||
|
||||
//add attributes needed by the diagram renderer
|
||||
QList<QString> att = diagRenderer->diagramAttributes();
|
||||
QList<QString>::const_iterator attIt = att.constBegin();
|
||||
for ( ; attIt != att.constEnd(); ++attIt )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, context.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
|
||||
const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( diagRenderer );
|
||||
if ( linearlyInterpolatedDiagramRenderer != NULL )
|
||||
{
|
||||
if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), context.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name();
|
||||
if ( !attributeNames.contains( name ) )
|
||||
attributeNames << name;
|
||||
}
|
||||
}
|
||||
|
||||
//and the ones needed for data defined diagram positions
|
||||
if ( mSettings.xPosColumn != -1 )
|
||||
attributeNames << mFields.at( mSettings.xPosColumn ).name();
|
||||
if ( mSettings.yPosColumn != -1 )
|
||||
attributeNames << mFields.at( mSettings.yPosColumn ).name();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void QgsVectorLayerDiagramProvider::registerFeature( QgsFeature& feature, const QgsRenderContext& context )
|
||||
{
|
||||
QgsLabelFeature* label = registerDiagram( feature, context );
|
||||
if ( label )
|
||||
mFeatures << label;
|
||||
}
|
||||
|
||||
|
||||
QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& feat, const QgsRenderContext& context )
|
||||
{
|
||||
const QgsMapSettings& mapSettings = mEngine->mapSettings();
|
||||
|
||||
QgsDiagramRendererV2* dr = mSettings.renderer;
|
||||
if ( dr )
|
||||
|
@ -33,7 +33,7 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide
|
||||
public:
|
||||
|
||||
//! Convenience constructor to initialize the provider from given vector layer
|
||||
explicit QgsVectorLayerDiagramProvider( QgsVectorLayer* layer );
|
||||
explicit QgsVectorLayerDiagramProvider( QgsVectorLayer* layer, bool ownFeatureLoop = true );
|
||||
|
||||
QgsVectorLayerDiagramProvider( const QgsDiagramLayerSettings* diagSettings,
|
||||
const QgsDiagramRendererV2* diagRenderer,
|
||||
@ -47,13 +47,19 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide
|
||||
|
||||
virtual QString id() const override;
|
||||
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsMapSettings& mapSettings, const QgsRenderContext& context ) override;
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsRenderContext& context ) override;
|
||||
|
||||
virtual void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const override;
|
||||
|
||||
// new virtual methods
|
||||
|
||||
virtual bool prepare( const QgsRenderContext& context, QStringList& attributeNames );
|
||||
|
||||
virtual void registerFeature( QgsFeature& feature, const QgsRenderContext& context );
|
||||
|
||||
protected:
|
||||
void init();
|
||||
QgsLabelFeature* registerDiagram( QgsFeature& feat, const QgsMapSettings& mapSettings, const QgsRenderContext& context );
|
||||
QgsLabelFeature* registerDiagram( QgsFeature& feat, const QgsRenderContext& context );
|
||||
|
||||
protected:
|
||||
|
||||
@ -66,6 +72,7 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide
|
||||
QgsAbstractFeatureSource* mSource;
|
||||
bool mOwnsSource;
|
||||
|
||||
QList<QgsLabelFeature*> mFeatures;
|
||||
};
|
||||
|
||||
#endif // QGSVECTORLAYERDIAGRAMPROVIDER_H
|
||||
|
@ -45,7 +45,7 @@ static void _fixQPictureDPI( QPainter* p )
|
||||
|
||||
typedef QgsPalLayerSettings QgsVectorLayerLabelSettings;
|
||||
|
||||
QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer* layer )
|
||||
QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer* layer, bool withFeatureLoop )
|
||||
{
|
||||
if ( layer->customProperty( "labeling" ).toString() != QString( "pal" ) || !layer->labelsEnabled() )
|
||||
return;
|
||||
@ -54,7 +54,16 @@ QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer* layer
|
||||
mLayerId = layer->id();
|
||||
mFields = layer->fields();
|
||||
mCrs = layer->crs();
|
||||
mSource = new QgsVectorLayerFeatureSource( layer );
|
||||
if ( withFeatureLoop )
|
||||
{
|
||||
mSource = new QgsVectorLayerFeatureSource( layer );
|
||||
mOwnsSource = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSource = 0;
|
||||
mOwnsSource = false;
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
@ -97,7 +106,19 @@ void QgsVectorLayerLabelProvider::init()
|
||||
|
||||
QgsVectorLayerLabelProvider::~QgsVectorLayerLabelProvider()
|
||||
{
|
||||
// delete all QgsDataDefined objects (which also deletes their QgsExpression object)
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined* >::iterator it = mSettings.dataDefinedProperties.begin();
|
||||
for ( ; it != mSettings.dataDefinedProperties.constEnd(); ++it )
|
||||
{
|
||||
delete( it.value() );
|
||||
it.value() = 0;
|
||||
}
|
||||
mSettings.dataDefinedProperties.clear();
|
||||
|
||||
qDeleteAll( mSettings.geometries );
|
||||
|
||||
if ( mOwnsSource )
|
||||
delete mSource;
|
||||
}
|
||||
|
||||
QString QgsVectorLayerLabelProvider::id() const
|
||||
@ -105,10 +126,10 @@ QString QgsVectorLayerLabelProvider::id() const
|
||||
return mLayerId;
|
||||
}
|
||||
|
||||
|
||||
QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMapSettings& mapSettings, const QgsRenderContext& ctx )
|
||||
bool QgsVectorLayerLabelProvider::prepare( const QgsRenderContext& context, QStringList& attributeNames )
|
||||
{
|
||||
QgsVectorLayerLabelSettings& lyr = mSettings;
|
||||
const QgsMapSettings& mapSettings = mEngine->mapSettings();
|
||||
|
||||
QgsDebugMsgLevel( "PREPARE LAYER " + mLayerId, 4 );
|
||||
|
||||
@ -116,7 +137,7 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
{
|
||||
if ( lyr.fieldName.isEmpty() )
|
||||
{
|
||||
return QList<QgsLabelFeature*>();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( lyr.isExpression )
|
||||
@ -125,7 +146,7 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
if ( exp.hasEvalError() )
|
||||
{
|
||||
QgsDebugMsgLevel( "Prepare error:" + exp.evalErrorString(), 4 );
|
||||
return QList<QgsLabelFeature*>();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -133,13 +154,11 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
// If we aren't an expression, we check to see if we can find the column.
|
||||
if ( mFields.fieldNameIndex( lyr.fieldName ) == -1 )
|
||||
{
|
||||
return QList<QgsLabelFeature*>();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList attrNames;
|
||||
|
||||
lyr.mCurFields = mFields;
|
||||
|
||||
if ( lyr.drawLabels )
|
||||
@ -149,7 +168,7 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
{
|
||||
// prepare expression for use in QgsPalLayerSettings::registerFeature()
|
||||
QgsExpression* exp = lyr.getLabelExpression();
|
||||
exp->prepare( &ctx.expressionContext() );
|
||||
exp->prepare( &context.expressionContext() );
|
||||
if ( exp->hasEvalError() )
|
||||
{
|
||||
QgsDebugMsgLevel( "Prepare error:" + exp->evalErrorString(), 4 );
|
||||
@ -157,12 +176,12 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
Q_FOREACH ( const QString& name, exp->referencedColumns() )
|
||||
{
|
||||
QgsDebugMsgLevel( "REFERENCED COLUMN = " + name, 4 );
|
||||
attrNames.append( name );
|
||||
attributeNames.append( name );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attrNames.append( lyr.fieldName );
|
||||
attributeNames.append( lyr.fieldName );
|
||||
}
|
||||
|
||||
// add field indices of data defined expression or field
|
||||
@ -179,26 +198,29 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
|
||||
// store parameters for data defined expressions
|
||||
QMap<QString, QVariant> exprParams;
|
||||
exprParams.insert( "scale", ctx.rendererScale() );
|
||||
exprParams.insert( "scale", context.rendererScale() );
|
||||
|
||||
dd->setExpressionParams( exprParams );
|
||||
|
||||
// this will return columns for expressions or field name, depending upon what is set to be used
|
||||
QStringList cols = dd->referencedColumns( ctx.expressionContext() ); // <-- prepares any expressions, too
|
||||
QStringList cols = dd->referencedColumns( context.expressionContext() ); // <-- prepares any expressions, too
|
||||
|
||||
//QgsDebugMsgLevel( QString( "Data defined referenced columns:" ) + cols.join( "," ), 4 );
|
||||
Q_FOREACH ( const QString& name, cols )
|
||||
{
|
||||
attrNames.append( name );
|
||||
attributeNames.append( name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOW INITIALIZE QgsPalLayerSettings
|
||||
|
||||
// TODO: ideally these (non-configuration) members should get out of QgsPalLayerSettings to here
|
||||
// (together with registerFeature() & related methods) and QgsPalLayerSettings just stores config
|
||||
|
||||
//raster and vector scale factors
|
||||
lyr.vectorScaleFactor = ctx.scaleFactor();
|
||||
lyr.rasterCompressFactor = ctx.rasterScaleFactor();
|
||||
lyr.vectorScaleFactor = context.scaleFactor();
|
||||
lyr.rasterCompressFactor = context.rasterScaleFactor();
|
||||
|
||||
// save the pal layer to our layer context (with some additional info)
|
||||
lyr.fieldIndex = mFields.fieldNameIndex( lyr.fieldName );
|
||||
@ -206,7 +228,14 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
lyr.xform = &mapSettings.mapToPixel();
|
||||
lyr.ct = 0;
|
||||
if ( mapSettings.hasCrsTransformEnabled() )
|
||||
lyr.ct = new QgsCoordinateTransform( mCrs, mapSettings.destinationCrs() );
|
||||
{
|
||||
if ( context.coordinateTransform() )
|
||||
// this is context for layer rendering - use its CT as it includes correct datum transform
|
||||
lyr.ct = context.coordinateTransform()->clone();
|
||||
else
|
||||
// otherwise fall back to creating our own CT - this one may not have the correct datum transform!
|
||||
lyr.ct = new QgsCoordinateTransform( mCrs, mapSettings.destinationCrs() );
|
||||
}
|
||||
lyr.ptZero = lyr.xform->toMapCoordinates( 0, 0 );
|
||||
lyr.ptOne = lyr.xform->toMapCoordinates( 1, 0 );
|
||||
|
||||
@ -220,30 +249,53 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
|
||||
|
||||
lyr.mFeatsSendingToPal = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsRenderContext& ctx )
|
||||
{
|
||||
if ( !mSource )
|
||||
{
|
||||
// we have created the provider with "own feature loop" == false
|
||||
// so it is assumed that prepare() has been already called followed by registerFeature() calls
|
||||
return mLabels;
|
||||
}
|
||||
|
||||
QStringList attrNames;
|
||||
if ( !prepare( ctx, attrNames ) )
|
||||
return QList<QgsLabelFeature*>();
|
||||
|
||||
QgsRectangle layerExtent = ctx.extent();
|
||||
if ( lyr.ct )
|
||||
layerExtent = lyr.ct->transformBoundingBox( ctx.extent(), QgsCoordinateTransform::ReverseTransform );
|
||||
if ( mSettings.ct )
|
||||
layerExtent = mSettings.ct->transformBoundingBox( ctx.extent(), QgsCoordinateTransform::ReverseTransform );
|
||||
|
||||
QgsFeatureRequest request;
|
||||
request.setFilterRect( layerExtent );
|
||||
request.setSubsetOfAttributes( attrNames, mFields );
|
||||
QgsFeatureIterator fit = mSource->getFeatures( request );
|
||||
|
||||
QList<QgsLabelFeature*> labels;
|
||||
|
||||
QgsFeature fet;
|
||||
while ( fit.nextFeature( fet ) )
|
||||
{
|
||||
QgsLabelFeature* label = 0;
|
||||
lyr.registerFeature( fet, ctx, QString(), &label );
|
||||
if ( label )
|
||||
labels << label;
|
||||
registerFeature( fet, ctx );
|
||||
}
|
||||
|
||||
return labels;
|
||||
return mLabels;
|
||||
}
|
||||
|
||||
|
||||
void QgsVectorLayerLabelProvider::registerFeature( QgsFeature& feature, const QgsRenderContext& context )
|
||||
{
|
||||
QgsLabelFeature* label = 0;
|
||||
mSettings.registerFeature( feature, context, QString(), &label );
|
||||
if ( label )
|
||||
mLabels << label;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QgsVectorLayerLabelProvider::drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const
|
||||
{
|
||||
if ( !mSettings.drawLabels )
|
||||
@ -303,7 +355,7 @@ void QgsVectorLayerLabelProvider::drawLabel( QgsRenderContext& context, pal::Lab
|
||||
// update tmpLyr with any data defined drop shadow values
|
||||
QgsPalLabeling::dataDefinedDropShadow( tmpLyr, ddValues );
|
||||
|
||||
tmpLyr.showingShadowRects = mEngine->flags().testFlag( QgsLabelingEngineV2::DrawShadowRects );
|
||||
tmpLyr.showingShadowRects = mEngine->testFlag( QgsLabelingEngineV2::DrawShadowRects );
|
||||
|
||||
// Render the components of a label in reverse order
|
||||
// (backgrounds -> text)
|
||||
@ -367,7 +419,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
|
||||
component.setOrigin( outPt );
|
||||
component.setRotation( label->getAlpha() );
|
||||
|
||||
if ( mEngine->flags().testFlag( QgsLabelingEngineV2::DrawLabelRectOnly ) ) // TODO: this should get directly to labeling engine
|
||||
if ( mEngine->testFlag( QgsLabelingEngineV2::DrawLabelRectOnly ) ) // TODO: this should get directly to labeling engine
|
||||
{
|
||||
//debugging rect
|
||||
if ( drawType != QgsPalLabeling::LabelText )
|
||||
@ -602,7 +654,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition* label, Q
|
||||
// scale for any print output or image saving @ specific dpi
|
||||
painter->scale( component.dpiRatio(), component.dpiRatio() );
|
||||
|
||||
if ( mEngine->flags().testFlag( QgsLabelingEngineV2::RenderOutlineLabels ) )
|
||||
if ( mEngine->testFlag( QgsLabelingEngineV2::RenderOutlineLabels ) )
|
||||
{
|
||||
// draw outlined text
|
||||
_fixQPictureDPI( painter );
|
||||
|
@ -32,7 +32,7 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
|
||||
public:
|
||||
|
||||
//! Convenience constructor to initialize the provider from given vector layer
|
||||
explicit QgsVectorLayerLabelProvider( QgsVectorLayer* layer );
|
||||
explicit QgsVectorLayerLabelProvider( QgsVectorLayer* layer, bool withFeatureLoop = true );
|
||||
|
||||
QgsVectorLayerLabelProvider( const QgsPalLayerSettings& settings,
|
||||
const QString& layerId,
|
||||
@ -45,10 +45,28 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
|
||||
|
||||
virtual QString id() const override;
|
||||
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsMapSettings& mapSettings, const QgsRenderContext& context ) override;
|
||||
virtual QList<QgsLabelFeature*> labelFeatures( const QgsRenderContext& context ) override;
|
||||
|
||||
virtual void drawLabel( QgsRenderContext& context, pal::LabelPosition* label ) const override;
|
||||
|
||||
// new virtual methods
|
||||
|
||||
/**
|
||||
* Prepare for registration of features. Must be called after provider has been added to engine (uses its map settings)
|
||||
* @param context render context.
|
||||
* @param attributeNames list of attribute names to which additional required attributes shall be added
|
||||
* @return List of attributes necessary for labeling
|
||||
*/
|
||||
virtual bool prepare( const QgsRenderContext& context, QStringList& attributeNames );
|
||||
|
||||
/**
|
||||
* Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels
|
||||
*
|
||||
* @param feature 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.
|
||||
*/
|
||||
virtual void registerFeature( QgsFeature& feature, const QgsRenderContext& context );
|
||||
|
||||
protected:
|
||||
void init();
|
||||
@ -57,10 +75,13 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
|
||||
protected:
|
||||
QgsPalLayerSettings mSettings;
|
||||
QString mLayerId;
|
||||
// these are needed only if using own renderer loop
|
||||
QgsFields mFields;
|
||||
QgsCoordinateReferenceSystem mCrs;
|
||||
QgsAbstractFeatureSource* mSource;
|
||||
bool mOwnsSource;
|
||||
|
||||
QList<QgsLabelFeature*> mLabels;
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,6 +47,8 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
|
||||
, mCache( 0 )
|
||||
, mLabeling( false )
|
||||
, mDiagrams( false )
|
||||
, mLabelProvider( 0 )
|
||||
, mDiagramProvider( 0 )
|
||||
, mLayerTransparency( 0 )
|
||||
{
|
||||
mSource = new QgsVectorLayerFeatureSource( layer );
|
||||
@ -312,6 +314,18 @@ void QgsVectorLayerRenderer::drawRendererV2( QgsFeatureIterator& fit )
|
||||
mContext.labelingEngine()->registerDiagramFeature( mLayerID, fet, mContext );
|
||||
}
|
||||
}
|
||||
// new labeling engine
|
||||
if ( rendered && mContext.labelingEngineV2() )
|
||||
{
|
||||
if ( mLabelProvider )
|
||||
{
|
||||
mLabelProvider->registerFeature( fet, mContext );
|
||||
}
|
||||
if ( mDiagramProvider )
|
||||
{
|
||||
mDiagramProvider->registerFeature( fet, mContext );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( const QgsCsException &cse )
|
||||
{
|
||||
@ -469,9 +483,15 @@ void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList
|
||||
if ( QgsLabelingEngineV2* engine2 = mContext.labelingEngineV2() )
|
||||
{
|
||||
if ( layer->labelsEnabled() )
|
||||
engine2->addProvider( new QgsVectorLayerLabelProvider( layer ) );
|
||||
if ( layer->diagramsEnabled() )
|
||||
engine2->addProvider( new QgsVectorLayerDiagramProvider( layer ) );
|
||||
{
|
||||
mLabelProvider = new QgsVectorLayerLabelProvider( layer, false );
|
||||
engine2->addProvider( mLabelProvider );
|
||||
if ( !mLabelProvider->prepare( mContext, attributeNames ) )
|
||||
{
|
||||
engine2->removeProvider( mLabelProvider );
|
||||
mLabelProvider = 0; // deleted by engine
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -480,10 +500,9 @@ void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList
|
||||
{
|
||||
mLabeling = true;
|
||||
|
||||
QgsPalLayerSettings& palyr = mContext.labelingEngine()->layer( mLayerID );
|
||||
Q_UNUSED( palyr );
|
||||
|
||||
#if 0 // TODO: limit of labels, font not found
|
||||
QgsPalLayerSettings& palyr = mContext.labelingEngine()->layer( mLayerID );
|
||||
|
||||
// see if feature count limit is set for labeling
|
||||
if ( palyr.limitNumLabels && palyr.maxNumLabels > 0 )
|
||||
{
|
||||
@ -514,58 +533,29 @@ void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList
|
||||
void QgsVectorLayerRenderer::prepareDiagrams( QgsVectorLayer* layer, QStringList& attributeNames )
|
||||
{
|
||||
if ( !mContext.labelingEngine() )
|
||||
{
|
||||
if ( QgsLabelingEngineV2* engine2 = mContext.labelingEngineV2() )
|
||||
{
|
||||
if ( layer->diagramsEnabled() )
|
||||
{
|
||||
mDiagramProvider = new QgsVectorLayerDiagramProvider( layer );
|
||||
// need to be added before calling prepare() - uses map settings from engine
|
||||
engine2->addProvider( mDiagramProvider );
|
||||
if ( !mDiagramProvider->prepare( mContext, attributeNames ) )
|
||||
{
|
||||
engine2->removeProvider( mDiagramProvider );
|
||||
mDiagramProvider = 0; // deleted by engine
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !layer->diagramsEnabled() )
|
||||
return;
|
||||
|
||||
mDiagrams = true;
|
||||
|
||||
const QgsDiagramRendererV2* diagRenderer = layer->diagramRenderer();
|
||||
const QgsDiagramLayerSettings* diagSettings = layer->diagramLayerSettings();
|
||||
mContext.labelingEngine()->prepareDiagramLayer( layer, attributeNames, mContext ); // will make internal copy of diagSettings + initialize it
|
||||
|
||||
mContext.labelingEngine()->addDiagramLayer( layer, diagSettings ); // will make internal copy of diagSettings + initialize it
|
||||
|
||||
//add attributes needed by the diagram renderer
|
||||
QList<QString> att = diagRenderer->diagramAttributes();
|
||||
QList<QString>::const_iterator attIt = att.constBegin();
|
||||
for ( ; attIt != att.constEnd(); ++attIt )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, mContext.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
|
||||
const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( layer->diagramRenderer() );
|
||||
if ( linearlyInterpolatedDiagramRenderer != NULL )
|
||||
{
|
||||
if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
|
||||
{
|
||||
QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), mContext.expressionContext() );
|
||||
QStringList columns = expression->referencedColumns();
|
||||
QStringList::const_iterator columnsIterator = columns.constBegin();
|
||||
for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
|
||||
{
|
||||
if ( !attributeNames.contains( *columnsIterator ) )
|
||||
attributeNames << *columnsIterator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name();
|
||||
if ( !attributeNames.contains( name ) )
|
||||
attributeNames << name;
|
||||
}
|
||||
}
|
||||
|
||||
//and the ones needed for data defined diagram positions
|
||||
if ( diagSettings->xPosColumn != -1 )
|
||||
attributeNames << mFields.at( diagSettings->xPosColumn ).name();
|
||||
if ( diagSettings->yPosColumn != -1 )
|
||||
attributeNames << mFields.at( diagSettings->yPosColumn ).name();
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ typedef QList<int> QgsAttributeList;
|
||||
|
||||
#include "qgsmaplayerrenderer.h"
|
||||
|
||||
class QgsVectorLayerLabelProvider;
|
||||
class QgsVectorLayerDiagramProvider;
|
||||
|
||||
/**
|
||||
* Implementation of threaded rendering for vector layers.
|
||||
@ -102,9 +104,18 @@ class QgsVectorLayerRenderer : public QgsMapLayerRenderer
|
||||
|
||||
QStringList mAttrNames;
|
||||
|
||||
//! used with old labeling engine (QgsPalLabeling): whether labeling is enabled
|
||||
bool mLabeling;
|
||||
//! used with new labeling engine (QgsPalLabeling): whether diagrams are enabled
|
||||
bool mDiagrams;
|
||||
|
||||
//! used with new labeling engine (QgsLabelingEngineV2): provider for labels.
|
||||
//! may be null. no need to delete: if exists it is owned by labeling engine
|
||||
QgsVectorLayerLabelProvider* mLabelProvider;
|
||||
//! used with new labeling engine (QgsLabelingEngineV2): provider for diagrams.
|
||||
//! may be null. no need to delete: if exists it is owned by labeling engine
|
||||
QgsVectorLayerDiagramProvider* mDiagramProvider;
|
||||
|
||||
int mLayerTransparency;
|
||||
QPainter::CompositionMode mFeatureBlendMode;
|
||||
|
||||
|
@ -77,7 +77,8 @@ void TestQgsLabelingEngineV2::testBasic()
|
||||
vl->setCustomProperty( "labeling/enabled", true );
|
||||
vl->setCustomProperty( "labeling/fieldName", "Class" );
|
||||
|
||||
QgsLabelingEngineV2 engine( mapSettings );
|
||||
QgsLabelingEngineV2 engine;
|
||||
engine.setMapSettings( mapSettings );
|
||||
engine.addProvider( new QgsVectorLayerLabelProvider( vl ) );
|
||||
//engine.setFlags( QgsLabelingEngineV2::RenderOutlineLabels | QgsLabelingEngineV2::DrawLabelRectOnly );
|
||||
engine.run( context );
|
||||
@ -87,6 +88,12 @@ void TestQgsLabelingEngineV2::testBasic()
|
||||
// TODO: replace with render checker
|
||||
img.save( "/tmp/tstlabels.png" );
|
||||
|
||||
// now let's test the variant when integrated into rendering loop
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
QImage img2 = job.renderedImage();
|
||||
img2.save( "/tmp/tstlabels2.png" );
|
||||
|
||||
vl->setCustomProperty( "labeling/enabled", false );
|
||||
}
|
||||
|
||||
@ -112,7 +119,8 @@ void TestQgsLabelingEngineV2::testDiagrams()
|
||||
vl->loadNamedStyle( QString( TEST_DATA_DIR ) + "/points_diagrams.qml", res );
|
||||
Q_ASSERT( res );
|
||||
|
||||
QgsLabelingEngineV2 engine( mapSettings );
|
||||
QgsLabelingEngineV2 engine;
|
||||
engine.setMapSettings( mapSettings );
|
||||
engine.addProvider( new QgsVectorLayerDiagramProvider( vl ) );
|
||||
engine.run( context );
|
||||
|
||||
@ -120,6 +128,12 @@ void TestQgsLabelingEngineV2::testDiagrams()
|
||||
|
||||
// TODO: replace with render checker
|
||||
img.save( "/tmp/tstdiagrams.png" );
|
||||
|
||||
// now let's test the variant when integrated into rendering loop
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
QImage img2 = job.renderedImage();
|
||||
img2.save( "/tmp/tstdiagrams2.png" );
|
||||
}
|
||||
|
||||
QTEST_MAIN( TestQgsLabelingEngineV2 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user