37 #include <QProgressDialog> 
   38 #include <QTreeWidgetItem> 
   39 #include <QVBoxLayout> 
   40 #include <QMessageBox> 
   43 #ifdef ENABLE_MODELTEST 
   44 #include "modeltest.h" 
   50   return new QgsRuleBasedRendererWidget( layer, style, renderer );
 
   55   , mContextMenu( new QMenu( this ) )
 
   71     mRenderer = std::make_unique< QgsRuleBasedRenderer >( symbol );
 
   77   this->layout()->setContentsMargins( 0, 0, 0, 0 );
 
   80 #ifdef ENABLE_MODELTEST 
   81   new ModelTest( 
mModel, 
this ); 
 
   83   viewRules->setModel( 
mModel );
 
   86   mDeleteAction->setShortcut( QKeySequence( QKeySequence::Delete ) );
 
   92   mRefineMenu = 
new QMenu( tr( 
"Refine Current Rule" ), btnRefineRule );
 
  105   connect( viewRules, &QWidget::customContextMenuRequested,  
this, &QgsRuleBasedRendererWidget::showContextMenu );
 
  139   qDeleteAll( mCopyBuffer );
 
  144   return mRenderer.get();
 
  153       mDeleteAction->setShortcut( QKeySequence() );
 
  167     QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
 
  168     mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
 
  169     QModelIndex newindex = mModel->index( currentIndex.row() + 1, 0, currentIndex.parent() );
 
  170     viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
 
  175     int rows = mModel->rowCount();
 
  176     mModel->insertRule( QModelIndex(), rows, newrule );
 
  177     QModelIndex newindex = mModel->index( rows, 0 );
 
  178     viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
 
  185   QItemSelectionModel *sel = viewRules->selectionModel();
 
  186   QModelIndex idx = sel->currentIndex();
 
  187   if ( !idx.isValid() )
 
  189   return mModel->ruleForIndex( idx );
 
  194   editRule( viewRules->selectionModel()->currentIndex() );
 
  199   if ( !index.isValid() )
 
  207     QgsRendererRulePropsWidget *widget = 
new QgsRendererRulePropsWidget( rule, mLayer, mStyle, 
this, mContext );
 
  208     widget->setPanelTitle( tr( 
"Edit Rule" ) );
 
  218     mModel->updateRule( index.parent(), index.row() );
 
  219     mModel->clearFeatureCounts();
 
  220     emit widgetChanged();
 
  226   QItemSelection sel = viewRules->selectionModel()->selection();
 
  227   QgsDebugMsg( QStringLiteral( 
"REMOVE RULES!!! ranges: %1" ).arg( sel.count() ) );
 
  228   const auto constSel = sel;
 
  229   for ( 
const QItemSelectionRange &range : constSel )
 
  231     QgsDebugMsg( QStringLiteral( 
"RANGE: r %1 - %2" ).arg( range.top() ).arg( range.bottom() ) );
 
  232     if ( range.isValid() )
 
  233       mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
 
  236   viewRules->selectionModel()->clear();
 
  237   mModel->clearFeatureCounts();
 
  243   btnEditRule->setEnabled( current.isValid() );
 
  252 #include <QDialogButtonBox> 
  253 #include <QInputDialog> 
  254 #include <QClipboard> 
  258   QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
 
  260   if ( indexlist.isEmpty() )
 
  265     refineRuleCategoriesGui();
 
  266   else if ( type == 1 ) 
 
  267     refineRuleRangesGui();
 
  269     refineRuleScalesGui( indexlist );
 
  274   const auto constIndexlist = indexlist;
 
  275   for ( 
const QModelIndex &index : constIndexlist )
 
  276     viewRules->expand( index );
 
  296   QgsCategorizedSymbolRendererWidget *w = 
new QgsCategorizedSymbolRendererWidget( mLayer, mStyle, 
nullptr );
 
  297   w->setPanelTitle( tr( 
"Add Categories to Rules" ) );
 
  299   w->setContext( mContext );
 
  305   QgsGraduatedSymbolRendererWidget *w = 
new QgsGraduatedSymbolRendererWidget( mLayer, mStyle, 
nullptr );
 
  306   w->setPanelTitle( tr( 
"Add Ranges to Rules" ) );
 
  308   w->setContext( mContext );
 
  314   for ( 
const QModelIndex &index : indexList )
 
  319     if ( !initialRule->
symbol() )
 
  321       QMessageBox::warning( 
this, tr( 
"Scale Refinement" ), tr( 
"Parent rule %1 must have a symbol for this operation." ).arg( initialRule->
label() ) );
 
  326   QString txt = QInputDialog::getText( 
this,
 
  327                                        tr( 
"Scale Refinement" ),
 
  328                                        tr( 
"Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
 
  334   const auto constSplit = txt.split( 
',' );
 
  335   for ( 
const QString &item : constSplit )
 
  337     int scale = item.toInt( &ok );
 
  339       scales.append( scale );
 
  341       QMessageBox::information( 
this, tr( 
"Scale Refinement" ), tr( 
"\"%1\" is not valid scale denominator, ignoring it." ).arg( item ) );
 
  344   for ( 
const QModelIndex &index : indexList )
 
  347     mModel->willAddRules( index, scales.count() + 1 );
 
  350   mModel->finishedAddingRules();
 
  363       mRenderer->setLegendSymbolItem( legendSymbol.ruleKey(), sym->
clone() );
 
  367   emit widgetChanged();
 
  372   QList<QgsSymbol *> symbolList;
 
  379   QItemSelection sel = viewRules->selectionModel()->selection();
 
  380   const auto constSel = sel;
 
  381   for ( 
const QItemSelectionRange &range : constSel )
 
  383     QModelIndex parent = range.parent();
 
  386     for ( 
int row = range.top(); row <= range.bottom(); row++ )
 
  388       symbolList.append( children.at( row )->symbol() );
 
  398   QItemSelection sel = viewRules->selectionModel()->selection();
 
  399   const auto constSel = sel;
 
  400   for ( 
const QItemSelectionRange &range : constSel )
 
  402     QModelIndex parent = range.parent();
 
  405     for ( 
int row = range.top(); row <= range.bottom(); row++ )
 
  407       rl.append( children.at( row )->clone() );
 
  422   emit widgetChanged();
 
  432   if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
 
  434     qDeleteAll( mCopyBuffer );
 
  436     mCopyBuffer = selectedRules();
 
  438   else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
 
  440     QgsRuleBasedRenderer::RuleList::const_iterator rIt = mCopyBuffer.constBegin();
 
  441     for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
 
  443       int rows = mModel->rowCount();
 
  444       mModel->insertRule( QModelIndex(), rows, ( *rIt )->clone() );
 
  483   QString path = 
"/Windows/RuleBasedTree/sectionWidth/" + QString::number( section );
 
  490   QString path = QStringLiteral( 
"/Windows/RuleBasedTree/sectionWidth/" );
 
  491   QHeaderView *head = viewRules->header();
 
  492   head->resizeSection( 0, settings.
value( path + QString::number( 0 ), 150 ).toInt() );
 
  493   head->resizeSection( 1, settings.
value( path + QString::number( 1 ), 150 ).toInt() );
 
  494   head->resizeSection( 2, settings.
value( path + QString::number( 2 ), 80 ).toInt() );
 
  495   head->resizeSection( 3, settings.
value( path + QString::number( 3 ), 80 ).toInt() );
 
  496   head->resizeSection( 4, settings.
value( path + QString::number( 4 ), 50 ).toInt() );
 
  497   head->resizeSection( 5, settings.
value( path + QString::number( 5 ), 50 ).toInt() );
 
  502   QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
 
  505   if ( indexlist.isEmpty() )
 
  508   QMimeData *mime = mModel->mimeData( indexlist );
 
  509   QApplication::clipboard()->setMimeData( mime );
 
  514   const QMimeData *mime = QApplication::clipboard()->mimeData();
 
  515   QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
 
  517   if ( indexlist.isEmpty() )
 
  518     index = mModel->index( mModel->rowCount(), 0 );
 
  520     index = indexlist.first();
 
  521   mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
 
  530   const QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
 
  531   for ( 
const QModelIndex &index : indexList )
 
  535       if ( !rule->symbol() || rule->symbol()->type() != tempSymbol->type() )
 
  538       mModel->setSymbol( index, tempSymbol->clone() );
 
  541   emit widgetChanged();
 
  544 void QgsRuleBasedRendererWidget::refineRuleCategoriesAccepted( 
QgsPanelWidget *panel )
 
  546   QgsCategorizedSymbolRendererWidget *w = qobject_cast<QgsCategorizedSymbolRendererWidget *>( panel );
 
  550   QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
 
  551   const auto constIndexList = indexList;
 
  552   for ( 
const QModelIndex &index : constIndexList )
 
  555     mModel->willAddRules( index, r->
categories().count() );
 
  558   mModel->finishedAddingRules();
 
  561 void QgsRuleBasedRendererWidget::refineRuleRangesAccepted( 
QgsPanelWidget *panel )
 
  563   QgsGraduatedSymbolRendererWidget *w = qobject_cast<QgsGraduatedSymbolRendererWidget *>( panel );
 
  566   QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
 
  567   const auto constIndexList = indexList;
 
  568   for ( 
const QModelIndex &index : constIndexList )
 
  571     mModel->willAddRules( index, r->
ranges().count() );
 
  574   mModel->finishedAddingRules();
 
  577 void QgsRuleBasedRendererWidget::ruleWidgetPanelAccepted( 
QgsPanelWidget *panel )
 
  579   QgsRendererRulePropsWidget *widget = qobject_cast<QgsRendererRulePropsWidget *>( panel );
 
  586   QModelIndex index = viewRules->selectionModel()->currentIndex();
 
  587   mModel->updateRule( index.parent(), index.row() );
 
  588   mModel->clearFeatureCounts();
 
  591 void QgsRuleBasedRendererWidget::liveUpdateRuleFromPanel()
 
  593   ruleWidgetPanelAccepted( qobject_cast<QgsPanelWidget *>( sender() ) );
 
  596 void QgsRuleBasedRendererWidget::showContextMenu( QPoint )
 
  598   mContextMenu->clear();
 
  599   mContextMenu->addAction( mCopyAction );
 
  600   mContextMenu->addAction( mPasteAction );
 
  602   const QList< QAction * > actions = contextMenu->actions();
 
  603   for ( QAction *act : actions )
 
  605     mContextMenu->addAction( act );
 
  608   mContextMenu->addMenu( mRefineMenu );
 
  610   mContextMenu->exec( QCursor::pos() );
 
  616   if ( !mLayer || !mRenderer || !mRenderer->rootRule() )
 
  620   QHash<QgsRuleBasedRenderer::Rule *, QgsRuleBasedRendererCount> countMap;
 
  624   const auto constRuleList = ruleList;
 
  627     countMap[rule].count = 0;
 
  628     countMap[rule].duplicateCount = 0;
 
  637   const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
 
  645   mRenderer->startRender( renderContext, mLayer->fields() );
 
  652   long long nFeatures = mLayer->featureCount();
 
  653   QProgressDialog p( tr( 
"Calculating feature count." ), tr( 
"Abort" ), 0, 100 );
 
  654   p.setWindowModality( Qt::WindowModal );
 
  655   long long featuresCounted = 0;
 
  663     const auto constFeatureRuleList = featureRuleList;
 
  666       countMap[rule].count++;
 
  667       if ( featureRuleList.size() > 1 )
 
  669         countMap[rule].duplicateCount++;
 
  671       const auto constFeatureRuleList = featureRuleList;
 
  674         if ( duplicateRule == rule ) 
continue;
 
  675         countMap[rule].duplicateCountMap[duplicateRule] += 1;
 
  679     if ( featuresCounted % 50 == 0 )
 
  681       if ( featuresCounted > nFeatures ) 
 
  685       p.setValue( 
static_cast< double >( featuresCounted ) / nFeatures * 100.0 );
 
  686       if ( p.wasCanceled() )
 
  692   p.setValue( nFeatures );
 
  694   mRenderer->stopRender( renderContext );
 
  697   const auto constKeys = countMap.keys();
 
  700     QgsDebugMsg( QStringLiteral( 
"rule: %1 count %2" ).arg( rule->label() ).arg( countMap[rule].count ) );
 
  704   mModel->setFeatureCounts( countMap );
 
  709   bool enabled = !viewRules->selectionModel()->selectedIndexes().isEmpty();
 
  710   btnRefineRule->setEnabled( enabled );
 
  711   btnRemoveRule->setEnabled( enabled );
 
  720   , mContext( context )
 
  723   layout()->setContentsMargins( 0, 0, 0, 0 );
 
  735     groupScale->setChecked( 
true );
 
  743     groupSymbol->setChecked( 
true );
 
  748     groupSymbol->setChecked( 
false );
 
  757   QVBoxLayout *l = 
new QVBoxLayout;
 
  759   groupSymbol->setLayout( l );
 
  769   connect( mFilterRadio, &QRadioButton::toggled, 
this, [ = ]( 
bool toggled ) { filterFrame->setEnabled( toggled ) ; } );
 
  770   connect( mElseRadio, &QRadioButton::toggled, 
this, [ = ]( 
bool toggled ) { 
if ( toggled ) editFilter->setText( QStringLiteral( 
"ELSE" ) );} );
 
  780   setWindowModality( Qt::WindowModal );
 
  783   QVBoxLayout *layout = 
new QVBoxLayout( 
this );
 
  785   scrollArea->setFrameShape( QFrame::NoFrame );
 
  786   layout->addWidget( scrollArea );
 
  788   buttonBox = 
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
 
  789   mPropsWidget = 
new QgsRendererRulePropsWidget( 
rule, layer, style, 
this, context );
 
  791   scrollArea->setWidget( mPropsWidget );
 
  792   layout->addWidget( buttonBox );
 
  793   this->setWindowTitle( 
"Edit Rule" );
 
  797   connect( buttonBox, &QDialogButtonBox::rejected, 
this, &QDialog::reject );
 
  798   connect( buttonBox, &QDialogButtonBox::helpRequested, 
this, &QgsRendererRulePropsDialog::showHelp );
 
  803   mPropsWidget->testFilter();
 
  808   mPropsWidget->buildExpression();
 
  813   mPropsWidget->apply();
 
  817 void QgsRendererRulePropsDialog::showHelp()
 
  819   QgsHelp::openHelp( QStringLiteral( 
"working_with_vector/vector_properties.html#rule-based-rendering" ) );
 
  828   const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
 
  842   if ( !mFilterRadio->isChecked() )
 
  848     QMessageBox::critical( 
this, tr( 
"Test Filter" ),  tr( 
"Filter expression parsing error:\n" ) + filter.
parserErrorString() );
 
  855   const auto constAdditionalExpressionContextScopes = mContext.additionalExpressionContextScopes();
 
  861   if ( !filter.
prepare( &context ) )
 
  863     QMessageBox::critical( 
this, tr( 
"Test Filter" ), filter.
evalErrorString() );
 
  867   QApplication::setOverrideCursor( Qt::WaitCursor );
 
  883   QApplication::restoreOverrideCursor();
 
  885   QMessageBox::information( 
this, tr( 
"Test Filter" ), tr( 
"Filter returned %n feature(s)", 
"number of filtered features", count ) );
 
  890   QString filter = mElseRadio->isChecked() ? QStringLiteral( 
"ELSE" ) : editFilter->text();
 
  891   mRule->setFilterExpression( filter );
 
  892   mRule->setLabel( editLabel->text() );
 
  893   mRule->setDescription( editDescription->text() );
 
  895   mRule->setMinimumScale( groupScale->isChecked() ? mScaleRangeWidget->minimumScale() : 0 );
 
  896   mRule->setMaximumScale( groupScale->isChecked() ? mScaleRangeWidget->maximumScale() : 0 );
 
  897   mRule->setSymbol( groupSymbol->isChecked() ? mSymbol->clone() : 
nullptr );
 
  903   mSymbolSelector->setDockMode( dockMode );
 
  918   : QAbstractItemModel( parent )
 
  925   if ( !
index.isValid() )
 
  926     return Qt::ItemIsDropEnabled;
 
  929   Qt::ItemFlag drop = ( 
index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
 
  931   Qt::ItemFlag checkable = ( 
index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
 
  933   return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
 
  934          Qt::ItemIsEditable | checkable |
 
  935          Qt::ItemIsDragEnabled | drop;
 
  940   if ( !
index.isValid() )
 
  945   if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
 
  947     switch ( 
index.column() )
 
  950         return rule->
label();
 
  973           if ( role == Qt::DisplayRole )
 
  981               QString tip = QStringLiteral( 
"<p style='margin:0px;'><ul>" );
 
  983               for ( 
auto it = duplicateMap.constBegin(); it != duplicateMap.constEnd(); ++it )
 
  985                 QString label = it.key()->label().replace( 
'&', QLatin1String( 
"&" ) ).replace( 
'>', QLatin1String( 
">" ) ).replace( 
'<', QLatin1String( 
"<" ) );
 
  986                 tip += tr( 
"<li><nobr>%1 features also in rule %2</nobr></li>" ).arg( it.value() ).arg( label );
 
  988               tip += QLatin1String( 
"</ul>" );
 
 1002   else if ( role == Qt::DecorationRole && 
index.column() == 0 && rule->
symbol() )
 
 1007   else if ( role == Qt::TextAlignmentRole )
 
 1009     return ( 
index.column() == 2 || 
index.column() == 3 ) ? 
static_cast<Qt::Alignment::Int
>( Qt::AlignRight ) : 
static_cast<Qt::Alignment::Int
>( Qt::AlignLeft );
 
 1011   else if ( role == Qt::FontRole && 
index.column() == 1 )
 
 1016       italicFont.setItalic( 
true );
 
 1021   else if ( role == Qt::EditRole )
 
 1023     switch ( 
index.column() )
 
 1026         return rule->
label();
 
 1037   else if ( role == Qt::CheckStateRole )
 
 1039     if ( 
index.column() != 0 )
 
 1041     return rule->
active() ? Qt::Checked : Qt::Unchecked;
 
 1049   if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 7 )
 
 1052     lst << tr( 
"Label" ) << tr( 
"Rule" ) << tr( 
"Min. Scale" ) << tr( 
"Max. Scale" ) << tr( 
"Count" ) << tr( 
"Duplicate Count" );
 
 1053     return lst[section];
 
 1055   else if ( orientation == Qt::Horizontal && role == Qt::ToolTipRole )
 
 1059       return tr( 
"Number of features in this rule." );
 
 1061     else if ( section == 5 )  
 
 1063       return tr( 
"Number of features in this rule which are also present in other rule(s)." );
 
 1072   if ( 
parent.column() > 0 )
 
 1077   return parentRule->
children().count();
 
 1087   if ( hasIndex( row, column, 
parent ) )
 
 1091     return createIndex( row, column, childRule );
 
 1093   return QModelIndex();
 
 1098   if ( !
index.isValid() )
 
 1099     return QModelIndex();
 
 1105     return QModelIndex();
 
 1108   int row = parentRule->
parent()->
children().indexOf( parentRule );
 
 1110   return createIndex( row, 0, parentRule );
 
 1115   if ( !
index.isValid() )
 
 1120   if ( role == Qt::CheckStateRole )
 
 1122     rule->
setActive( value.toInt() == Qt::Checked );
 
 1127   if ( role != Qt::EditRole )
 
 1130   switch ( 
index.column() )
 
 1133       rule->
setLabel( value.toString() );
 
 1154   return Qt::MoveAction; 
 
 1160   types << QStringLiteral( 
"application/vnd.text.list" );
 
 1166   QMimeData *
mimeData = 
new QMimeData();
 
 1167   QByteArray encodedData;
 
 1169   QDataStream stream( &encodedData, QIODevice::WriteOnly );
 
 1171   const auto constIndexes = indexes;
 
 1172   for ( 
const QModelIndex &
index : constIndexes )
 
 1175     if ( !
index.isValid() || 
index.column() != 0 )
 
 1184     QDomElement rootElem = doc.createElement( QStringLiteral( 
"rule_mime" ) );
 
 1185     rootElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"renderer" ) ); 
 
 1186     QDomElement rulesElem = rule->
save( doc, symbols );
 
 1187     rootElem.appendChild( rulesElem );
 
 1189     rootElem.appendChild( symbolsElem );
 
 1190     doc.appendChild( rootElem );
 
 1194     stream << doc.toString( -1 );
 
 1197   mimeData->setData( QStringLiteral( 
"application/vnd.text.list" ), encodedData );
 
 1206   if ( ruleElem.hasAttribute( QStringLiteral( 
"description" ) ) )
 
 1207     ruleElem.setAttribute( QStringLiteral( 
"label" ), ruleElem.attribute( QStringLiteral( 
"description" ) ) );
 
 1210   QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral( 
"rule" ) );
 
 1211   while ( !childRuleElem.isNull() )
 
 1214     childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral( 
"rule" ) );
 
 1220     Qt::DropAction action, 
int row, 
int column, 
const QModelIndex &parent )
 
 1224   if ( action == Qt::IgnoreAction )
 
 1227   if ( !
data->hasFormat( QStringLiteral( 
"application/vnd.text.list" ) ) )
 
 1230   if ( 
parent.column() > 0 )
 
 1233   QByteArray encodedData = 
data->data( QStringLiteral( 
"application/vnd.text.list" ) );
 
 1234   QDataStream stream( &encodedData, QIODevice::ReadOnly );
 
 1243   while ( !stream.atEnd() )
 
 1249     if ( !doc.setContent( text ) )
 
 1251     QDomElement rootElem = doc.documentElement();
 
 1252     if ( rootElem.tagName() != QLatin1String( 
"rule_mime" ) )
 
 1254     if ( rootElem.attribute( QStringLiteral( 
"type" ) ) == QLatin1String( 
"labeling" ) )
 
 1255       rootElem.appendChild( doc.createElement( QStringLiteral( 
"symbols" ) ) );
 
 1256     QDomElement symbolsElem = rootElem.firstChildElement( QStringLiteral( 
"symbols" ) );
 
 1257     if ( symbolsElem.isNull() )
 
 1260     QDomElement ruleElem = rootElem.firstChildElement( QStringLiteral( 
"rule" ) );
 
 1261     if ( rootElem.attribute( QStringLiteral( 
"type" ) ) == QLatin1String( 
"labeling" ) )
 
 1274   if ( 
index.isValid() )
 
 1283   if ( row < 0 || row >= parentRule->
children().count() )
 
 1286   QgsDebugMsg( QStringLiteral( 
"Called: row %1 count %2 parent ~~%3~~" ).arg( row ).arg( count ).arg( parentRule->
dump() ) );
 
 1288   beginRemoveRows( 
parent, row, row + count - 1 );
 
 1290   for ( 
int i = 0; i < count; i++ )
 
 1292     if ( row < parentRule->children().count() )
 
 1300       QgsDebugMsg( QStringLiteral( 
"trying to remove invalid index - this should not happen!" ) );
 
 1312   beginInsertRows( 
parent, before, before );
 
 1314   QgsDebugMsg( QStringLiteral( 
"insert before %1 rule: %2" ).arg( before ).arg( newrule->
dump() ) );
 
 1330   emit dataChanged( 
index( 0, 0, idx ),
 
 1333   for ( 
int i = 0; i < 
rowCount( idx ); i++ )
 
 1342   if ( !
index.isValid() )
 
 1363   beginInsertRows( 
parent, row, row + count - 1 );