QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
56 {
57  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
58  bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
59 
60  QString exp = expression;
61  QString nullValue = QgsApplication::nullRepresentation();
62  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  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  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  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
152  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()->setMargin( 0 );
259  mContainer->layout()->setContentsMargins( 0, 0, 0, 0 );
260  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
261 
262  if ( fldType == QVariant::String )
263  {
264  mLineEdit = new QgsFieldValuesLineEdit();
265  static_cast< QgsFieldValuesLineEdit * >( mLineEdit )->setLayer( layer() );
266  static_cast< QgsFieldValuesLineEdit * >( mLineEdit )->setAttributeIndex( mFieldIdx );
267  }
268  else
269  {
270  mLineEdit = new QgsFilterLineEdit();
271  }
272  mContainer->layout()->addWidget( mLineEdit );
273  mContainer->setFocusProxy( mLineEdit );
274 
275  if ( fldType == QVariant::String )
276  {
277  mCheckbox = new QCheckBox( QStringLiteral( "Case sensitive" ) );
278  mContainer->layout()->addWidget( mCheckbox );
279  connect( mCheckbox, &QCheckBox::stateChanged, this, &QgsDefaultSearchWidgetWrapper::setCaseString );
280  mCheckbox->setChecked( Qt::Unchecked );
281  }
282 
283  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsDefaultSearchWidgetWrapper::textChanged );
284  connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsDefaultSearchWidgetWrapper::filterChanged );
285  connect( mLineEdit, &QLineEdit::textEdited, this, &QgsSearchWidgetWrapper::valueChanged );
286 
287  mCaseString = QStringLiteral( "ILIKE" );
288 }
289 
291 {
292  return true;
293 }
294 
296 {
297  return mLineEdit;
298 }
299 
301 {
302  return mCheckbox;
303 }
304 
305 void QgsDefaultSearchWidgetWrapper::filterChanged()
306 {
308 }
309 
310 void QgsDefaultSearchWidgetWrapper::textChanged( const QString &text )
311 {
312  if ( text.isEmpty() )
313  emit valueCleared();
314 
315  setExpression( text );
316 }
Shows a search widget on a filter form.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QString name
Definition: qgsfield.h:58
Supports value "contains" searching.
Supports searching for non-null values.
void setExpression(const QString &exp) override
Supports searching for values outside of a set range.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QCheckBox * caseSensitiveCheckBox()
Returns a pointer to the case sensitivity checkbox in the widget.
QString expression() const override
Will be used to access the widget&#39;s value.
Supports searching for strings that end with.
QString createFieldIdentifier() const
Gets a field name or expression to use as field comparison.
QgsFilterLineEdit * lineEdit()
Returns a pointer to the line edit part of the widget.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
Supports searching for null values.
Supports searching for strings that start with.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
void valueChanged()
Emitted when a user changes the value of the search widget.
QgsSearchWidgetWrapper::FilterFlags defaultFlags() const override
Returns the filter flags which should be set by default for the search widget.
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.
Supports value does not contain searching.
void expressionChanged(const QString &exp)
Emitted whenever the expression changes.
bool valid() const override
Returns true if the widget has been properly initialized.
A line edit with an autocompleter which takes unique values from a vector layer&#39;s fields...
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes...
void valueCleared()
Emitted when a user changes the value of the search widget back to an empty, default state...
QgsDefaultSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsDefaultSearchWidgetWrapper.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
QWidget * widget()
Access the widget managed by this wrapper.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Represents a vector layer which manages a vector based data sets.
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
QVariant::Type type
Definition: qgsfield.h:56
Supports searches between two values.