rulebasedrenderer_v2.diff

Martin Dobias, 2010-06-10 03:48 AM

Download (54 KB)

View differences:

src/gui/symbology-ng/qgsrulebasedrendererv2widget.h (revision 0)
1
/***************************************************************************
2
    qgsrulebasedrendererv2widget.h - Settings widget for rule-based renderer
3
    ---------------------
4
    begin                : May 2010
5
    copyright            : (C) 2010 by Martin Dobias
6
    email                : wonder.sk at gmail.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

  
16
#ifndef QGSRULEBASEDRENDERERV2WIDGET_H
17
#define QGSRULEBASEDRENDERERV2WIDGET_H
18

  
19
#include "qgsrendererv2widget.h"
20

  
21
#include "qgsrulebasedrendererv2.h"
22
class QMenu;
23

  
24
///////
25

  
26
#include <QTreeWidget>
27

  
28
class QgsRendererRulesTreeWidget : public QTreeWidget
29
{
30
  public:
31
    QgsRendererRulesTreeWidget( QWidget* parent = 0 );
32

  
33
    void setRenderer( QgsRuleBasedRendererV2* r );
34

  
35
    enum Grouping { NoGrouping, GroupingByScale, GroupingByFilter };
36

  
37
    void setGrouping( Grouping g );
38

  
39
    void populateRules();
40

  
41
  protected:
42
    void populateRulesNoGrouping();
43
    void populateRulesGroupByScale();
44
    void populateRulesGroupByFilter();
45

  
46
    QgsRuleBasedRendererV2* mR;
47
    Grouping mGrouping;
48
};
49

  
50
///////
51

  
52
#include "ui_qgsrulebasedrendererv2widget.h"
53

  
54
class GUI_EXPORT QgsRuleBasedRendererV2Widget : public QgsRendererV2Widget, private Ui::QgsRuleBasedRendererV2Widget
55
{
56
    Q_OBJECT
57

  
58
  public:
59

  
60
    static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
61

  
62
    QgsRuleBasedRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
63
    ~QgsRuleBasedRendererV2Widget();
64

  
65
    virtual QgsFeatureRendererV2* renderer();
66

  
67
  public slots:
68

  
69
    void addRule();
70
    void editRule();
71
    void removeRule();
72

  
73
    void setGrouping();
74

  
75
    void refineRuleScales();
76
    void refineRuleCategories();
77
    void refineRuleRanges();
78

  
79
  protected:
80

  
81
    void refineRule( int type );
82
    QList<QgsRuleBasedRendererV2::Rule> refineRuleCategoriesGui( QgsRuleBasedRendererV2::Rule& initialRule );
83
    QList<QgsRuleBasedRendererV2::Rule> refineRuleRangesGui( QgsRuleBasedRendererV2::Rule& initialRule );
84
    QList<QgsRuleBasedRendererV2::Rule> refineRuleScalesGui( QgsRuleBasedRendererV2::Rule& initialRule );
85

  
86
    QgsRuleBasedRendererV2* mRenderer;
87

  
88
    QMenu* mRefineMenu;
89
};
90

  
91
///////
92

  
93
#include <QDialog>
94

  
95
#include "ui_qgsrendererrulepropsdialogbase.h"
96

  
97
class GUI_EXPORT QgsRendererRulePropsDialog : public QDialog, private Ui::QgsRendererRulePropsDialog
98
{
99
    Q_OBJECT
100

  
101
  public:
102
    QgsRendererRulePropsDialog( const QgsRuleBasedRendererV2::Rule& rule, QgsVectorLayer* layer, QgsStyleV2* style );
103

  
104
    void updateRuleFromGui();
105
    const QgsRuleBasedRendererV2::Rule& rule() { return mRule; }
106

  
107
  public slots:
108
    void testFilter();
109

  
110
  protected:
111
    QgsRuleBasedRendererV2::Rule mRule;
112
    QgsVectorLayer* mLayer;
113
    QgsStyleV2* mStyle;
114
};
115

  
116

  
117
#endif // QGSRULEBASEDRENDERERV2WIDGET_H
src/gui/symbology-ng/qgsrulebasedrendererv2widget.cpp (revision 0)
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.sk at gmail.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

  
16
#include "qgsrulebasedrendererv2widget.h"
17

  
18
#include "qgsrulebasedrendererv2.h"
19
#include "qgssymbollayerv2utils.h"
20
#include "qgssymbolv2.h"
21
#include "qgsvectorlayer.h"
22
#include "qgsapplication.h"
23
#include "qgssearchtreenode.h"
24
#include "qgssymbolv2selectordialog.h"
25

  
26
#include <QMenu>
27
#include <QTreeWidgetItem>
28
#include <QVBoxLayout>
29
#include <QMessageBox>
30

  
31
QgsRendererV2Widget* QgsRuleBasedRendererV2Widget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
32
{
33
  return new QgsRuleBasedRendererV2Widget( layer, style, renderer );
34
}
35

  
36
QgsRuleBasedRendererV2Widget::QgsRuleBasedRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
37
    : QgsRendererV2Widget( layer, style )
38
{
39

  
40
  // try to recognize the previous renderer
41
  // (null renderer means "no previous renderer")
42
  if ( !renderer || renderer->type() != "RuleRenderer" )
43
  {
44
    // we're not going to use it - so let's delete the renderer
45
    delete renderer;
46

  
47
    // some default options
48
    QgsSymbolV2* symbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
49

  
50
    mRenderer = new QgsRuleBasedRendererV2( symbol );
51
  }
52
  else
53
  {
54
    mRenderer = static_cast<QgsRuleBasedRendererV2*>( renderer );
55
  }
56

  
57
  setupUi( this );
58

  
59
  treeRules->setRenderer( mRenderer );
60

  
61
  mRefineMenu = new QMenu( btnRefineRule );
62
  mRefineMenu->addAction( tr( "Add scales" ), this, SLOT( refineRuleScales() ) );
63
  mRefineMenu->addAction( tr( "Add categories" ), this, SLOT( refineRuleCategories() ) );
64
  mRefineMenu->addAction( tr( "Add ranges" ), this, SLOT( refineRuleRanges() ) );
65
  btnRefineRule->setMenu( mRefineMenu );
66

  
67
  btnAddRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.png" ) ) );
68
  btnEditRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.png" ) ) );
69
  btnRemoveRule->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.png" ) ) );
70

  
71
  connect( treeRules, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( editRule() ) );
72

  
73
  connect( btnAddRule, SIGNAL( clicked() ), this, SLOT( addRule() ) );
74
  connect( btnEditRule, SIGNAL( clicked() ), this, SLOT( editRule() ) );
75
  connect( btnRemoveRule, SIGNAL( clicked() ), this, SLOT( removeRule() ) );
76

  
77
  connect( radNoGrouping, SIGNAL( clicked() ), this, SLOT( setGrouping() ) );
78
  connect( radGroupFilter, SIGNAL( clicked() ), this, SLOT( setGrouping() ) );
79
  connect( radGroupScale, SIGNAL( clicked() ), this, SLOT( setGrouping() ) );
80

  
81
  treeRules->populateRules();
82
}
83

  
84
QgsRuleBasedRendererV2Widget::~QgsRuleBasedRendererV2Widget()
85
{
86
  delete mRenderer;
87
}
88

  
89
QgsFeatureRendererV2* QgsRuleBasedRendererV2Widget::renderer()
90
{
91
  return mRenderer;
92
}
93

  
94
void QgsRuleBasedRendererV2Widget::setGrouping()
95
{
96
  QObject* origin = sender();
97
  if ( origin == radNoGrouping )
98
    treeRules->setGrouping( QgsRendererRulesTreeWidget::NoGrouping );
99
  else if ( origin == radGroupFilter )
100
    treeRules->setGrouping( QgsRendererRulesTreeWidget::GroupingByFilter );
101
  else if ( origin == radGroupScale )
102
    treeRules->setGrouping( QgsRendererRulesTreeWidget::GroupingByScale );
103
}
104

  
105
void QgsRuleBasedRendererV2Widget::addRule()
106
{
107
  QgsRuleBasedRendererV2::Rule newrule( QgsSymbolV2::defaultSymbol( mLayer->geometryType() ) );
108

  
109
  QgsRendererRulePropsDialog dlg( newrule, mLayer, mStyle );
110
  if ( dlg.exec() )
111
  {
112
    // add rule
113
    dlg.updateRuleFromGui();
114
    mRenderer->addRule( dlg.rule() );
115
    treeRules->populateRules();
116
  }
117
}
118

  
119

  
120

  
121
void QgsRuleBasedRendererV2Widget::editRule()
122
{
123
  QTreeWidgetItem * item = treeRules->currentItem();
124
  if ( ! item ) return;
125

  
126
  int rule_index = item->data( 0, Qt::UserRole + 1 ).toInt();
127
  if ( rule_index < 0 )
128
  {
129
    QMessageBox::information( this, tr( "Edit rule" ), tr( "Groups of rules cannot be edited." ) );
130
    return;
131
  }
132
  QgsRuleBasedRendererV2::Rule& rule = mRenderer->ruleAt( rule_index );
133

  
134
  QgsRendererRulePropsDialog dlg( rule, mLayer, mStyle );
135
  if ( dlg.exec() )
136
  {
137
    // update rule
138
    dlg.updateRuleFromGui();
139
    mRenderer->updateRuleAt( rule_index, dlg.rule() );
140

  
141
    treeRules->populateRules();
142
  }
143
}
144

  
145
void QgsRuleBasedRendererV2Widget::removeRule()
146
{
147
  QTreeWidgetItem * item = treeRules->currentItem();
148
  if ( ! item ) return;
149

  
150
  int rule_index = item->data( 0, Qt::UserRole + 1 ).toInt();
151
  if ( rule_index < 0 )
152
  {
153
    QList<int> rule_indexes;
154
    // this is a group
155
    for ( int i = 0; i < item->childCount(); i++ )
156
    {
157
      int idx = item->child( i )->data( 0, Qt::UserRole + 1 ).toInt();
158
      rule_indexes.append( idx );
159
    }
160
    // delete in decreasing order to avoid shifting of indexes
161
    qSort( rule_indexes.begin(), rule_indexes.end(), qGreater<int>() );
162
    foreach( int idx, rule_indexes )
163
    mRenderer->removeRuleAt( idx );
164
  }
165
  else
166
  {
167
    // this is a rule
168
    mRenderer->removeRuleAt( rule_index );
169
  }
170

  
171
  treeRules->populateRules();
172
}
173

  
174

  
175
#include "qgscategorizedsymbolrendererv2.h"
176
#include "qgscategorizedsymbolrendererv2widget.h"
177
#include "qgsgraduatedsymbolrendererv2.h"
178
#include "qgsgraduatedsymbolrendererv2widget.h"
179
#include <QDialogButtonBox>
180
#include <QInputDialog>
181

  
182
void QgsRuleBasedRendererV2Widget::refineRule( int type )
183
{
184
  QTreeWidgetItem * item = treeRules->currentItem();
185
  if ( ! item ) return;
186

  
187
  int rule_index = item->data( 0, Qt::UserRole + 1 ).toInt();
188
  if ( rule_index < 0 ) return;
189

  
190
  QgsRuleBasedRendererV2::Rule& initialRule = mRenderer->ruleAt( rule_index );
191

  
192

  
193
  QList<QgsRuleBasedRendererV2::Rule> refinedRules;
194
  if ( type == 0 ) // categories
195
    refinedRules = refineRuleCategoriesGui( initialRule );
196
  else if ( type == 1 ) // ranges
197
    refinedRules = refineRuleRangesGui( initialRule );
198
  else // scales
199
    refinedRules = refineRuleScalesGui( initialRule );
200

  
201
  if ( refinedRules.count() == 0 )
202
    return;
203

  
204
  // delete original rule
205
  mRenderer->removeRuleAt( rule_index );
206

  
207
  // add new rules
208
  for ( int i = 0; i < refinedRules.count(); i++ )
209
  {
210
    mRenderer->insertRule( rule_index + i, refinedRules.at( i ) );
211
  }
212

  
213
  treeRules->populateRules();
214
}
215

  
216
void QgsRuleBasedRendererV2Widget::refineRuleCategories()
217
{
218
  refineRule( 0 );
219
}
220

  
221
void QgsRuleBasedRendererV2Widget::refineRuleRanges()
222
{
223
  refineRule( 1 );
224
}
225

  
226
void QgsRuleBasedRendererV2Widget::refineRuleScales()
227
{
228
  refineRule( 2 );
229
}
230

  
231
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2Widget::refineRuleCategoriesGui( QgsRuleBasedRendererV2::Rule& initialRule )
232
{
233
  QDialog dlg;
234
  dlg.setWindowTitle( tr( "Refine a rule to categories" ) );
235
  QVBoxLayout* l = new QVBoxLayout();
236
  QgsCategorizedSymbolRendererV2Widget* w = new QgsCategorizedSymbolRendererV2Widget( mLayer, mStyle, NULL );
237
  l->addWidget( w );
238
  QDialogButtonBox* bb = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
239
  l->addWidget( bb );
240
  connect( bb, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
241
  connect( bb, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
242
  dlg.setLayout( l );
243

  
244
  if ( !dlg.exec() )
245
    return QList<QgsRuleBasedRendererV2::Rule>();
246

  
247
  // create new rules
248
  QgsCategorizedSymbolRendererV2* r = static_cast<QgsCategorizedSymbolRendererV2*>( w->renderer() );
249
  return QgsRuleBasedRendererV2::refineRuleCategories( initialRule, r );
250
}
251

  
252

  
253
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2Widget::refineRuleRangesGui( QgsRuleBasedRendererV2::Rule& initialRule )
254
{
255
  QDialog dlg;
256
  dlg.setWindowTitle( tr( "Refine a rule to ranges" ) );
257
  QVBoxLayout* l = new QVBoxLayout();
258
  QgsGraduatedSymbolRendererV2Widget* w = new QgsGraduatedSymbolRendererV2Widget( mLayer, mStyle, NULL );
259
  l->addWidget( w );
260
  QDialogButtonBox* bb = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
261
  l->addWidget( bb );
262
  connect( bb, SIGNAL( accepted() ), &dlg, SLOT( accept() ) );
263
  connect( bb, SIGNAL( rejected() ), &dlg, SLOT( reject() ) );
264
  dlg.setLayout( l );
265

  
266
  if ( !dlg.exec() )
267
    return QList<QgsRuleBasedRendererV2::Rule>();
268

  
269
  // create new rules
270
  QgsGraduatedSymbolRendererV2* r = static_cast<QgsGraduatedSymbolRendererV2*>( w->renderer() );
271
  return QgsRuleBasedRendererV2::refineRuleRanges( initialRule, r );
272
}
273

  
274
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2Widget::refineRuleScalesGui( QgsRuleBasedRendererV2::Rule& initialRule )
275
{
276
  QString txt = QInputDialog::getText( this,
277
                                       tr( "Scale refinement" ),
278
                                       tr( "Please enter scale denominators at which will split the rule, separate them by commas (e.g. 1000,5000):" ) );
279
  if ( txt.isEmpty() )
280
    return QList<QgsRuleBasedRendererV2::Rule>();
281

  
282
  QList<int> scales;
283
  bool ok;
284
  foreach( QString item, txt.split( ',' ) )
285
  {
286
    int scale = item.toInt( &ok );
287
    if ( ok )
288
      scales.append( scale );
289
    else
290
      QMessageBox::information( this, tr( "Error" ), QString( tr( "\"%1\" is not valid scale denominator, ignoring it." ) ).arg( item ) );
291
  }
292

  
293
  return QgsRuleBasedRendererV2::refineRuleScales( initialRule, scales );
294
}
295

  
296

  
297
///////////
298

  
299
QgsRendererRulePropsDialog::QgsRendererRulePropsDialog( const QgsRuleBasedRendererV2::Rule& rule, QgsVectorLayer* layer, QgsStyleV2* style )
300
    : mRule( rule ), mLayer( layer )
301
{
302
  setupUi( this );
303

  
304
  editFilter->setText( mRule.filterExpression() );
305

  
306
  if ( mRule.dependsOnScale() )
307
  {
308
    groupScale->setChecked( true );
309
    spinMinScale->setValue( rule.scaleMinDenom() );
310
    spinMaxScale->setValue( rule.scaleMaxDenom() );
311
  }
312

  
313
  QgsSymbolV2SelectorDialog* symbolSel = new QgsSymbolV2SelectorDialog( mRule.symbol(), style, this, true );
314
  QVBoxLayout* l = new QVBoxLayout;
315
  l->addWidget( symbolSel );
316
  groupSymbol->setLayout( l );
317

  
318
  connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
319
}
320

  
321
void QgsRendererRulePropsDialog::testFilter()
322
{
323
  QgsSearchString filterParsed;
324
  if ( ! filterParsed.setString( editFilter->text() ) )
325
  {
326
    QMessageBox::critical( this, tr( "Error" ),  tr( "Filter expression parsing error:\n" ) + filterParsed.parserErrorMsg() );
327
    return;
328
  }
329

  
330
  QgsSearchTreeNode* tree = filterParsed.tree();
331
  if ( ! tree )
332
  {
333
    QMessageBox::critical( this, tr( "Error" ), tr( "Filter is empty" ) );
334
    return;
335
  }
336

  
337
  QApplication::setOverrideCursor( Qt::WaitCursor );
338

  
339
  const QgsFieldMap& fields = mLayer->pendingFields();
340
  mLayer->select( fields.keys(), QgsRectangle(), false );
341

  
342
  int count = 0;
343
  QgsFeature f;
344
  while ( mLayer->nextFeature( f ) )
345
  {
346
    if ( tree->checkAgainst( fields, f.attributeMap() ) )
347
      count++;
348
    if ( tree->hasError() )
349
      break;
350
  }
351

  
352
  QApplication::restoreOverrideCursor();
353

  
354
  QMessageBox::information( this, tr( "Filter" ), tr( "Filter returned %1 features" ).arg( count ) );
355
}
356

  
357
void QgsRendererRulePropsDialog::updateRuleFromGui()
358
{
359
  mRule.setFilterExpression( editFilter->text() );
360
  mRule.setScaleMinDenom( groupScale->isChecked() ? spinMinScale->value() : 0 );
361
  mRule.setScaleMaxDenom( groupScale->isChecked() ? spinMaxScale->value() : 0 );
362
}
363

  
364
////////
365

  
366
QgsRendererRulesTreeWidget::QgsRendererRulesTreeWidget( QWidget* parent )
367
    : QTreeWidget( parent ), mR( NULL ), mGrouping( NoGrouping )
368
{
369
  setSelectionMode( QAbstractItemView::SingleSelection );
370
  /*
371
    setDragEnabled(true);
372
    viewport()->setAcceptDrops(true);
373
    setDropIndicatorShown(true);
374
    setDragDropMode(QAbstractItemView::InternalMove);
375
  */
376
}
377

  
378
void QgsRendererRulesTreeWidget::setRenderer( QgsRuleBasedRendererV2* r )
379
{
380
  mR = r;
381
}
382

  
383
void QgsRendererRulesTreeWidget::setGrouping( Grouping g )
384
{
385
  mGrouping = g;
386
  setRootIsDecorated( mGrouping != NoGrouping );
387
  populateRules();
388
}
389

  
390
void QgsRendererRulesTreeWidget::populateRules()
391
{
392
  if ( !mR ) return;
393

  
394
  clear();
395
  if ( mGrouping == NoGrouping )
396
    populateRulesNoGrouping();
397
  else if ( mGrouping == GroupingByScale )
398
    populateRulesGroupByScale();
399
  else
400
    populateRulesGroupByFilter();
401
}
402

  
403
void QgsRendererRulesTreeWidget::populateRulesNoGrouping()
404
{
405
  QList<QTreeWidgetItem *> lst;
406
  for ( int i = 0; i < mR->ruleCount(); ++i )
407
  {
408
    QgsRuleBasedRendererV2::Rule& rule = mR->ruleAt( i );
409

  
410
    QTreeWidgetItem* item = new QTreeWidgetItem;
411
    QString txt = rule.filterExpression();
412
    if ( txt.isEmpty() ) txt = tr( "(no filter)" );
413
    if ( rule.dependsOnScale() )
414
    {
415
      txt += QString( ", scale <1:%1, 1:%2>" ).arg( rule.scaleMinDenom() ).arg( rule.scaleMaxDenom() );
416
    }
417

  
418
    item->setText( 0, txt );
419
    item->setData( 0, Qt::UserRole + 1, i );
420
    item->setIcon( 0, QgsSymbolLayerV2Utils::symbolPreviewIcon( rule.symbol(), QSize( 16, 16 ) ) );
421

  
422
    lst << item;
423
  }
424

  
425
  addTopLevelItems( lst );
426
}
427

  
428
void QgsRendererRulesTreeWidget::populateRulesGroupByScale()
429
{
430
  QMap< QPair<int, int>, QTreeWidgetItem*> scale_items;
431

  
432
  for ( int i = 0; i < mR->ruleCount(); ++i )
433
  {
434
    QgsRuleBasedRendererV2::Rule& rule = mR->ruleAt( i );
435

  
436
    QPair<int, int> scale = qMakePair( rule.scaleMinDenom(), rule.scaleMaxDenom() );
437
    if ( ! scale_items.contains( scale ) )
438
    {
439
      QString txt;
440
      if ( rule.dependsOnScale() )
441
        txt = QString( "scale <1:%1, 1:%2>" ).arg( rule.scaleMinDenom() ).arg( rule.scaleMaxDenom() );
442
      else
443
        txt = "any scale";
444

  
445
      QTreeWidgetItem* scale_item = new QTreeWidgetItem;
446
      scale_item->setText( 0, txt );
447
      scale_item->setData( 0, Qt::UserRole + 1, -2 );
448
      scale_item->setFlags( scale_item->flags() & ~Qt::ItemIsDragEnabled ); // groups cannot be dragged
449
      scale_items[scale] = scale_item;
450
    }
451

  
452
    QString filter = rule.filterExpression();
453

  
454
    QTreeWidgetItem* item = new QTreeWidgetItem( scale_items[scale] );
455
    item->setText( 0, filter.isEmpty() ? tr( "(no filter)" ) : filter );
456
    item->setData( 0, Qt::UserRole + 1, i );
457
    item->setIcon( 0, QgsSymbolLayerV2Utils::symbolPreviewIcon( rule.symbol(), QSize( 16, 16 ) ) );
458
  }
459
  addTopLevelItems( scale_items.values() );
460
}
461

  
462
void QgsRendererRulesTreeWidget::populateRulesGroupByFilter()
463
{
464
  QMap<QString, QTreeWidgetItem *> filter_items;
465

  
466
  for ( int i = 0; i < mR->ruleCount(); ++i )
467
  {
468
    QgsRuleBasedRendererV2::Rule& rule = mR->ruleAt( i );
469

  
470
    QString filter = rule.filterExpression();
471
    if ( ! filter_items.contains( filter ) )
472
    {
473
      QTreeWidgetItem* filter_item = new QTreeWidgetItem;
474
      filter_item->setText( 0, filter.isEmpty() ? tr( "(no filter)" ) : filter );
475
      filter_item->setData( 0, Qt::UserRole + 1, -1 );
476
      filter_item->setFlags( filter_item->flags() & ~Qt::ItemIsDragEnabled ); // groups cannot be dragged
477
      filter_items[filter] = filter_item;
478
    }
479

  
480
    QString txt;
481
    if ( rule.dependsOnScale() )
482
      txt = QString( "scale <1:%1, 1:%2>" ).arg( rule.scaleMinDenom() ).arg( rule.scaleMaxDenom() );
483
    else
484
      txt = "any scale";
485

  
486
    QTreeWidgetItem* item = new QTreeWidgetItem( filter_items[filter] );
487
    item->setText( 0, txt );
488
    item->setData( 0, Qt::UserRole + 1, i );
489
    item->setIcon( 0, QgsSymbolLayerV2Utils::symbolPreviewIcon( rule.symbol(), QSize( 16, 16 ) ) );
490

  
491
  }
492
  addTopLevelItems( filter_items.values() );
493
}
src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp (working copy)
8 8
#include "qgssinglesymbolrendererv2widget.h"
9 9
#include "qgscategorizedsymbolrendererv2widget.h"
10 10
#include "qgsgraduatedsymbolrendererv2widget.h"
11
#include "qgsrulebasedrendererv2widget.h"
11 12

  
12 13
#include "qgssymbollevelsv2dialog.h"
13 14

  
......
18 19
#include <QKeyEvent>
19 20
#include <QMessageBox>
20 21

  
21
static bool _initRenderer( QString name, QgsRendererV2WidgetFunc f, QString iconName )
22
static bool _initRenderer( QString name, QgsRendererV2WidgetFunc f, QString iconName = QString() )
22 23
{
23 24
  QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
24 25
  QgsRendererV2AbstractMetadata* am = reg->rendererMetadata( name );
......
30 31

  
31 32
  m->setWidgetFunction( f );
32 33

  
33
  QString iconPath = QgsApplication::defaultThemePath() + iconName;
34
  QPixmap pix;
35
  if ( pix.load( iconPath, "png" ) )
36
    m->setIcon( pix );
34
  if ( !iconName.isEmpty() )
35
  {
36
    QString iconPath = QgsApplication::defaultThemePath() + iconName;
37
    QPixmap pix;
38
    if ( pix.load( iconPath, "png" ) )
39
      m->setIcon( pix );
40
  }
37 41

  
38 42
  QgsDebugMsg( "Set for " + name );
39 43
  return true;
......
48 52
  _initRenderer( "singleSymbol", QgsSingleSymbolRendererV2Widget::create, "rendererSingleSymbol.png" );
49 53
  _initRenderer( "categorizedSymbol", QgsCategorizedSymbolRendererV2Widget::create, "rendererCategorizedSymbol.png" );
50 54
  _initRenderer( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create, "rendererGraduatedSymbol.png" );
55
  _initRenderer( "RuleRenderer", QgsRuleBasedRendererV2Widget::create );
51 56
  initialized = true;
52 57
}
53 58

  
src/gui/CMakeLists.txt (working copy)
10 10
symbology-ng/qgssinglesymbolrendererv2widget.cpp
11 11
symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
12 12
symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
13
symbology-ng/qgsrulebasedrendererv2widget.cpp
13 14
symbology-ng/qgsrendererv2propertiesdialog.cpp
14 15
symbology-ng/qgsstylev2managerdialog.cpp
15 16
symbology-ng/qgssymbollevelsv2dialog.cpp
......
63 64
symbology-ng/qgssinglesymbolrendererv2widget.h
64 65
symbology-ng/qgscategorizedsymbolrendererv2widget.h
65 66
symbology-ng/qgsgraduatedsymbolrendererv2widget.h
67
symbology-ng/qgsrulebasedrendererv2widget.h
66 68
symbology-ng/qgsrendererv2propertiesdialog.h
67 69
symbology-ng/qgsstylev2managerdialog.h
68 70
symbology-ng/qgssymbollevelsv2dialog.h
src/core/symbology-ng/qgsrendererv2registry.cpp (working copy)
4 4
#include "qgssinglesymbolrendererv2.h"
5 5
#include "qgscategorizedsymbolrendererv2.h"
6 6
#include "qgsgraduatedsymbolrendererv2.h"
7
#include "qgsrulebasedrendererv2.h"
7 8

  
8

  
9 9
QgsRendererV2Registry* QgsRendererV2Registry::mInstance = NULL;
10 10

  
11 11
QgsRendererV2Registry::QgsRendererV2Registry()
......
20 20
  addRenderer( new QgsRendererV2Metadata( "graduatedSymbol",
21 21
                                          QObject::tr( "Graduated" ),
22 22
                                          QgsGraduatedSymbolRendererV2::create ) );
23

  
24
  addRenderer( new QgsRendererV2Metadata( "RuleRenderer",
25
                                          QObject::tr( "Rule-based" ),
26
                                          QgsRuleBasedRendererV2::create ) );
23 27
}
24 28

  
25 29
QgsRendererV2Registry::~QgsRendererV2Registry()
src/core/symbology-ng/qgsrulebasedrendererv2.h (revision 0)
1
/***************************************************************************
2
    qgsrulebasedrendererv2.h - Rule-based renderer (symbology-ng)
3
    ---------------------
4
    begin                : May 2010
5
    copyright            : (C) 2010 by Martin Dobias
6
    email                : wonder.sk at gmail.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

  
16
#ifndef QGSRULEBASEDRENDERERV2_H
17
#define QGSRULEBASEDRENDERERV2_H
18

  
19
#include "qgsfield.h"
20
#include "qgssearchstring.h"
21

  
22
#include "qgsrendererv2.h"
23

  
24
class QgsCategorizedSymbolRendererV2;
25
class QgsGraduatedSymbolRendererV2;
26

  
27
/**
28
When drawing a vector layer with rule-based renderer, it goes through
29
the rules and draws features with symbols from rules that match.
30
 */
31
class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
32
{
33
  public:
34

  
35
    /**
36
      This class keeps data about a rules for rule-based renderer.
37
      A rule consists of a symbol, filter expression and range of scales.
38
      If filter is empty, it matches all features.
39
      If scale range has both values zero, it matches all scales.
40
      If one of the min/max scale denominators is zero, there is no lower/upper bound for scales.
41
      A rule matches if both filter and scale range match.
42
     */
43
    class Rule
44
    {
45
      public:
46
        //! Constructor takes ownership of the symbol
47
        Rule( QgsSymbolV2* symbol, int scaleMinDenom = 0, int scaleMaxDenom = 0, QString filterExp = QString() );
48
        Rule( const Rule& other );
49
        ~Rule();
50
        QString dump() const;
51
        QStringList needsFields() const;
52
        bool isFilterOK( const QgsFieldMap& fields, QgsFeature& f ) const;
53
        bool isScaleOK( double scale ) const;
54

  
55
        QgsSymbolV2* symbol() { return mSymbol; }
56
        bool dependsOnScale() const { return mScaleMinDenom != 0 || mScaleMaxDenom != 0; }
57
        int scaleMinDenom() const { return mScaleMinDenom; }
58
        int scaleMaxDenom() const { return mScaleMaxDenom; }
59
        QString filterExpression() const { return mFilterExp; }
60

  
61
        void setScaleMinDenom( int scaleMinDenom ) { mScaleMinDenom = scaleMinDenom; }
62
        void setScaleMaxDenom( int scaleMaxDenom ) { mScaleMaxDenom = scaleMaxDenom; }
63
        void setFilterExpression( QString filterExp ) { mFilterExp = filterExp; initFilter(); }
64

  
65
        Rule& operator=( const Rule& other );
66

  
67
      protected:
68

  
69
        void initFilter();
70

  
71
        QgsSymbolV2* mSymbol;
72
        int mScaleMinDenom, mScaleMaxDenom;
73
        QString mFilterExp;
74

  
75
        // temporary
76
        QgsSearchString mFilterParsed;
77
        QgsSearchTreeNode* mFilterTree;
78
    };
79

  
80
    /////
81

  
82
    static QgsFeatureRendererV2* create( QDomElement& element );
83

  
84
    //! Constructor. Takes ownership of the defult symbol.
85
    QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol );
86

  
87
    //! return symbol for current feature. Should not be used individually: there could be more symbols for a feature
88
    virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature );
89

  
90
    virtual void renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false );
91

  
92
    virtual void startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer );
93

  
94
    virtual void stopRender( QgsRenderContext& context );
95

  
96
    virtual QList<QString> usedAttributes();
97

  
98
    virtual QgsFeatureRendererV2* clone();
99

  
100
    virtual QgsSymbolV2List symbols();
101

  
102
    //! store renderer info to XML element
103
    virtual QDomElement save( QDomDocument& doc );
104

  
105
    /////
106

  
107
    //! return the total number of rules
108
    int ruleCount();
109
    //! get reference to rule at index (valid indexes: 0...count-1)
110
    Rule& ruleAt( int index );
111
    //! add rule to the end of the list of rules
112
    void addRule( const Rule& rule );
113
    //! insert rule to a specific position of the list of rules
114
    void insertRule( int index, const Rule& rule );
115
    //! modify the rule at a specific position of the list of rules
116
    void updateRuleAt( int index, const Rule& rule );
117
    //! remove the rule at the specified index
118
    void removeRuleAt( int index );
119

  
120
    //////
121

  
122
    //! take a rule and create a list of new rules based on the categories from categorized symbol renderer
123
    static QList<Rule> refineRuleCategories( Rule& initialRule, QgsCategorizedSymbolRendererV2* r );
124
    //! take a rule and create a list of new rules based on the ranges from graduated symbol renderer
125
    static QList<Rule> refineRuleRanges( Rule& initialRule, QgsGraduatedSymbolRendererV2* r );
126
    //! take a rule and create a list of new rules with intervals of scales given by the passed scale denominators
127
    static QList<Rule> refineRuleScales( Rule& initialRule, QList<int> scales );
128

  
129
  protected:
130
    //! the list of rules
131
    QList<Rule> mRules;
132
    //! the default symbol, used for the first rule with no filter
133
    QgsSymbolV2* mDefaultSymbol;
134

  
135
    // temporary
136
    QList<Rule*> mCurrentRules;
137
    QgsFieldMap mCurrentFields;
138
    QgsSymbolV2* mCurrentSymbol;
139
};
140

  
141
#endif // QGSRULEBASEDRENDERERV2_H
src/core/symbology-ng/qgsrulebasedrendererv2.cpp (revision 0)
1
/***************************************************************************
2
    qgsrulebasedrendererv2.cpp - Rule-based renderer (symbology-ng)
3
    ---------------------
4
    begin                : May 2010
5
    copyright            : (C) 2010 by Martin Dobias
6
    email                : wonder.sk at gmail.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

  
16
#include "qgsrulebasedrendererv2.h"
17

  
18
#include "qgssearchtreenode.h"
19
#include "qgssymbollayerv2utils.h"
20
#include "qgsrendercontext.h"
21
#include "qgsvectorlayer.h"
22
#include "qgslogger.h"
23

  
24
#include <QSet>
25

  
26
#include <QDomDocument>
27
#include <QDomElement>
28

  
29

  
30

  
31
QgsRuleBasedRendererV2::Rule::Rule( QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp )
32
    : mSymbol( symbol ),
33
    mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom ),
34
    mFilterExp( filterExp )
35
{
36
  initFilter();
37
}
38

  
39
QgsRuleBasedRendererV2::Rule::Rule( const QgsRuleBasedRendererV2::Rule& other )
40
    : mSymbol( NULL )
41
{
42
  *this = other;
43
}
44

  
45
QgsRuleBasedRendererV2::Rule::~Rule()
46
{
47
  delete mSymbol;
48
}
49

  
50
void QgsRuleBasedRendererV2::Rule::initFilter()
51
{
52
  if ( !mFilterExp.isEmpty() )
53
  {
54
    mFilterParsed.setString( mFilterExp );
55
    mFilterTree = mFilterParsed.tree(); // may be NULL if there's no input
56
  }
57
  else
58
  {
59
    mFilterTree = NULL;
60
  }
61
}
62

  
63
QString QgsRuleBasedRendererV2::Rule::dump() const
64
{
65
  return QString( "RULE - scale [%1,%2] - filter %3 - symbol %4" )
66
         .arg( mScaleMinDenom ).arg( mScaleMaxDenom )
67
         .arg( mFilterExp ).arg( mSymbol->dump() );
68

  
69
}
70

  
71
QStringList QgsRuleBasedRendererV2::Rule::needsFields() const
72
{
73
  if ( ! mFilterTree )
74
    return QStringList();
75

  
76
  return mFilterTree->referencedColumns();
77
}
78

  
79
bool QgsRuleBasedRendererV2::Rule::isFilterOK( const QgsFieldMap& fields, QgsFeature& f ) const
80
{
81
  if ( ! mFilterTree )
82
    return true;
83

  
84
  bool res = mFilterTree->checkAgainst( fields, f.attributeMap() );
85
  //print "is_ok", res, feature.id(), feature.attributeMap()
86
  return res;
87
}
88

  
89
bool QgsRuleBasedRendererV2::Rule::isScaleOK( double scale ) const
90
{
91
  if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
92
    return true;
93
  if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
94
    return false;
95
  if ( mScaleMaxDenom != 0 && mScaleMaxDenom < scale )
96
    return false;
97
  return true;
98
}
99

  
100
QgsRuleBasedRendererV2::Rule& QgsRuleBasedRendererV2::Rule::operator=( const QgsRuleBasedRendererV2::Rule & other )
101
{
102
  if ( this != &other )
103
  {
104
    delete mSymbol;
105
    mSymbol = other.mSymbol->clone();
106

  
107
    mScaleMinDenom = other.mScaleMinDenom;
108
    mScaleMaxDenom = other.mScaleMaxDenom;
109
    mFilterExp = other.mFilterExp;
110
    initFilter();
111
  }
112
  return *this;
113
}
114

  
115
/////////////////////
116

  
117
QgsRuleBasedRendererV2::QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol )
118
    : QgsFeatureRendererV2( "RuleRenderer" )
119
{
120
  mDefaultSymbol = defaultSymbol;
121

  
122
  // add the default rule
123
  mRules << Rule( defaultSymbol->clone() );
124
}
125

  
126

  
127
QgsSymbolV2* QgsRuleBasedRendererV2::symbolForFeature( QgsFeature& feature )
128
{
129
  return mCurrentSymbol;
130
}
131

  
132
void QgsRuleBasedRendererV2::renderFeature( QgsFeature& feature,
133
    QgsRenderContext& context,
134
    int layer,
135
    bool selected,
136
    bool drawVertexMarker )
137
{
138
  for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
139
  {
140
    Rule* rule = *it;
141
    if ( rule->isFilterOK( mCurrentFields, feature ) )
142
    {
143
      mCurrentSymbol = rule->symbol();
144
      // will ask for mCurrentSymbol
145
      QgsFeatureRendererV2::renderFeature( feature, context, layer, selected, drawVertexMarker );
146
    }
147
  }
148
}
149

  
150

  
151
void QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
152
{
153
  double currentScale = context.rendererScale();
154
  // filter out rules which are not compatible with this scale
155

  
156
  mCurrentRules.clear();
157
  for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
158
  {
159
    Rule& rule = *it;
160
    if ( rule.isScaleOK( currentScale ) )
161
      mCurrentRules.append( &rule );
162
  }
163

  
164
  mCurrentFields = vlayer->pendingFields();
165

  
166
  for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
167
  {
168
    Rule* rule = *it;
169
    rule->symbol()->startRender( context );
170
  }
171
}
172

  
173
void QgsRuleBasedRendererV2::stopRender( QgsRenderContext& context )
174
{
175
  for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it != mCurrentRules.end(); ++it )
176
  {
177
    Rule* rule = *it;
178
    rule->symbol()->stopRender( context );
179
  }
180

  
181
  mCurrentRules.clear();
182
  mCurrentFields.clear();
183
}
184

  
185
QList<QString> QgsRuleBasedRendererV2::usedAttributes()
186
{
187
  QSet<QString> attrs;
188
  for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
189
  {
190
    Rule& rule = *it;
191
    attrs.unite( rule.needsFields().toSet() );
192
  }
193
  return attrs.values();
194
}
195

  
196
QgsFeatureRendererV2* QgsRuleBasedRendererV2::clone()
197
{
198
  QgsSymbolV2* s = mDefaultSymbol->clone();
199
  QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( s );
200
  r->mRules = mRules;
201
  return r;
202
}
203

  
204
QgsSymbolV2List QgsRuleBasedRendererV2::symbols()
205
{
206
  QgsSymbolV2List lst;
207
  for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++it )
208
  {
209
    Rule& rule = *it;
210
    lst.append( rule.symbol() );
211
  }
212

  
213
  return lst;
214
}
215

  
216
QDomElement QgsRuleBasedRendererV2::save( QDomDocument& doc )
217
{
218
  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
219
  rendererElem.setAttribute( "type", "RuleRenderer" );
220

  
221
  QDomElement rulesElem = doc.createElement( "rules" );
222

  
223
  QgsSymbolV2Map symbols;
224
  symbols["default"] = mDefaultSymbol;
225

  
226
  int i = 0;
227
  for ( QList<Rule>::iterator it = mRules.begin(); it != mRules.end(); ++i, ++it )
228
  {
229
    Rule& rule = *it;
230
    symbols[QString::number( i )] = rule.symbol();
231
    QDomElement ruleElem = doc.createElement( "rule" );
232
    ruleElem.setAttribute( "symbol", i );
233
    ruleElem.setAttribute( "filter", rule.filterExpression() );
234
    ruleElem.setAttribute( "scalemindenom", rule.scaleMinDenom() );
235
    ruleElem.setAttribute( "scalemaxdenom", rule.scaleMaxDenom() );
236
    rulesElem.appendChild( ruleElem );
237
  }
238
  rendererElem.appendChild( rulesElem );
239

  
240
  QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
241
  rendererElem.appendChild( symbolsElem );
242

  
243
  return rendererElem;
244
}
245

  
246

  
247
QgsFeatureRendererV2* QgsRuleBasedRendererV2::create( QDomElement& element )
248
{
249
  // load symbols
250
  QDomElement symbolsElem = element.firstChildElement( "symbols" );
251
  if ( symbolsElem.isNull() )
252
    return NULL;
253

  
254
  QgsSymbolV2Map symbolMap = QgsSymbolLayerV2Utils::loadSymbols( symbolsElem );
255

  
256
  if ( !symbolMap.contains( "default" ) )
257
  {
258
    QgsDebugMsg( "default symbol not found!" );
259
    return NULL;
260
  }
261

  
262
  QgsRuleBasedRendererV2* r = new QgsRuleBasedRendererV2( symbolMap.take( "default" ) );
263
  r->mRules.clear();
264

  
265
  QDomElement rulesElem = element.firstChildElement( "rules" );
266
  QDomElement ruleElem = rulesElem.firstChildElement( "rule" );
267
  while ( !ruleElem.isNull() )
268
  {
269
    QString symbolIdx = ruleElem.attribute( "symbol" );
270
    if ( symbolMap.contains( symbolIdx ) )
271
    {
272
      QString filterExp = ruleElem.attribute( "filter" );
273
      int scaleMinDenom = ruleElem.attribute( "scalemindenom", "0" ).toInt();
274
      int scaleMaxDenom = ruleElem.attribute( "scalemaxdenom", "0" ).toInt();
275
      r->mRules.append( Rule( symbolMap.take( symbolIdx ), scaleMinDenom, scaleMaxDenom, filterExp ) );
276
    }
277
    else
278
    {
279
      QgsDebugMsg( "symbol for rule " + symbolIdx + " not found! (skipping)" );
280
    }
281
    ruleElem = ruleElem.nextSiblingElement( "rule" );
282
  }
283

  
284
  // delete symbols if there are any more
285
  QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
286

  
287
  return r;
288
}
289

  
290

  
291
int QgsRuleBasedRendererV2::ruleCount()
292
{
293
  return mRules.count();
294
}
295

  
296
QgsRuleBasedRendererV2::Rule& QgsRuleBasedRendererV2::ruleAt( int index )
297
{
298
  return mRules[index];
299
}
300

  
301
void QgsRuleBasedRendererV2::addRule( const QgsRuleBasedRendererV2::Rule& rule )
302
{
303
  mRules.append( rule );
304
}
305

  
306
void QgsRuleBasedRendererV2::insertRule( int index, const QgsRuleBasedRendererV2::Rule& rule )
307
{
308
  mRules.insert( index, rule );
309
}
310

  
311
void QgsRuleBasedRendererV2::updateRuleAt( int index, const QgsRuleBasedRendererV2::Rule& rule )
312
{
313
  mRules[index] = rule;
314
}
315

  
316
void QgsRuleBasedRendererV2::removeRuleAt( int index )
317
{
318
  mRules.removeAt( index );
319
}
320

  
321
#include "qgscategorizedsymbolrendererv2.h"
322
#include "qgsgraduatedsymbolrendererv2.h"
323

  
324
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleCategories( QgsRuleBasedRendererV2::Rule& initialRule, QgsCategorizedSymbolRendererV2* r )
325
{
326
  QList<Rule> rules;
327
  foreach( const QgsRendererCategoryV2& cat, r->categories() )
328
  {
329
    QString newfilter = QString( "%1 = '%2'" ).arg( r->classAttribute() ).arg( cat.value().toString() );
330
    QString filter = initialRule.filterExpression();
331
    if ( filter.isEmpty() )
332
      filter = newfilter;
333
    else
334
      filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
335
    rules.append( Rule( cat.symbol()->clone(), initialRule.scaleMinDenom(), initialRule.scaleMaxDenom(), filter ) );
336
  }
337
  return rules;
338
}
339

  
340
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleRanges( QgsRuleBasedRendererV2::Rule& initialRule, QgsGraduatedSymbolRendererV2* r )
341
{
342
  QList<Rule> rules;
343
  foreach( const QgsRendererRangeV2& rng, r->ranges() )
344
  {
345
    QString newfilter = QString( "%1 >= '%2' AND %1 <= '%3'" ).arg( r->classAttribute() ).arg( rng.lowerValue() ).arg( rng.upperValue() );
346
    QString filter = initialRule.filterExpression();
347
    if ( filter.isEmpty() )
348
      filter = newfilter;
349
    else
350
      filter = QString( "(%1) AND (%2)" ).arg( filter ).arg( newfilter );
351
    rules.append( Rule( rng.symbol()->clone(), initialRule.scaleMinDenom(), initialRule.scaleMaxDenom(), filter ) );
352
  }
353
  return rules;
354
}
355

  
356
QList<QgsRuleBasedRendererV2::Rule> QgsRuleBasedRendererV2::refineRuleScales( QgsRuleBasedRendererV2::Rule& initialRule, QList<int> scales )
357
{
358
  QList<Rule> rules;
359
  int oldScale = 0;
360
  foreach( int scale, scales )
361
  {
362
    rules.append( Rule( initialRule.symbol()->clone(), oldScale, scale, initialRule.filterExpression() ) );
363
    oldScale = scale;
364
  }
365
  // last rule
366
  rules.append( Rule( initialRule.symbol()->clone(), oldScale, 0, initialRule.filterExpression() ) );
367
  return rules;
368
}
src/core/CMakeLists.txt (working copy)
32 32
  symbology-ng/qgssinglesymbolrendererv2.cpp
33 33
  symbology-ng/qgscategorizedsymbolrendererv2.cpp
34 34
  symbology-ng/qgsgraduatedsymbolrendererv2.cpp
35
  symbology-ng/qgsrulebasedrendererv2.cpp
35 36
  symbology-ng/qgsvectorcolorrampv2.cpp
36 37
  symbology-ng/qgsstylev2.cpp
37 38
  symbology-ng/qgssymbologyv2conversion.cpp
src/ui/qgsrulebasedrendererv2widget.ui (revision 0)
1
<?xml version="1.0" encoding="UTF-8"?>
2
<ui version="4.0">
3
 <class>QgsRuleBasedRendererV2Widget</class>
4
 <widget class="QWidget" name="QgsRuleBasedRendererV2Widget">
5
  <property name="geometry">
6
   <rect>
7
    <x>0</x>
8
    <y>0</y>
9
    <width>460</width>
10
    <height>221</height>
11
   </rect>
12
  </property>
13
  <property name="windowTitle">
14
   <string>Form</string>
15
  </property>
16
  <layout class="QGridLayout" name="gridLayout">
17
   <item row="0" column="0">
18
    <widget class="QLabel" name="label">
19
     <property name="text">
20
      <string>Rules:</string>
21
     </property>
22
    </widget>
23
   </item>
24
   <item row="1" column="0">
25
    <widget class="QgsRendererRulesTreeWidget" name="treeRules">
26
     <property name="rootIsDecorated">
27
      <bool>false</bool>
28
     </property>
29
     <property name="headerHidden">
30
      <bool>true</bool>
31
     </property>
32
     <column>
33
      <property name="text">
34
       <string>Rule</string>
35
      </property>
36
     </column>
37
    </widget>
38
   </item>
39
   <item row="1" column="1">
40
    <layout class="QVBoxLayout" name="verticalLayout">
41
     <item>
42
      <widget class="QPushButton" name="btnAddRule">
43
       <property name="text">
44
        <string>Add</string>
45
       </property>
46
      </widget>
47
     </item>
48
     <item>
49
      <widget class="QPushButton" name="btnRefineRule">
50
       <property name="text">
51
        <string>Refine</string>
52
       </property>
53
      </widget>
54
     </item>
55
     <item>
56
      <widget class="QPushButton" name="btnEditRule">
57
       <property name="text">
58
        <string>Edit</string>
59
       </property>
60
      </widget>
61
     </item>
62
     <item>
63
      <widget class="QPushButton" name="btnRemoveRule">
64
       <property name="text">
65
        <string>Remove</string>
66
       </property>
67
      </widget>
68
     </item>
69
    </layout>
70
   </item>
71
   <item row="2" column="0" colspan="2">
72
    <widget class="QGroupBox" name="groupBox">
73
     <property name="title">
74
      <string>Rule grouping</string>
75
     </property>
76
     <layout class="QHBoxLayout" name="horizontalLayout">
77
      <item>
78
       <widget class="QRadioButton" name="radNoGrouping">
79
        <property name="text">
80
         <string>No grouping</string>
81
        </property>
82
        <property name="checked">
83
         <bool>true</bool>
84
        </property>
85
       </widget>
86
      </item>
87
      <item>
88
       <widget class="QRadioButton" name="radGroupFilter">
89
        <property name="text">
90
         <string>Group by filter</string>
91
        </property>
92
       </widget>
93
      </item>
94
      <item>
95
       <widget class="QRadioButton" name="radGroupScale">
96
        <property name="text">
97
         <string>Group by scale</string>
98
        </property>
99
       </widget>
100
      </item>
101
     </layout>
102
    </widget>
103
   </item>
104
  </layout>
105
 </widget>
106
 <customwidgets>
107
  <customwidget>
108
   <class>QgsRendererRulesTreeWidget</class>
109
   <extends>QTreeWidget</extends>
110
   <header>qgsrulebasedrendererv2widget.h</header>
111
  </customwidget>
112
 </customwidgets>
113
 <resources/>
114
 <connections/>
115
</ui>
src/ui/qgsrendererrulepropsdialogbase.ui (revision 0)
1
<?xml version="1.0" encoding="UTF-8"?>
2
<ui version="4.0">
3
 <class>QgsRendererRulePropsDialog</class>
4
 <widget class="QDialog" name="QgsRendererRulePropsDialog">
5
  <property name="geometry">
6
   <rect>
7
    <x>0</x>
8
    <y>0</y>
9
    <width>547</width>
10
    <height>300</height>
11
   </rect>
12
  </property>
13
  <property name="windowTitle">
14
   <string>Rule properties</string>
15
  </property>
16
  <layout class="QVBoxLayout" name="verticalLayout">
17
   <item>
18
    <layout class="QHBoxLayout" name="horizontalLayout">
19
     <item>
20
      <widget class="QLabel" name="label">
21
       <property name="text">
22
        <string>Filter</string>
23
       </property>
24
      </widget>
25
     </item>
26
     <item>
27
      <widget class="QLineEdit" name="editFilter"/>
28
     </item>
29
     <item>
30
      <widget class="QPushButton" name="btnTestFilter">
31
       <property name="text">
32
        <string>Test</string>
33
       </property>
34
      </widget>
35
     </item>
36
    </layout>
37
   </item>
38
   <item>
39
    <widget class="QGroupBox" name="groupScale">
40
     <property name="title">
41
      <string>Scale range</string>
42
     </property>
43
     <property name="checkable">
44
      <bool>true</bool>
45
     </property>
46
     <property name="checked">
47
      <bool>false</bool>
48
     </property>
49
     <layout class="QHBoxLayout" name="horizontalLayout_2">
50
      <item>
51
       <widget class="QLabel" name="label_2">
52
        <property name="text">
53
         <string>Min. scale</string>
54
        </property>
55
        <property name="alignment">
56
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
57
        </property>
58
       </widget>
59
      </item>
60
      <item>
61
       <widget class="QSpinBox" name="spinMinScale">
62
        <property name="prefix">
63
         <string>1 : </string>
64
        </property>
65
        <property name="minimum">
66
         <number>0</number>
67
        </property>
68
        <property name="maximum">
69
         <number>1000000000</number>
70
        </property>
71
        <property name="singleStep">
72
         <number>1000</number>
73
        </property>
74
        <property name="value">
75
         <number>1000</number>
76
        </property>
77
       </widget>
78
      </item>
79
      <item>
80
       <widget class="QLabel" name="label_3">
81
        <property name="text">
82
         <string>Max. scale</string>
83
        </property>
84
        <property name="alignment">
85
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
86
        </property>
87
       </widget>
88
      </item>
89
      <item>
90
       <widget class="QSpinBox" name="spinMaxScale">
91
        <property name="prefix">
92
         <string>1 : </string>
93
        </property>
94
        <property name="minimum">
95
         <number>0</number>
96
        </property>
97
        <property name="maximum">
98
         <number>1000000000</number>
99
        </property>
100
        <property name="singleStep">
101
         <number>1000</number>
102
        </property>
103
        <property name="value">
104
         <number>1000</number>
105
        </property>
106
       </widget>
107
      </item>
108
     </layout>
109
    </widget>
110
   </item>
111
   <item>
112
    <widget class="QGroupBox" name="groupSymbol">
113
     <property name="sizePolicy">
114
      <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
115
       <horstretch>0</horstretch>
116
       <verstretch>0</verstretch>
117
      </sizepolicy>
118
     </property>
119
     <property name="title">
120
      <string>Symbol</string>
121
     </property>
122
    </widget>
123
   </item>
124
   <item>
125
    <widget class="QDialogButtonBox" name="buttonBox">
126
     <property name="orientation">
127
      <enum>Qt::Horizontal</enum>
128
     </property>
129
     <property name="standardButtons">
130
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
131
     </property>
132
    </widget>
133
   </item>
... This diff was truncated because it exceeds the maximum size that can be displayed.