QGIS API Documentation  3.23.0-Master (dd0cd13a00)
qgsdefaultsearchwidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdefaultsearchwidgettwrapper.cpp
3  --------------------------------------
4  Date : 31.5.2015
5  Copyright : (C) 2015 Karolina Alexiou (carolinux)
6  Email : carolinegr at gmail dot 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 
17 
18 #include "qgsfields.h"
19 #include "qgsfieldvalidator.h"
20 #include "qgsexpression.h"
21 #include "qgsfieldvalueslineedit.h"
22 #include "qgssettings.h"
23 #include "qgsapplication.h"
24 
25 #include <QHBoxLayout>
26 
28  : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
29  , mCaseString( QStringLiteral( "LIKE" ) )
30 {
31 }
32 
34 {
35  return mExpression;
36 }
37 
38 void QgsDefaultSearchWidgetWrapper::setCaseString( int caseSensitiveCheckState )
39 {
40  if ( caseSensitiveCheckState == Qt::Checked )
41  {
42  mCaseString = QStringLiteral( "LIKE" );
43  }
44  else
45  {
46  mCaseString = QStringLiteral( "ILIKE" );
47  }
48  // need to update also the line edit
49  setExpression( mLineEdit->text() );
50 
51  if ( applyDirectly() )
53 }
54 
55 void QgsDefaultSearchWidgetWrapper::setExpression( const QString &expression )
56 {
57  const QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
58  const bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
59 
60  QString exp = expression;
61  const QString nullValue = QgsApplication::nullRepresentation();
62  const QString fieldName = layer()->fields().at( mFieldIdx ).name();
63  QString str;
64  if ( exp == nullValue )
65  {
66  str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
67  }
68  else
69  {
70  str = QStringLiteral( "%1 %2 '%3'" )
71  .arg( QgsExpression::quotedColumnRef( fieldName ),
72  numeric ? QStringLiteral( "=" ) : mCaseString,
73  numeric ?
74  exp.replace( '\'', QLatin1String( "''" ) )
75  :
76  '%' + exp.replace( '\'', QLatin1String( "''" ) ) + '%' ); // escape quotes
77  }
78  mExpression = str;
79 }
80 
82 {
83  return new QWidget( parent );
84 }
85 
87 {
88  return false;
89 }
90 
91 QgsSearchWidgetWrapper::FilterFlags QgsDefaultSearchWidgetWrapper::supportedFlags() const
92 {
93  FilterFlags flags = EqualTo | NotEqualTo | IsNull | IsNotNull;
94 
95  const QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
96  switch ( fldType )
97  {
98  case QVariant::Int:
99  case QVariant::UInt:
100  case QVariant::Double:
101  case QVariant::LongLong:
102  case QVariant::ULongLong:
103  case QVariant::Date:
104  case QVariant::DateTime:
105  case QVariant::Time:
107  break;
108 
109  case QVariant::String:
111  break;
112 
113  default:
114  break;
115  }
116  return flags;
117 }
118 
119 QgsSearchWidgetWrapper::FilterFlags QgsDefaultSearchWidgetWrapper::defaultFlags() const
120 {
121  const QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
122  switch ( fldType )
123  {
124  case QVariant::Int:
125  case QVariant::UInt:
126  case QVariant::Double:
127  case QVariant::LongLong:
128  case QVariant::ULongLong:
129  //numeric
130  return EqualTo;
131 
132  case QVariant::Date:
133  case QVariant::DateTime:
134  case QVariant::Time:
135  return EqualTo;
136 
137  case QVariant::String:
138  return Contains;
139 
140  default:
141  break;
142  }
143  return EqualTo;
144 }
145 
146 QString QgsDefaultSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
147 {
148  //clear any unsupported flags
149  flags &= supportedFlags();
150 
151  const QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
152  const QString fieldName = createFieldIdentifier();
153 
154  if ( flags & IsNull )
155  return fieldName + " IS NULL";
156  if ( flags & IsNotNull )
157  return fieldName + " IS NOT NULL";
158 
159  switch ( fldType )
160  {
161  case QVariant::Int:
162  case QVariant::UInt:
163  case QVariant::Double:
164  case QVariant::LongLong:
165  case QVariant::ULongLong:
166  {
167  if ( flags & EqualTo )
168  return fieldName + '=' + mLineEdit->text();
169  else if ( flags & NotEqualTo )
170  return fieldName + "<>" + mLineEdit->text();
171  else if ( flags & GreaterThan )
172  return fieldName + '>' + mLineEdit->text();
173  else if ( flags & LessThan )
174  return fieldName + '<' + mLineEdit->text();
175  else if ( flags & GreaterThanOrEqualTo )
176  return fieldName + ">=" + mLineEdit->text();
177  else if ( flags & LessThanOrEqualTo )
178  return fieldName + "<=" + mLineEdit->text();
179  break;
180  }
181 
182  case QVariant::Date:
183  case QVariant::DateTime:
184  case QVariant::Time:
185  {
186  if ( flags & EqualTo )
187  return fieldName + "='" + mLineEdit->text() + '\'';
188  else if ( flags & NotEqualTo )
189  return fieldName + "<>'" + mLineEdit->text() + '\'';
190  else if ( flags & GreaterThan )
191  return fieldName + ">'" + mLineEdit->text() + '\'';
192  else if ( flags & LessThan )
193  return fieldName + "<'" + mLineEdit->text() + '\'';
194  else if ( flags & GreaterThanOrEqualTo )
195  return fieldName + ">='" + mLineEdit->text() + '\'';
196  else if ( flags & LessThanOrEqualTo )
197  return fieldName + "<='" + mLineEdit->text() + '\'';
198  break;
199  }
200 
201  case QVariant::String:
202  {
203  // case insensitive!
204  if ( flags & EqualTo || flags & NotEqualTo )
205  {
206  if ( mCheckbox && mCheckbox->isChecked() )
207  return fieldName + ( ( flags & EqualTo ) ? "=" : "<>" )
208  + QgsExpression::quotedString( mLineEdit->text() );
209  else
210  return QStringLiteral( "lower(%1)" ).arg( fieldName )
211  + ( ( flags & EqualTo ) ? "=" : "<>" ) +
212  QStringLiteral( "lower(%1)" ).arg( QgsExpression::quotedString( mLineEdit->text() ) );
213  }
214  else if ( flags & Contains || flags & DoesNotContain || flags & StartsWith || flags & EndsWith )
215  {
216  QString exp = fieldName + ( mCheckbox && mCheckbox->isChecked() ? " LIKE " : " ILIKE " );
217  QString value = QgsExpression::quotedString( mLineEdit->text() );
218  value.chop( 1 );
219  value = value.remove( 0, 1 );
220  exp += '\'';
221  if ( !flags.testFlag( StartsWith ) )
222  exp += '%';
223  exp += value;
224  if ( !flags.testFlag( EndsWith ) )
225  exp += '%';
226  exp += '\'';
227  if ( flags & DoesNotContain )
228  exp.prepend( "NOT (" ).append( ')' );
229  return exp;
230  }
231 
232  break;
233  }
234 
235  default:
236  break;
237  }
238 
239  return QString();
240 }
241 
243 {
244  mLineEdit->setText( QString() );
245 }
246 
248 {
249  mLineEdit->setEnabled( enabled );
250  if ( mCheckbox )
251  mCheckbox->setEnabled( enabled );
252 }
253 
255 {
256  mContainer = widget;
257  mContainer->setLayout( new QHBoxLayout() );
258  mContainer->layout()->setContentsMargins( 0, 0, 0, 0 );
259  const QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
260 
261  if ( fldType == QVariant::String )
262  {
263  mLineEdit = new QgsFieldValuesLineEdit();
264  static_cast< QgsFieldValuesLineEdit * >( mLineEdit )->setLayer( layer() );
265  static_cast< QgsFieldValuesLineEdit * >( mLineEdit )->setAttributeIndex( mFieldIdx );
266  }
267  else
268  {
269  mLineEdit = new QgsFilterLineEdit();
270  }
271  mContainer->layout()->addWidget( mLineEdit );
272  mContainer->setFocusProxy( mLineEdit );
273 
274  if ( fldType == QVariant::String )
275  {
276  mCheckbox = new QCheckBox( QStringLiteral( "Case sensitive" ) );
277  mContainer->layout()->addWidget( mCheckbox );
278  connect( mCheckbox, &QCheckBox::stateChanged, this, &QgsDefaultSearchWidgetWrapper::setCaseString );
279  mCheckbox->setChecked( Qt::Unchecked );
280  }
281 
282  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsDefaultSearchWidgetWrapper::textChanged );
283  connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsDefaultSearchWidgetWrapper::filterChanged );
284  connect( mLineEdit, &QLineEdit::textEdited, this, &QgsSearchWidgetWrapper::valueChanged );
285 
286  mCaseString = QStringLiteral( "ILIKE" );
287 }
288 
290 {
291  return true;
292 }
293 
295 {
296  return mLineEdit;
297 }
298 
300 {
301  return mCheckbox;
302 }
303 
304 void QgsDefaultSearchWidgetWrapper::filterChanged()
305 {
307 }
308 
309 void QgsDefaultSearchWidgetWrapper::textChanged( const QString &text )
310 {
311  if ( text.isEmpty() )
312  emit valueCleared();
313 
314  setExpression( text );
315 }
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
void setExpression(const QString &exp) override
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QString expression() const override
Will be used to access the widget's value.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
QCheckBox * caseSensitiveCheckBox()
Returns a pointer to the case sensitivity checkbox in the widget.
QgsFilterLineEdit * lineEdit()
Returns a pointer to the line edit part of the widget.
QgsDefaultSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsDefaultSearchWidgetWrapper.
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes.
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.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
A line edit with an autocompleter which takes unique values from a vector layer's fields.
QString name
Definition: qgsfield.h:60
QVariant::Type type
Definition: qgsfield.h:58
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.
@ Contains
Supports value "contains" searching.
@ IsNotBetween
Supports searching for values outside of a set range.
@ StartsWith
Supports searching for strings that start with.
@ LessThan
Supports less than.
@ IsNull
Supports searching for null values.
@ EndsWith
Supports searching for strings that end with.
@ GreaterThan
Supports greater than.
@ IsNotNull
Supports searching for non-null values.
@ EqualTo
Supports equal to.
@ DoesNotContain
Supports value does not contain searching.
@ Between
Supports searches between two values.
@ 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.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QWidget * widget()
Access the widget managed by this wrapper.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
#define str(x)
Definition: qgis.cpp:37