mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-08 00:06:51 -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
|
%End
|
||||||
public:
|
public:
|
||||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
public:
|
||||||
|
|
||||||
class Rule
|
class Rule
|
||||||
{
|
{
|
||||||
@ -312,8 +312,6 @@ Set pal settings for a specific provider (takes ownership).
|
|||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ Rule based labeling for a vector layer.
|
|||||||
%End
|
%End
|
||||||
public:
|
public:
|
||||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
public:
|
||||||
|
|
||||||
class Rule
|
class Rule
|
||||||
{
|
{
|
||||||
@ -312,8 +312,6 @@ Set pal settings for a specific provider (takes ownership).
|
|||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,8 +31,10 @@ QgsVectorLayerLabelProvider *QgsRuleBasedLabelProvider::createProvider( QgsVecto
|
|||||||
|
|
||||||
bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
|
bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
|
||||||
{
|
{
|
||||||
for ( QgsVectorLayerLabelProvider *provider : std::as_const( mSubProviders ) )
|
for ( const auto &subprovider : std::as_const( mSubProviders ) )
|
||||||
provider->setEngine( mEngine );
|
{
|
||||||
|
subprovider.second->setEngine( mEngine );
|
||||||
|
}
|
||||||
|
|
||||||
// populate sub-providers
|
// populate sub-providers
|
||||||
mRules->rootRule()->prepare( context, attributeNames, mSubProviders );
|
mRules->rootRule()->prepare( context, attributeNames, mSubProviders );
|
||||||
@ -48,8 +50,10 @@ QList<QgsLabelFeature *> QgsRuleBasedLabelProvider::registerFeature( const QgsFe
|
|||||||
QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
|
QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
|
||||||
{
|
{
|
||||||
QList<QgsAbstractLabelProvider *> lst;
|
QList<QgsAbstractLabelProvider *> lst;
|
||||||
for ( QgsVectorLayerLabelProvider *subprovider : std::as_const( mSubProviders ) )
|
for ( const auto &subprovider : std::as_const( mSubProviders ) )
|
||||||
lst << subprovider;
|
{
|
||||||
|
lst << subprovider.second;
|
||||||
|
}
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,14 +316,25 @@ QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument &doc, const QgsReadWr
|
|||||||
return ruleElem;
|
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 )
|
if ( mSettings )
|
||||||
{
|
{
|
||||||
// add provider!
|
// add provider!
|
||||||
QgsVectorLayerLabelProvider *p = provider->createProvider( layer, mRuleKey, false, mSettings.get() );
|
QgsVectorLayerLabelProvider *p = provider->createProvider( layer, mRuleKey, false, mSettings.get() );
|
||||||
delete subProviders.value( this, nullptr );
|
auto it = std::find_if( subProviders.begin(), subProviders.end(),
|
||||||
subProviders[this] = p;
|
[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
|
// 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 )
|
if ( mSettings )
|
||||||
{
|
{
|
||||||
QgsVectorLayerLabelProvider *p = subProviders[this];
|
auto it = std::find_if( subProviders.begin(), subProviders.end(),
|
||||||
if ( !p->prepare( context, attributeNames ) )
|
[this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
|
||||||
{
|
{
|
||||||
subProviders.remove( this );
|
return item.first == this;
|
||||||
delete p;
|
} );
|
||||||
|
|
||||||
|
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;
|
QList< QgsLabelFeature * > labels;
|
||||||
if ( !isFilterOK( feature, context )
|
if ( !isFilterOK( feature, context )
|
||||||
@ -366,9 +390,15 @@ std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature *
|
|||||||
bool registered = false;
|
bool registered = false;
|
||||||
|
|
||||||
// do we have active subprovider for the rule?
|
// 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;
|
registered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,10 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
|||||||
public:
|
public:
|
||||||
class Rule;
|
class Rule;
|
||||||
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
typedef QList<QgsRuleBasedLabeling::Rule *> RuleList;
|
||||||
typedef QMap<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> RuleToProviderMap;
|
private:
|
||||||
|
typedef std::vector<std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *>> RuleToProviderVec;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
@ -261,7 +264,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
|||||||
* add providers
|
* add providers
|
||||||
* \note not available in Python bindings
|
* \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)
|
* 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
|
* call prepare() on sub-providers and populate attributeNames
|
||||||
* \note not available in Python bindings
|
* \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
|
* Register individual features
|
||||||
@ -284,7 +287,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
|
|||||||
*
|
*
|
||||||
* \note not available in Python bindings
|
* \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
|
* 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:
|
protected:
|
||||||
std::unique_ptr<Rule> mRootRule;
|
std::unique_ptr<Rule> mRootRule;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SIP_RUN
|
#ifndef SIP_RUN
|
||||||
@ -425,7 +426,7 @@ class CORE_EXPORT QgsRuleBasedLabelProvider : public QgsVectorLayerLabelProvider
|
|||||||
//! owned copy
|
//! owned copy
|
||||||
std::unique_ptr<QgsRuleBasedLabeling> mRules;
|
std::unique_ptr<QgsRuleBasedLabeling> mRules;
|
||||||
//! label providers are owned by labeling engine
|
//! label providers are owned by labeling engine
|
||||||
QgsRuleBasedLabeling::RuleToProviderMap mSubProviders;
|
std::vector<std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *>> mSubProviders;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user