QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsvaluerelationwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvaluerelationwidgetwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias dot kuhn at gmx dot ch
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 "qgsfield.h"
19 #include "qgsmaplayerregistry.h"
21 #include "qgsvectorlayer.h"
22 
25 {
26  switch ( p1.first.type() )
27  {
28  case QVariant::String:
29  return p1.first.toString() < p2.first.toString();
30  break;
31 
32  case QVariant::Double:
33  return p1.first.toDouble() < p2.first.toDouble();
34  break;
35 
36  default:
37  return p1.first.toInt() < p2.first.toInt();
38  break;
39  }
40 }
41 
44 {
45  return p1.second < p2.second;
46 }
47 
48 QgsValueRelationWidgetWrapper::QgsValueRelationWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent )
49  : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
50 {
51 }
52 
53 
55 {
56  QVariant v;
57 
58  if ( mComboBox )
59  {
60  int cbxIdx = mComboBox->currentIndex();
61  if ( cbxIdx > -1 )
62  {
63  v = mComboBox->itemData( mComboBox->currentIndex() );
64  }
65  }
66 
67  if ( mListWidget )
68  {
69  QStringList selection;
70  for ( int i = 0; i < mListWidget->count(); ++i )
71  {
72  QListWidgetItem* item = mListWidget->item( i );
73  if ( item->checkState() == Qt::Checked )
74  selection << item->data( Qt::UserRole ).toString();
75  }
76 
77  v = selection.join( "," ).prepend( "{" ).append( "}" );
78  }
79 
80  return v;
81 }
82 
84 {
85  if ( config( "AllowMulti" ).toBool() )
86  {
87  return new QListWidget( parent );
88  }
89  else
90  {
91  return new QComboBox( parent );
92  }
93 }
94 
96 {
97  mCache = createCache( config() );
98 
99  mComboBox = qobject_cast<QComboBox*>( editor );
100  mListWidget = qobject_cast<QListWidget*>( editor );
101 
102  if ( mComboBox )
103  {
104  if ( config( "AllowNull" ).toBool() )
105  {
106  mComboBox->addItem( tr( "(no selection)" ), QVariant( field().type() ) );
107  }
108 
109  Q_FOREACH ( const ValueRelationItem& element, mCache )
110  {
111  mComboBox->addItem( element.second, element.first );
112  }
113 
114  connect( mComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( valueChanged() ) );
115  }
116  else if ( mListWidget )
117  {
118  Q_FOREACH ( const ValueRelationItem& element, mCache )
119  {
120  QListWidgetItem *item;
121  item = new QListWidgetItem( element.second );
122  item->setData( Qt::UserRole, element.first );
123 
124  mListWidget->addItem( item );
125  }
126  connect( mListWidget, SIGNAL( itemChanged( QListWidgetItem* ) ), this, SLOT( valueChanged() ) );
127  }
128 }
129 
130 void QgsValueRelationWidgetWrapper::setValue( const QVariant& value )
131 {
132  if ( mListWidget )
133  {
134  QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," );
135 
136  for ( int i = 0; i < mListWidget->count(); ++i )
137  {
138  QListWidgetItem* item = mListWidget->item( i );
139  if ( config( "OrderByValue" ).toBool() )
140  {
141  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
142  }
143  else
144  {
145  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
146  }
147  }
148  }
149  else if ( mComboBox )
150  {
151  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
152  }
153 }
154 
155 
157 {
158  ValueRelationCache cache;
159 
160  QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( config.value( "Layer" ).toString() ) );
161 
162  if ( layer )
163  {
164  int ki = layer->fieldNameIndex( config.value( "Key" ).toString() );
165  int vi = layer->fieldNameIndex( config.value( "Value" ).toString() );
166 
167  QgsExpression *e = 0;
168  if ( !config.value( "FilterExpression" ).toString().isEmpty() )
169  {
170  e = new QgsExpression( config.value( "FilterExpression" ).toString() );
171  if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
172  ki = -1;
173  }
174 
175  if ( ki >= 0 && vi >= 0 )
176  {
177  QSet<int> attributes;
178  attributes << ki << vi;
179 
180  QgsFeatureRequest::Flags flags = QgsFeatureRequest::NoGeometry;
181 
182  bool requiresAllAttributes = false;
183  if ( e )
184  {
185  if ( e->needsGeometry() )
187 
188  Q_FOREACH ( const QString& field, e->referencedColumns() )
189  {
190  if ( field == QgsFeatureRequest::AllAttributes )
191  {
192  requiresAllAttributes = true;
193  break;
194  }
195  int idx = layer->fieldNameIndex( field );
196  if ( idx < 0 )
197  continue;
198  attributes << idx;
199  }
200  }
201 
203  if ( !requiresAllAttributes )
204  {
205  fr.setSubsetOfAttributes( attributes.toList() );
206  }
207 
208  QgsFeatureIterator fit = layer->getFeatures( fr );
209 
210  QgsFeature f;
211  while ( fit.nextFeature( f ) )
212  {
213  if ( e && !e->evaluate( &f ).toBool() )
214  continue;
215 
216  cache.append( ValueRelationItem( f.attribute( ki ), f.attribute( vi ).toString() ) );
217  }
218  }
219  }
220 
221  if ( config.value( "OrderByValue" ).toBool() )
222  {
223  qSort( cache.begin(), cache.end(), orderByValueLessThan );
224  }
225  else
226  {
227  qSort( cache.begin(), cache.end(), orderByKeyLessThan );
228  }
229 
230  return cache;
231 }
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
Wrapper for iterator of features from vector data provider or vector layer.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:94
QStringList referencedColumns() const
Get list of columns referenced by the expression.
QVariant value()
Will be used to access the widget's value.
void valueChanged()
Will call the value() method to determine the emitted value.
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
Manages an editor widget Widget and wrapper share the same parent.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsVectorLayer * layer()
Access the QgsVectorLayer, you are working on.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QgsValueRelationWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor=0, QWidget *parent=0)
QgsField field()
Access the field.
bool orderByValueLessThan(const QgsValueRelationWidgetWrapper::ValueRelationItem &p1, const QgsValueRelationWidgetWrapper::ValueRelationItem &p2)
QWidget * createWidget(QWidget *parent)
This method should create a new widget with the provided parent.
QPair< QVariant, QString > ValueRelationItem
const QgsEditorWidgetConfig config()
Returns the whole config.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
bool orderByKeyLessThan(const QgsValueRelationWidgetWrapper::ValueRelationItem &p1, const QgsValueRelationWidgetWrapper::ValueRelationItem &p2)
static const QString AllAttributes
static ValueRelationCache createCache(const QgsEditorWidgetConfig &config)
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
void initWidget(QWidget *editor)
This method should initialize the editor widget with runtime data.
QMap< QString, QVariant > QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
QVector< ValueRelationItem > ValueRelationCache
#define tr(sourceText)