QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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->setPanelTitle( tr( "Edit rule" ) );
182  connect( widget, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( ruleWidgetPanelAccepted( QgsPanelWidget* ) ) );
183  connect( widget, SIGNAL( widgetChanged() ), this, SLOT( liveUpdateRuleFromPanel() ) );
184  openPanel( widget );
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 
256 {
258  w->setPanelTitle( tr( "Add categories to rules" ) );
259  connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleCategoriesAccepted( QgsPanelWidget* ) ) );
260  w->setMapCanvas( mMapCanvas );
261  openPanel( w );
262 }
263 
265 {
267  w->setPanelTitle( tr( "Add ranges to rules" ) );
268  connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleRangesAccepted( QgsPanelWidget* ) ) );
269  w->setMapCanvas( mMapCanvas );
270  openPanel( w );
271 }
272 
273 void QgsRuleBasedRendererV2Widget::refineRuleScalesGui( const QModelIndexList& indexList )
274 {
275  Q_FOREACH ( const QModelIndex& index, indexList )
276  {
277  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
278 
279  // If any of the rules don't have a symbol let the user know and exit.
280  if ( !initialRule->symbol() )
281  {
282  QMessageBox::warning( this, tr( "Scale refinement" ), tr( "Parent rule %1 must have a symbol for this operation." ).arg( initialRule->label() ) );
283  return;
284  }
285  }
286 
287  QString txt = QInputDialog::getText( this,
288  tr( "Scale refinement" ),
289  tr( "Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
290  if ( txt.isEmpty() )
291  return;
292 
293  QList<int> scales;
294  bool ok;
295  Q_FOREACH ( const QString& item, txt.split( ',' ) )
296  {
297  int scale = item.toInt( &ok );
298  if ( ok )
299  scales.append( scale );
300  else
301  QMessageBox::information( this, tr( "Error" ), QString( tr( "\"%1\" is not valid scale denominator, ignoring it." ) ).arg( item ) );
302  }
303 
304  Q_FOREACH ( const QModelIndex& index, indexList )
305  {
306  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
307  mModel->willAddRules( index, scales.count() + 1 );
308  QgsRuleBasedRendererV2::refineRuleScales( initialRule, scales );
309  }
311 }
312 
314 {
315  QList<QgsSymbolV2*> symbolList;
316 
317  if ( !mRenderer )
318  {
319  return symbolList;
320  }
321 
322  QItemSelection sel = viewRules->selectionModel()->selection();
323  Q_FOREACH ( const QItemSelectionRange& range, sel )
324  {
325  QModelIndex parent = range.parent();
326  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
328  for ( int row = range.top(); row <= range.bottom(); row++ )
329  {
330  symbolList.append( children[row]->symbol() );
331  }
332  }
333 
334  return symbolList;
335 }
336 
338 {
340  QItemSelection sel = viewRules->selectionModel()->selection();
341  Q_FOREACH ( const QItemSelectionRange& range, sel )
342  {
343  QModelIndex parent = range.parent();
344  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
346  for ( int row = range.top(); row <= range.bottom(); row++ )
347  {
348  rl.append( children[row]->clone() );
349  }
350  }
351  return rl;
352 }
353 
355 {
356  // TODO: model/view
357  /*
358  if ( treeRules )
359  {
360  treeRules->populateRules();
361  }
362  */
363  emit widgetChanged();
364 }
365 
367 {
368  if ( !event )
369  {
370  return;
371  }
372 
373  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
374  {
375  qDeleteAll( mCopyBuffer );
376  mCopyBuffer.clear();
378  }
379  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
380  {
382  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
383  {
384  int rows = mModel->rowCount();
385  mModel->insertRule( QModelIndex(), rows, ( *rIt )->clone() );
386  }
387  }
388 }
389 
390 #include "qgssymbollevelsv2dialog.h"
391 
393 {
395 
396  QgsSymbolLevelsV2Dialog dlg( lst, true, this );
397  dlg.setForceOrderingEnabled( true );
398 
399  dlg.exec();
400 }
401 
402 void QgsRuleBasedRendererV2Widget::saveSectionWidth( int section, int oldSize, int newSize )
403 {
404  Q_UNUSED( oldSize );
405  // skip last section, as it stretches
406  if ( section == 5 )
407  return;
408  QSettings settings;
409  QString path = "/Windows/RuleBasedTree/sectionWidth/" + QString::number( section );
410  settings.setValue( path, newSize );
411 }
412 
414 {
415  QSettings settings;
416  QString path = "/Windows/RuleBasedTree/sectionWidth/";
417  QHeaderView* head = viewRules->header();
418  head->resizeSection( 0, settings.value( path + QString::number( 0 ), 150 ).toInt() );
419  head->resizeSection( 1, settings.value( path + QString::number( 1 ), 150 ).toInt() );
420  head->resizeSection( 2, settings.value( path + QString::number( 2 ), 80 ).toInt() );
421  head->resizeSection( 3, settings.value( path + QString::number( 3 ), 80 ).toInt() );
422  head->resizeSection( 4, settings.value( path + QString::number( 4 ), 50 ).toInt() );
423  head->resizeSection( 5, settings.value( path + QString::number( 5 ), 50 ).toInt() );
424 }
425 
427 {
428  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
429  QgsDebugMsg( QString( "%1" ).arg( indexlist.count() ) );
430 
431  if ( indexlist.isEmpty() )
432  return;
433 
434  QMimeData* mime = mModel->mimeData( indexlist );
436 }
437 
439 {
440  const QMimeData* mime = QApplication::clipboard()->mimeData();
441  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
443  if ( indexlist.isEmpty() )
444  index = mModel->index( mModel->rowCount(), 0 );
445  else
446  index = indexlist.first();
447  mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
448 }
449 
450 void QgsRuleBasedRendererV2Widget::refineRuleCategoriesAccepted( QgsPanelWidget *panel )
451 {
453 
454  // create new rules
456  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
457  Q_FOREACH ( const QModelIndex& index, indexList )
458  {
459  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
460  mModel->willAddRules( index, r->categories().count() );
462  }
464 }
465 
466 void QgsRuleBasedRendererV2Widget::refineRuleRangesAccepted( QgsPanelWidget *panel )
467 {
469  // create new rules
471  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
472  Q_FOREACH ( const QModelIndex& index, indexList )
473  {
474  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
475  mModel->willAddRules( index, r->ranges().count() );
477  }
479 }
480 
481 void QgsRuleBasedRendererV2Widget::ruleWidgetPanelAccepted( QgsPanelWidget *panel )
482 {
483  QgsRendererRulePropsWidget *widget = qobject_cast<QgsRendererRulePropsWidget*>( panel );
484  if ( !widget )
485  return;
486 
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 
517  QgsRenderContext renderContext;
518  renderContext.setRendererScale( 0 ); // ignore scale
519 
520  QgsExpressionContext context;
524  if ( mMapCanvas )
525  {
528  }
529  else
530  {
532  }
534 
535  renderContext.setExpressionContext( context );
536 
537  mRenderer->startRender( renderContext, mLayer->fields() );
538  // QgsRuleBasedRenderer::filter must be called after startRender
540  req.setExpressionContext( context );
542  QgsFeatureIterator fit = mLayer->getFeatures( req );
543 
544  int nFeatures = mLayer->featureCount();
545  QProgressDialog p( tr( "Calculating feature count." ), tr( "Abort" ), 0, nFeatures );
546  p.setWindowModality( Qt::WindowModal );
547  int featuresCounted = 0;
548 
549  QgsFeature f;
550  while ( fit.nextFeature( f ) )
551  {
552  renderContext.expressionContext().setFeature( f );
553  QgsRuleBasedRendererV2::RuleList featureRuleList = mRenderer->rootRule()->rulesForFeature( f, &renderContext );
554 
555  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, featureRuleList )
556  {
557  countMap[rule].count++;
558  if ( featureRuleList.size() > 1 )
559  {
560  countMap[rule].duplicateCount++;
561  }
562  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, featureRuleList )
563  {
564  if ( duplicateRule == rule ) continue;
565  countMap[rule].duplicateCountMap[duplicateRule] += 1;
566  }
567  }
568  ++featuresCounted;
569  if ( featuresCounted % 50 == 0 )
570  {
571  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
572  {
573  p.setMaximum( 0 );
574  }
575  p.setValue( featuresCounted );
576  if ( p.wasCanceled() )
577  {
578  return;
579  }
580  }
581  }
582  p.setValue( nFeatures );
583 
584  mRenderer->stopRender( renderContext );
585 
586 #ifdef QGISDEBUG
587  Q_FOREACH ( QgsRuleBasedRendererV2::Rule *rule, countMap.keys() )
588  {
589  QgsDebugMsg( QString( "rule: %1 count %2" ).arg( rule->label() ).arg( countMap[rule].count ) );
590  }
591 #endif
592 
593  mModel->setFeatureCounts( countMap );
594 }
595 
597 {
598  bool enabled = !viewRules->selectionModel()->selectedIndexes().isEmpty();
599  btnRefineRule->setEnabled( enabled );
600  btnRemoveRule->setEnabled( enabled );
601 }
602 
604 
606  : QgsPanelWidget( parent )
607  , mRule( rule )
608  , mLayer( layer )
609  , mSymbolSelector( nullptr )
610  , mSymbol( nullptr )
611  , mMapCanvas( mapCanvas )
612 {
613  setupUi( this );
614  layout()->setMargin( 0 );
615  layout()->setContentsMargins( 0, 0, 0, 0 );
616 
617  editFilter->setText( mRule->filterExpression() );
618  editFilter->setToolTip( mRule->filterExpression() );
619  editLabel->setText( mRule->label() );
620  editDescription->setText( mRule->description() );
621  editDescription->setToolTip( mRule->description() );
622 
623  if ( mRule->dependsOnScale() )
624  {
625  groupScale->setChecked( true );
626  // caution: rule uses scale denom, scale widget uses true scales
627  if ( rule->scaleMinDenom() > 0 )
628  mScaleRangeWidget->setMaximumScale( 1.0 / rule->scaleMinDenom() );
629  if ( rule->scaleMaxDenom() > 0 )
630  mScaleRangeWidget->setMinimumScale( 1.0 / rule->scaleMaxDenom() );
631  }
632  mScaleRangeWidget->setMapCanvas( mMapCanvas );
633 
634  if ( mRule->symbol() )
635  {
636  groupSymbol->setChecked( true );
637  mSymbol = mRule->symbol()->clone(); // use a clone!
638  }
639  else
640  {
641  groupSymbol->setChecked( false );
643  }
644 
646  mSymbolSelector->setMapCanvas( mMapCanvas );
647  connect( mSymbolSelector, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
648  connect( mSymbolSelector, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
649 
650  QVBoxLayout* l = new QVBoxLayout;
651  l->addWidget( mSymbolSelector );
652  groupSymbol->setLayout( l );
653 
654  connect( btnExpressionBuilder, SIGNAL( clicked() ), this, SLOT( buildExpression() ) );
655  connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
656  connect( editFilter, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
657  connect( editLabel, SIGNAL( editingFinished() ), this, SIGNAL( widgetChanged() ) );
658  connect( editDescription, SIGNAL( editingFinished() ), this, SIGNAL( widgetChanged() ) );
659  connect( groupSymbol, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
660  connect( groupScale, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
661  connect( mScaleRangeWidget, SIGNAL( rangeChanged( double, double ) ), this, SIGNAL( widgetChanged() ) );
662 }
663 
665 {
666 
667 }
668 
670  : QDialog( parent )
671 {
672 
673 #ifdef Q_OS_MAC
674  setWindowModality( Qt::WindowModal );
675 #endif
676  this->setLayout( new QVBoxLayout() );
677 
678  buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
679  mPropsWidget = new QgsRendererRulePropsWidget( rule, layer, style, this, mapCanvas );
680 
681  this->layout()->addWidget( mPropsWidget );
682  this->layout()->addWidget( buttonBox );
683 
684  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
685  connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
686 
687  QSettings settings;
688  restoreGeometry( settings.value( "/Windows/QgsRendererRulePropsDialog/geometry" ).toByteArray() );
689 }
690 
692 {
693  QSettings settings;
694  settings.setValue( "/Windows/QgsRendererRulePropsDialog/geometry", saveGeometry() );
695 }
696 
698 {
699  mPropsWidget->testFilter();
700 }
701 
703 {
704  mPropsWidget->buildExpression();
705 }
706 
708 {
709  mPropsWidget->apply();
710  QDialog::accept();
711 }
712 
714 {
715  QgsExpressionContext context;
719  if ( mMapCanvas )
720  {
721  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
722  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
723  }
724  else
725  {
727  }
728  context << QgsExpressionContextUtils::layerScope( mLayer );
729 
730  QgsExpressionBuilderDialog dlg( mLayer, editFilter->text(), this, "generic", context );
731 
732  if ( dlg.exec() )
733  editFilter->setText( dlg.expressionText() );
734 }
735 
737 {
738  QgsExpression filter( editFilter->text() );
739  if ( filter.hasParserError() )
740  {
741  QMessageBox::critical( this, tr( "Error" ), tr( "Filter expression parsing error:\n" ) + filter.parserErrorString() );
742  return;
743  }
744 
745  QgsExpressionContext context;
749  if ( mMapCanvas )
750  {
751  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
752  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
753  }
754  else
755  {
757  }
758  context << QgsExpressionContextUtils::layerScope( mLayer );
759 
760  if ( !filter.prepare( &context ) )
761  {
762  QMessageBox::critical( this, tr( "Evaluation error" ), filter.evalErrorString() );
763  return;
764  }
765 
766  QApplication::setOverrideCursor( Qt::WaitCursor );
767 
770  .setFilterExpression( editFilter->text() )
771  .setExpressionContext( context );
772 
773  QgsFeatureIterator fit = mLayer->getFeatures( req );
774 
775  int count = 0;
776  QgsFeature f;
777  while ( fit.nextFeature( f ) )
778  {
779  count++;
780  }
781 
783 
784  QMessageBox::information( this, tr( "Filter" ), tr( "Filter returned %n feature(s)", "number of filtered features", count ) );
785 }
786 
788 {
789  mRule->setFilterExpression( editFilter->text() );
790  mRule->setLabel( editLabel->text() );
791  mRule->setDescription( editDescription->text() );
792  // caution: rule uses scale denom, scale widget uses true scales
793  mRule->setScaleMinDenom( groupScale->isChecked() ? mScaleRangeWidget->minimumScaleDenom() : 0 );
794  mRule->setScaleMaxDenom( groupScale->isChecked() ? mScaleRangeWidget->maximumScaleDenom() : 0 );
795  mRule->setSymbol( groupSymbol->isChecked() ? mSymbol->clone() : nullptr );
796 }
797 
799 {
800  QgsPanelWidget::setDockMode( dockMode );
801  mSymbolSelector->setDockMode( dockMode );
802 }
803 
805 
806 /*
807  setDragEnabled(true);
808  viewport()->setAcceptDrops(true);
809  setDropIndicatorShown(true);
810  setDragDropMode(QAbstractItemView::InternalMove);
811 */
812 
813 static QString _formatScale( int denom )
814 {
815  if ( denom != 0 )
816  {
817  QString txt = QString( "1:%L1" ).arg( denom );
818  return txt;
819  }
820  else
821  return QString();
822 }
823 
825 
827  : mR( r )
828 {
829 }
830 
832 {
833  if ( !index.isValid() )
834  return Qt::ItemIsDropEnabled;
835 
836  // allow drop only at first column
837  Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
838 
839  Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
840 
841  return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
842  Qt::ItemIsEditable | checkable |
843  Qt::ItemIsDragEnabled | drop;
844 }
845 
847 {
848  if ( !index.isValid() )
849  return QVariant();
850 
852 
853  if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
854  {
855  switch ( index.column() )
856  {
857  case 0:
858  return rule->label();
859  case 1:
860  if ( rule->isElse() )
861  {
862  return "ELSE";
863  }
864  else
865  {
866  return rule->filterExpression().isEmpty() ? tr( "(no filter)" ) : rule->filterExpression();
867  }
868  case 2:
869  return rule->dependsOnScale() ? _formatScale( rule->scaleMaxDenom() ) : QVariant();
870  case 3:
871  return rule->dependsOnScale() ? _formatScale( rule->scaleMinDenom() ) : QVariant();
872  case 4:
873  if ( mFeatureCountMap.count( rule ) == 1 )
874  {
875  return QVariant( mFeatureCountMap[rule].count );
876  }
877  return QVariant();
878  case 5:
879  if ( mFeatureCountMap.count( rule ) == 1 )
880  {
881  if ( role == Qt::DisplayRole )
882  {
883  return QVariant( mFeatureCountMap[rule].duplicateCount );
884  }
885  else // tooltip - detailed info about duplicates
886  {
887  if ( mFeatureCountMap[rule].duplicateCount > 0 )
888  {
889  QString tip = "<p style='margin:0px;'><ul>";
890  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, mFeatureCountMap[rule].duplicateCountMap.keys() )
891  {
892  QString label = duplicateRule->label().replace( '&', "&amp;" ).replace( '>', "&gt;" ).replace( '<', "&lt;" );
893  tip += tr( "<li><nobr>%1 features also in rule %2</nobr></li>" ).arg( mFeatureCountMap[rule].duplicateCountMap[duplicateRule] ).arg( label );
894  }
895  tip += "</ul>";
896  return tip;
897  }
898  else
899  {
900  return 0;
901  }
902  }
903  }
904  return QVariant();
905  default:
906  return QVariant();
907  }
908  }
909  else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() )
910  {
911  return QgsSymbolLayerV2Utils::symbolPreviewIcon( rule->symbol(), QSize( 16, 16 ) );
912  }
913  else if ( role == Qt::TextAlignmentRole )
914  {
915  return ( index.column() == 2 || index.column() == 3 ) ? Qt::AlignRight : Qt::AlignLeft;
916  }
917  else if ( role == Qt::FontRole && index.column() == 1 )
918  {
919  if ( rule->isElse() )
920  {
921  QFont italicFont;
922  italicFont.setItalic( true );
923  return italicFont;
924  }
925  return QVariant();
926  }
927  else if ( role == Qt::EditRole )
928  {
929  switch ( index.column() )
930  {
931  case 0:
932  return rule->label();
933  case 1:
934  return rule->filterExpression();
935  case 2:
936  return rule->scaleMaxDenom();
937  case 3:
938  return rule->scaleMinDenom();
939  default:
940  return QVariant();
941  }
942  }
943  else if ( role == Qt::CheckStateRole )
944  {
945  if ( index.column() != 0 )
946  return QVariant();
947  return rule->active() ? Qt::Checked : Qt::Unchecked;
948  }
949  else
950  return QVariant();
951 }
952 
953 QVariant QgsRuleBasedRendererV2Model::headerData( int section, Qt::Orientation orientation, int role ) const
954 {
955  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 7 )
956  {
957  QStringList lst;
958  lst << tr( "Label" ) << tr( "Rule" ) << tr( "Min. scale" ) << tr( "Max. scale" ) << tr( "Count" ) << tr( "Duplicate count" );
959  return lst[section];
960  }
961  else if ( orientation == Qt::Horizontal && role == Qt::ToolTipRole )
962  {
963  if ( section == 4 ) // Count
964  {
965  return tr( "Number of features in this rule." );
966  }
967  else if ( section == 5 ) // Duplicate count
968  {
969  return tr( "Number of features in this rule which are also present in other rule(s)." );
970  }
971  }
972 
973  return QVariant();
974 }
975 
977 {
978  if ( parent.column() > 0 )
979  return 0;
980 
981  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
982 
983  return parentRule->children().count();
984 }
985 
987 {
988  return 6;
989 }
990 
992 {
993  if ( hasIndex( row, column, parent ) )
994  {
995  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
996  QgsRuleBasedRendererV2::Rule* childRule = parentRule->children()[row];
997  return createIndex( row, column, childRule );
998  }
999  return QModelIndex();
1000 }
1001 
1003 {
1004  if ( !index.isValid() )
1005  return QModelIndex();
1006 
1007  QgsRuleBasedRendererV2::Rule* childRule = ruleForIndex( index );
1008  QgsRuleBasedRendererV2::Rule* parentRule = childRule->parent();
1009 
1010  if ( parentRule == mR->rootRule() )
1011  return QModelIndex();
1012 
1013  // this is right: we need to know row number of our parent (in our grandparent)
1014  int row = parentRule->parent()->children().indexOf( parentRule );
1015 
1016  return createIndex( row, 0, parentRule );
1017 }
1018 
1019 bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
1020 {
1021  if ( !index.isValid() )
1022  return false;
1023 
1024  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1025 
1026  if ( role == Qt::CheckStateRole )
1027  {
1028  rule->setActive( value.toInt() == Qt::Checked );
1029  emit dataChanged( index, index );
1030  return true;
1031  }
1032 
1033  if ( role != Qt::EditRole )
1034  return false;
1035 
1036  switch ( index.column() )
1037  {
1038  case 0: // label
1039  rule->setLabel( value.toString() );
1040  break;
1041  case 1: // filter
1042  rule->setFilterExpression( value.toString() );
1043  break;
1044  case 2: // scale min
1045  rule->setScaleMaxDenom( value.toInt() );
1046  break;
1047  case 3: // scale max
1048  rule->setScaleMinDenom( value.toInt() );
1049  break;
1050  default:
1051  return false;
1052  }
1053 
1054  emit dataChanged( index, index );
1055  return true;
1056 }
1057 
1059 {
1060  return Qt::MoveAction; // | Qt::CopyAction
1061 }
1062 
1064 {
1065  QStringList types;
1066  types << "application/vnd.text.list";
1067  return types;
1068 }
1069 
1070 QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes ) const
1071 {
1072  QMimeData *mimeData = new QMimeData();
1073  QByteArray encodedData;
1074 
1075  QDataStream stream( &encodedData, QIODevice::WriteOnly );
1076 
1077  Q_FOREACH ( const QModelIndex &index, indexes )
1078  {
1079  // each item consists of several columns - let's add it with just first one
1080  if ( !index.isValid() || index.column() != 0 )
1081  continue;
1082 
1083  // we use a clone of the existing rule because it has a new unique rule key
1084  // non-unique rule keys would confuse other components using them (e.g. legend)
1085  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index )->clone();
1086  QDomDocument doc;
1087  QgsSymbolV2Map symbols;
1088 
1089  QDomElement rootElem = doc.createElement( "rule_mime" );
1090  rootElem.setAttribute( "type", "renderer" ); // for determining whether rules are from renderer or labeling
1091  QDomElement rulesElem = rule->save( doc, symbols );
1092  rootElem.appendChild( rulesElem );
1093  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
1094  rootElem.appendChild( symbolsElem );
1095  doc.appendChild( rootElem );
1096 
1097  delete rule;
1098 
1099  stream << doc.toString( -1 );
1100  }
1101 
1102  mimeData->setData( "application/vnd.text.list", encodedData );
1103  return mimeData;
1104 }
1105 
1106 
1107 // manipulate DOM before dropping it so that rules are more useful
1109 {
1110  // labeling rules recognize only "description"
1111  if ( ruleElem.hasAttribute( "description" ) )
1112  ruleElem.setAttribute( "label", ruleElem.attribute( "description" ) );
1113 
1114  // run recursively
1115  QDomElement childRuleElem = ruleElem.firstChildElement( "rule" );
1116  while ( !childRuleElem.isNull() )
1117  {
1118  _labeling2rendererRules( childRuleElem );
1119  childRuleElem = childRuleElem.nextSiblingElement( "rule" );
1120  }
1121 }
1122 
1123 
1125  Qt::DropAction action, int row, int column, const QModelIndex &parent )
1126 {
1127  Q_UNUSED( column );
1128 
1129  if ( action == Qt::IgnoreAction )
1130  return true;
1131 
1132  if ( !data->hasFormat( "application/vnd.text.list" ) )
1133  return false;
1134 
1135  if ( parent.column() > 0 )
1136  return false;
1137 
1138  QByteArray encodedData = data->data( "application/vnd.text.list" );
1139  QDataStream stream( &encodedData, QIODevice::ReadOnly );
1140  int rows = 0;
1141 
1142  if ( row == -1 )
1143  {
1144  // the item was dropped at a parent - we may decide where to put the items - let's append them
1145  row = rowCount( parent );
1146  }
1147 
1148  while ( !stream.atEnd() )
1149  {
1150  QString text;
1151  stream >> text;
1152 
1153  QDomDocument doc;
1154  if ( !doc.setContent( text ) )
1155  continue;
1156  QDomElement rootElem = doc.documentElement();
1157  if ( rootElem.tagName() != "rule_mime" )
1158  continue;
1159  if ( rootElem.attribute( "type" ) == "labeling" )
1160  rootElem.appendChild( doc.createElement( "symbols" ) );
1161  QDomElement symbolsElem = rootElem.firstChildElement( "symbols" );
1162  if ( symbolsElem.isNull() )
1163  continue;
1164  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
1165  QDomElement ruleElem = rootElem.firstChildElement( "rule" );
1166  if ( rootElem.attribute( "type" ) == "labeling" )
1167  _labeling2rendererRules( ruleElem );
1169 
1170  insertRule( parent, row + rows, rule );
1171 
1172  ++rows;
1173  }
1174  return true;
1175 }
1176 
1178 {
1179  if ( index.isValid() )
1180  return static_cast<QgsRuleBasedRendererV2::Rule*>( index.internalPointer() );
1181  return mR->rootRule();
1182 }
1183 
1185 {
1186  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1187 
1188  if ( row < 0 || row >= parentRule->children().count() )
1189  return false;
1190 
1191  QgsDebugMsg( QString( "Called: row %1 count %2 parent ~~%3~~" ).arg( row ).arg( count ).arg( parentRule->dump() ) );
1192 
1193  beginRemoveRows( parent, row, row + count - 1 );
1194 
1195  for ( int i = 0; i < count; i++ )
1196  {
1197  if ( row < parentRule->children().count() )
1198  {
1199  //QgsRuleBasedRendererV2::Rule* r = parentRule->children()[row];
1200  parentRule->removeChildAt( row );
1201  //parentRule->takeChildAt( row );
1202  }
1203  else
1204  {
1205  QgsDebugMsg( "trying to remove invalid index - this should not happen!" );
1206  }
1207  }
1208 
1209  endRemoveRows();
1210 
1211  return true;
1212 }
1213 
1214 
1216 {
1217  beginInsertRows( parent, before, before );
1218 
1219  QgsDebugMsg( QString( "insert before %1 rule: %2" ).arg( before ).arg( newrule->dump() ) );
1220 
1221  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1222  parentRule->insertChild( before, newrule );
1223 
1224  endInsertRows();
1225 }
1226 
1228 {
1229  emit dataChanged( index( row, 0, parent ),
1230  index( row, columnCount( parent ), parent ) );
1231 }
1232 
1234 {
1235  emit dataChanged( index( 0, 0, idx ),
1236  index( rowCount( idx ) - 1, columnCount( idx ) - 1, idx ) );
1237 
1238  for ( int i = 0; i < rowCount( idx ); i++ )
1239  {
1240  updateRule( index( i, 0, idx ) );
1241  }
1242 }
1243 
1244 
1246 {
1247  if ( !index.isValid() )
1248  return;
1249 
1250  beginRemoveRows( index.parent(), index.row(), index.row() );
1251 
1252  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1253  rule->parent()->removeChild( rule );
1254 
1255  endRemoveRows();
1256 }
1257 
1259 {
1260  int row = rowCount( parent ); // only consider appending
1261  beginInsertRows( parent, row, row + count - 1 );
1262 }
1263 
1265 {
1266  emit endInsertRows();
1267 }
1268 
1270 {
1271  mFeatureCountMap = theCountMap;
1272  updateRule( QModelIndex() );
1273 }
1274 
1276 {
1278  updateRule( QModelIndex() );
1279 }
bool hasIndex(int row, int column, const QModelIndex &parent) const
QLayout * layout() 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 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)
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.
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)
void setContentsMargins(int left, int top, int right, int bottom)
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)
int bottom() const
virtual void reject()
void keyPressEvent(QKeyEvent *event) override
Overridden key press event to handle the esc event on the widget.
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
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
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)
QgsRuleBasedRendererV2::Rule * mRule
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
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...
QgsFields fields() const
Returns the list of fields of this layer.
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.
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 setValue(const QString &key, const QVariant &value)
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
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)
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
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
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 setMargin(int margin)
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)
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: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...
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.
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