QGIS API Documentation  3.0.2-Girona (307d082)
qgsvaluerelationsearchwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvaluerelationsearchwidgetwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis 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 "qgsfields.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsfilterlineedit.h"
23 #include "qgssettings.h"
24 
25 #include <QStringListModel>
26 #include <QCompleter>
27 
29  : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
30 
31 {
32 }
33 
35 {
36  return !mLineEdit;
37 }
38 
40 {
41  return mExpression;
42 }
43 
45 {
46  QVariant v;
47 
48  if ( mComboBox )
49  {
50  int cbxIdx = mComboBox->currentIndex();
51  if ( cbxIdx > -1 )
52  {
53  v = mComboBox->currentData();
54  }
55  }
56 
57  if ( mListWidget )
58  {
59  QStringList selection;
60  for ( int i = 0; i < mListWidget->count(); ++i )
61  {
62  QListWidgetItem *item = mListWidget->item( i );
63  if ( item->checkState() == Qt::Checked )
64  selection << item->data( Qt::UserRole ).toString();
65  }
66 
67  v = selection.join( QStringLiteral( "," ) ).prepend( '{' ).append( '}' );
68  }
69 
70  if ( mLineEdit )
71  {
72  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &i, mCache )
73  {
74  if ( i.value == mLineEdit->text() )
75  {
76  v = i.key;
77  break;
78  }
79  }
80  }
81 
82  return v;
83 }
84 
85 QgsSearchWidgetWrapper::FilterFlags QgsValueRelationSearchWidgetWrapper::supportedFlags() const
86 {
87  return EqualTo | NotEqualTo | IsNull | IsNotNull;
88 }
89 
90 QgsSearchWidgetWrapper::FilterFlags QgsValueRelationSearchWidgetWrapper::defaultFlags() const
91 {
92  return EqualTo;
93 }
94 
95 QString QgsValueRelationSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
96 {
97  QString fieldName = createFieldIdentifier();
98 
99  //clear any unsupported flags
100  flags &= supportedFlags();
101  if ( flags & IsNull )
102  return fieldName + " IS NULL";
103  if ( flags & IsNotNull )
104  return fieldName + " IS NOT NULL";
105 
106  QVariant v = value();
107  if ( !v.isValid() )
108  return QString();
109 
110  switch ( v.type() )
111  {
112  case QVariant::Int:
113  case QVariant::UInt:
114  case QVariant::Double:
115  case QVariant::LongLong:
116  case QVariant::ULongLong:
117  {
118  if ( flags & EqualTo )
119  return fieldName + '=' + v.toString();
120  else if ( flags & NotEqualTo )
121  return fieldName + "<>" + v.toString();
122  break;
123  }
124 
125  default:
126  {
127  if ( flags & EqualTo )
128  return fieldName + "='" + v.toString() + '\'';
129  else if ( flags & NotEqualTo )
130  return fieldName + "<>'" + v.toString() + '\'';
131  break;
132  }
133  }
134 
135  return QString();
136 }
137 
139 {
140  if ( mComboBox )
141  {
142  mComboBox->setCurrentIndex( 0 );
143  }
144  if ( mListWidget )
145  {
146  mListWidget->clearSelection();
147  }
148  if ( mLineEdit )
149  {
150  mLineEdit->setText( QString() );
151  }
152 }
153 
155 {
156  if ( mComboBox )
157  {
158  mComboBox->setEnabled( enabled );
159  }
160  if ( mListWidget )
161  {
162  mListWidget->setEnabled( enabled );
163  }
164  if ( mLineEdit )
165  {
166  mLineEdit->setEnabled( enabled );
167  }
168 }
169 
171 {
172  return true;
173 }
174 
176 {
177  QVariant vl = value();
178  if ( !vl.isValid() )
179  {
180  clearExpression();
181  emit valueCleared();
182  }
183  else
184  {
185  QgsSettings settings;
186  setExpression( vl.isNull() ? QgsApplication::nullRepresentation() : vl.toString() );
187  emit valueChanged();
188  }
190 }
191 
193 {
194  QString exp = expression;
195  QString nullValue = QgsApplication::nullRepresentation();
196  QString fieldName = layer()->fields().at( mFieldIdx ).name();
197 
198  QString str;
199  if ( exp == nullValue )
200  {
201  str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
202  }
203  else
204  {
205  str = QStringLiteral( "%1 = '%3'" )
206  .arg( QgsExpression::quotedColumnRef( fieldName ),
207  exp.replace( '\'', QLatin1String( "''" ) )
208  );
209  }
210  mExpression = str;
211 }
212 
214 {
215  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
216  {
217  return new QgsFilterLineEdit( parent );
218  }
219  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
220  {
221  return new QgsFilterLineEdit( parent );
222  }
223  else
224  {
225  return new QComboBox( parent );
226  }
227 }
228 
230 {
232 
233  mComboBox = qobject_cast<QComboBox *>( editor );
234  mListWidget = qobject_cast<QListWidget *>( editor );
235  mLineEdit = qobject_cast<QLineEdit *>( editor );
236 
237  if ( mComboBox )
238  {
239  mComboBox->addItem( tr( "Please select" ), QVariant() ); // creates an invalid to allow selecting all features
240  if ( config( QStringLiteral( "AllowNull" ) ).toBool() )
241  {
242  mComboBox->addItem( tr( "(no selection)" ), QVariant( layer()->fields().at( mFieldIdx ).type() ) );
243  }
244 
245  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
246  {
247  mComboBox->addItem( element.value, element.key );
248  }
249 
250  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsValueRelationSearchWidgetWrapper::onValueChanged );
251  }
252  else if ( mListWidget )
253  {
254  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &element, mCache )
255  {
256  QListWidgetItem *item = nullptr;
257  item = new QListWidgetItem( element.value );
258  item->setData( Qt::UserRole, element.key );
259 
260  mListWidget->addItem( item );
261  }
262  connect( mListWidget, &QListWidget::itemChanged, this, &QgsValueRelationSearchWidgetWrapper::onValueChanged );
263  }
264  else if ( mLineEdit )
265  {
266  QStringList values;
267  values.reserve( mCache.size() );
268  Q_FOREACH ( const QgsValueRelationFieldFormatter::ValueRelationItem &i, mCache )
269  {
270  values << i.value;
271  }
272 
273  QStringListModel *m = new QStringListModel( values, mLineEdit );
274  QCompleter *completer = new QCompleter( m, mLineEdit );
275  completer->setCaseSensitivity( Qt::CaseInsensitive );
276  mLineEdit->setCompleter( completer );
277  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsValueRelationSearchWidgetWrapper::onValueChanged );
278  }
279 }
280 
281 
QgsValueRelationSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsValueRelationSearchWidgetWrapper.
Shows a search widget on a filter form.
QString name
Definition: qgsfield.h:57
This class is a composition of two QSettings instances:
Definition: qgssettings.h:57
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
bool valid() const override
Return true if the widget has been properly initialized.
Supports searching for non-null values.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
void clearExpression()
clears the expression to search for all features
QVariantMap config() const
Returns the whole config.
QString createFieldIdentifier() const
Get a field name or expression to use as field comparison.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes...
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:145
Supports searching for null values.
QgsFields fields() const override
Returns the list of fields of this layer.
void valueChanged()
Emitted when a user changes the value of the search widget.
void onValueChanged()
Called when current value of search widget changes.
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void expressionChanged(const QString &exp)
Emitted whenever the expression changes.
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
QgsSearchWidgetWrapper::FilterFlags defaultFlags() const override
Returns the filter flags which should be set by default for the search widget.
void valueCleared()
Emitted when a user changes the value of the search widget back to an empty, default state...
QgsVectorLayer * layer() const
Access the QgsVectorLayer, you are working on.
Represents a vector layer which manages a vector based data sets.
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
QString expression() const override
Will be used to access the widget&#39;s value.