QGIS API Documentation  2.14.11-Essen
qgsrulebasedrendererv2widget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrulebasedrendererv2widget.cpp - Settings widget for rule-based renderer
3  ---------------------
4  begin : May 2010
5  copyright : (C) 2010 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 
17 
18 #include "qgsrulebasedrendererv2.h"
19 #include "qgssymbollayerv2utils.h"
20 #include "qgssymbolv2.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsapplication.h"
23 #include "qgsexpression.h"
25 #include "qgslogger.h"
26 #include "qstring.h"
28 
29 #include <QKeyEvent>
30 #include <QMenu>
31 #include <QProgressDialog>
32 #include <QSettings>
33 #include <QTreeWidgetItem>
34 #include <QVBoxLayout>
35 #include <QMessageBox>
36 
37 #ifdef ENABLE_MODELTEST
38 #include "modeltest.h"
39 #endif
40 
42 {
43  return new QgsRuleBasedRendererV2Widget( layer, style, renderer );
44 }
45 
47  : QgsRendererV2Widget( layer, style )
48 {
49  mRenderer = nullptr;
50  // try to recognize the previous renderer
51  // (null renderer means "no previous renderer")
52 
53 
54  if ( renderer )
55  {
57  }
58  if ( !mRenderer )
59  {
60  // some default options
62 
63  mRenderer = new QgsRuleBasedRendererV2( symbol );
64  }
65 
66  setupUi( this );
67 
69 #ifdef ENABLE_MODELTEST
70  new ModelTest( mModel, this ); // for model validity checking
71 #endif
72  viewRules->setModel( mModel );
73 
74  mDeleteAction = new QAction( tr( "Remove Rule" ), this );
75  mDeleteAction->setShortcut( QKeySequence( QKeySequence::Delete ) );
76 
77  viewRules->addAction( mDeleteAction );
78  viewRules->addAction( mCopyAction );
79  viewRules->addAction( mPasteAction );
80 
81  mRefineMenu = new QMenu( tr( "Refine current rule" ), btnRefineRule );
82  mRefineMenu->addAction( tr( "Add scales to rule" ), this, SLOT( refineRuleScales() ) );
83  mRefineMenu->addAction( tr( "Add categories to rule" ), this, SLOT( refineRuleCategories() ) );
84  mRefineMenu->addAction( tr( "Add ranges to rule" ), this, SLOT( refineRuleRanges() ) );
85  btnRefineRule->setMenu( mRefineMenu );
87 
88  btnAddRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
89  btnEditRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.png" ) ) );
90  btnRemoveRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
91 
92  connect( viewRules, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( editRule( const QModelIndex & ) ) );
93 
94  // support for context menu (now handled generically)
95  connect( viewRules, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) );
96 
97  connect( viewRules->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SLOT( currentRuleChanged( QModelIndex, QModelIndex ) ) );
98  connect( viewRules->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( selectedRulesChanged() ) );
99 
100  connect( btnAddRule, SIGNAL( clicked() ), this, SLOT( addRule() ) );
101  connect( btnEditRule, SIGNAL( clicked() ), this, SLOT( editRule() ) );
102  connect( btnRemoveRule, SIGNAL( clicked() ), this, SLOT( removeRule() ) );
103  connect( mDeleteAction, SIGNAL( triggered() ), this, SLOT( removeRule() ) );
104  connect( btnCountFeatures, SIGNAL( clicked() ), this, SLOT( countFeatures() ) );
105 
106  connect( btnRenderingOrder, SIGNAL( clicked() ), this, SLOT( setRenderingOrder() ) );
107 
110 
111  // store/restore header section widths
112  connect( viewRules->header(), SIGNAL( sectionResized( int, int, int ) ), this, SLOT( saveSectionWidth( int, int, int ) ) );
113 
115 
116 }
117 
119 {
120  qDeleteAll( mCopyBuffer );
121  delete mRenderer;
122 }
123 
125 {
126  return mRenderer;
127 }
128 
130 {
133 
134  QgsRendererRulePropsDialog dlg( newrule, mLayer, mStyle, this, mMapCanvas );
135  if ( dlg.exec() )
136  {
138  if ( current )
139  {
140  // add after this rule
141  QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
142  mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
143  }
144  else
145  {
146  // append to root rule
147  int rows = mModel->rowCount();
148  mModel->insertRule( QModelIndex(), rows, newrule );
149  }
151  }
152  else
153  {
154  delete newrule;
155  }
156 }
157 
159 {
160  QItemSelectionModel* sel = viewRules->selectionModel();
161  QModelIndex idx = sel->currentIndex();
162  if ( !idx.isValid() )
163  return nullptr;
164  return mModel->ruleForIndex( idx );
165 }
166 
168 {
169  editRule( viewRules->selectionModel()->currentIndex() );
170 }
171 
173 {
174  if ( !index.isValid() )
175  return;
177 
178  QgsRendererRulePropsDialog dlg( rule, mLayer, mStyle, this, mMapCanvas );
179  if ( dlg.exec() )
180  {
181  // model should know about the change and emit dataChanged signal for the view
182  mModel->updateRule( index.parent(), index.row() );
184  }
185 }
186 
188 {
189  QItemSelection sel = viewRules->selectionModel()->selection();
190  QgsDebugMsg( QString( "REMOVE RULES!!! ranges: %1" ).arg( sel.count() ) );
191  Q_FOREACH ( const QItemSelectionRange& range, sel )
192  {
193  QgsDebugMsg( QString( "RANGE: r %1 - %2" ).arg( range.top() ).arg( range.bottom() ) );
194  if ( range.isValid() )
195  mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
196  }
197  // make sure that the selection is gone
198  viewRules->selectionModel()->clear();
200 }
201 
203 {
204  Q_UNUSED( previous );
205  btnEditRule->setEnabled( current.isValid() );
206 }
207 
208 
214 #include <QDialogButtonBox>
215 #include <QInputDialog>
216 #include <QClipboard>
217 
219 {
220  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
221 
222  if ( indexlist.isEmpty() )
223  return;
224 
225 
226  if ( type == 0 ) // categories
227  refineRuleCategoriesGui( indexlist );
228  else if ( type == 1 ) // ranges
229  refineRuleRangesGui( indexlist );
230  else // scales
231  refineRuleScalesGui( indexlist );
232 
233  // TODO: set initial rule's symbol to NULL (?)
234 
235  // show the newly added rules
236  Q_FOREACH ( const QModelIndex& index, indexlist )
237  viewRules->expand( index );
238 }
239 
241 {
242  refineRule( 0 );
243 }
244 
246 {
247  refineRule( 1 );
248 }
249 
251 {
252  refineRule( 2 );
253 }
254 
255 void QgsRuleBasedRendererV2Widget::refineRuleCategoriesGui( const QModelIndexList& indexList )
256 {
257  QDialog dlg;
258  dlg.setWindowTitle( tr( "Refine a rule to categories" ) );
259  QVBoxLayout* l = new QVBoxLayout();
261  w->setMapCanvas( mMapCanvas );
262  l->addWidget( w );
263  QDialogButtonBox* bb = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
264  l->addWidget( bb );
265  connect( bb, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
266  connect( bb, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
267  dlg.setLayout( l );
268 
269  if ( !dlg.exec() )
270  return;
271 
272  // create new rules
274  Q_FOREACH ( const QModelIndex& index, indexList )
275  {
276  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
277  mModel->willAddRules( index, r->categories().count() );
279  }
281 }
282 
283 
284 void QgsRuleBasedRendererV2Widget::refineRuleRangesGui( const QModelIndexList& indexList )
285 {
286 
287 
288  QDialog dlg;
289  dlg.setWindowTitle( tr( "Refine a rule to ranges" ) );
290  QVBoxLayout* l = new QVBoxLayout();
292  w->setMapCanvas( mMapCanvas );
293  l->addWidget( w );
294  QDialogButtonBox* bb = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
295  l->addWidget( bb );
296  connect( bb, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
297  connect( bb, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
298  dlg.setLayout( l );
299 
300  if ( !dlg.exec() )
301  return;
302 
303  // create new rules
305  Q_FOREACH ( const QModelIndex& index, indexList )
306  {
307  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
308  mModel->willAddRules( index, r->ranges().count() );
310  }
312 }
313 
314 void QgsRuleBasedRendererV2Widget::refineRuleScalesGui( const QModelIndexList& indexList )
315 {
316  Q_FOREACH ( const QModelIndex& index, indexList )
317  {
318  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
319 
320  // If any of the rules don't have a symbol let the user know and exit.
321  if ( !initialRule->symbol() )
322  {
323  QMessageBox::warning( this, tr( "Scale refinement" ), tr( "Parent rule %1 must have a symbol for this operation." ).arg( initialRule->label() ) );
324  return;
325  }
326  }
327 
328  QString txt = QInputDialog::getText( this,
329  tr( "Scale refinement" ),
330  tr( "Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
331  if ( txt.isEmpty() )
332  return;
333 
334  QList<int> scales;
335  bool ok;
336  Q_FOREACH ( const QString& item, txt.split( ',' ) )
337  {
338  int scale = item.toInt( &ok );
339  if ( ok )
340  scales.append( scale );
341  else
342  QMessageBox::information( this, tr( "Error" ), QString( tr( "\"%1\" is not valid scale denominator, ignoring it." ) ).arg( item ) );
343  }
344 
345  Q_FOREACH ( const QModelIndex& index, indexList )
346  {
347  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
348  mModel->willAddRules( index, scales.count() + 1 );
349  QgsRuleBasedRendererV2::refineRuleScales( initialRule, scales );
350  }
352 }
353 
355 {
356  QList<QgsSymbolV2*> symbolList;
357 
358  if ( !mRenderer )
359  {
360  return symbolList;
361  }
362 
363  QItemSelection sel = viewRules->selectionModel()->selection();
364  Q_FOREACH ( const QItemSelectionRange& range, sel )
365  {
366  QModelIndex parent = range.parent();
367  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
369  for ( int row = range.top(); row <= range.bottom(); row++ )
370  {
371  symbolList.append( children[row]->symbol() );
372  }
373  }
374 
375  return symbolList;
376 }
377 
379 {
381  QItemSelection sel = viewRules->selectionModel()->selection();
382  Q_FOREACH ( const QItemSelectionRange& range, sel )
383  {
384  QModelIndex parent = range.parent();
385  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
387  for ( int row = range.top(); row <= range.bottom(); row++ )
388  {
389  rl.append( children[row]->clone() );
390  }
391  }
392  return rl;
393 }
394 
396 {
397  // TODO: model/view
398  /*
399  if ( treeRules )
400  {
401  treeRules->populateRules();
402  }
403  */
404 }
405 
407 {
408  if ( !event )
409  {
410  return;
411  }
412 
413  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
414  {
415  qDeleteAll( mCopyBuffer );
416  mCopyBuffer.clear();
418  }
419  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
420  {
422  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
423  {
424  int rows = mModel->rowCount();
425  mModel->insertRule( QModelIndex(), rows, ( *rIt )->clone() );
426  }
427  }
428 }
429 
430 #include "qgssymbollevelsv2dialog.h"
431 
433 {
435 
436  QgsSymbolLevelsV2Dialog dlg( lst, true, this );
437  dlg.setForceOrderingEnabled( true );
438 
439  dlg.exec();
440 }
441 
442 void QgsRuleBasedRendererV2Widget::saveSectionWidth( int section, int oldSize, int newSize )
443 {
444  Q_UNUSED( oldSize );
445  // skip last section, as it stretches
446  if ( section == 5 )
447  return;
448  QSettings settings;
449  QString path = "/Windows/RuleBasedTree/sectionWidth/" + QString::number( section );
450  settings.setValue( path, newSize );
451 }
452 
454 {
455  QSettings settings;
456  QString path = "/Windows/RuleBasedTree/sectionWidth/";
457  QHeaderView* head = viewRules->header();
458  head->resizeSection( 0, settings.value( path + QString::number( 0 ), 150 ).toInt() );
459  head->resizeSection( 1, settings.value( path + QString::number( 1 ), 150 ).toInt() );
460  head->resizeSection( 2, settings.value( path + QString::number( 2 ), 80 ).toInt() );
461  head->resizeSection( 3, settings.value( path + QString::number( 3 ), 80 ).toInt() );
462  head->resizeSection( 4, settings.value( path + QString::number( 4 ), 50 ).toInt() );
463  head->resizeSection( 5, settings.value( path + QString::number( 5 ), 50 ).toInt() );
464 }
465 
467 {
468  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
469  QgsDebugMsg( QString( "%1" ).arg( indexlist.count() ) );
470 
471  if ( indexlist.isEmpty() )
472  return;
473 
474  QMimeData* mime = mModel->mimeData( indexlist );
476 }
477 
479 {
480  const QMimeData* mime = QApplication::clipboard()->mimeData();
481  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
483  if ( indexlist.isEmpty() )
484  index = mModel->index( mModel->rowCount(), 0 );
485  else
486  index = indexlist.first();
487  mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
488 }
489 
490 
492 {
493  if ( !mLayer || !mRenderer || !mRenderer->rootRule() )
494  {
495  return;
496  }
498 
500  // insert all so that we have counts 0
501  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, ruleList )
502  {
503  countMap[rule].count = 0;
504  countMap[rule].duplicateCount = 0;
505  }
506 
507  QgsRenderContext renderContext;
508  renderContext.setRendererScale( 0 ); // ignore scale
509 
510  QgsExpressionContext context;
514  if ( mMapCanvas )
515  {
518  }
519  else
520  {
522  }
524 
525  renderContext.setExpressionContext( context );
526 
527  mRenderer->startRender( renderContext, mLayer->fields() );
528  // QgsRuleBasedRenderer::filter must be called after startRender
530  req.setExpressionContext( context );
532  QgsFeatureIterator fit = mLayer->getFeatures( req );
533 
534  int nFeatures = mLayer->featureCount();
535  QProgressDialog p( tr( "Calculating feature count." ), tr( "Abort" ), 0, nFeatures );
536  p.setWindowModality( Qt::WindowModal );
537  int featuresCounted = 0;
538 
539  QgsFeature f;
540  while ( fit.nextFeature( f ) )
541  {
542  renderContext.expressionContext().setFeature( f );
543  QgsRuleBasedRendererV2::RuleList featureRuleList = mRenderer->rootRule()->rulesForFeature( f, &renderContext );
544 
545  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, featureRuleList )
546  {
547  countMap[rule].count++;
548  if ( featureRuleList.size() > 1 )
549  {
550  countMap[rule].duplicateCount++;
551  }
552  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, featureRuleList )
553  {
554  if ( duplicateRule == rule ) continue;
555  countMap[rule].duplicateCountMap[duplicateRule] += 1;
556  }
557  }
558  ++featuresCounted;
559  if ( featuresCounted % 50 == 0 )
560  {
561  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
562  {
563  p.setMaximum( 0 );
564  }
565  p.setValue( featuresCounted );
566  if ( p.wasCanceled() )
567  {
568  return;
569  }
570  }
571  }
572  p.setValue( nFeatures );
573 
574  mRenderer->stopRender( renderContext );
575 
576 #ifdef QGISDEBUG
577  Q_FOREACH ( QgsRuleBasedRendererV2::Rule *rule, countMap.keys() )
578  {
579  QgsDebugMsg( QString( "rule: %1 count %2" ).arg( rule->label() ).arg( countMap[rule].count ) );
580  }
581 #endif
582 
583  mModel->setFeatureCounts( countMap );
584 }
585 
587 {
588  bool enabled = !viewRules->selectionModel()->selectedIndexes().isEmpty();
589  btnRefineRule->setEnabled( enabled );
590  btnRemoveRule->setEnabled( enabled );
591 }
592 
594 
596  : QDialog( parent ), mRule( rule ), mLayer( layer ), mSymbolSelector( nullptr ), mSymbol( nullptr ), mMapCanvas( mapCanvas )
597 {
598  setupUi( this );
599 #ifdef Q_OS_MAC
600  setWindowModality( Qt::WindowModal );
601 #endif
602 
603  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
604  connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
605 
606  editFilter->setText( mRule->filterExpression() );
607  editFilter->setToolTip( mRule->filterExpression() );
608  editLabel->setText( mRule->label() );
609  editDescription->setText( mRule->description() );
610  editDescription->setToolTip( mRule->description() );
611 
612  if ( mRule->dependsOnScale() )
613  {
614  groupScale->setChecked( true );
615  // caution: rule uses scale denom, scale widget uses true scales
616  if ( rule->scaleMinDenom() > 0 )
617  mScaleRangeWidget->setMaximumScale( 1.0 / rule->scaleMinDenom() );
618  if ( rule->scaleMaxDenom() > 0 )
619  mScaleRangeWidget->setMinimumScale( 1.0 / rule->scaleMaxDenom() );
620  }
621  mScaleRangeWidget->setMapCanvas( mMapCanvas );
622 
623  if ( mRule->symbol() )
624  {
625  groupSymbol->setChecked( true );
626  mSymbol = mRule->symbol()->clone(); // use a clone!
627  }
628  else
629  {
630  groupSymbol->setChecked( false );
632  }
633 
634  mSymbolSelector = new QgsSymbolV2SelectorDialog( mSymbol, style, mLayer, this, true );
635  mSymbolSelector->setMapCanvas( mMapCanvas );
636  QVBoxLayout* l = new QVBoxLayout;
637  l->addWidget( mSymbolSelector );
638  groupSymbol->setLayout( l );
639 
640  connect( btnExpressionBuilder, SIGNAL( clicked() ), this, SLOT( buildExpression() ) );
641  connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
642 
643  QSettings settings;
644  restoreGeometry( settings.value( "/Windows/QgsRendererRulePropsDialog/geometry" ).toByteArray() );
645 }
646 
648 {
649  delete mSymbol;
650  QSettings settings;
651  settings.setValue( "/Windows/QgsRendererRulePropsDialog/geometry", saveGeometry() );
652 }
653 
655 {
656  QgsExpressionContext context;
660  if ( mMapCanvas )
661  {
664  }
665  else
666  {
668  }
670 
671  QgsExpressionBuilderDialog dlg( mLayer, editFilter->text(), this, "generic", context );
672 
673  if ( dlg.exec() )
674  editFilter->setText( dlg.expressionText() );
675 }
676 
678 {
679  QgsExpression filter( editFilter->text() );
680  if ( filter.hasParserError() )
681  {
682  QMessageBox::critical( this, tr( "Error" ), tr( "Filter expression parsing error:\n" ) + filter.parserErrorString() );
683  return;
684  }
685 
686  QgsExpressionContext context;
690  if ( mMapCanvas )
691  {
694  }
695  else
696  {
698  }
700 
701  if ( !filter.prepare( &context ) )
702  {
703  QMessageBox::critical( this, tr( "Evaluation error" ), filter.evalErrorString() );
704  return;
705  }
706 
707  QApplication::setOverrideCursor( Qt::WaitCursor );
708 
711  .setFilterExpression( editFilter->text() )
712  .setExpressionContext( context );
713 
714  QgsFeatureIterator fit = mLayer->getFeatures( req );
715 
716  int count = 0;
717  QgsFeature f;
718  while ( fit.nextFeature( f ) )
719  {
720  count++;
721  }
722 
724 
725  QMessageBox::information( this, tr( "Filter" ), tr( "Filter returned %n feature(s)", "number of filtered features", count ) );
726 }
727 
729 {
730  mRule->setFilterExpression( editFilter->text() );
731  mRule->setLabel( editLabel->text() );
732  mRule->setDescription( editDescription->text() );
733  // caution: rule uses scale denom, scale widget uses true scales
734  mRule->setScaleMinDenom( groupScale->isChecked() ? mScaleRangeWidget->minimumScaleDenom() : 0 );
735  mRule->setScaleMaxDenom( groupScale->isChecked() ? mScaleRangeWidget->maximumScaleDenom() : 0 );
736  mRule->setSymbol( groupSymbol->isChecked() ? mSymbol->clone() : nullptr );
737 
738  QDialog::accept();
739 }
740 
742 
743 /*
744  setDragEnabled(true);
745  viewport()->setAcceptDrops(true);
746  setDropIndicatorShown(true);
747  setDragDropMode(QAbstractItemView::InternalMove);
748 */
749 
750 static QString _formatScale( int denom )
751 {
752  if ( denom != 0 )
753  {
754  QString txt = QString( "1:%L1" ).arg( denom );
755  return txt;
756  }
757  else
758  return QString();
759 }
760 
762 
764  : mR( r )
765 {
766 }
767 
769 {
770  if ( !index.isValid() )
771  return Qt::ItemIsDropEnabled;
772 
773  // allow drop only at first column
774  Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
775 
776  Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
777 
778  return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
779  Qt::ItemIsEditable | checkable |
780  Qt::ItemIsDragEnabled | drop;
781 }
782 
784 {
785  if ( !index.isValid() )
786  return QVariant();
787 
789 
790  if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
791  {
792  switch ( index.column() )
793  {
794  case 0:
795  return rule->label();
796  case 1:
797  if ( rule->isElse() )
798  {
799  return "ELSE";
800  }
801  else
802  {
803  return rule->filterExpression().isEmpty() ? tr( "(no filter)" ) : rule->filterExpression();
804  }
805  case 2:
806  return rule->dependsOnScale() ? _formatScale( rule->scaleMaxDenom() ) : QVariant();
807  case 3:
808  return rule->dependsOnScale() ? _formatScale( rule->scaleMinDenom() ) : QVariant();
809  case 4:
810  if ( mFeatureCountMap.count( rule ) == 1 )
811  {
812  return QVariant( mFeatureCountMap[rule].count );
813  }
814  return QVariant();
815  case 5:
816  if ( mFeatureCountMap.count( rule ) == 1 )
817  {
818  if ( role == Qt::DisplayRole )
819  {
820  return QVariant( mFeatureCountMap[rule].duplicateCount );
821  }
822  else // tooltip - detailed info about duplicates
823  {
824  if ( mFeatureCountMap[rule].duplicateCount > 0 )
825  {
826  QString tip = "<p style='margin:0px;'><ul>";
827  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, mFeatureCountMap[rule].duplicateCountMap.keys() )
828  {
829  QString label = duplicateRule->label().replace( '&', "&amp;" ).replace( '>', "&gt;" ).replace( '<', "&lt;" );
830  tip += tr( "<li><nobr>%1 features also in rule %2</nobr></li>" ).arg( mFeatureCountMap[rule].duplicateCountMap[duplicateRule] ).arg( label );
831  }
832  tip += "</ul>";
833  return tip;
834  }
835  else
836  {
837  return 0;
838  }
839  }
840  }
841  return QVariant();
842  default:
843  return QVariant();
844  }
845  }
846  else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() )
847  {
848  return QgsSymbolLayerV2Utils::symbolPreviewIcon( rule->symbol(), QSize( 16, 16 ) );
849  }
850  else if ( role == Qt::TextAlignmentRole )
851  {
852  return ( index.column() == 2 || index.column() == 3 ) ? Qt::AlignRight : Qt::AlignLeft;
853  }
854  else if ( role == Qt::FontRole && index.column() == 1 )
855  {
856  if ( rule->isElse() )
857  {
858  QFont italicFont;
859  italicFont.setItalic( true );
860  return italicFont;
861  }
862  return QVariant();
863  }
864  else if ( role == Qt::EditRole )
865  {
866  switch ( index.column() )
867  {
868  case 0:
869  return rule->label();
870  case 1:
871  return rule->filterExpression();
872  case 2:
873  return rule->scaleMaxDenom();
874  case 3:
875  return rule->scaleMinDenom();
876  default:
877  return QVariant();
878  }
879  }
880  else if ( role == Qt::CheckStateRole )
881  {
882  if ( index.column() != 0 )
883  return QVariant();
884  return rule->active() ? Qt::Checked : Qt::Unchecked;
885  }
886  else
887  return QVariant();
888 }
889 
890 QVariant QgsRuleBasedRendererV2Model::headerData( int section, Qt::Orientation orientation, int role ) const
891 {
892  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 7 )
893  {
894  QStringList lst;
895  lst << tr( "Label" ) << tr( "Rule" ) << tr( "Min. scale" ) << tr( "Max. scale" ) << tr( "Count" ) << tr( "Duplicate count" );
896  return lst[section];
897  }
898  else if ( orientation == Qt::Horizontal && role == Qt::ToolTipRole )
899  {
900  if ( section == 4 ) // Count
901  {
902  return tr( "Number of features in this rule." );
903  }
904  else if ( section == 5 ) // Duplicate count
905  {
906  return tr( "Number of features in this rule which are also present in other rule(s)." );
907  }
908  }
909 
910  return QVariant();
911 }
912 
914 {
915  if ( parent.column() > 0 )
916  return 0;
917 
918  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
919 
920  return parentRule->children().count();
921 }
922 
924 {
925  return 6;
926 }
927 
929 {
930  if ( hasIndex( row, column, parent ) )
931  {
932  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
933  QgsRuleBasedRendererV2::Rule* childRule = parentRule->children()[row];
934  return createIndex( row, column, childRule );
935  }
936  return QModelIndex();
937 }
938 
940 {
941  if ( !index.isValid() )
942  return QModelIndex();
943 
944  QgsRuleBasedRendererV2::Rule* childRule = ruleForIndex( index );
945  QgsRuleBasedRendererV2::Rule* parentRule = childRule->parent();
946 
947  if ( parentRule == mR->rootRule() )
948  return QModelIndex();
949 
950  // this is right: we need to know row number of our parent (in our grandparent)
951  int row = parentRule->parent()->children().indexOf( parentRule );
952 
953  return createIndex( row, 0, parentRule );
954 }
955 
956 bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
957 {
958  if ( !index.isValid() )
959  return false;
960 
962 
963  if ( role == Qt::CheckStateRole )
964  {
965  rule->setActive( value.toInt() == Qt::Checked );
966  emit dataChanged( index, index );
967  return true;
968  }
969 
970  if ( role != Qt::EditRole )
971  return false;
972 
973  switch ( index.column() )
974  {
975  case 0: // label
976  rule->setLabel( value.toString() );
977  break;
978  case 1: // filter
979  rule->setFilterExpression( value.toString() );
980  break;
981  case 2: // scale min
982  rule->setScaleMaxDenom( value.toInt() );
983  break;
984  case 3: // scale max
985  rule->setScaleMinDenom( value.toInt() );
986  break;
987  default:
988  return false;
989  }
990 
991  emit dataChanged( index, index );
992  return true;
993 }
994 
996 {
997  return Qt::MoveAction; // | Qt::CopyAction
998 }
999 
1001 {
1002  QStringList types;
1003  types << "application/vnd.text.list";
1004  return types;
1005 }
1006 
1007 QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes ) const
1008 {
1009  QMimeData *mimeData = new QMimeData();
1010  QByteArray encodedData;
1011 
1012  QDataStream stream( &encodedData, QIODevice::WriteOnly );
1013 
1014  Q_FOREACH ( const QModelIndex &index, indexes )
1015  {
1016  // each item consists of several columns - let's add it with just first one
1017  if ( !index.isValid() || index.column() != 0 )
1018  continue;
1019 
1020  // we use a clone of the existing rule because it has a new unique rule key
1021  // non-unique rule keys would confuse other components using them (e.g. legend)
1022  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index )->clone();
1023  QDomDocument doc;
1024  QgsSymbolV2Map symbols;
1025 
1026  QDomElement rootElem = doc.createElement( "rule_mime" );
1027  rootElem.setAttribute( "type", "renderer" ); // for determining whether rules are from renderer or labeling
1028  QDomElement rulesElem = rule->save( doc, symbols );
1029  rootElem.appendChild( rulesElem );
1030  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
1031  rootElem.appendChild( symbolsElem );
1032  doc.appendChild( rootElem );
1033 
1034  delete rule;
1035 
1036  stream << doc.toString( -1 );
1037  }
1038 
1039  mimeData->setData( "application/vnd.text.list", encodedData );
1040  return mimeData;
1041 }
1042 
1043 
1044 // manipulate DOM before dropping it so that rules are more useful
1046 {
1047  // labeling rules recognize only "description"
1048  if ( ruleElem.hasAttribute( "description" ) )
1049  ruleElem.setAttribute( "label", ruleElem.attribute( "description" ) );
1050 
1051  // run recursively
1052  QDomElement childRuleElem = ruleElem.firstChildElement( "rule" );
1053  while ( !childRuleElem.isNull() )
1054  {
1055  _labeling2rendererRules( childRuleElem );
1056  childRuleElem = childRuleElem.nextSiblingElement( "rule" );
1057  }
1058 }
1059 
1060 
1062  Qt::DropAction action, int row, int column, const QModelIndex &parent )
1063 {
1064  Q_UNUSED( column );
1065 
1066  if ( action == Qt::IgnoreAction )
1067  return true;
1068 
1069  if ( !data->hasFormat( "application/vnd.text.list" ) )
1070  return false;
1071 
1072  if ( parent.column() > 0 )
1073  return false;
1074 
1075  QByteArray encodedData = data->data( "application/vnd.text.list" );
1076  QDataStream stream( &encodedData, QIODevice::ReadOnly );
1077  int rows = 0;
1078 
1079  if ( row == -1 )
1080  {
1081  // the item was dropped at a parent - we may decide where to put the items - let's append them
1082  row = rowCount( parent );
1083  }
1084 
1085  while ( !stream.atEnd() )
1086  {
1087  QString text;
1088  stream >> text;
1089 
1090  QDomDocument doc;
1091  if ( !doc.setContent( text ) )
1092  continue;
1093  QDomElement rootElem = doc.documentElement();
1094  if ( rootElem.tagName() != "rule_mime" )
1095  continue;
1096  if ( rootElem.attribute( "type" ) == "labeling" )
1097  rootElem.appendChild( doc.createElement( "symbols" ) );
1098  QDomElement symbolsElem = rootElem.firstChildElement( "symbols" );
1099  if ( symbolsElem.isNull() )
1100  continue;
1101  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
1102  QDomElement ruleElem = rootElem.firstChildElement( "rule" );
1103  if ( rootElem.attribute( "type" ) == "labeling" )
1104  _labeling2rendererRules( ruleElem );
1106 
1107  insertRule( parent, row + rows, rule );
1108 
1109  ++rows;
1110  }
1111  return true;
1112 }
1113 
1115 {
1116  if ( index.isValid() )
1117  return static_cast<QgsRuleBasedRendererV2::Rule*>( index.internalPointer() );
1118  return mR->rootRule();
1119 }
1120 
1122 {
1123  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1124 
1125  if ( row < 0 || row >= parentRule->children().count() )
1126  return false;
1127 
1128  QgsDebugMsg( QString( "Called: row %1 count %2 parent ~~%3~~" ).arg( row ).arg( count ).arg( parentRule->dump() ) );
1129 
1130  beginRemoveRows( parent, row, row + count - 1 );
1131 
1132  for ( int i = 0; i < count; i++ )
1133  {
1134  if ( row < parentRule->children().count() )
1135  {
1136  //QgsRuleBasedRendererV2::Rule* r = parentRule->children()[row];
1137  parentRule->removeChildAt( row );
1138  //parentRule->takeChildAt( row );
1139  }
1140  else
1141  {
1142  QgsDebugMsg( "trying to remove invalid index - this should not happen!" );
1143  }
1144  }
1145 
1146  endRemoveRows();
1147 
1148  return true;
1149 }
1150 
1151 
1153 {
1154  beginInsertRows( parent, before, before );
1155 
1156  QgsDebugMsg( QString( "insert before %1 rule: %2" ).arg( before ).arg( newrule->dump() ) );
1157 
1158  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1159  parentRule->insertChild( before, newrule );
1160 
1161  endInsertRows();
1162 }
1163 
1165 {
1166  emit dataChanged( index( row, 0, parent ),
1167  index( row, columnCount( parent ), parent ) );
1168 }
1169 
1171 {
1172  emit dataChanged( index( 0, 0, idx ),
1173  index( rowCount( idx ) - 1, columnCount( idx ) - 1, idx ) );
1174 
1175  for ( int i = 0; i < rowCount( idx ); i++ )
1176  {
1177  updateRule( index( i, 0, idx ) );
1178  }
1179 }
1180 
1181 
1183 {
1184  if ( !index.isValid() )
1185  return;
1186 
1187  beginRemoveRows( index.parent(), index.row(), index.row() );
1188 
1189  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1190  rule->parent()->removeChild( rule );
1191 
1192  endRemoveRows();
1193 }
1194 
1196 {
1197  int row = rowCount( parent ); // only consider appending
1198  beginInsertRows( parent, row, row + count - 1 );
1199 }
1200 
1202 {
1203  emit endInsertRows();
1204 }
1205 
1207 {
1208  mFeatureCountMap = theCountMap;
1209  updateRule( QModelIndex() );
1210 }
1211 
1213 {
1215  updateRule( QModelIndex() );
1216 }
const QgsCategoryList & categories() const
bool hasIndex(int row, int column, const QModelIndex &parent) const
void customContextMenuRequested(const QPoint &pos)
QgsRuleBasedRendererV2Widget(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
bool active() const
Returns if this rule is active.
QgsRendererRulePropsDialog(QgsRuleBasedRendererV2::Rule *rule, QgsVectorLayer *layer, QgsStyleV2 *style, QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr)
static QDomElement saveSymbols(QgsSymbolV2Map &symbols, const QString &tagName, QDomDocument &doc)
Class for parsing and evaluation of expressions (formerly called "search strings").
void setLabel(const QString &label)
void clear()
const QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
Wrapper for iterator of features from vector data provider or vector layer.
static QgsSymbolV2Map loadSymbols(QDomElement &element)
QByteArray toByteArray() const
static unsigned index
void refineRuleScalesGui(const QModelIndexList &index)
virtual QString filter(const QgsFields &fields=QgsFields()) override
If a renderer does not require all the features this method may be overridden and return an expressio...
QByteArray data(const QString &mimeType) const
void setupUi(QWidget *widget)
QgsSymbolV2SelectorDialog * mSymbolSelector
int bottom() const
virtual void reject()
void keyPressEvent(QKeyEvent *event) override
QgsRuleBasedRendererV2Model * mModel
QModelIndex currentIndex() const
const QMimeData * mimeData(Mode mode) const
QDomNode appendChild(const QDomNode &newChild)
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
void setMaximum(int maximum)
static QgsExpressionContextScope * atlasScope(const QgsAtlasComposition *atlas)
Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
QString attribute(const QString &name, const QString &defValue) const
void setWindowModality(Qt::WindowModality windowModality)
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual bool hasFormat(const QString &mimeType) const
void setActive(bool state)
Sets if this rule is active.
QString toString(int indent) const
void setScaleMaxDenom(int scaleMaxDenom)
Set the maximum denominator for which this rule shall apply.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
virtual QgsSymbolV2 * clone() const =0
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
void rejected()
QStyle * style() const
void setRendererScale(double scale)
void setIcon(const QIcon &icon)
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
const QObjectList & children() const
QgsRuleBasedRendererV2::Rule * ruleForIndex(const QModelIndex &index) const
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
void addAction(QAction *action)
QgsMapCanvas * mMapCanvas
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QList< QgsSymbolV2 * > selectedSymbols() override
Subclasses may provide the capability of changing multiple symbols at once by implementing the follow...
void refineRuleCategoriesGui(const QModelIndexList &index)
QgsRuleBasedRendererV2Model(QgsRuleBasedRendererV2 *r)
QDomElement nextSiblingElement(const QString &tagName) const
Qt::DropActions supportedDropActions() const override
void accepted()
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap) const
int exec()
QgsRuleBasedRendererV2::RuleList mCopyBuffer
QDomElement documentElement() const
virtual QgsFeatureRendererV2 * renderer() override
return pointer to the renderer (no transfer of ownership)
void updateRule(const QModelIndex &parent, int row)
void saveSectionWidth(int section, int oldSize, int newSize)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
virtual QgsFeatureRendererV2 * renderer() override
return pointer to the renderer (no transfer of ownership)
void clear()
QgsRuleBasedRendererV2::Rule * currentRule()
bool isElse()
Check if this rule is an ELSE rule.
QString tr(const char *sourceText, const char *disambiguation, int n)
StandardButton information(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
void removeChildAt(int i)
delete child rule
int size() const
QgsFields fields() const
Returns the list of fields of this layer.
QString description() const
A human readable description for this rule.
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
The QgsMapSettings class contains configuration for rendering of the map.
int indexOf(const T &value, int from) const
void resizeSection(int logicalIndex, int size)
virtual QgsFeatureRendererV2 * renderer() override
return pointer to the renderer (no transfer of ownership)
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
QList< Key > keys() const
void setDescription(const QString &description)
Set a human readable description for this rule.
void setValue(const QString &key, const QVariant &value)
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
void setValue(int progress)
bool isValid() const
void refineRuleRangesGui(const QModelIndexList &index)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QString number(int n, int base)
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
int count(const T &value) const
QgsVectorLayer * mLayer
void append(const T &value)
static void refineRuleCategories(Rule *initialRule, QgsCategorizedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the categories from categorized symbol renderer ...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void setLayout(QLayout *layout)
int toInt(bool *ok) const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
bool hasAttribute(const QString &name) const
virtual void stopRender(QgsRenderContext &context) override
Needs to be called when a render cycle has finished to clean up.
QClipboard * clipboard()
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
bool restoreGeometry(const QByteArray &geometry)
const QgsRangeList & ranges() const
static QString _formatScale(int denom)
void setAttribute(const QString &name, const QString &value)
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int toInt(bool *ok, int base) const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static Rule * create(QDomElement &ruleElem, QgsSymbolV2Map &symbolMap)
Create a rule from an XML definition.
bool isEmpty() const
void beginRemoveRows(const QModelIndex &parent, int first, int last)
int row() const
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setOverrideCursor(const QCursor &cursor)
QList< int > QgsAttributeList
This class keeps data about a rules for rule-based renderer.
void restoreOverrideCursor()
void * internalPointer() const
Rule * clone() const
clone this rule, return new instance
QModelIndex parent() const
RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
Single scope for storing variables and functions for use within a QgsExpressionContext.
QMap< QgsRuleBasedRendererV2::Rule *, QgsRuleBasedRendererV2Count > mFeatureCountMap
void setMimeData(QMimeData *src, Mode mode)
QModelIndex parent() const
void removeRule(const QModelIndex &index)
static QgsRendererV2Widget * create(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
bool atEnd() const
static void refineRuleRanges(Rule *initialRule, QgsGraduatedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the ranges from graduated symbol renderer ...
virtual void accept()
void currentRuleChanged(const QModelIndex &current=QModelIndex(), const QModelIndex &previous=QModelIndex())
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, QFlags< Qt::WindowType > flags, QFlags< Qt::InputMethodHint > inputMethodHints)
void setFeatureCounts(const QMap< QgsRuleBasedRendererV2::Rule *, QgsRuleBasedRendererV2Count > &theCountMap)
QModelIndex createIndex(int row, int column, void *ptr) const
virtual bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
int key() const
void setShortcut(const QKeySequence &shortcut)
QgsExpressionContext & expressionContext()
Gets the expression context.
QString filterExpression() const
A filter that will check if this rule applies.
QMimeData * mimeData(const QModelIndexList &indexes) const override
void setItalic(bool enable)
void beginInsertRows(const QModelIndex &parent, int first, int last)
bool isNull() const
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void contextMenuViewCategories(QPoint p)
QString & replace(int position, int n, QChar after)
void setForceOrderingEnabled(bool enabled)
QVariant value(const QString &key, const QVariant &defaultValue) const
QStringList mimeTypes() const override
Contains information about the context of a rendering operation.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
void insertRule(const QModelIndex &parent, int before, QgsRuleBasedRendererV2::Rule *newrule)
QgsExpressionContextScope & expressionContextScope()
Returns a reference to the expression context scope for the map canvas.
Definition: qgsmapcanvas.h:443
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
QByteArray saveGeometry() const
typedef DropActions
Rule * parent()
The parent rule.
QAction * addMenu(QMenu *menu)
When drawing a vector layer with rule-based renderer, it goes through the rules and draws features wi...
void setWindowTitle(const QString &)
RuleList rulesForFeature(QgsFeature &feat, QgsRenderContext *context=nullptr)
tell which rules will be used to render the feature
QDomElement firstChildElement(const QString &tagName) const
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
provide model index for parent&#39;s child item
virtual int columnCount(const QModelIndex &=QModelIndex()) const override
QgsRuleBasedRendererV2::RuleList selectedRules()
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Needs to be called when a new render cycle is started.
RuleList & children()
Return all children rules of this rule.
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
int column() const
Base class for renderer settings widgets.
QgsRuleBasedRendererV2::Rule * mRule
void setSymbol(QgsSymbolV2 *sym)
set a new symbol (or NULL). Deletes old symbol.
virtual QList< QString > usedAttributes() override
Returns a set of attributes required for this renderer.
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
static QgsRuleBasedRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsRuleBasedRendererV2 from an existing renderer.
QString tagName() const
void _labeling2rendererRules(QDomElement &ruleElem)
void setData(const QString &mimeType, const QByteArray &data)
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
const_iterator constEnd() const
void insertChild(int i, Rule *rule)
add child rule, take ownership, sets this as parent
void setFilterExpression(const QString &filterExp)
Set the expression used to check if a given feature shall be rendered with this rule.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
const_iterator constBegin() const
bool isValid() const
Geometry is not required. It may still be returned if e.g. required for a filter condition.
void setScaleMinDenom(int scaleMinDenom)
Set the minimum denominator for which this rule shall apply.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
Represents a vector layer which manages a vector based data sets.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
virtual bool event(QEvent *event)
int count(const Key &key) const
A generic dialog for building expression strings.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="") override
return a list of item text / symbol
QString dump(int indent=0) const
Dump for debug purpose.
void willAddRules(const QModelIndex &parent, int count)
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
static void refineRuleScales(Rule *initialRule, QList< int > scales)
take a rule and create a list of new rules with intervals of scales given by the passed scale denomin...
typedef ItemFlags