QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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  , mComboBox( NULL )
51  , mListWidget( NULL )
52  , mLayer( NULL )
53 {
54 }
55 
56 
58 {
59  QVariant v;
60 
61  if ( mComboBox )
62  {
63  int cbxIdx = mComboBox->currentIndex();
64  if ( cbxIdx > -1 )
65  {
66  v = mComboBox->itemData( mComboBox->currentIndex() );
67  }
68  }
69 
70  if ( mListWidget )
71  {
72  QStringList selection;
73  for ( int i = 0; i < mListWidget->count(); ++i )
74  {
75  QListWidgetItem* item = mListWidget->item( i );
76  if ( item->checkState() == Qt::Checked )
77  selection << item->data( Qt::UserRole ).toString();
78  }
79 
80  v = selection.join( "," ).prepend( "{" ).append( "}" );
81  }
82 
83  return v;
84 }
85 
87 {
88  if ( config( "AllowMulti" ).toBool() )
89  {
90  return new QListWidget( parent );
91  }
92  else
93  {
94  return new QComboBox( parent );
95  }
96 }
97 
99 {
100  mCache = createCache( config() );
101 
102  mComboBox = qobject_cast<QComboBox*>( editor );
103  mListWidget = qobject_cast<QListWidget*>( editor );
104 
105  if ( mComboBox )
106  {
107  if ( config( "AllowNull" ).toBool() )
108  {
109  mComboBox->addItem( tr( "(no selection)" ), QVariant( field().type() ) );
110  }
111 
112  Q_FOREACH ( const ValueRelationItem& element, mCache )
113  {
114  mComboBox->addItem( element.second, element.first );
115  }
116 
117  connect( mComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( valueChanged() ) );
118  }
119  else if ( mListWidget )
120  {
121  Q_FOREACH ( const ValueRelationItem& element, mCache )
122  {
123  QListWidgetItem *item;
124  item = new QListWidgetItem( element.second );
125  item->setData( Qt::UserRole, element.first );
126 
127  mListWidget->addItem( item );
128  }
129  connect( mListWidget, SIGNAL( itemChanged( QListWidgetItem* ) ), this, SLOT( valueChanged() ) );
130  }
131 }
132 
133 void QgsValueRelationWidgetWrapper::setValue( const QVariant& value )
134 {
135  if ( mListWidget )
136  {
137  QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," );
138 
139  for ( int i = 0; i < mListWidget->count(); ++i )
140  {
141  QListWidgetItem* item = mListWidget->item( i );
142  if ( config( "OrderByValue" ).toBool() )
143  {
144  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
145  }
146  else
147  {
148  item->setCheckState( checkList.contains( item->data( Qt::UserRole ).toString() ) ? Qt::Checked : Qt::Unchecked );
149  }
150  }
151  }
152  else if ( mComboBox )
153  {
154  mComboBox->setCurrentIndex( mComboBox->findData( value ) );
155  }
156 }
157 
158 
160 {
161  ValueRelationCache cache;
162 
163  QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( config.value( "Layer" ).toString() ) );
164 
165  if ( layer )
166  {
167  int ki = layer->fieldNameIndex( config.value( "Key" ).toString() );
168  int vi = layer->fieldNameIndex( config.value( "Value" ).toString() );
169 
170  QgsExpression *e = 0;
171  if ( !config.value( "FilterExpression" ).toString().isEmpty() )
172  {
173  e = new QgsExpression( config.value( "FilterExpression" ).toString() );
174  if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
175  ki = -1;
176  }
177 
178  if ( ki >= 0 && vi >= 0 )
179  {
180  QSet<int> attributes;
181  attributes << ki << vi;
182 
183  QgsFeatureRequest::Flags flags = QgsFeatureRequest::NoGeometry;
184 
185  bool requiresAllAttributes = false;
186  if ( e )
187  {
188  if ( e->needsGeometry() )
190 
191  Q_FOREACH ( const QString& field, e->referencedColumns() )
192  {
193  if ( field == QgsFeatureRequest::AllAttributes )
194  {
195  requiresAllAttributes = true;
196  break;
197  }
198  int idx = layer->fieldNameIndex( field );
199  if ( idx < 0 )
200  continue;
201  attributes << idx;
202  }
203  }
204 
206  if ( !requiresAllAttributes )
207  {
208  fr.setSubsetOfAttributes( attributes.toList() );
209  }
210 
211  QgsFeatureIterator fit = layer->getFeatures( fr );
212 
213  QgsFeature f;
214  while ( fit.nextFeature( f ) )
215  {
216  if ( e && !e->evaluate( &f ).toBool() )
217  continue;
218 
219  cache.append( ValueRelationItem( f.attribute( ki ), f.attribute( vi ).toString() ) );
220  }
221  }
222  delete e;
223  }
224 
225  if ( config.value( "OrderByValue" ).toBool() )
226  {
227  qSort( cache.begin(), cache.end(), orderByValueLessThan );
228  }
229  else
230  {
231  qSort( cache.begin(), cache.end(), orderByKeyLessThan );
232  }
233 
234  return cache;
235 }