QGIS API Documentation  3.2.0-Bonn (bc43194)
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.
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:145
Supports searching for null values.
Supports searching for strings that start with.
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.
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:55
Supports searches between two values.