QGIS API Documentation  2.17.0-Master (2f94c66)
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 #include "qgspanelwidget.h"
29 
30 #include <QKeyEvent>
31 #include <QMenu>
32 #include <QProgressDialog>
33 #include <QSettings>
34 #include <QTreeWidgetItem>
35 #include <QVBoxLayout>
36 #include <QMessageBox>
37 
38 #ifdef ENABLE_MODELTEST
39 #include "modeltest.h"
40 #endif
41 
43 {
44  return new QgsRuleBasedRendererV2Widget( layer, style, renderer );
45 }
46 
48  : QgsRendererV2Widget( layer, style )
49 {
50  mRenderer = nullptr;
51  // try to recognize the previous renderer
52  // (null renderer means "no previous renderer")
53 
54 
55  if ( renderer )
56  {
58  }
59  if ( !mRenderer )
60  {
61  // some default options
63 
64  mRenderer = new QgsRuleBasedRendererV2( symbol );
65  }
66 
67  setupUi( this );
68 
70 #ifdef ENABLE_MODELTEST
71  new ModelTest( mModel, this ); // for model validity checking
72 #endif
73  viewRules->setModel( mModel );
74 
75  mDeleteAction = new QAction( tr( "Remove Rule" ), this );
76  mDeleteAction->setShortcut( QKeySequence( QKeySequence::Delete ) );
77 
78  viewRules->addAction( mDeleteAction );
79  viewRules->addAction( mCopyAction );
80  viewRules->addAction( mPasteAction );
81 
82  mRefineMenu = new QMenu( tr( "Refine current rule" ), btnRefineRule );
83  mRefineMenu->addAction( tr( "Add scales to rule" ), this, SLOT( refineRuleScales() ) );
84  mRefineMenu->addAction( tr( "Add categories to rule" ), this, SLOT( refineRuleCategories() ) );
85  mRefineMenu->addAction( tr( "Add ranges to rule" ), this, SLOT( refineRuleRanges() ) );
86  btnRefineRule->setMenu( mRefineMenu );
88 
89  btnAddRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
90  btnEditRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.png" ) ) );
91  btnRemoveRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
92 
93  connect( viewRules, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( editRule( const QModelIndex & ) ) );
94 
95  // support for context menu (now handled generically)
96  connect( viewRules, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) );
97 
98  connect( viewRules->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SLOT( currentRuleChanged( QModelIndex, QModelIndex ) ) );
99  connect( viewRules->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( selectedRulesChanged() ) );
100 
101  connect( btnAddRule, SIGNAL( clicked() ), this, SLOT( addRule() ) );
102  connect( btnEditRule, SIGNAL( clicked() ), this, SLOT( editRule() ) );
103  connect( btnRemoveRule, SIGNAL( clicked() ), this, SLOT( removeRule() ) );
104  connect( mDeleteAction, SIGNAL( triggered() ), this, SLOT( removeRule() ) );
105  connect( btnCountFeatures, SIGNAL( clicked() ), this, SLOT( countFeatures() ) );
106 
107  connect( btnRenderingOrder, SIGNAL( clicked() ), this, SLOT( setRenderingOrder() ) );
108 
109  connect( mModel, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ), this, SIGNAL( widgetChanged() ) );
110  connect( mModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SIGNAL( widgetChanged() ) );
111  connect( mModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SIGNAL( widgetChanged() ) );
112 
115 
116  // store/restore header section widths
117  connect( viewRules->header(), SIGNAL( sectionResized( int, int, int ) ), this, SLOT( saveSectionWidth( int, int, int ) ) );
118 
120 
121 }
122 
124 {
125  qDeleteAll( mCopyBuffer );
126  delete mRenderer;
127 }
128 
130 {
131  return mRenderer;
132 }
133 
135 {
138 
140  if ( current )
141  {
142  // add after this rule
143  QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
144  mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
145  QModelIndex newindex = mModel->index( currentIndex.row() + 1, 0, currentIndex.parent() );
146  viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
147  }
148  else
149  {
150  // append to root rule
151  int rows = mModel->rowCount();
152  mModel->insertRule( QModelIndex(), rows, newrule );
153  QModelIndex newindex = mModel->index( rows, 0 );
154  viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
155  }
156  editRule();
157 }
158 
160 {
161  QItemSelectionModel* sel = viewRules->selectionModel();
162  QModelIndex idx = sel->currentIndex();
163  if ( !idx.isValid() )
164  return nullptr;
165  return mModel->ruleForIndex( idx );
166 }
167 
169 {
170  editRule( viewRules->selectionModel()->currentIndex() );
171 }
172 
174 {
175  if ( !index.isValid() )
176  return;
177 
179 
181  widget->setDockMode( true );
182  widget->setPanelTitle( tr( "Edit rule" ) );
183  connect( widget, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( ruleWidgetPanelAccepted( QgsPanelWidget* ) ) );
184  connect( widget, SIGNAL( widgetChanged() ), this, SLOT( liveUpdateRuleFromPanel() ) );
185  openPanel( widget );
186 }
187 
189 {
190  QItemSelection sel = viewRules->selectionModel()->selection();
191  QgsDebugMsg( QString( "REMOVE RULES!!! ranges: %1" ).arg( sel.count() ) );
192  Q_FOREACH ( const QItemSelectionRange& range, sel )
193  {
194  QgsDebugMsg( QString( "RANGE: r %1 - %2" ).arg( range.top() ).arg( range.bottom() ) );
195  if ( range.isValid() )
196  mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
197  }
198  // make sure that the selection is gone
199  viewRules->selectionModel()->clear();
201 }
202 
204 {
205  Q_UNUSED( previous );
206  btnEditRule->setEnabled( current.isValid() );
207 }
208 
209 
215 #include <QDialogButtonBox>
216 #include <QInputDialog>
217 #include <QClipboard>
218 
220 {
221  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
222 
223  if ( indexlist.isEmpty() )
224  return;
225 
226 
227  if ( type == 0 ) // categories
228  refineRuleCategoriesGui( indexlist );
229  else if ( type == 1 ) // ranges
230  refineRuleRangesGui( indexlist );
231  else // scales
232  refineRuleScalesGui( indexlist );
233 
234  // TODO: set initial rule's symbol to NULL (?)
235 
236  // show the newly added rules
237  Q_FOREACH ( const QModelIndex& index, indexlist )
238  viewRules->expand( index );
239 }
240 
242 {
243  refineRule( 0 );
244 }
245 
247 {
248  refineRule( 1 );
249 }
250 
252 {
253  refineRule( 2 );
254 }
255 
257 {
259  w->setPanelTitle( tr( "Add categories to rules" ) );
260  connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleCategoriesAccepted( QgsPanelWidget* ) ) );
261  w->setDockMode( this->dockMode() );
262  w->setMapCanvas( mMapCanvas );
263  openPanel( w );
264 }
265 
267 {
269  w->setPanelTitle( tr( "Add ranges to rules" ) );
270  connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleRangesAccepted( QgsPanelWidget* ) ) );
271  w->setMapCanvas( mMapCanvas );
272  w->setDockMode( this->dockMode() );
273  openPanel( w );
274 }
275 
276 void QgsRuleBasedRendererV2Widget::refineRuleScalesGui( const QModelIndexList& indexList )
277 {
278  Q_FOREACH ( const QModelIndex& index, indexList )
279  {
280  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
281 
282  // If any of the rules don't have a symbol let the user know and exit.
283  if ( !initialRule->symbol() )
284  {
285  QMessageBox::warning( this, tr( "Scale refinement" ), tr( "Parent rule %1 must have a symbol for this operation." ).arg( initialRule->label() ) );
286  return;
287  }
288  }
289 
290  QString txt = QInputDialog::getText( this,
291  tr( "Scale refinement" ),
292  tr( "Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
293  if ( txt.isEmpty() )
294  return;
295 
296  QList<int> scales;
297  bool ok;
298  Q_FOREACH ( const QString& item, txt.split( ',' ) )
299  {
300  int scale = item.toInt( &ok );
301  if ( ok )
302  scales.append( scale );
303  else
304  QMessageBox::information( this, tr( "Error" ), QString( tr( "\"%1\" is not valid scale denominator, ignoring it." ) ).arg( item ) );
305  }
306 
307  Q_FOREACH ( const QModelIndex& index, indexList )
308  {
309  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
310  mModel->willAddRules( index, scales.count() + 1 );
311  QgsRuleBasedRendererV2::refineRuleScales( initialRule, scales );
312  }
314 }
315 
317 {
318  QList<QgsSymbolV2*> symbolList;
319 
320  if ( !mRenderer )
321  {
322  return symbolList;
323  }
324 
325  QItemSelection sel = viewRules->selectionModel()->selection();
326  Q_FOREACH ( const QItemSelectionRange& range, sel )
327  {
328  QModelIndex parent = range.parent();
329  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
331  for ( int row = range.top(); row <= range.bottom(); row++ )
332  {
333  symbolList.append( children[row]->symbol() );
334  }
335  }
336 
337  return symbolList;
338 }
339 
341 {
343  QItemSelection sel = viewRules->selectionModel()->selection();
344  Q_FOREACH ( const QItemSelectionRange& range, sel )
345  {
346  QModelIndex parent = range.parent();
347  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
349  for ( int row = range.top(); row <= range.bottom(); row++ )
350  {
351  rl.append( children[row]->clone() );
352  }
353  }
354  return rl;
355 }
356 
358 {
359  // TODO: model/view
360  /*
361  if ( treeRules )
362  {
363  treeRules->populateRules();
364  }
365  */
366  emit widgetChanged();
367 }
368 
370 {
371  if ( !event )
372  {
373  return;
374  }
375 
376  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
377  {
378  qDeleteAll( mCopyBuffer );
379  mCopyBuffer.clear();
381  }
382  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
383  {
385  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
386  {
387  int rows = mModel->rowCount();
388  mModel->insertRule( QModelIndex(), rows, ( *rIt )->clone() );
389  }
390  }
391 }
392 
393 #include "qgssymbollevelsv2dialog.h"
394 
396 {
398 
399  QgsSymbolLevelsV2Dialog dlg( lst, true, this );
400  dlg.setForceOrderingEnabled( true );
401 
402  dlg.exec();
403 }
404 
405 void QgsRuleBasedRendererV2Widget::saveSectionWidth( int section, int oldSize, int newSize )
406 {
407  Q_UNUSED( oldSize );
408  // skip last section, as it stretches
409  if ( section == 5 )
410  return;
411  QSettings settings;
412  QString path = "/Windows/RuleBasedTree/sectionWidth/" + QString::number( section );
413  settings.setValue( path, newSize );
414 }
415 
417 {
418  QSettings settings;
419  QString path = "/Windows/RuleBasedTree/sectionWidth/";
420  QHeaderView* head = viewRules->header();
421  head->resizeSection( 0, settings.value( path + QString::number( 0 ), 150 ).toInt() );
422  head->resizeSection( 1, settings.value( path + QString::number( 1 ), 150 ).toInt() );
423  head->resizeSection( 2, settings.value( path + QString::number( 2 ), 80 ).toInt() );
424  head->resizeSection( 3, settings.value( path + QString::number( 3 ), 80 ).toInt() );
425  head->resizeSection( 4, settings.value( path + QString::number( 4 ), 50 ).toInt() );
426  head->resizeSection( 5, settings.value( path + QString::number( 5 ), 50 ).toInt() );
427 }
428 
430 {
431  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
432  QgsDebugMsg( QString( "%1" ).arg( indexlist.count() ) );
433 
434  if ( indexlist.isEmpty() )
435  return;
436 
437  QMimeData* mime = mModel->mimeData( indexlist );
439 }
440 
442 {
443  const QMimeData* mime = QApplication::clipboard()->mimeData();
444  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
446  if ( indexlist.isEmpty() )
447  index = mModel->index( mModel->rowCount(), 0 );
448  else
449  index = indexlist.first();
450  mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
451 }
452 
453 void QgsRuleBasedRendererV2Widget::refineRuleCategoriesAccepted( QgsPanelWidget *panel )
454 {
456 
457  // create new rules
459  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
460  Q_FOREACH ( const QModelIndex& index, indexList )
461  {
462  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
463  mModel->willAddRules( index, r->categories().count() );
465  }
467 }
468 
469 void QgsRuleBasedRendererV2Widget::refineRuleRangesAccepted( QgsPanelWidget *panel )
470 {
472  // create new rules
474  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
475  Q_FOREACH ( const QModelIndex& index, indexList )
476  {
477  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
478  mModel->willAddRules( index, r->ranges().count() );
480  }
482 }
483 
484 void QgsRuleBasedRendererV2Widget::ruleWidgetPanelAccepted( QgsPanelWidget *panel )
485 {
486  QgsRendererRulePropsWidget* widget = qobject_cast<QgsRendererRulePropsWidget*>( panel );
487  widget->apply();
488 
489  // model should know about the change and emit dataChanged signal for the view
490  QModelIndex index = viewRules->selectionModel()->currentIndex();
491  mModel->updateRule( index.parent(), index.row() );
493 }
494 
495 void QgsRuleBasedRendererV2Widget::liveUpdateRuleFromPanel()
496 {
497  ruleWidgetPanelAccepted( qobject_cast<QgsPanelWidget*>( sender() ) );
498 }
499 
500 
502 {
503  if ( !mLayer || !mRenderer || !mRenderer->rootRule() )
504  {
505  return;
506  }
508 
510  // insert all so that we have counts 0
511  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, ruleList )
512  {
513  countMap[rule].count = 0;
514  countMap[rule].duplicateCount = 0;
515  }
516 
518 
519  QgsRenderContext renderContext;
520  renderContext.setRendererScale( 0 ); // ignore scale
521 
522  QgsExpressionContext context;
526  if ( mMapCanvas )
527  {
530  }
531  else
532  {
534  }
536 
537  renderContext.setExpressionContext( context );
538 
539  mRenderer->startRender( renderContext, mLayer->fields() );
540 
541  int nFeatures = mLayer->featureCount();
542  QProgressDialog p( tr( "Calculating feature count." ), tr( "Abort" ), 0, nFeatures );
543  p.setWindowModality( Qt::WindowModal );
544  int featuresCounted = 0;
545 
546  QgsFeature f;
547  while ( fit.nextFeature( f ) )
548  {
549  renderContext.expressionContext().setFeature( f );
550  QgsRuleBasedRendererV2::RuleList featureRuleList = mRenderer->rootRule()->rulesForFeature( f, &renderContext );
551 
552  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, featureRuleList )
553  {
554  countMap[rule].count++;
555  if ( featureRuleList.size() > 1 )
556  {
557  countMap[rule].duplicateCount++;
558  }
559  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, featureRuleList )
560  {
561  if ( duplicateRule == rule ) continue;
562  countMap[rule].duplicateCountMap[duplicateRule] += 1;
563  }
564  }
565  ++featuresCounted;
566  if ( featuresCounted % 50 == 0 )
567  {
568  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
569  {
570  p.setMaximum( 0 );
571  }
572  p.setValue( featuresCounted );
573  if ( p.wasCanceled() )
574  {
575  return;
576  }
577  }
578  }
579  p.setValue( nFeatures );
580 
581  mRenderer->stopRender( renderContext );
582 
583 #ifdef QGISDEBUG
584  Q_FOREACH ( QgsRuleBasedRendererV2::Rule *rule, countMap.keys() )
585  {
586  QgsDebugMsg( QString( "rule: %1 count %2" ).arg( rule->label() ).arg( countMap[rule].count ) );
587  }
588 #endif
589 
590  mModel->setFeatureCounts( countMap );
591 }
592 
594 {
595  bool enabled = !viewRules->selectionModel()->selectedIndexes().isEmpty();
596  btnRefineRule->setEnabled( enabled );
597  btnRemoveRule->setEnabled( enabled );
598 }
599 
601 
603  : QgsPanelWidget( parent )
604  , mRule( rule )
605  , mLayer( layer )
606  , mSymbolSelector( nullptr )
607  , mSymbol( nullptr )
608  , mMapCanvas( mapCanvas )
609 {
610  setupUi( this );
611 
612  editFilter->setText( mRule->filterExpression() );
613  editFilter->setToolTip( mRule->filterExpression() );
614  editLabel->setText( mRule->label() );
615  editDescription->setText( mRule->description() );
616  editDescription->setToolTip( mRule->description() );
617 
618  if ( mRule->dependsOnScale() )
619  {
620  groupScale->setChecked( true );
621  // caution: rule uses scale denom, scale widget uses true scales
622  if ( rule->scaleMinDenom() > 0 )
623  mScaleRangeWidget->setMaximumScale( 1.0 / rule->scaleMinDenom() );
624  if ( rule->scaleMaxDenom() > 0 )
625  mScaleRangeWidget->setMinimumScale( 1.0 / rule->scaleMaxDenom() );
626  }
627  mScaleRangeWidget->setMapCanvas( mMapCanvas );
628 
629  if ( mRule->symbol() )
630  {
631  groupSymbol->setChecked( true );
632  mSymbol = mRule->symbol()->clone(); // use a clone!
633  }
634  else
635  {
636  groupSymbol->setChecked( false );
638  }
639 
641  mSymbolSelector->setMapCanvas( mMapCanvas );
642  connect( mSymbolSelector, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
643  connect( mSymbolSelector, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
644 
645  QVBoxLayout* l = new QVBoxLayout;
646  l->addWidget( mSymbolSelector );
647  groupSymbol->setLayout( l );
648 
649  connect( btnExpressionBuilder, SIGNAL( clicked() ), this, SLOT( buildExpression() ) );
650  connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
651  connect( editFilter, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
652  connect( editLabel, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
653  connect( editDescription, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
654  connect( groupSymbol, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
655  connect( groupScale, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
656  connect( mScaleRangeWidget, SIGNAL( rangeChanged( double, double ) ), this, SIGNAL( widgetChanged() ) );
657 }
658 
660 {
661 
662 }
663 
665  : QDialog( parent )
666 {
667 
668 #ifdef Q_OS_MAC
669  setWindowModality( Qt::WindowModal );
670 #endif
671  this->setLayout( new QVBoxLayout() );
672 
673  buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
674  mPropsWidget = new QgsRendererRulePropsWidget( rule, layer, style, this, mapCanvas );
675 
676  this->layout()->addWidget( mPropsWidget );
677  this->layout()->addWidget( buttonBox );
678 
679  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
680  connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
681 
682  QSettings settings;
683  restoreGeometry( settings.value( "/Windows/QgsRendererRulePropsDialog/geometry" ).toByteArray() );
684 }
685 
687 {
688  QSettings settings;
689  settings.setValue( "/Windows/QgsRendererRulePropsDialog/geometry", saveGeometry() );
690 }
691 
693 {
694  mPropsWidget->testFilter();
695 }
696 
698 {
699  mPropsWidget->buildExpression();
700 }
701 
703 {
704  mPropsWidget->apply();
705  QDialog::accept();
706 }
707 
709 {
710  QgsExpressionContext context;
714  if ( mMapCanvas )
715  {
716  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
717  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
718  }
719  else
720  {
722  }
723  context << QgsExpressionContextUtils::layerScope( mLayer );
724 
725  QgsExpressionBuilderDialog dlg( mLayer, editFilter->text(), this, "generic", context );
726 
727  if ( dlg.exec() )
728  editFilter->setText( dlg.expressionText() );
729 }
730 
732 {
733  QgsExpression filter( editFilter->text() );
734  if ( filter.hasParserError() )
735  {
736  QMessageBox::critical( this, tr( "Error" ), tr( "Filter expression parsing error:\n" ) + filter.parserErrorString() );
737  return;
738  }
739 
740  QgsExpressionContext context;
744  if ( mMapCanvas )
745  {
746  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
747  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
748  }
749  else
750  {
752  }
753  context << QgsExpressionContextUtils::layerScope( mLayer );
754 
755  if ( !filter.prepare( &context ) )
756  {
757  QMessageBox::critical( this, tr( "Evaluation error" ), filter.evalErrorString() );
758  return;
759  }
760 
761  QApplication::setOverrideCursor( Qt::WaitCursor );
762 
763  QgsFeatureIterator fit = mLayer->getFeatures();
764 
765  int count = 0;
766  QgsFeature f;
767  while ( fit.nextFeature( f ) )
768  {
769  context.setFeature( f );
770 
771  QVariant value = filter.evaluate( &context );
772  if ( value.toInt() != 0 )
773  count++;
774  if ( filter.hasEvalError() )
775  break;
776  }
777 
779 
780  QMessageBox::information( this, tr( "Filter" ), tr( "Filter returned %n feature(s)", "number of filtered features", count ) );
781 }
782 
784 {
785  mRule->setFilterExpression( editFilter->text() );
786  mRule->setLabel( editLabel->text() );
787  mRule->setDescription( editDescription->text() );
788  // caution: rule uses scale denom, scale widget uses true scales
789  mRule->setScaleMinDenom( groupScale->isChecked() ? mScaleRangeWidget->minimumScaleDenom() : 0 );
790  mRule->setScaleMaxDenom( groupScale->isChecked() ? mScaleRangeWidget->maximumScaleDenom() : 0 );
791  mRule->setSymbol( groupSymbol->isChecked() ? mSymbol->clone() : nullptr );
792 }
793 
795 {
796  QgsPanelWidget::setDockMode( dockMode );
797  mSymbolSelector->setDockMode( true );
798 }
799 
801 
802 /*
803  setDragEnabled(true);
804  viewport()->setAcceptDrops(true);
805  setDropIndicatorShown(true);
806  setDragDropMode(QAbstractItemView::InternalMove);
807 */
808 
809 static QString _formatScale( int denom )
810 {
811  if ( denom != 0 )
812  {
813  QString txt = QString( "1:%L1" ).arg( denom );
814  return txt;
815  }
816  else
817  return QString();
818 }
819 
821 
823  : mR( r )
824 {
825 }
826 
828 {
829  if ( !index.isValid() )
830  return Qt::ItemIsDropEnabled;
831 
832  // allow drop only at first column
833  Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
834 
835  Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
836 
837  return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
838  Qt::ItemIsEditable | checkable |
839  Qt::ItemIsDragEnabled | drop;
840 }
841 
843 {
844  if ( !index.isValid() )
845  return QVariant();
846 
848 
849  if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
850  {
851  switch ( index.column() )
852  {
853  case 0:
854  return rule->label();
855  case 1:
856  if ( rule->isElse() )
857  {
858  return "ELSE";
859  }
860  else
861  {
862  return rule->filterExpression().isEmpty() ? tr( "(no filter)" ) : rule->filterExpression();
863  }
864  case 2:
865  return rule->dependsOnScale() ? _formatScale( rule->scaleMaxDenom() ) : QVariant();
866  case 3:
867  return rule->dependsOnScale() ? _formatScale( rule->scaleMinDenom() ) : QVariant();
868  case 4:
869  if ( mFeatureCountMap.count( rule ) == 1 )
870  {
871  return QVariant( mFeatureCountMap[rule].count );
872  }
873  return QVariant();
874  case 5:
875  if ( mFeatureCountMap.count( rule ) == 1 )
876  {
877  if ( role == Qt::DisplayRole )
878  {
879  return QVariant( mFeatureCountMap[rule].duplicateCount );
880  }
881  else // tooltip - detailed info about duplicates
882  {
883  if ( mFeatureCountMap[rule].duplicateCount > 0 )
884  {
885  QString tip = "<p style='margin:0px;'><ul>";
886  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, mFeatureCountMap[rule].duplicateCountMap.keys() )
887  {
888  QString label = duplicateRule->label().replace( '&', "&amp;" ).replace( '>', "&gt;" ).replace( '<', "&lt;" );
889  tip += tr( "<li><nobr>%1 features also in rule %2</nobr></li>" ).arg( mFeatureCountMap[rule].duplicateCountMap[duplicateRule] ).arg( label );
890  }
891  tip += "</ul>";
892  return tip;
893  }
894  else
895  {
896  return 0;
897  }
898  }
899  }
900  return QVariant();
901  default:
902  return QVariant();
903  }
904  }
905  else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() )
906  {
907  return QgsSymbolLayerV2Utils::symbolPreviewIcon( rule->symbol(), QSize( 16, 16 ) );
908  }
909  else if ( role == Qt::TextAlignmentRole )
910  {
911  return ( index.column() == 2 || index.column() == 3 ) ? Qt::AlignRight : Qt::AlignLeft;
912  }
913  else if ( role == Qt::FontRole && index.column() == 1 )
914  {
915  if ( rule->isElse() )
916  {
917  QFont italicFont;
918  italicFont.setItalic( true );
919  return italicFont;
920  }
921  return QVariant();
922  }
923  else if ( role == Qt::EditRole )
924  {
925  switch ( index.column() )
926  {
927  case 0:
928  return rule->label();
929  case 1:
930  return rule->filterExpression();
931  case 2:
932  return rule->scaleMaxDenom();
933  case 3:
934  return rule->scaleMinDenom();
935  default:
936  return QVariant();
937  }
938  }
939  else if ( role == Qt::CheckStateRole )
940  {
941  if ( index.column() != 0 )
942  return QVariant();
943  return rule->active() ? Qt::Checked : Qt::Unchecked;
944  }
945  else
946  return QVariant();
947 }
948 
949 QVariant QgsRuleBasedRendererV2Model::headerData( int section, Qt::Orientation orientation, int role ) const
950 {
951  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 7 )
952  {
953  QStringList lst;
954  lst << tr( "Label" ) << tr( "Rule" ) << tr( "Min. scale" ) << tr( "Max. scale" ) << tr( "Count" ) << tr( "Duplicate count" );
955  return lst[section];
956  }
957  else if ( orientation == Qt::Horizontal && role == Qt::ToolTipRole )
958  {
959  if ( section == 4 ) // Count
960  {
961  return tr( "Number of features in this rule." );
962  }
963  else if ( section == 5 ) // Duplicate count
964  {
965  return tr( "Number of features in this rule which are also present in other rule(s)." );
966  }
967  }
968 
969  return QVariant();
970 }
971 
973 {
974  if ( parent.column() > 0 )
975  return 0;
976 
977  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
978 
979  return parentRule->children().count();
980 }
981 
983 {
984  return 6;
985 }
986 
988 {
989  if ( hasIndex( row, column, parent ) )
990  {
991  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
992  QgsRuleBasedRendererV2::Rule* childRule = parentRule->children()[row];
993  return createIndex( row, column, childRule );
994  }
995  return QModelIndex();
996 }
997 
999 {
1000  if ( !index.isValid() )
1001  return QModelIndex();
1002 
1003  QgsRuleBasedRendererV2::Rule* childRule = ruleForIndex( index );
1004  QgsRuleBasedRendererV2::Rule* parentRule = childRule->parent();
1005 
1006  if ( parentRule == mR->rootRule() )
1007  return QModelIndex();
1008 
1009  // this is right: we need to know row number of our parent (in our grandparent)
1010  int row = parentRule->parent()->children().indexOf( parentRule );
1011 
1012  return createIndex( row, 0, parentRule );
1013 }
1014 
1015 bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
1016 {
1017  if ( !index.isValid() )
1018  return false;
1019 
1020  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1021 
1022  if ( role == Qt::CheckStateRole )
1023  {
1024  rule->setActive( value.toInt() == Qt::Checked );
1025  emit dataChanged( index, index );
1026  return true;
1027  }
1028 
1029  if ( role != Qt::EditRole )
1030  return false;
1031 
1032  switch ( index.column() )
1033  {
1034  case 0: // label
1035  rule->setLabel( value.toString() );
1036  break;
1037  case 1: // filter
1038  rule->setFilterExpression( value.toString() );
1039  break;
1040  case 2: // scale min
1041  rule->setScaleMaxDenom( value.toInt() );
1042  break;
1043  case 3: // scale max
1044  rule->setScaleMinDenom( value.toInt() );
1045  break;
1046  default:
1047  return false;
1048  }
1049 
1050  emit dataChanged( index, index );
1051  return true;
1052 }
1053 
1055 {
1056  return Qt::MoveAction; // | Qt::CopyAction
1057 }
1058 
1060 {
1061  QStringList types;
1062  types << "application/vnd.text.list";
1063  return types;
1064 }
1065 
1066 QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes ) const
1067 {
1068  QMimeData *mimeData = new QMimeData();
1069  QByteArray encodedData;
1070 
1071  QDataStream stream( &encodedData, QIODevice::WriteOnly );
1072 
1073  Q_FOREACH ( const QModelIndex &index, indexes )
1074  {
1075  // each item consists of several columns - let's add it with just first one
1076  if ( !index.isValid() || index.column() != 0 )
1077  continue;
1078 
1079  // we use a clone of the existing rule because it has a new unique rule key
1080  // non-unique rule keys would confuse other components using them (e.g. legend)
1081  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index )->clone();
1082  QDomDocument doc;
1083  QgsSymbolV2Map symbols;
1084 
1085  QDomElement rootElem = doc.createElement( "rule_mime" );
1086  rootElem.setAttribute( "type", "renderer" ); // for determining whether rules are from renderer or labeling
1087  QDomElement rulesElem = rule->save( doc, symbols );
1088  rootElem.appendChild( rulesElem );
1089  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
1090  rootElem.appendChild( symbolsElem );
1091  doc.appendChild( rootElem );
1092 
1093  delete rule;
1094 
1095  stream << doc.toString( -1 );
1096  }
1097 
1098  mimeData->setData( "application/vnd.text.list", encodedData );
1099  return mimeData;
1100 }
1101 
1102 
1103 // manipulate DOM before dropping it so that rules are more useful
1105 {
1106  // labeling rules recognize only "description"
1107  if ( ruleElem.hasAttribute( "description" ) )
1108  ruleElem.setAttribute( "label", ruleElem.attribute( "description" ) );
1109 
1110  // run recursively
1111  QDomElement childRuleElem = ruleElem.firstChildElement( "rule" );
1112  while ( !childRuleElem.isNull() )
1113  {
1114  _labeling2rendererRules( childRuleElem );
1115  childRuleElem = childRuleElem.nextSiblingElement( "rule" );
1116  }
1117 }
1118 
1119 
1121  Qt::DropAction action, int row, int column, const QModelIndex &parent )
1122 {
1123  Q_UNUSED( column );
1124 
1125  if ( action == Qt::IgnoreAction )
1126  return true;
1127 
1128  if ( !data->hasFormat( "application/vnd.text.list" ) )
1129  return false;
1130 
1131  if ( parent.column() > 0 )
1132  return false;
1133 
1134  QByteArray encodedData = data->data( "application/vnd.text.list" );
1135  QDataStream stream( &encodedData, QIODevice::ReadOnly );
1136  int rows = 0;
1137 
1138  if ( row == -1 )
1139  {
1140  // the item was dropped at a parent - we may decide where to put the items - let's append them
1141  row = rowCount( parent );
1142  }
1143 
1144  while ( !stream.atEnd() )
1145  {
1146  QString text;
1147  stream >> text;
1148 
1149  QDomDocument doc;
1150  if ( !doc.setContent( text ) )
1151  continue;
1152  QDomElement rootElem = doc.documentElement();
1153  if ( rootElem.tagName() != "rule_mime" )
1154  continue;
1155  if ( rootElem.attribute( "type" ) == "labeling" )
1156  rootElem.appendChild( doc.createElement( "symbols" ) );
1157  QDomElement symbolsElem = rootElem.firstChildElement( "symbols" );
1158  if ( symbolsElem.isNull() )
1159  continue;
1160  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
1161  QDomElement ruleElem = rootElem.firstChildElement( "rule" );
1162  if ( rootElem.attribute( "type" ) == "labeling" )
1163  _labeling2rendererRules( ruleElem );
1165 
1166  insertRule( parent, row + rows, rule );
1167 
1168  ++rows;
1169  }
1170  return true;
1171 }
1172 
1174 {
1175  if ( index.isValid() )
1176  return static_cast<QgsRuleBasedRendererV2::Rule*>( index.internalPointer() );
1177  return mR->rootRule();
1178 }
1179 
1181 {
1182  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1183 
1184  if ( row < 0 || row >= parentRule->children().count() )
1185  return false;
1186 
1187  QgsDebugMsg( QString( "Called: row %1 count %2 parent ~~%3~~" ).arg( row ).arg( count ).arg( parentRule->dump() ) );
1188 
1189  beginRemoveRows( parent, row, row + count - 1 );
1190 
1191  for ( int i = 0; i < count; i++ )
1192  {
1193  if ( row < parentRule->children().count() )
1194  {
1195  //QgsRuleBasedRendererV2::Rule* r = parentRule->children()[row];
1196  parentRule->removeChildAt( row );
1197  //parentRule->takeChildAt( row );
1198  }
1199  else
1200  {
1201  QgsDebugMsg( "trying to remove invalid index - this should not happen!" );
1202  }
1203  }
1204 
1205  endRemoveRows();
1206 
1207  return true;
1208 }
1209 
1210 
1212 {
1213  beginInsertRows( parent, before, before );
1214 
1215  QgsDebugMsg( QString( "insert before %1 rule: %2" ).arg( before ).arg( newrule->dump() ) );
1216 
1217  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1218  parentRule->insertChild( before, newrule );
1219 
1220  endInsertRows();
1221 }
1222 
1224 {
1225  emit dataChanged( index( row, 0, parent ),
1226  index( row, columnCount( parent ), parent ) );
1227 }
1228 
1230 {
1231  emit dataChanged( index( 0, 0, idx ),
1232  index( rowCount( idx ) - 1, columnCount( idx ) - 1, idx ) );
1233 
1234  for ( int i = 0; i < rowCount( idx ); i++ )
1235  {
1236  updateRule( index( i, 0, idx ) );
1237  }
1238 }
1239 
1240 
1242 {
1243  if ( !index.isValid() )
1244  return;
1245 
1246  beginRemoveRows( index.parent(), index.row(), index.row() );
1247 
1248  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1249  rule->parent()->removeChild( rule );
1250 
1251  endRemoveRows();
1252 }
1253 
1255 {
1256  int row = rowCount( parent ); // only consider appending
1257  beginInsertRows( parent, row, row + count - 1 );
1258 }
1259 
1261 {
1262  emit endInsertRows();
1263 }
1264 
1266 {
1267  mFeatureCountMap = theCountMap;
1268  updateRule( QModelIndex() );
1269 }
1270 
1272 {
1274  updateRule( QModelIndex() );
1275 }
bool hasIndex(int row, int column, const QModelIndex &parent) const
QLayout * layout() const
QString dump(int indent=0) const
Dump for debug purpose.
void customContextMenuRequested(const QPoint &pos)
QgsRuleBasedRendererV2Widget(QgsVectorLayer *layer, QgsStyleV2 *style, QgsFeatureRendererV2 *renderer)
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 openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void setLabel(const QString &label)
QString description() const
A human readable description for this rule.
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
Symbol selector widget that cna be used to select and build a symbol.
static QgsSymbolV2Map loadSymbols(QDomElement &element)
QByteArray toByteArray() const
static unsigned index
void refineRuleScalesGui(const QModelIndexList &index)
QByteArray data(const QString &mimeType) const
void setupUi(QWidget *widget)
int bottom() const
virtual void reject()
void keyPressEvent(QKeyEvent *event) override
Overridden key press event to handle the esc event on the widget.
bool dockMode()
Return the dock mode state.
QgsRuleBasedRendererV2Model * mModel
QgsRuleBasedRendererV2::Rule * rule()
Return the current set rule.
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
QgsFields fields() const
Returns the list of fields of this layer.
virtual bool hasFormat(const QString &mimeType) const
void setActive(bool state)
Sets if this rule is active.
QString toString(int indent) const
QObject * sender() 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 testFilter()
Test the filter that is set in the widget.
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
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
void addAction(QAction *action)
QgsMapCanvas * mMapCanvas
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)
QgsRuleBasedRendererV2::Rule * mRule
QDomElement nextSiblingElement(const QString &tagName) const
Qt::DropActions supportedDropActions() const override
Rule * clone() const
clone this rule, return new instance
void accepted()
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
int exec()
QgsRuleBasedRendererV2::RuleList mCopyBuffer
Base class for any widget that can be shown as a inline panel.
QDomElement documentElement() const
void updateRule(const QModelIndex &parent, int row)
virtual QgsFeatureRendererV2 * renderer() override
return pointer to the renderer (no transfer of ownership)
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()
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
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:109
void removeChildAt(int i)
delete child rule
int size() const
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
QgsRendererRulePropsWidget(QgsRuleBasedRendererV2::Rule *rule, QgsVectorLayer *layer, QgsStyleV2 *style, QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr)
Widget to edit the details of a rule based renderer 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 setValue(const QString &key, const QVariant &value)
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void setValue(int progress)
bool isValid() const
void refineRuleRangesGui(const QModelIndexList &index)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QString number(int n, int base)
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
int count(const T &value) const
QgsVectorLayer * mLayer
QgsSymbolV2SelectorWidget * mSymbolSelector
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)
static QString _formatScale(int denom)
void setAttribute(const QString &name, const QString &value)
void buildExpression()
Open the expression builder widget to check if the.
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
const QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
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)
This class keeps data about a rules for rule-based renderer.
void restoreOverrideCursor()
void * internalPointer() const
QModelIndex parent() const
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 ...
void addWidget(QWidget *w)
virtual void accept()
void widgetChanged()
Emitted when the widget state changes.
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)
RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
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.
QMimeData * mimeData(const QModelIndexList &indexes) const override
void setItalic(bool enable)
void beginInsertRows(const QModelIndex &parent, int first, int last)
bool isNull() const
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.
QString filterExpression() const
A filter that will check if this rule applies.
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:455
void setPanelTitle(QString panelTitle)
Set the title of the panel when shown in the interface.
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
QByteArray saveGeometry() const
typedef DropActions
void apply()
Apply any changes from the widget to the set rule.
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...
QgsRuleBasedRendererV2::Rule * ruleForIndex(const QModelIndex &index) const
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)
virtual void setDockMode(bool dockMode)
Set the widget in dock mode.
int column() const
Base class for renderer settings widgets.
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.
bool active() const
Returns if this rule is active.
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
void willAddRules(const QModelIndex &parent, int count)
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap) const
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