QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 }
qgsfields.h
QgsExpression::quotedString
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
Definition: qgsexpression.cpp:73
QgsDefaultSearchWidgetWrapper::setExpression
void setExpression(const QString &exp) override
Definition: qgsdefaultsearchwidgetwrapper.cpp:55
QgsSearchWidgetWrapper::expressionChanged
void expressionChanged(const QString &exp)
Emitted whenever the expression changes.
QgsSearchWidgetWrapper::valueChanged
void valueChanged()
Emitted when a user changes the value of the search widget.
QgsSearchWidgetWrapper::Between
@ Between
Supports searches between two values.
Definition: qgssearchwidgetwrapper.h:102
QgsSearchWidgetWrapper::NotEqualTo
@ NotEqualTo
Supports not equal to.
Definition: qgssearchwidgetwrapper.h:97
qgsexpression.h
QgsDefaultSearchWidgetWrapper::expression
QString expression() const override
Will be used to access the widget's value.
Definition: qgsdefaultsearchwidgetwrapper.cpp:33
QgsSearchWidgetWrapper
Shows a search widget on a filter form.
Definition: qgssearchwidgetwrapper.h:85
QgsFilterLineEdit
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Definition: qgsfilterlineedit.h:39
QgsDefaultSearchWidgetWrapper::caseSensitiveCheckBox
QCheckBox * caseSensitiveCheckBox()
Returns a pointer to the case sensitivity checkbox in the widget.
Definition: qgsdefaultsearchwidgetwrapper.cpp:299
qgsdefaultsearchwidgetwrapper.h
QgsDefaultSearchWidgetWrapper::setEnabled
void setEnabled(bool enabled) override
Definition: qgsdefaultsearchwidgetwrapper.cpp:247
QgsDefaultSearchWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsdefaultsearchwidgetwrapper.cpp:81
QgsSearchWidgetWrapper::GreaterThanOrEqualTo
@ GreaterThanOrEqualTo
Supports >=.
Definition: qgssearchwidgetwrapper.h:100
QgsField::name
QString name
Definition: qgsfield.h:60
QgsWidgetWrapper::widget
QWidget * widget()
Access the widget managed by this wrapper.
Definition: qgswidgetwrapper.cpp:47
QgsSearchWidgetWrapper::valueCleared
void valueCleared()
Emitted when a user changes the value of the search widget back to an empty, default state.
QgsDefaultSearchWidgetWrapper::defaultFlags
QgsSearchWidgetWrapper::FilterFlags defaultFlags() const override
Returns the filter flags which should be set by default for the search widget.
Definition: qgsdefaultsearchwidgetwrapper.cpp:119
QgsSearchWidgetWrapper::StartsWith
@ StartsWith
Supports searching for strings that start with.
Definition: qgssearchwidgetwrapper.h:109
qgsapplication.h
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsDefaultSearchWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsdefaultsearchwidgetwrapper.cpp:254
QgsSearchWidgetWrapper::DoesNotContain
@ DoesNotContain
Supports value does not contain searching.
Definition: qgssearchwidgetwrapper.h:105
QgsWidgetWrapper::layer
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Definition: qgswidgetwrapper.cpp:92
QgsSearchWidgetWrapper::mFieldIdx
int mFieldIdx
Definition: qgssearchwidgetwrapper.h:266
QgsSearchWidgetWrapper::EndsWith
@ EndsWith
Supports searching for strings that end with.
Definition: qgssearchwidgetwrapper.h:110
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:2018
QgsDefaultSearchWidgetWrapper::lineEdit
QgsFilterLineEdit * lineEdit()
Returns a pointer to the line edit part of the widget.
Definition: qgsdefaultsearchwidgetwrapper.cpp:294
QgsFieldValuesLineEdit
A line edit with an autocompleter which takes unique values from a vector layer's fields....
Definition: qgsfieldvalueslineedit.h:100
QgsSearchWidgetWrapper::IsNotBetween
@ IsNotBetween
Supports searching for values outside of a set range.
Definition: qgssearchwidgetwrapper.h:107
QgsSearchWidgetWrapper::Contains
@ Contains
Supports value "contains" searching.
Definition: qgssearchwidgetwrapper.h:104
qgsfieldvalueslineedit.h
QgsSearchWidgetWrapper::mExpression
QString mExpression
Definition: qgssearchwidgetwrapper.h:265
QgsSearchWidgetWrapper::GreaterThan
@ GreaterThan
Supports greater than.
Definition: qgssearchwidgetwrapper.h:98
QgsSearchWidgetWrapper::IsNull
@ IsNull
Supports searching for null values.
Definition: qgssearchwidgetwrapper.h:106
QgsDefaultSearchWidgetWrapper::clearWidget
void clearWidget() override
Definition: qgsdefaultsearchwidgetwrapper.cpp:242
qgsfieldvalidator.h
str
#define str(x)
Definition: qgis.cpp:37
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsDefaultSearchWidgetWrapper::supportedFlags
QgsSearchWidgetWrapper::FilterFlags supportedFlags() const override
Returns filter flags supported by the search widget.
Definition: qgsdefaultsearchwidgetwrapper.cpp:91
QgsSearchWidgetWrapper::LessThanOrEqualTo
@ LessThanOrEqualTo
Supports <=.
Definition: qgssearchwidgetwrapper.h:101
QgsDefaultSearchWidgetWrapper::applyDirectly
bool applyDirectly() override
If this is true, then this search widget should take effect directly when its expression changes.
Definition: qgsdefaultsearchwidgetwrapper.cpp:86
qgssettings.h
QgsDefaultSearchWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsdefaultsearchwidgetwrapper.cpp:289
QgsExpression::quotedColumnRef
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Definition: qgsexpression.cpp:68
QgsSearchWidgetWrapper::LessThan
@ LessThan
Supports less than.
Definition: qgssearchwidgetwrapper.h:99
QgsSearchWidgetWrapper::createFieldIdentifier
QString createFieldIdentifier() const
Gets a field name or expression to use as field comparison.
Definition: qgssearchwidgetwrapper.cpp:104
QgsSearchWidgetWrapper::EqualTo
@ EqualTo
Supports equal to.
Definition: qgssearchwidgetwrapper.h:96
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsSearchWidgetWrapper::IsNotNull
@ IsNotNull
Supports searching for non-null values.
Definition: qgssearchwidgetwrapper.h:108
QgsDefaultSearchWidgetWrapper::QgsDefaultSearchWidgetWrapper
QgsDefaultSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsDefaultSearchWidgetWrapper.
Definition: qgsdefaultsearchwidgetwrapper.cpp:27
QgsField::type
QVariant::Type type
Definition: qgsfield.h:58
QgsDefaultSearchWidgetWrapper::createExpression
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
Definition: qgsdefaultsearchwidgetwrapper.cpp:146