mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
Ensure consistent label positioning by sorting rule based label providers
This commit is contained in:
parent
5745bd634b
commit
12a2079225
@ -21,7 +21,7 @@ Rule based labeling for a vector layer.
|
||||
%End
|
||||
public:
|
||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
||||
public:
|
||||
|
||||
class Rule
|
||||
{
|
||||
@ -312,8 +312,6 @@ Set pal settings for a specific provider (takes ownership).
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ Rule based labeling for a vector layer.
|
||||
%End
|
||||
public:
|
||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
||||
public:
|
||||
|
||||
class Rule
|
||||
{
|
||||
@ -312,8 +312,6 @@ Set pal settings for a specific provider (takes ownership).
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -31,8 +31,10 @@ QgsVectorLayerLabelProvider *QgsRuleBasedLabelProvider::createProvider( QgsVecto
|
||||
|
||||
bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
|
||||
{
|
||||
for ( QgsVectorLayerLabelProvider *provider : std::as_const( mSubProviders ) )
|
||||
provider->setEngine( mEngine );
|
||||
for ( const auto &subprovider : std::as_const( mSubProviders ) )
|
||||
{
|
||||
subprovider.second->setEngine( mEngine );
|
||||
}
|
||||
|
||||
// populate sub-providers
|
||||
mRules->rootRule()->prepare( context, attributeNames, mSubProviders );
|
||||
@ -48,8 +50,10 @@ QList<QgsLabelFeature *> QgsRuleBasedLabelProvider::registerFeature( const QgsFe
|
||||
QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
|
||||
{
|
||||
QList<QgsAbstractLabelProvider *> lst;
|
||||
for ( QgsVectorLayerLabelProvider *subprovider : std::as_const( mSubProviders ) )
|
||||
lst << subprovider;
|
||||
for ( const auto &subprovider : std::as_const( mSubProviders ) )
|
||||
{
|
||||
lst << subprovider.second;
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
@ -312,14 +316,25 @@ QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument &doc, const QgsReadWr
|
||||
return ruleElem;
|
||||
}
|
||||
|
||||
void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer *layer, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, QgsRuleBasedLabelProvider *provider )
|
||||
void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer *layer, QgsRuleBasedLabeling::RuleToProviderVec &subProviders, QgsRuleBasedLabelProvider *provider )
|
||||
{
|
||||
if ( mSettings )
|
||||
{
|
||||
// add provider!
|
||||
QgsVectorLayerLabelProvider *p = provider->createProvider( layer, mRuleKey, false, mSettings.get() );
|
||||
delete subProviders.value( this, nullptr );
|
||||
subProviders[this] = p;
|
||||
auto it = std::find_if( subProviders.begin(), subProviders.end(),
|
||||
[this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
|
||||
{
|
||||
return item.first == this;
|
||||
} );
|
||||
|
||||
if ( it != subProviders.end() )
|
||||
{
|
||||
delete it->second;
|
||||
subProviders.erase( it );
|
||||
}
|
||||
|
||||
subProviders.push_back( {this, p} );
|
||||
}
|
||||
|
||||
// call recursively
|
||||
@ -329,15 +344,24 @@ void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer *layer, QgsR
|
||||
}
|
||||
}
|
||||
|
||||
void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QString> &attributeNames, QgsRuleBasedLabeling::RuleToProviderMap &subProviders )
|
||||
void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QString> &attributeNames, QgsRuleBasedLabeling::RuleToProviderVec &subProviders )
|
||||
{
|
||||
if ( mSettings )
|
||||
{
|
||||
QgsVectorLayerLabelProvider *p = subProviders[this];
|
||||
if ( !p->prepare( context, attributeNames ) )
|
||||
auto it = std::find_if( subProviders.begin(), subProviders.end(),
|
||||
[this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
|
||||
{
|
||||
subProviders.remove( this );
|
||||
delete p;
|
||||
return item.first == this;
|
||||
} );
|
||||
|
||||
if ( it != subProviders.end() )
|
||||
{
|
||||
QgsVectorLayerLabelProvider *p = it->second;
|
||||
if ( !p->prepare( context, attributeNames ) )
|
||||
{
|
||||
subProviders.erase( it );
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +378,7 @@ void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QStrin
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature * > > QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||
std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature * > > QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderVec &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
|
||||
{
|
||||
QList< QgsLabelFeature * > labels;
|
||||
if ( !isFilterOK( feature, context )
|
||||
@ -366,9 +390,15 @@ std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature *
|
||||
bool registered = false;
|
||||
|
||||
// do we have active subprovider for the rule?
|
||||
if ( subProviders.contains( this ) && mIsActive )
|
||||
auto it = std::find_if( subProviders.begin(), subProviders.end(),
|
||||
[this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
|
||||
{
|
||||
labels.append( subProviders[this]->registerFeature( feature, context, obstacleGeometry, symbol ) );
|
||||
return item.first == this;
|
||||
} );
|
||||
|
||||
if ( it != subProviders.end() && mIsActive )
|
||||
{
|
||||
labels.append( it->second->registerFeature( feature, context, obstacleGeometry, symbol ) );
|
||||
registered = true;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,10 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
||||
public:
|
||||
class Rule;
|
||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
||||
private:
|
||||
typedef std::vector<std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *>> RuleToProviderVec;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -261,7 +264,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
||||
* add providers
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
void createSubProviders( QgsVectorLayer *layer, RuleToProviderMap &subProviders, QgsRuleBasedLabelProvider *provider ) SIP_SKIP;
|
||||
void createSubProviders( QgsVectorLayer *layer, RuleToProviderVec &subProviders, QgsRuleBasedLabelProvider *provider ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* append rule keys of descendants that contain valid settings (i.e. they will be sub-providers)
|
||||
@ -273,7 +276,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
||||
* call prepare() on sub-providers and populate attributeNames
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
void prepare( QgsRenderContext &context, QSet<QString> &attributeNames, RuleToProviderMap &subProviders ) SIP_SKIP;
|
||||
void prepare( QgsRenderContext &context, QSet<QString> &attributeNames, RuleToProviderVec &subProviders ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Register individual features
|
||||
@ -284,7 +287,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
std::tuple< RegisterResult, QList< QgsLabelFeature * > > registerFeature( const QgsFeature &feature, QgsRenderContext &context, RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) SIP_SKIP;
|
||||
std::tuple< RegisterResult, QList< QgsLabelFeature * > > registerFeature( const QgsFeature &feature, QgsRenderContext &context, RuleToProviderVec &subProviders, const QgsGeometry &obstacleGeometry = QgsGeometry(), const QgsSymbol *symbol = nullptr ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns TRUE if this rule or any of its children requires advanced composition effects
|
||||
@ -391,8 +394,6 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Rule> mRootRule;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#ifndef SIP_RUN
|
||||
@ -425,7 +426,7 @@ class CORE_EXPORT QgsRuleBasedLabelProvider : public QgsVectorLayerLabelProvider
|
||||
//! owned copy
|
||||
std::unique_ptr<QgsRuleBasedLabeling> mRules;
|
||||
//! label providers are owned by labeling engine
|
||||
QgsRuleBasedLabeling::RuleToProviderMap mSubProviders;
|
||||
std::vector<std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *>> mSubProviders;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user