LCOV - code coverage report
Current view: top level - core/labeling - qgsrulebasedlabeling.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 337 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :     qgsrulebasedlabeling.cpp
       3                 :            :     ---------------------
       4                 :            :     begin                : September 2015
       5                 :            :     copyright            : (C) 2015 by Martin Dobias
       6                 :            :     email                : wonder dot sk at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : #include "qgsrulebasedlabeling.h"
      16                 :            : #include "qgssymbollayerutils.h"
      17                 :            : #include "qgsstyleentityvisitor.h"
      18                 :            : 
      19                 :          0 : QgsRuleBasedLabelProvider::QgsRuleBasedLabelProvider( const QgsRuleBasedLabeling &rules, QgsVectorLayer *layer, bool withFeatureLoop )
      20                 :          0 :   : QgsVectorLayerLabelProvider( layer, QString(), withFeatureLoop, nullptr )
      21                 :          0 : {
      22                 :          0 :   mRules.reset( rules.clone() );
      23                 :          0 :   mRules->rootRule()->createSubProviders( layer, mSubProviders, this );
      24                 :          0 : }
      25                 :            : 
      26                 :          0 : QgsVectorLayerLabelProvider *QgsRuleBasedLabelProvider::createProvider( QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings )
      27                 :            : {
      28                 :          0 :   return new QgsVectorLayerLabelProvider( layer, providerId, withFeatureLoop, settings );
      29                 :          0 : }
      30                 :            : 
      31                 :          0 : bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
      32                 :            : {
      33                 :          0 :   for ( QgsVectorLayerLabelProvider *provider : std::as_const( mSubProviders ) )
      34                 :          0 :     provider->setEngine( mEngine );
      35                 :            : 
      36                 :            :   // populate sub-providers
      37                 :          0 :   mRules->rootRule()->prepare( context, attributeNames, mSubProviders );
      38                 :          0 :   return true;
      39                 :            : }
      40                 :            : 
      41                 :          0 : void QgsRuleBasedLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
      42                 :            : {
      43                 :            :   // will register the feature to relevant sub-providers
      44                 :          0 :   mRules->rootRule()->registerFeature( feature, context, mSubProviders, obstacleGeometry, symbol );
      45                 :          0 : }
      46                 :            : 
      47                 :          0 : QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
      48                 :            : {
      49                 :          0 :   QList<QgsAbstractLabelProvider *> lst;
      50                 :          0 :   for ( QgsVectorLayerLabelProvider *subprovider : std::as_const( mSubProviders ) )
      51                 :          0 :     lst << subprovider;
      52                 :          0 :   return lst;
      53                 :          0 : }
      54                 :            : 
      55                 :            : 
      56                 :            : ////////////////////
      57                 :            : 
      58                 :          0 : QgsRuleBasedLabeling::Rule::Rule( QgsPalLayerSettings *settings, double scaleMinDenom, double scaleMaxDenom, const QString &filterExp, const QString &description, bool elseRule )
      59                 :          0 :   : mSettings( settings )
      60                 :          0 :   , mMaximumScale( scaleMinDenom )
      61                 :          0 :   , mMinimumScale( scaleMaxDenom )
      62                 :          0 :   , mFilterExp( filterExp )
      63                 :          0 :   , mDescription( description )
      64                 :          0 :   , mElseRule( elseRule )
      65                 :            : 
      66                 :            : {
      67                 :          0 :   initFilter();
      68                 :          0 : }
      69                 :            : 
      70                 :          0 : QgsRuleBasedLabeling::Rule::~Rule()
      71                 :            : {
      72                 :          0 :   qDeleteAll( mChildren );
      73                 :            :   // do NOT delete parent
      74                 :          0 : }
      75                 :            : 
      76                 :          0 : void QgsRuleBasedLabeling::Rule::setSettings( QgsPalLayerSettings *settings )
      77                 :            : {
      78                 :          0 :   if ( mSettings.get() == settings )
      79                 :          0 :     return;
      80                 :            : 
      81                 :          0 :   mSettings.reset( settings );
      82                 :          0 : }
      83                 :            : 
      84                 :          0 : QgsRuleBasedLabeling::RuleList QgsRuleBasedLabeling::Rule::descendants() const
      85                 :            : {
      86                 :          0 :   RuleList l;
      87                 :          0 :   for ( Rule *c : mChildren )
      88                 :            :   {
      89                 :          0 :     l += c;
      90                 :          0 :     l += c->descendants();
      91                 :            :   }
      92                 :          0 :   return l;
      93                 :          0 : }
      94                 :            : 
      95                 :          0 : void QgsRuleBasedLabeling::Rule::initFilter()
      96                 :            : {
      97                 :          0 :   if ( mElseRule || mFilterExp.compare( QLatin1String( "ELSE" ), Qt::CaseInsensitive ) == 0 )
      98                 :            :   {
      99                 :          0 :     mElseRule = true;
     100                 :          0 :     mFilter.reset( nullptr );
     101                 :          0 :   }
     102                 :          0 :   else if ( !mFilterExp.isEmpty() )
     103                 :            :   {
     104                 :          0 :     mFilter.reset( new QgsExpression( mFilterExp ) );
     105                 :          0 :   }
     106                 :            :   else
     107                 :            :   {
     108                 :          0 :     mFilter.reset( nullptr );
     109                 :            :   }
     110                 :          0 : }
     111                 :            : 
     112                 :          0 : void QgsRuleBasedLabeling::Rule::updateElseRules()
     113                 :            : {
     114                 :          0 :   mElseRules.clear();
     115                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     116                 :            :   {
     117                 :          0 :     if ( rule->isElse() )
     118                 :          0 :       mElseRules << rule;
     119                 :            :   }
     120                 :          0 : }
     121                 :            : 
     122                 :          0 : bool QgsRuleBasedLabeling::Rule::requiresAdvancedEffects() const
     123                 :            : {
     124                 :          0 :   if ( mSettings && mSettings->format().containsAdvancedEffects() )
     125                 :          0 :     return true;
     126                 :            : 
     127                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     128                 :            :   {
     129                 :          0 :     if ( rule->requiresAdvancedEffects() )
     130                 :          0 :       return true;
     131                 :            :   }
     132                 :            : 
     133                 :          0 :   return false;
     134                 :          0 : }
     135                 :            : 
     136                 :          0 : bool QgsRuleBasedLabeling::Rule::accept( QgsStyleEntityVisitorInterface *visitor ) const
     137                 :            : {
     138                 :            :   // NOTE: if visitEnter returns false it means "don't visit the rule", not "abort all further visitations"
     139                 :          0 :   if ( mParent && !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::SymbolRule, mRuleKey, mDescription ) ) )
     140                 :          0 :     return true;
     141                 :            : 
     142                 :          0 :   if ( mSettings )
     143                 :            :   {
     144                 :          0 :     QgsStyleLabelSettingsEntity entity( *mSettings );
     145                 :          0 :     if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
     146                 :          0 :       return false;
     147                 :          0 :   }
     148                 :            : 
     149                 :          0 :   if ( !mChildren.empty() )
     150                 :            :   {
     151                 :          0 :     for ( const Rule *rule : mChildren )
     152                 :            :     {
     153                 :          0 :       if ( !rule->accept( visitor ) )
     154                 :          0 :         return false;
     155                 :            :     }
     156                 :          0 :   }
     157                 :            : 
     158                 :          0 :   if ( mParent && !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::SymbolRule, mRuleKey, mDescription ) ) )
     159                 :          0 :     return false;
     160                 :            : 
     161                 :          0 :   return true;
     162                 :          0 : }
     163                 :            : 
     164                 :          0 : void QgsRuleBasedLabeling::Rule::subProviderIds( QStringList &list ) const
     165                 :            : {
     166                 :          0 :   for ( const Rule *rule : std::as_const( mChildren ) )
     167                 :            :   {
     168                 :          0 :     if ( rule->settings() )
     169                 :          0 :       list << rule->ruleKey();
     170                 :            : 
     171                 :          0 :     rule->subProviderIds( list );
     172                 :            :   }
     173                 :          0 : }
     174                 :            : 
     175                 :            : 
     176                 :          0 : void QgsRuleBasedLabeling::Rule::appendChild( QgsRuleBasedLabeling::Rule *rule )
     177                 :            : {
     178                 :          0 :   mChildren.append( rule );
     179                 :          0 :   rule->mParent = this;
     180                 :          0 :   updateElseRules();
     181                 :          0 : }
     182                 :            : 
     183                 :          0 : void QgsRuleBasedLabeling::Rule::insertChild( int i, QgsRuleBasedLabeling::Rule *rule )
     184                 :            : {
     185                 :          0 :   mChildren.insert( i, rule );
     186                 :          0 :   rule->mParent = this;
     187                 :          0 :   updateElseRules();
     188                 :          0 : }
     189                 :            : 
     190                 :          0 : void QgsRuleBasedLabeling::Rule::removeChildAt( int i )
     191                 :            : {
     192                 :          0 :   delete mChildren.at( i );
     193                 :          0 :   mChildren.removeAt( i );
     194                 :          0 :   updateElseRules();
     195                 :          0 : }
     196                 :            : 
     197                 :          0 : const QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::findRuleByKey( const QString &key ) const
     198                 :            : {
     199                 :            :   // we could use a hash / map for search if this will be slow...
     200                 :            : 
     201                 :          0 :   if ( key == mRuleKey )
     202                 :          0 :     return this;
     203                 :            : 
     204                 :          0 :   for ( Rule *rule : mChildren )
     205                 :            :   {
     206                 :          0 :     const Rule *r = rule->findRuleByKey( key );
     207                 :          0 :     if ( r )
     208                 :          0 :       return r;
     209                 :            :   }
     210                 :          0 :   return nullptr;
     211                 :          0 : }
     212                 :            : 
     213                 :          0 : QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::findRuleByKey( const QString &key )
     214                 :            : {
     215                 :          0 :   if ( key == mRuleKey )
     216                 :          0 :     return this;
     217                 :            : 
     218                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     219                 :            :   {
     220                 :          0 :     Rule *r = rule->findRuleByKey( key );
     221                 :          0 :     if ( r )
     222                 :          0 :       return r;
     223                 :            :   }
     224                 :          0 :   return nullptr;
     225                 :          0 : }
     226                 :            : 
     227                 :          0 : QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::clone() const
     228                 :            : {
     229                 :          0 :   QgsPalLayerSettings *s = mSettings.get() ? new QgsPalLayerSettings( *mSettings ) : nullptr;
     230                 :          0 :   Rule *newrule = new Rule( s, mMaximumScale, mMinimumScale, mFilterExp, mDescription );
     231                 :          0 :   newrule->setActive( mIsActive );
     232                 :            :   // clone children
     233                 :          0 :   for ( Rule *rule : mChildren )
     234                 :          0 :     newrule->appendChild( rule->clone() );
     235                 :          0 :   return newrule;
     236                 :          0 : }
     237                 :            : 
     238                 :          0 : QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::create( const QDomElement &ruleElem, const QgsReadWriteContext &context )
     239                 :            : {
     240                 :          0 :   QgsPalLayerSettings *settings = nullptr;
     241                 :          0 :   QDomElement settingsElem = ruleElem.firstChildElement( QStringLiteral( "settings" ) );
     242                 :          0 :   if ( !settingsElem.isNull() )
     243                 :            :   {
     244                 :          0 :     settings = new QgsPalLayerSettings;
     245                 :          0 :     settings->readXml( settingsElem, context );
     246                 :          0 :   }
     247                 :            : 
     248                 :          0 :   QString filterExp = ruleElem.attribute( QStringLiteral( "filter" ) );
     249                 :          0 :   QString description = ruleElem.attribute( QStringLiteral( "description" ) );
     250                 :          0 :   int scaleMinDenom = ruleElem.attribute( QStringLiteral( "scalemindenom" ), QStringLiteral( "0" ) ).toInt();
     251                 :          0 :   int scaleMaxDenom = ruleElem.attribute( QStringLiteral( "scalemaxdenom" ), QStringLiteral( "0" ) ).toInt();
     252                 :          0 :   QString ruleKey = ruleElem.attribute( QStringLiteral( "key" ) );
     253                 :          0 :   Rule *rule = new Rule( settings, scaleMinDenom, scaleMaxDenom, filterExp, description );
     254                 :            : 
     255                 :          0 :   if ( !ruleKey.isEmpty() )
     256                 :          0 :     rule->mRuleKey = ruleKey;
     257                 :            : 
     258                 :          0 :   rule->setActive( ruleElem.attribute( QStringLiteral( "active" ), QStringLiteral( "1" ) ).toInt() );
     259                 :            : 
     260                 :          0 :   QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral( "rule" ) );
     261                 :          0 :   while ( !childRuleElem.isNull() )
     262                 :            :   {
     263                 :          0 :     Rule *childRule = create( childRuleElem, context );
     264                 :          0 :     if ( childRule )
     265                 :            :     {
     266                 :          0 :       rule->appendChild( childRule );
     267                 :          0 :     }
     268                 :            :     else
     269                 :            :     {
     270                 :            :       //QgsDebugMsg( QStringLiteral( "failed to init a child rule!" ) );
     271                 :            :     }
     272                 :          0 :     childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral( "rule" ) );
     273                 :            :   }
     274                 :            : 
     275                 :          0 :   return rule;
     276                 :          0 : }
     277                 :            : 
     278                 :          0 : QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
     279                 :            : {
     280                 :          0 :   QDomElement ruleElem = doc.createElement( QStringLiteral( "rule" ) );
     281                 :            : 
     282                 :          0 :   if ( mSettings )
     283                 :            :   {
     284                 :          0 :     ruleElem.appendChild( mSettings->writeXml( doc, context ) );
     285                 :          0 :   }
     286                 :          0 :   if ( !mFilterExp.isEmpty() )
     287                 :          0 :     ruleElem.setAttribute( QStringLiteral( "filter" ), mFilterExp );
     288                 :          0 :   if ( !qgsDoubleNear( mMaximumScale, 0 ) )
     289                 :          0 :     ruleElem.setAttribute( QStringLiteral( "scalemindenom" ), mMaximumScale );
     290                 :          0 :   if ( !qgsDoubleNear( mMinimumScale, 0 ) )
     291                 :          0 :     ruleElem.setAttribute( QStringLiteral( "scalemaxdenom" ), mMinimumScale );
     292                 :          0 :   if ( !mDescription.isEmpty() )
     293                 :          0 :     ruleElem.setAttribute( QStringLiteral( "description" ), mDescription );
     294                 :          0 :   if ( !mIsActive )
     295                 :          0 :     ruleElem.setAttribute( QStringLiteral( "active" ), 0 );
     296                 :          0 :   ruleElem.setAttribute( QStringLiteral( "key" ), mRuleKey );
     297                 :            : 
     298                 :          0 :   for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
     299                 :            :   {
     300                 :          0 :     Rule *rule = *it;
     301                 :          0 :     ruleElem.appendChild( rule->save( doc, context ) );
     302                 :          0 :   }
     303                 :          0 :   return ruleElem;
     304                 :          0 : }
     305                 :            : 
     306                 :          0 : void QgsRuleBasedLabeling::Rule::createSubProviders( QgsVectorLayer *layer, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, QgsRuleBasedLabelProvider *provider )
     307                 :            : {
     308                 :          0 :   if ( mSettings )
     309                 :            :   {
     310                 :            :     // add provider!
     311                 :          0 :     QgsVectorLayerLabelProvider *p = provider->createProvider( layer, mRuleKey, false, mSettings.get() );
     312                 :          0 :     delete subProviders.value( this, nullptr );
     313                 :          0 :     subProviders[this] = p;
     314                 :          0 :   }
     315                 :            : 
     316                 :            :   // call recursively
     317                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     318                 :            :   {
     319                 :          0 :     rule->createSubProviders( layer, subProviders, provider );
     320                 :            :   }
     321                 :          0 : }
     322                 :            : 
     323                 :          0 : void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QString> &attributeNames, QgsRuleBasedLabeling::RuleToProviderMap &subProviders )
     324                 :            : {
     325                 :          0 :   if ( mSettings )
     326                 :            :   {
     327                 :          0 :     QgsVectorLayerLabelProvider *p = subProviders[this];
     328                 :          0 :     if ( !p->prepare( context, attributeNames ) )
     329                 :            :     {
     330                 :          0 :       subProviders.remove( this );
     331                 :          0 :       delete p;
     332                 :          0 :     }
     333                 :          0 :   }
     334                 :            : 
     335                 :          0 :   if ( mFilter )
     336                 :            :   {
     337                 :          0 :     attributeNames.unite( mFilter->referencedColumns() );
     338                 :          0 :     mFilter->prepare( &context.expressionContext() );
     339                 :          0 :   }
     340                 :            : 
     341                 :          0 :   // call recursively
     342                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     343                 :            :   {
     344                 :          0 :     rule->prepare( context, attributeNames, subProviders );
     345                 :            :   }
     346                 :          0 : }
     347                 :            : 
     348                 :          0 : QgsRuleBasedLabeling::Rule::RegisterResult QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
     349                 :            : {
     350                 :          0 :   if ( !isFilterOK( feature, context )
     351                 :          0 :        || !isScaleOK( context.rendererScale() ) )
     352                 :          0 :   {
     353                 :          0 :     return Filtered;
     354                 :            :   }
     355                 :            : 
     356                 :          0 :   bool registered = false;
     357                 :            : 
     358                 :            :   // do we have active subprovider for the rule?
     359                 :          0 :   if ( subProviders.contains( this ) && mIsActive )
     360                 :            :   {
     361                 :          0 :     subProviders[this]->registerFeature( feature, context, obstacleGeometry, symbol );
     362                 :          0 :     registered = true;
     363                 :          0 :   }
     364                 :            : 
     365                 :          0 :   bool willRegisterSomething = false;
     366                 :            : 
     367                 :            :   // call recursively
     368                 :          0 :   for ( Rule *rule : std::as_const( mChildren ) )
     369                 :            :   {
     370                 :            :     // Don't process else rules yet
     371                 :          0 :     if ( !rule->isElse() )
     372                 :            :     {
     373                 :          0 :       RegisterResult res = rule->registerFeature( feature, context, subProviders, obstacleGeometry );
     374                 :            :       // consider inactive items as "registered" so the else rule will ignore them
     375                 :          0 :       willRegisterSomething |= ( res == Registered || res == Inactive );
     376                 :          0 :       registered |= willRegisterSomething;
     377                 :          0 :     }
     378                 :            :   }
     379                 :            : 
     380                 :            :   // If none of the rules passed then we jump into the else rules and process them.
     381                 :          0 :   if ( !willRegisterSomething )
     382                 :            :   {
     383                 :          0 :     for ( Rule *rule : std::as_const( mElseRules ) )
     384                 :            :     {
     385                 :          0 :       registered |= rule->registerFeature( feature, context, subProviders, obstacleGeometry, symbol ) != Filtered;
     386                 :            :     }
     387                 :          0 :   }
     388                 :            : 
     389                 :          0 :   if ( !mIsActive )
     390                 :          0 :     return Inactive;
     391                 :          0 :   else if ( registered )
     392                 :          0 :     return Registered;
     393                 :            :   else
     394                 :          0 :     return Filtered;
     395                 :          0 : }
     396                 :            : 
     397                 :          0 : bool QgsRuleBasedLabeling::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext &context ) const
     398                 :            : {
     399                 :          0 :   if ( ! mFilter || mElseRule )
     400                 :          0 :     return true;
     401                 :            : 
     402                 :          0 :   context.expressionContext().setFeature( f );
     403                 :          0 :   QVariant res = mFilter->evaluate( &context.expressionContext() );
     404                 :          0 :   return res.toBool();
     405                 :          0 : }
     406                 :            : 
     407                 :          0 : bool QgsRuleBasedLabeling::Rule::isScaleOK( double scale ) const
     408                 :            : {
     409                 :          0 :   if ( qgsDoubleNear( scale, 0.0 ) ) // so that we can count features in classes without scale context
     410                 :          0 :     return true;
     411                 :          0 :   if ( qgsDoubleNear( mMaximumScale, 0.0 ) && qgsDoubleNear( mMinimumScale, 0.0 ) )
     412                 :          0 :     return true;
     413                 :          0 :   if ( !qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
     414                 :          0 :     return false;
     415                 :          0 :   if ( !qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
     416                 :          0 :     return false;
     417                 :          0 :   return true;
     418                 :          0 : }
     419                 :            : 
     420                 :            : ////////////////////
     421                 :            : 
     422                 :          0 : QgsRuleBasedLabeling::QgsRuleBasedLabeling( QgsRuleBasedLabeling::Rule *root )
     423                 :          0 :   : mRootRule( root )
     424                 :          0 : {
     425                 :          0 : }
     426                 :            : 
     427                 :          0 : QgsRuleBasedLabeling *QgsRuleBasedLabeling::clone() const
     428                 :            : {
     429                 :          0 :   Rule *rootRule = mRootRule->clone();
     430                 :            : 
     431                 :            :   // normally with clone() the individual rules get new keys (UUID), but here we want to keep
     432                 :            :   // the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. map themes)
     433                 :          0 :   rootRule->setRuleKey( mRootRule->ruleKey() );
     434                 :          0 :   RuleList origDescendants = mRootRule->descendants();
     435                 :          0 :   RuleList clonedDescendants = rootRule->descendants();
     436                 :            :   Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
     437                 :          0 :   for ( int i = 0; i < origDescendants.count(); ++i )
     438                 :          0 :     clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
     439                 :            : 
     440                 :          0 :   return new QgsRuleBasedLabeling( rootRule );
     441                 :          0 : }
     442                 :            : 
     443                 :          0 : QgsRuleBasedLabeling::~QgsRuleBasedLabeling()
     444                 :          0 : {
     445                 :          0 : }
     446                 :            : 
     447                 :          0 : QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::rootRule()
     448                 :            : {
     449                 :          0 :   return mRootRule.get();
     450                 :            : }
     451                 :            : 
     452                 :          0 : const QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::rootRule() const
     453                 :            : {
     454                 :          0 :   return mRootRule.get();
     455                 :            : }
     456                 :            : 
     457                 :            : 
     458                 :          0 : QgsRuleBasedLabeling *QgsRuleBasedLabeling::create( const QDomElement &element, const QgsReadWriteContext &context )
     459                 :            : {
     460                 :          0 :   QDomElement rulesElem = element.firstChildElement( QStringLiteral( "rules" ) );
     461                 :            : 
     462                 :          0 :   Rule *root = Rule::create( rulesElem, context );
     463                 :          0 :   if ( !root )
     464                 :          0 :     return nullptr;
     465                 :            : 
     466                 :          0 :   QgsRuleBasedLabeling *rl = new QgsRuleBasedLabeling( root );
     467                 :          0 :   return rl;
     468                 :          0 : }
     469                 :            : 
     470                 :          0 : QString QgsRuleBasedLabeling::type() const
     471                 :            : {
     472                 :          0 :   return QStringLiteral( "rule-based" );
     473                 :            : }
     474                 :            : 
     475                 :          0 : QDomElement QgsRuleBasedLabeling::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
     476                 :            : {
     477                 :          0 :   QDomElement elem = doc.createElement( QStringLiteral( "labeling" ) );
     478                 :          0 :   elem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "rule-based" ) );
     479                 :            : 
     480                 :          0 :   QDomElement rulesElem = mRootRule->save( doc, context );
     481                 :          0 :   rulesElem.setTagName( QStringLiteral( "rules" ) ); // instead of just "rule"
     482                 :          0 :   elem.appendChild( rulesElem );
     483                 :            : 
     484                 :          0 :   return elem;
     485                 :          0 : }
     486                 :            : 
     487                 :          0 : QgsVectorLayerLabelProvider *QgsRuleBasedLabeling::provider( QgsVectorLayer *layer ) const
     488                 :            : {
     489                 :          0 :   return new QgsRuleBasedLabelProvider( *this, layer, false );
     490                 :          0 : }
     491                 :            : 
     492                 :          0 : QStringList QgsRuleBasedLabeling::subProviders() const
     493                 :            : {
     494                 :          0 :   QStringList lst;
     495                 :          0 :   mRootRule->subProviderIds( lst );
     496                 :          0 :   return lst;
     497                 :          0 : }
     498                 :            : 
     499                 :          0 : QgsPalLayerSettings QgsRuleBasedLabeling::settings( const QString &providerId ) const
     500                 :            : {
     501                 :          0 :   const Rule *rule = mRootRule->findRuleByKey( providerId );
     502                 :          0 :   if ( rule && rule->settings() )
     503                 :          0 :     return *rule->settings();
     504                 :            : 
     505                 :          0 :   return QgsPalLayerSettings();
     506                 :          0 : }
     507                 :            : 
     508                 :          0 : bool QgsRuleBasedLabeling::accept( QgsStyleEntityVisitorInterface *visitor ) const
     509                 :            : {
     510                 :          0 :   return mRootRule->accept( visitor );
     511                 :            : }
     512                 :            : 
     513                 :          0 : bool QgsRuleBasedLabeling::requiresAdvancedEffects() const
     514                 :            : {
     515                 :          0 :   return mRootRule->requiresAdvancedEffects();
     516                 :            : }
     517                 :            : 
     518                 :          0 : void QgsRuleBasedLabeling::setSettings( QgsPalLayerSettings *settings, const QString &providerId )
     519                 :            : {
     520                 :          0 :   if ( settings )
     521                 :            :   {
     522                 :          0 :     Rule *rule = mRootRule->findRuleByKey( providerId );
     523                 :          0 :     if ( rule && rule->settings() )
     524                 :          0 :       rule->setSettings( settings );
     525                 :          0 :   }
     526                 :          0 : }
     527                 :            : 
     528                 :          0 : void QgsRuleBasedLabeling::toSld( QDomNode &parent, const QVariantMap &props ) const
     529                 :            : {
     530                 :          0 :   if ( !mRootRule )
     531                 :            :   {
     532                 :          0 :     return;
     533                 :            :   }
     534                 :            : 
     535                 :          0 :   const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
     536                 :          0 :   for ( Rule *rule : rules )
     537                 :            :   {
     538                 :          0 :     QgsPalLayerSettings *settings = rule->settings();
     539                 :            : 
     540                 :          0 :     if ( settings && settings->drawLabels )
     541                 :            :     {
     542                 :          0 :       QDomDocument doc = parent.ownerDocument();
     543                 :            : 
     544                 :          0 :       QDomElement ruleElement = doc.createElement( QStringLiteral( "se:Rule" ) );
     545                 :          0 :       parent.appendChild( ruleElement );
     546                 :            : 
     547                 :          0 :       if ( !rule->filterExpression().isEmpty() )
     548                 :            :       {
     549                 :          0 :         QgsSymbolLayerUtils::createFunctionElement( doc, ruleElement, rule->filterExpression() );
     550                 :          0 :       }
     551                 :            : 
     552                 :            :       // scale dependencies, the actual behavior is that the PAL settings min/max and
     553                 :            :       // the rule min/max get intersected
     554                 :          0 :       QVariantMap localProps = QVariantMap( props );
     555                 :          0 :       QgsSymbolLayerUtils::mergeScaleDependencies( rule->maximumScale(), rule->minimumScale(), localProps );
     556                 :          0 :       if ( settings->scaleVisibility )
     557                 :            :       {
     558                 :          0 :         QgsSymbolLayerUtils::mergeScaleDependencies( settings->maximumScale, settings->minimumScale, localProps );
     559                 :          0 :       }
     560                 :          0 :       QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, localProps );
     561                 :            : 
     562                 :          0 :       QgsAbstractVectorLayerLabeling::writeTextSymbolizer( ruleElement, *settings, props );
     563                 :          0 :     }
     564                 :            : 
     565                 :            :   }
     566                 :            : 
     567                 :          0 : }

Generated by: LCOV version 1.14