QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 
24 #include <QHBoxLayout>
25 
27  : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
28  , mCaseString( QStringLiteral( "LIKE" ) )
29 {
30 }
31 
33 {
34  return mExpression;
35 }
36 
37 void QgsDefaultSearchWidgetWrapper::setCaseString( int caseSensitiveCheckState )
38 {
39  if ( caseSensitiveCheckState == Qt::Checked )
40  {
41  mCaseString = QStringLiteral( "LIKE" );
42  }
43  else
44  {
45  mCaseString = QStringLiteral( "ILIKE" );
46  }
47  // need to update also the line edit
48  setExpression( mLineEdit->text() );
49 
50  if ( applyDirectly() )
52 }
53 
55 {
56  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
57  bool numeric = ( fldType == QVariant::Int || fldType == QVariant::Double || fldType == QVariant::LongLong );
58 
59  QString exp = expression;
60  QString nullValue = QgsApplication::nullRepresentation();
61  QString fieldName = layer()->fields().at( mFieldIdx ).name();
62  QString str;
63  if ( exp == nullValue )
64  {
65  str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
66  }
67  else
68  {
69  str = QStringLiteral( "%1 %2 '%3'" )
70  .arg( QgsExpression::quotedColumnRef( fieldName ),
71  numeric ? QStringLiteral( "=" ) : mCaseString,
72  numeric ?
73  exp.replace( '\'', QLatin1String( "''" ) )
74  :
75  '%' + exp.replace( '\'', QLatin1String( "''" ) ) + '%' ); // escape quotes
76  }
77  mExpression = str;
78 }
79 
81 {
82  return new QWidget( parent );
83 }
84 
86 {
87  return false;
88 }
89 
90 QgsSearchWidgetWrapper::FilterFlags QgsDefaultSearchWidgetWrapper::supportedFlags() const
91 {
92  FilterFlags flags = EqualTo | NotEqualTo | IsNull | IsNotNull;
93 
94  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
95  switch ( fldType )
96  {
97  case QVariant::Int:
98  case QVariant::UInt:
99  case QVariant::Double:
100  case QVariant::LongLong:
101  case QVariant::ULongLong:
102  case QVariant::Date:
103  case QVariant::DateTime:
104  case QVariant::Time:
106  break;
107 
108  case QVariant::String:
110  break;
111 
112  default:
113  break;
114  }
115  return flags;
116 }
117 
118 QgsSearchWidgetWrapper::FilterFlags QgsDefaultSearchWidgetWrapper::defaultFlags() const
119 {
120  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
121  switch ( fldType )
122  {
123  case QVariant::Int:
124  case QVariant::UInt:
125  case QVariant::Double:
126  case QVariant::LongLong:
127  case QVariant::ULongLong:
128  //numeric
129  return EqualTo;
130 
131  case QVariant::Date:
132  case QVariant::DateTime:
133  case QVariant::Time:
134  return EqualTo;
135 
136  case QVariant::String:
137  return Contains;
138 
139  default:
140  break;
141  }
142  return EqualTo;
143 }
144 
145 QString QgsDefaultSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
146 {
147  //clear any unsupported flags
148  flags &= supportedFlags();
149 
150  QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
151  QString fieldName = createFieldIdentifier();
152 
153  if ( flags & IsNull )
154  return fieldName + " IS NULL";
155  if ( flags & IsNotNull )
156  return fieldName + " IS NOT NULL";
157 
158  switch ( fldType )
159  {
160  case QVariant::Int:
161  case QVariant::UInt:
162  case QVariant::Double:
163  case QVariant::LongLong:
164  case QVariant::ULongLong:
165  {
166  if ( flags & EqualTo )
167  return fieldName + '=' + mLineEdit->text();
168  else if ( flags & NotEqualTo )
169  return fieldName + "<>" + mLineEdit->text();
170  else if ( flags & GreaterThan )
171  return fieldName + '>' + mLineEdit->text();
172  else if ( flags & LessThan )
173  return fieldName + '<' + mLineEdit->text();
174  else if ( flags & GreaterThanOrEqualTo )
175  return fieldName + ">=" + mLineEdit->text();
176  else if ( flags & LessThanOrEqualTo )
177  return fieldName + "<=" + mLineEdit->text();
178  break;
179  }
180 
181  case QVariant::Date:
182  case QVariant::DateTime:
183  case QVariant::Time:
184  {
185  if ( flags & EqualTo )
186  return fieldName + "='" + mLineEdit->text() + '\'';
187  else if ( flags & NotEqualTo )
188  return fieldName + "<>'" + mLineEdit->text() + '\'';
189  else if ( flags & GreaterThan )
190  return fieldName + ">'" + mLineEdit->text() + '\'';
191  else if ( flags & LessThan )
192  return fieldName + "<'" + mLineEdit->text() + '\'';
193  else if ( flags & GreaterThanOrEqualTo )
194  return fieldName + ">='" + mLineEdit->text() + '\'';
195  else if ( flags & LessThanOrEqualTo )
196  return fieldName + "<='" + mLineEdit->text() + '\'';
197  break;
198  }
199 
200  case QVariant::String:
201  {
202  // case insensitive!
203  if ( flags & EqualTo || flags & NotEqualTo )
204  {
205  if ( mCheckbox && mCheckbox->isChecked() )
206  return fieldName + ( flags & EqualTo ? "=" : "<>" )
207  + QgsExpression::quotedString( mLineEdit->text() );
208  else
209  return QStringLiteral( "lower(%1)" ).arg( fieldName )
210  + ( flags & EqualTo ? "=" : "<>" ) +
211  QStringLiteral( "lower(%1)" ).arg( QgsExpression::quotedString( mLineEdit->text() ) );
212  }
213  else if ( flags & Contains || flags & DoesNotContain || flags & StartsWith || flags & EndsWith )
214  {
215  QString exp = fieldName + ( mCheckbox && mCheckbox->isChecked() ? " LIKE " : " ILIKE " );
216  QString value = QgsExpression::quotedString( mLineEdit->text() );
217  value.chop( 1 );
218  value = value.remove( 0, 1 );
219  exp += '\'';
220  if ( !flags.testFlag( StartsWith ) )
221  exp += '%';
222  exp += value;
223  if ( !flags.testFlag( EndsWith ) )
224  exp += '%';
225  exp += '\'';
226  if ( flags & DoesNotContain )
227  exp.prepend( "NOT (" ).append( ')' );
228  return exp;
229  }
230 
231  break;
232  }
233 
234  default:
235  break;
236  }
237 
238  return QString();
239 }
240 
242 {
243  mLineEdit->setText( QString() );
244 }
245 
247 {
248  mLineEdit->setEnabled( enabled );
249  if ( mCheckbox )
250  mCheckbox->setEnabled( enabled );
251 }
252 
254 {
255  mContainer = widget;
256  mContainer->setLayout( new QHBoxLayout() );
257  mContainer->layout()->setMargin( 0 );
258  mContainer->layout()->setContentsMargins( 0, 0, 0, 0 );
259  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 }
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:57
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.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
QString expression() const override
Will be used to access the widget&#39;s value.
Supports searching for strings that end with.
QgsFilterLineEdit * lineEdit()
Returns a pointer to the line edit part of the widget.
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.
QString createFieldIdentifier() const
Gets a field name or expression to use as field comparison.
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...
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
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.
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:55
Supports searches between two values.