QGIS API Documentation  2.15.0-Master (5f66276)
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 
113 
114  // store/restore header section widths
115  connect( viewRules->header(), SIGNAL( sectionResized( int, int, int ) ), this, SLOT( saveSectionWidth( int, int, int ) ) );
116 
118 
119 }
120 
122 {
123  qDeleteAll( mCopyBuffer );
124  delete mRenderer;
125 }
126 
128 {
129  return mRenderer;
130 }
131 
133 {
136 
138  if ( current )
139  {
140  // add after this rule
141  QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
142  mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
143  QModelIndex newindex = mModel->index( currentIndex.row() + 1, 0, currentIndex.parent() );
144  viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
145  }
146  else
147  {
148  // append to root rule
149  int rows = mModel->rowCount();
150  mModel->insertRule( QModelIndex(), rows, newrule );
151  QModelIndex newindex = mModel->index( rows, 0 );
152  viewRules->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect );
153  }
154  editRule();
155 }
156 
158 {
159  QItemSelectionModel* sel = viewRules->selectionModel();
160  QModelIndex idx = sel->currentIndex();
161  if ( !idx.isValid() )
162  return nullptr;
163  return mModel->ruleForIndex( idx );
164 }
165 
167 {
168  editRule( viewRules->selectionModel()->currentIndex() );
169 }
170 
172 {
173  if ( !index.isValid() )
174  return;
175 
177 
179  widget->setDockMode( true );
180  widget->setPanelTitle( tr( "Edit rule" ) );
181  connect( widget, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( ruleWidgetPanelAccepted( QgsPanelWidget* ) ) );
182  connect( widget, SIGNAL( widgetChanged() ), this, SLOT( liveUpdateRuleFromPanel() ) );
183  openPanel( widget );
184 }
185 
187 {
188  QItemSelection sel = viewRules->selectionModel()->selection();
189  QgsDebugMsg( QString( "REMOVE RULES!!! ranges: %1" ).arg( sel.count() ) );
190  Q_FOREACH ( const QItemSelectionRange& range, sel )
191  {
192  QgsDebugMsg( QString( "RANGE: r %1 - %2" ).arg( range.top() ).arg( range.bottom() ) );
193  if ( range.isValid() )
194  mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
195  }
196  // make sure that the selection is gone
197  viewRules->selectionModel()->clear();
199 }
200 
202 {
203  Q_UNUSED( previous );
204  btnEditRule->setEnabled( current.isValid() );
205 }
206 
207 
213 #include <QDialogButtonBox>
214 #include <QInputDialog>
215 #include <QClipboard>
216 
218 {
219  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
220 
221  if ( indexlist.isEmpty() )
222  return;
223 
224 
225  if ( type == 0 ) // categories
226  refineRuleCategoriesGui( indexlist );
227  else if ( type == 1 ) // ranges
228  refineRuleRangesGui( indexlist );
229  else // scales
230  refineRuleScalesGui( indexlist );
231 
232  // TODO: set initial rule's symbol to NULL (?)
233 
234  // show the newly added rules
235  Q_FOREACH ( const QModelIndex& index, indexlist )
236  viewRules->expand( index );
237 }
238 
240 {
241  refineRule( 0 );
242 }
243 
245 {
246  refineRule( 1 );
247 }
248 
250 {
251  refineRule( 2 );
252 }
253 
255 {
257  w->setPanelTitle( tr( "Add categories to rules" ) );
258  connect( w, SIGNAL( panelAccepted( QgsPanelWidget* ) ), this, SLOT( refineRuleCategoriesAccepted( QgsPanelWidget* ) ) );
259  w->setDockMode( this->dockMode() );
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  w->setDockMode( this->dockMode() );
271  openPanel( w );
272 }
273 
274 void QgsRuleBasedRendererV2Widget::refineRuleScalesGui( const QModelIndexList& indexList )
275 {
276  Q_FOREACH ( const QModelIndex& index, indexList )
277  {
278  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
279 
280  // If any of the rules don't have a symbol let the user know and exit.
281  if ( !initialRule->symbol() )
282  {
283  QMessageBox::warning( this, tr( "Scale refinement" ), tr( "Parent rule %1 must have a symbol for this operation." ).arg( initialRule->label() ) );
284  return;
285  }
286  }
287 
288  QString txt = QInputDialog::getText( this,
289  tr( "Scale refinement" ),
290  tr( "Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
291  if ( txt.isEmpty() )
292  return;
293 
294  QList<int> scales;
295  bool ok;
296  Q_FOREACH ( const QString& item, txt.split( ',' ) )
297  {
298  int scale = item.toInt( &ok );
299  if ( ok )
300  scales.append( scale );
301  else
302  QMessageBox::information( this, tr( "Error" ), QString( tr( "\"%1\" is not valid scale denominator, ignoring it." ) ).arg( item ) );
303  }
304 
305  Q_FOREACH ( const QModelIndex& index, indexList )
306  {
307  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
308  mModel->willAddRules( index, scales.count() + 1 );
309  QgsRuleBasedRendererV2::refineRuleScales( initialRule, scales );
310  }
312 }
313 
315 {
316  QList<QgsSymbolV2*> symbolList;
317 
318  if ( !mRenderer )
319  {
320  return symbolList;
321  }
322 
323  QItemSelection sel = viewRules->selectionModel()->selection();
324  Q_FOREACH ( const QItemSelectionRange& range, sel )
325  {
326  QModelIndex parent = range.parent();
327  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
329  for ( int row = range.top(); row <= range.bottom(); row++ )
330  {
331  symbolList.append( children[row]->symbol() );
332  }
333  }
334 
335  return symbolList;
336 }
337 
339 {
341  QItemSelection sel = viewRules->selectionModel()->selection();
342  Q_FOREACH ( const QItemSelectionRange& range, sel )
343  {
344  QModelIndex parent = range.parent();
345  QgsRuleBasedRendererV2::Rule* parentRule = mModel->ruleForIndex( parent );
347  for ( int row = range.top(); row <= range.bottom(); row++ )
348  {
349  rl.append( children[row]->clone() );
350  }
351  }
352  return rl;
353 }
354 
356 {
357  // TODO: model/view
358  /*
359  if ( treeRules )
360  {
361  treeRules->populateRules();
362  }
363  */
364  emit widgetChanged();
365 }
366 
368 {
369  if ( !event )
370  {
371  return;
372  }
373 
374  if ( event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier )
375  {
376  qDeleteAll( mCopyBuffer );
377  mCopyBuffer.clear();
379  }
380  else if ( event->key() == Qt::Key_V && event->modifiers() == Qt::ControlModifier )
381  {
383  for ( ; rIt != mCopyBuffer.constEnd(); ++rIt )
384  {
385  int rows = mModel->rowCount();
386  mModel->insertRule( QModelIndex(), rows, ( *rIt )->clone() );
387  }
388  }
389 }
390 
391 #include "qgssymbollevelsv2dialog.h"
392 
394 {
396 
397  QgsSymbolLevelsV2Dialog dlg( lst, true, this );
398  dlg.setForceOrderingEnabled( true );
399 
400  dlg.exec();
401 }
402 
403 void QgsRuleBasedRendererV2Widget::saveSectionWidth( int section, int oldSize, int newSize )
404 {
405  Q_UNUSED( oldSize );
406  // skip last section, as it stretches
407  if ( section == 5 )
408  return;
409  QSettings settings;
410  QString path = "/Windows/RuleBasedTree/sectionWidth/" + QString::number( section );
411  settings.setValue( path, newSize );
412 }
413 
415 {
416  QSettings settings;
417  QString path = "/Windows/RuleBasedTree/sectionWidth/";
418  QHeaderView* head = viewRules->header();
419  head->resizeSection( 0, settings.value( path + QString::number( 0 ), 150 ).toInt() );
420  head->resizeSection( 1, settings.value( path + QString::number( 1 ), 150 ).toInt() );
421  head->resizeSection( 2, settings.value( path + QString::number( 2 ), 80 ).toInt() );
422  head->resizeSection( 3, settings.value( path + QString::number( 3 ), 80 ).toInt() );
423  head->resizeSection( 4, settings.value( path + QString::number( 4 ), 50 ).toInt() );
424  head->resizeSection( 5, settings.value( path + QString::number( 5 ), 50 ).toInt() );
425 }
426 
428 {
429  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
430  QgsDebugMsg( QString( "%1" ).arg( indexlist.count() ) );
431 
432  if ( indexlist.isEmpty() )
433  return;
434 
435  QMimeData* mime = mModel->mimeData( indexlist );
437 }
438 
440 {
441  const QMimeData* mime = QApplication::clipboard()->mimeData();
442  QModelIndexList indexlist = viewRules->selectionModel()->selectedRows();
444  if ( indexlist.isEmpty() )
445  index = mModel->index( mModel->rowCount(), 0 );
446  else
447  index = indexlist.first();
448  mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
449 }
450 
451 void QgsRuleBasedRendererV2Widget::refineRuleCategoriesAccepted( QgsPanelWidget *panel )
452 {
454 
455  // create new rules
457  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
458  Q_FOREACH ( const QModelIndex& index, indexList )
459  {
460  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
461  mModel->willAddRules( index, r->categories().count() );
463  }
465  emit widgetChanged();
466 }
467 
468 void QgsRuleBasedRendererV2Widget::refineRuleRangesAccepted( QgsPanelWidget *panel )
469 {
471  // create new rules
473  QModelIndexList indexList = viewRules->selectionModel()->selectedRows();
474  Q_FOREACH ( const QModelIndex& index, indexList )
475  {
476  QgsRuleBasedRendererV2::Rule* initialRule = mModel->ruleForIndex( index );
477  mModel->willAddRules( index, r->ranges().count() );
479  }
481  emit widgetChanged();
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  emit widgetChanged();
494 }
495 
496 void QgsRuleBasedRendererV2Widget::liveUpdateRuleFromPanel()
497 {
498  ruleWidgetPanelAccepted( qobject_cast<QgsPanelWidget*>( sender() ) );
499 }
500 
501 
503 {
504  if ( !mLayer || !mRenderer || !mRenderer->rootRule() )
505  {
506  return;
507  }
509 
511  // insert all so that we have counts 0
512  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, ruleList )
513  {
514  countMap[rule].count = 0;
515  countMap[rule].duplicateCount = 0;
516  }
517 
519 
520  QgsRenderContext renderContext;
521  renderContext.setRendererScale( 0 ); // ignore scale
522 
523  QgsExpressionContext context;
527  if ( mMapCanvas )
528  {
531  }
532  else
533  {
535  }
537 
538  renderContext.setExpressionContext( context );
539 
540  mRenderer->startRender( renderContext, mLayer->fields() );
541 
542  int nFeatures = mLayer->featureCount();
543  QProgressDialog p( tr( "Calculating feature count." ), tr( "Abort" ), 0, nFeatures );
544  p.setWindowModality( Qt::WindowModal );
545  int featuresCounted = 0;
546 
547  QgsFeature f;
548  while ( fit.nextFeature( f ) )
549  {
550  renderContext.expressionContext().setFeature( f );
551  QgsRuleBasedRendererV2::RuleList featureRuleList = mRenderer->rootRule()->rulesForFeature( f, &renderContext );
552 
553  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* rule, featureRuleList )
554  {
555  countMap[rule].count++;
556  if ( featureRuleList.size() > 1 )
557  {
558  countMap[rule].duplicateCount++;
559  }
560  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, featureRuleList )
561  {
562  if ( duplicateRule == rule ) continue;
563  countMap[rule].duplicateCountMap[duplicateRule] += 1;
564  }
565  }
566  ++featuresCounted;
567  if ( featuresCounted % 50 == 0 )
568  {
569  if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
570  {
571  p.setMaximum( 0 );
572  }
573  p.setValue( featuresCounted );
574  if ( p.wasCanceled() )
575  {
576  return;
577  }
578  }
579  }
580  p.setValue( nFeatures );
581 
582  mRenderer->stopRender( renderContext );
583 
584 #ifdef QGISDEBUG
585  Q_FOREACH ( QgsRuleBasedRendererV2::Rule *rule, countMap.keys() )
586  {
587  QgsDebugMsg( QString( "rule: %1 count %2" ).arg( rule->label() ).arg( countMap[rule].count ) );
588  }
589 #endif
590 
591  mModel->setFeatureCounts( countMap );
592 }
593 
595 {
596  bool enabled = !viewRules->selectionModel()->selectedIndexes().isEmpty();
597  btnRefineRule->setEnabled( enabled );
598  btnRemoveRule->setEnabled( enabled );
599 }
600 
602 
604  : QgsPanelWidget( parent )
605  , mRule( rule )
606  , mLayer( layer )
607  , mSymbolSelector( nullptr )
608  , mSymbol( nullptr )
609  , mMapCanvas( mapCanvas )
610 {
611  setupUi( this );
612 
613  editFilter->setText( mRule->filterExpression() );
614  editFilter->setToolTip( mRule->filterExpression() );
615  editLabel->setText( mRule->label() );
616  editDescription->setText( mRule->description() );
617  editDescription->setToolTip( mRule->description() );
618 
619  if ( mRule->dependsOnScale() )
620  {
621  groupScale->setChecked( true );
622  // caution: rule uses scale denom, scale widget uses true scales
623  if ( rule->scaleMinDenom() > 0 )
624  mScaleRangeWidget->setMaximumScale( 1.0 / rule->scaleMinDenom() );
625  if ( rule->scaleMaxDenom() > 0 )
626  mScaleRangeWidget->setMinimumScale( 1.0 / rule->scaleMaxDenom() );
627  }
628  mScaleRangeWidget->setMapCanvas( mMapCanvas );
629 
630  if ( mRule->symbol() )
631  {
632  groupSymbol->setChecked( true );
633  mSymbol = mRule->symbol()->clone(); // use a clone!
634  }
635  else
636  {
637  groupSymbol->setChecked( false );
639  }
640 
642  mSymbolSelector->setMapCanvas( mMapCanvas );
643  connect( mSymbolSelector, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
644  connect( mSymbolSelector, SIGNAL( showPanel( QgsPanelWidget* ) ), this, SLOT( openPanel( QgsPanelWidget* ) ) );
645 
646  QVBoxLayout* l = new QVBoxLayout;
647  l->addWidget( mSymbolSelector );
648  groupSymbol->setLayout( l );
649 
650  connect( btnExpressionBuilder, SIGNAL( clicked() ), this, SLOT( buildExpression() ) );
651  connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
652  connect( editFilter, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
653  connect( editLabel, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
654  connect( editDescription, SIGNAL( textChanged( QString ) ), this, SIGNAL( widgetChanged() ) );
655  connect( groupSymbol, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
656  connect( groupScale, SIGNAL( toggled( bool ) ), this, SIGNAL( widgetChanged() ) );
657  connect( mScaleRangeWidget, SIGNAL( rangeChanged( double, double ) ), this, SIGNAL( widgetChanged() ) );
658 }
659 
661 {
662 
663 }
664 
666  : QDialog( parent )
667 {
668 
669 #ifdef Q_OS_MAC
670  setWindowModality( Qt::WindowModal );
671 #endif
672  this->setLayout( new QVBoxLayout() );
673 
674  buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
675  mPropsWidget = new QgsRendererRulePropsWidget( rule, layer, style, this, mapCanvas );
676 
677  this->layout()->addWidget( mPropsWidget );
678  this->layout()->addWidget( buttonBox );
679 
680  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
681  connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
682 
683  QSettings settings;
684  restoreGeometry( settings.value( "/Windows/QgsRendererRulePropsDialog/geometry" ).toByteArray() );
685 }
686 
688 {
689  QSettings settings;
690  settings.setValue( "/Windows/QgsRendererRulePropsDialog/geometry", saveGeometry() );
691 }
692 
694 {
695  mPropsWidget->testFilter();
696 }
697 
699 {
700  mPropsWidget->buildExpression();
701 }
702 
704 {
705  mPropsWidget->apply();
706  QDialog::accept();
707 }
708 
710 {
711  QgsExpressionContext context;
715  if ( mMapCanvas )
716  {
717  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
718  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
719  }
720  else
721  {
723  }
724  context << QgsExpressionContextUtils::layerScope( mLayer );
725 
726  QgsExpressionBuilderDialog dlg( mLayer, editFilter->text(), this, "generic", context );
727 
728  if ( dlg.exec() )
729  editFilter->setText( dlg.expressionText() );
730 }
731 
733 {
734  QgsExpression filter( editFilter->text() );
735  if ( filter.hasParserError() )
736  {
737  QMessageBox::critical( this, tr( "Error" ), tr( "Filter expression parsing error:\n" ) + filter.parserErrorString() );
738  return;
739  }
740 
741  QgsExpressionContext context;
745  if ( mMapCanvas )
746  {
747  context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
748  << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() );
749  }
750  else
751  {
753  }
754  context << QgsExpressionContextUtils::layerScope( mLayer );
755 
756  if ( !filter.prepare( &context ) )
757  {
758  QMessageBox::critical( this, tr( "Evaluation error" ), filter.evalErrorString() );
759  return;
760  }
761 
762  QApplication::setOverrideCursor( Qt::WaitCursor );
763 
764  QgsFeatureIterator fit = mLayer->getFeatures();
765 
766  int count = 0;
767  QgsFeature f;
768  while ( fit.nextFeature( f ) )
769  {
770  context.setFeature( f );
771 
772  QVariant value = filter.evaluate( &context );
773  if ( value.toInt() != 0 )
774  count++;
775  if ( filter.hasEvalError() )
776  break;
777  }
778 
780 
781  QMessageBox::information( this, tr( "Filter" ), tr( "Filter returned %n feature(s)", "number of filtered features", count ) );
782 }
783 
785 {
786  mRule->setFilterExpression( editFilter->text() );
787  mRule->setLabel( editLabel->text() );
788  mRule->setDescription( editDescription->text() );
789  // caution: rule uses scale denom, scale widget uses true scales
790  mRule->setScaleMinDenom( groupScale->isChecked() ? mScaleRangeWidget->minimumScaleDenom() : 0 );
791  mRule->setScaleMaxDenom( groupScale->isChecked() ? mScaleRangeWidget->maximumScaleDenom() : 0 );
792  mRule->setSymbol( groupSymbol->isChecked() ? mSymbol->clone() : nullptr );
793 }
794 
796 {
797  QgsPanelWidget::setDockMode( dockMode );
798  mSymbolSelector->setDockMode( true );
799 }
800 
802 
803 /*
804  setDragEnabled(true);
805  viewport()->setAcceptDrops(true);
806  setDropIndicatorShown(true);
807  setDragDropMode(QAbstractItemView::InternalMove);
808 */
809 
810 static QString _formatScale( int denom )
811 {
812  if ( denom != 0 )
813  {
814  QString txt = QString( "1:%L1" ).arg( denom );
815  return txt;
816  }
817  else
818  return QString();
819 }
820 
822 
824  : mR( r )
825 {
826 }
827 
829 {
830  if ( !index.isValid() )
831  return Qt::ItemIsDropEnabled;
832 
833  // allow drop only at first column
834  Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
835 
836  Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
837 
838  return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
839  Qt::ItemIsEditable | checkable |
840  Qt::ItemIsDragEnabled | drop;
841 }
842 
844 {
845  if ( !index.isValid() )
846  return QVariant();
847 
849 
850  if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
851  {
852  switch ( index.column() )
853  {
854  case 0:
855  return rule->label();
856  case 1:
857  if ( rule->isElse() )
858  {
859  return "ELSE";
860  }
861  else
862  {
863  return rule->filterExpression().isEmpty() ? tr( "(no filter)" ) : rule->filterExpression();
864  }
865  case 2:
866  return rule->dependsOnScale() ? _formatScale( rule->scaleMaxDenom() ) : QVariant();
867  case 3:
868  return rule->dependsOnScale() ? _formatScale( rule->scaleMinDenom() ) : QVariant();
869  case 4:
870  if ( mFeatureCountMap.count( rule ) == 1 )
871  {
872  return QVariant( mFeatureCountMap[rule].count );
873  }
874  return QVariant();
875  case 5:
876  if ( mFeatureCountMap.count( rule ) == 1 )
877  {
878  if ( role == Qt::DisplayRole )
879  {
880  return QVariant( mFeatureCountMap[rule].duplicateCount );
881  }
882  else // tooltip - detailed info about duplicates
883  {
884  if ( mFeatureCountMap[rule].duplicateCount > 0 )
885  {
886  QString tip = "<p style='margin:0px;'><ul>";
887  Q_FOREACH ( QgsRuleBasedRendererV2::Rule* duplicateRule, mFeatureCountMap[rule].duplicateCountMap.keys() )
888  {
889  QString label = duplicateRule->label().replace( '&', "&amp;" ).replace( '>', "&gt;" ).replace( '<', "&lt;" );
890  tip += tr( "<li><nobr>%1 features also in rule %2</nobr></li>" ).arg( mFeatureCountMap[rule].duplicateCountMap[duplicateRule] ).arg( label );
891  }
892  tip += "</ul>";
893  return tip;
894  }
895  else
896  {
897  return 0;
898  }
899  }
900  }
901  return QVariant();
902  default:
903  return QVariant();
904  }
905  }
906  else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() )
907  {
908  return QgsSymbolLayerV2Utils::symbolPreviewIcon( rule->symbol(), QSize( 16, 16 ) );
909  }
910  else if ( role == Qt::TextAlignmentRole )
911  {
912  return ( index.column() == 2 || index.column() == 3 ) ? Qt::AlignRight : Qt::AlignLeft;
913  }
914  else if ( role == Qt::FontRole && index.column() == 1 )
915  {
916  if ( rule->isElse() )
917  {
918  QFont italicFont;
919  italicFont.setItalic( true );
920  return italicFont;
921  }
922  return QVariant();
923  }
924  else if ( role == Qt::EditRole )
925  {
926  switch ( index.column() )
927  {
928  case 0:
929  return rule->label();
930  case 1:
931  return rule->filterExpression();
932  case 2:
933  return rule->scaleMaxDenom();
934  case 3:
935  return rule->scaleMinDenom();
936  default:
937  return QVariant();
938  }
939  }
940  else if ( role == Qt::CheckStateRole )
941  {
942  if ( index.column() != 0 )
943  return QVariant();
944  return rule->active() ? Qt::Checked : Qt::Unchecked;
945  }
946  else
947  return QVariant();
948 }
949 
950 QVariant QgsRuleBasedRendererV2Model::headerData( int section, Qt::Orientation orientation, int role ) const
951 {
952  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 7 )
953  {
954  QStringList lst;
955  lst << tr( "Label" ) << tr( "Rule" ) << tr( "Min. scale" ) << tr( "Max. scale" ) << tr( "Count" ) << tr( "Duplicate count" );
956  return lst[section];
957  }
958  else if ( orientation == Qt::Horizontal && role == Qt::ToolTipRole )
959  {
960  if ( section == 4 ) // Count
961  {
962  return tr( "Number of features in this rule." );
963  }
964  else if ( section == 5 ) // Duplicate count
965  {
966  return tr( "Number of features in this rule which are also present in other rule(s)." );
967  }
968  }
969 
970  return QVariant();
971 }
972 
974 {
975  if ( parent.column() > 0 )
976  return 0;
977 
978  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
979 
980  return parentRule->children().count();
981 }
982 
984 {
985  return 6;
986 }
987 
989 {
990  if ( hasIndex( row, column, parent ) )
991  {
992  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
993  QgsRuleBasedRendererV2::Rule* childRule = parentRule->children()[row];
994  return createIndex( row, column, childRule );
995  }
996  return QModelIndex();
997 }
998 
1000 {
1001  if ( !index.isValid() )
1002  return QModelIndex();
1003 
1004  QgsRuleBasedRendererV2::Rule* childRule = ruleForIndex( index );
1005  QgsRuleBasedRendererV2::Rule* parentRule = childRule->parent();
1006 
1007  if ( parentRule == mR->rootRule() )
1008  return QModelIndex();
1009 
1010  // this is right: we need to know row number of our parent (in our grandparent)
1011  int row = parentRule->parent()->children().indexOf( parentRule );
1012 
1013  return createIndex( row, 0, parentRule );
1014 }
1015 
1016 bool QgsRuleBasedRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role )
1017 {
1018  if ( !index.isValid() )
1019  return false;
1020 
1021  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1022 
1023  if ( role == Qt::CheckStateRole )
1024  {
1025  rule->setActive( value.toInt() == Qt::Checked );
1026  emit dataChanged( index, index );
1027  return true;
1028  }
1029 
1030  if ( role != Qt::EditRole )
1031  return false;
1032 
1033  switch ( index.column() )
1034  {
1035  case 0: // label
1036  rule->setLabel( value.toString() );
1037  break;
1038  case 1: // filter
1039  rule->setFilterExpression( value.toString() );
1040  break;
1041  case 2: // scale min
1042  rule->setScaleMaxDenom( value.toInt() );
1043  break;
1044  case 3: // scale max
1045  rule->setScaleMinDenom( value.toInt() );
1046  break;
1047  default:
1048  return false;
1049  }
1050 
1051  emit dataChanged( index, index );
1052  return true;
1053 }
1054 
1056 {
1057  return Qt::MoveAction; // | Qt::CopyAction
1058 }
1059 
1061 {
1062  QStringList types;
1063  types << "application/vnd.text.list";
1064  return types;
1065 }
1066 
1067 QMimeData *QgsRuleBasedRendererV2Model::mimeData( const QModelIndexList &indexes ) const
1068 {
1069  QMimeData *mimeData = new QMimeData();
1070  QByteArray encodedData;
1071 
1072  QDataStream stream( &encodedData, QIODevice::WriteOnly );
1073 
1074  Q_FOREACH ( const QModelIndex &index, indexes )
1075  {
1076  // each item consists of several columns - let's add it with just first one
1077  if ( !index.isValid() || index.column() != 0 )
1078  continue;
1079 
1080  // we use a clone of the existing rule because it has a new unique rule key
1081  // non-unique rule keys would confuse other components using them (e.g. legend)
1082  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index )->clone();
1083  QDomDocument doc;
1084  QgsSymbolV2Map symbols;
1085 
1086  QDomElement rootElem = doc.createElement( "rule_mime" );
1087  rootElem.setAttribute( "type", "renderer" ); // for determining whether rules are from renderer or labeling
1088  QDomElement rulesElem = rule->save( doc, symbols );
1089  rootElem.appendChild( rulesElem );
1090  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
1091  rootElem.appendChild( symbolsElem );
1092  doc.appendChild( rootElem );
1093 
1094  delete rule;
1095 
1096  stream << doc.toString( -1 );
1097  }
1098 
1099  mimeData->setData( "application/vnd.text.list", encodedData );
1100  return mimeData;
1101 }
1102 
1103 
1104 // manipulate DOM before dropping it so that rules are more useful
1106 {
1107  // labeling rules recognize only "description"
1108  if ( ruleElem.hasAttribute( "description" ) )
1109  ruleElem.setAttribute( "label", ruleElem.attribute( "description" ) );
1110 
1111  // run recursively
1112  QDomElement childRuleElem = ruleElem.firstChildElement( "rule" );
1113  while ( !childRuleElem.isNull() )
1114  {
1115  _labeling2rendererRules( childRuleElem );
1116  childRuleElem = childRuleElem.nextSiblingElement( "rule" );
1117  }
1118 }
1119 
1120 
1122  Qt::DropAction action, int row, int column, const QModelIndex &parent )
1123 {
1124  Q_UNUSED( column );
1125 
1126  if ( action == Qt::IgnoreAction )
1127  return true;
1128 
1129  if ( !data->hasFormat( "application/vnd.text.list" ) )
1130  return false;
1131 
1132  if ( parent.column() > 0 )
1133  return false;
1134 
1135  QByteArray encodedData = data->data( "application/vnd.text.list" );
1136  QDataStream stream( &encodedData, QIODevice::ReadOnly );
1137  int rows = 0;
1138 
1139  if ( row == -1 )
1140  {
1141  // the item was dropped at a parent - we may decide where to put the items - let's append them
1142  row = rowCount( parent );
1143  }
1144 
1145  while ( !stream.atEnd() )
1146  {
1147  QString text;
1148  stream >> text;
1149 
1150  QDomDocument doc;
1151  if ( !doc.setContent( text ) )
1152  continue;
1153  QDomElement rootElem = doc.documentElement();
1154  if ( rootElem.tagName() != "rule_mime" )
1155  continue;
1156  if ( rootElem.attribute( "type" ) == "labeling" )
1157  rootElem.appendChild( doc.createElement( "symbols" ) );
1158  QDomElement symbolsElem = rootElem.firstChildElement( "symbols" );
1159  if ( symbolsElem.isNull() )
1160  continue;
1161  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
1162  QDomElement ruleElem = rootElem.firstChildElement( "rule" );
1163  if ( rootElem.attribute( "type" ) == "labeling" )
1164  _labeling2rendererRules( ruleElem );
1166 
1167  insertRule( parent, row + rows, rule );
1168 
1169  ++rows;
1170  }
1171  return true;
1172 }
1173 
1175 {
1176  if ( index.isValid() )
1177  return static_cast<QgsRuleBasedRendererV2::Rule*>( index.internalPointer() );
1178  return mR->rootRule();
1179 }
1180 
1182 {
1183  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1184 
1185  if ( row < 0 || row >= parentRule->children().count() )
1186  return false;
1187 
1188  QgsDebugMsg( QString( "Called: row %1 count %2 parent ~~%3~~" ).arg( row ).arg( count ).arg( parentRule->dump() ) );
1189 
1190  beginRemoveRows( parent, row, row + count - 1 );
1191 
1192  for ( int i = 0; i < count; i++ )
1193  {
1194  if ( row < parentRule->children().count() )
1195  {
1196  //QgsRuleBasedRendererV2::Rule* r = parentRule->children()[row];
1197  parentRule->removeChildAt( row );
1198  //parentRule->takeChildAt( row );
1199  }
1200  else
1201  {
1202  QgsDebugMsg( "trying to remove invalid index - this should not happen!" );
1203  }
1204  }
1205 
1206  endRemoveRows();
1207 
1208  return true;
1209 }
1210 
1211 
1213 {
1214  beginInsertRows( parent, before, before );
1215 
1216  QgsDebugMsg( QString( "insert before %1 rule: %2" ).arg( before ).arg( newrule->dump() ) );
1217 
1218  QgsRuleBasedRendererV2::Rule* parentRule = ruleForIndex( parent );
1219  parentRule->insertChild( before, newrule );
1220 
1221  endInsertRows();
1222 }
1223 
1225 {
1226  emit dataChanged( index( row, 0, parent ),
1227  index( row, columnCount( parent ), parent ) );
1228 }
1229 
1231 {
1232  emit dataChanged( index( 0, 0, idx ),
1233  index( rowCount( idx ) - 1, columnCount( idx ) - 1, idx ) );
1234 
1235  for ( int i = 0; i < rowCount( idx ); i++ )
1236  {
1237  updateRule( index( i, 0, idx ) );
1238  }
1239 }
1240 
1241 
1243 {
1244  if ( !index.isValid() )
1245  return;
1246 
1247  beginRemoveRows( index.parent(), index.row(), index.row() );
1248 
1249  QgsRuleBasedRendererV2::Rule* rule = ruleForIndex( index );
1250  rule->parent()->removeChild( rule );
1251 
1252  endRemoveRows();
1253 }
1254 
1256 {
1257  int row = rowCount( parent ); // only consider appending
1258  beginInsertRows( parent, row, row + count - 1 );
1259 }
1260 
1262 {
1263  emit endInsertRows();
1264 }
1265 
1267 {
1268  mFeatureCountMap = theCountMap;
1269  updateRule( QModelIndex() );
1270 }
1271 
1273 {
1275  updateRule( QModelIndex() );
1276 }
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
Overriden 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)
Emiited when the panel is accpeted 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()
Emiited 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