QGIS API Documentation  3.23.0-Master (22c16f2067)
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 #include "qgsapplication.h"
25 
26 #include <QStringListModel>
27 #include <QCompleter>
28 
30  : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
31 
32 {
33 }
34 
36 {
37  return !mLineEdit;
38 }
39 
41 {
42  return mExpression;
43 }
44 
46 {
47  QVariant v;
48 
49  if ( mComboBox )
50  {
51  int cbxIdx = mComboBox->currentIndex();
52  if ( cbxIdx > -1 )
53  {
54  v = mComboBox->currentData();
55  }
56  }
57 
58  if ( mLineEdit )
59  {
60  const auto constMCache = mCache;
61  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &i : constMCache )
62  {
63  if ( i.value == mLineEdit->text() )
64  {
65  v = i.key;
66  break;
67  }
68  }
69  }
70 
71  return v;
72 }
73 
74 QgsSearchWidgetWrapper::FilterFlags QgsValueRelationSearchWidgetWrapper::supportedFlags() const
75 {
76  return EqualTo | NotEqualTo | IsNull | IsNotNull;
77 }
78 
79 QgsSearchWidgetWrapper::FilterFlags QgsValueRelationSearchWidgetWrapper::defaultFlags() const
80 {
81  return EqualTo;
82 }
83 
84 QString QgsValueRelationSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
85 {
86  QString fieldName = createFieldIdentifier();
87 
88  //clear any unsupported flags
89  flags &= supportedFlags();
90  if ( flags & IsNull )
91  return fieldName + " IS NULL";
92  if ( flags & IsNotNull )
93  return fieldName + " IS NOT NULL";
94 
95  QVariant v = value();
96  if ( !v.isValid() )
97  return QString();
98 
99  switch ( v.type() )
100  {
101  case QVariant::Int:
102  case QVariant::UInt:
103  case QVariant::Double:
104  case QVariant::LongLong:
105  case QVariant::ULongLong:
106  {
107  if ( flags & EqualTo )
108  return fieldName + '=' + v.toString();
109  else if ( flags & NotEqualTo )
110  return fieldName + "<>" + v.toString();
111  break;
112  }
113 
114  default:
115  {
116  if ( flags & EqualTo )
117  return fieldName + "='" + v.toString() + '\'';
118  else if ( flags & NotEqualTo )
119  return fieldName + "<>'" + v.toString() + '\'';
120  break;
121  }
122  }
123 
124  return QString();
125 }
126 
128 {
129  if ( mComboBox )
130  {
131  mComboBox->setCurrentIndex( 0 );
132  }
133  if ( mLineEdit )
134  {
135  mLineEdit->setText( QString() );
136  }
137 }
138 
140 {
141  if ( mComboBox )
142  {
143  mComboBox->setEnabled( enabled );
144  }
145  if ( mLineEdit )
146  {
147  mLineEdit->setEnabled( enabled );
148  }
149 }
150 
152 {
153  return true;
154 }
155 
157 {
158  QVariant vl = value();
159  if ( !vl.isValid() )
160  {
161  clearExpression();
162  emit valueCleared();
163  }
164  else
165  {
166  setExpression( vl.isNull() ? QgsApplication::nullRepresentation() : vl.toString() );
167  emit valueChanged();
168  }
170 }
171 
172 void QgsValueRelationSearchWidgetWrapper::setExpression( const QString &expression )
173 {
174  QString exp = expression;
175  QString nullValue = QgsApplication::nullRepresentation();
176  QString fieldName = layer()->fields().at( mFieldIdx ).name();
177 
178  QString str;
179  if ( exp == nullValue )
180  {
181  str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
182  }
183  else
184  {
185  str = QStringLiteral( "%1 = '%3'" )
186  .arg( QgsExpression::quotedColumnRef( fieldName ),
187  exp.replace( '\'', QLatin1String( "''" ) )
188  );
189  }
190  mExpression = str;
191 }
192 
194 {
195  if ( config( QStringLiteral( "AllowMulti" ) ).toBool() )
196  {
197  return new QgsFilterLineEdit( parent );
198  }
199  else if ( config( QStringLiteral( "UseCompleter" ) ).toBool() )
200  {
201  return new QgsFilterLineEdit( parent );
202  }
203  else
204  {
205  return new QComboBox( parent );
206  }
207 }
208 
210 {
212 
213  mComboBox = qobject_cast<QComboBox *>( editor );
214  mLineEdit = qobject_cast<QLineEdit *>( editor );
215 
216  if ( mComboBox )
217  {
218  mComboBox->addItem( tr( "Please Select" ), QVariant() ); // creates an invalid to allow selecting all features
219  if ( config( QStringLiteral( "AllowNull" ) ).toBool() )
220  {
221  mComboBox->addItem( tr( "(no selection)" ), QVariant( layer()->fields().at( mFieldIdx ).type() ) );
222  }
223 
224  const auto constMCache = mCache;
225  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &element : constMCache )
226  {
227  mComboBox->addItem( element.value, element.key );
228  }
229 
230  connect( mComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsValueRelationSearchWidgetWrapper::onValueChanged );
231  }
232  else if ( mLineEdit )
233  {
234  QStringList values;
235  values.reserve( mCache.size() );
236  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &i : std::as_const( mCache ) )
237  {
238  values << i.value;
239  }
240 
241  QStringListModel *m = new QStringListModel( values, mLineEdit );
242  QCompleter *completer = new QCompleter( m, mLineEdit );
243  completer->setCaseSensitivity( Qt::CaseInsensitive );
244  mLineEdit->setCompleter( completer );
245  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsValueRelationSearchWidgetWrapper::onValueChanged );
246  }
247 }
248 
249 
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QString name
Definition: qgsfield.h:60
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Shows a search widget on a filter form.
@ IsNull
Supports searching for null values.
@ IsNotNull
Supports searching for non-null values.
@ EqualTo
Supports equal to.
@ NotEqualTo
Supports not equal to.
void valueChanged()
Emitted when a user changes the value of the search widget.
void valueCleared()
Emitted when a user changes the value of the search widget back to an empty, default state.
void expressionChanged(const QString &exp)
Emitted whenever the expression changes.
QString createFieldIdentifier() const
Gets a field name or expression to use as field comparison.
void clearExpression()
clears the expression to search for all features
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QgsValueRelationSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsValueRelationSearchWidgetWrapper.
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
QString expression() const override
Will be used to access the widget's value.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QgsSearchWidgetWrapper::FilterFlags defaultFlags() const override
Returns the filter flags which should be set by default for the search widget.
bool valid() const override
Returns true if the widget has been properly initialized.
void onValueChanged()
Called when current value of search widget changes.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
QVariantMap config() const
Returns the whole config.
#define str(x)
Definition: qgis.cpp:37