QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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 "qgsapplication.h"
19#include "qgsdoublevalidator.h"
20#include "qgsexpression.h"
21#include "qgsfields.h"
22#include "qgsfieldvalidator.h"
24#include "qgssettings.h"
25
26#include <QHBoxLayout>
27
28#include "moc_qgsdefaultsearchwidgetwrapper.cpp"
29
31 : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
32 , mCaseString( QStringLiteral( "LIKE" ) )
33{
34}
35
37{
38 return mExpression;
39}
40
41void QgsDefaultSearchWidgetWrapper::setCaseString( int caseSensitiveCheckState )
42{
43 if ( caseSensitiveCheckState == Qt::Checked )
44 {
45 mCaseString = QStringLiteral( "LIKE" );
46 }
47 else
48 {
49 mCaseString = QStringLiteral( "ILIKE" );
50 }
51 // need to update also the line edit
52 setExpression( mLineEdit->text() );
53
54 if ( applyDirectly() )
56}
57
59{
60 const QString nullValue = QgsApplication::nullRepresentation();
61 const QString fieldName = layer()->fields().at( mFieldIdx ).name();
62 QString str;
63 if ( expression == nullValue )
64 {
65 str = QStringLiteral( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
66 }
67 else
68 {
69 QString exp = expression;
70 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
71 const bool isNumeric = QgsVariantUtils::isNumericType( fldType );
72
73 if ( isNumeric )
74 {
75 bool ok = false;
76 const double doubleValue = QgsDoubleValidator::toDouble( exp, &ok );
77 if ( ok )
78 {
79 exp = QString::number( doubleValue );
80 }
81 }
82 str = QStringLiteral( "%1 %2 '%3'" )
83 .arg( QgsExpression::quotedColumnRef( fieldName ), isNumeric ? QStringLiteral( "=" ) : mCaseString, isNumeric ? exp.replace( '\'', QLatin1String( "''" ) ) : '%' + exp.replace( '\'', QLatin1String( "''" ) ) + '%' ); // escape quotes
84 }
85 mExpression = str;
86}
87
89{
90 return new QWidget( parent );
91}
92
94{
95 return false;
96}
97
99{
101
102 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
103 switch ( fldType )
104 {
105 case QMetaType::Type::Int:
106 case QMetaType::Type::UInt:
107 case QMetaType::Type::Double:
108 case QMetaType::Type::LongLong:
109 case QMetaType::Type::ULongLong:
110 case QMetaType::Type::QDate:
111 case QMetaType::Type::QDateTime:
112 case QMetaType::Type::QTime:
114 break;
115
116 case QMetaType::Type::QString:
118 break;
119
120 default:
121 break;
122 }
123 return flags;
124}
125
127{
128 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
129 switch ( fldType )
130 {
131 //numeric
132 case QMetaType::Type::Int:
133 case QMetaType::Type::UInt:
134 case QMetaType::Type::Double:
135 case QMetaType::Type::LongLong:
136 case QMetaType::Type::ULongLong:
137
138 // date
139 case QMetaType::Type::QDate:
140 case QMetaType::Type::QDateTime:
141 case QMetaType::Type::QTime:
142 return EqualTo;
143
144 case QMetaType::Type::QString:
145 return Contains;
146
147 default:
148 break;
149 }
150 return EqualTo;
151}
152
154{
155 //clear any unsupported flags
156 flags &= supportedFlags();
157
158 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
159 const QString fieldName = createFieldIdentifier();
160
161 if ( flags & IsNull )
162 return fieldName + " IS NULL";
163 if ( flags & IsNotNull )
164 return fieldName + " IS NOT NULL";
165
166 QString text = mLineEdit->text();
167
168 if ( QgsVariantUtils::isNumericType( fldType ) )
169 {
170 bool ok = false;
171 const double doubleValue = QgsDoubleValidator::toDouble( text, &ok );
172 if ( ok )
173 {
174 text = QString::number( doubleValue );
175 ;
176 }
177 }
178
179 switch ( fldType )
180 {
181 case QMetaType::Type::Int:
182 case QMetaType::Type::UInt:
183 case QMetaType::Type::Double:
184 case QMetaType::Type::LongLong:
185 case QMetaType::Type::ULongLong:
186 {
187 if ( flags & EqualTo )
188 return fieldName + '=' + text;
189 else if ( flags & NotEqualTo )
190 return fieldName + "<>" + text;
191 else if ( flags & GreaterThan )
192 return fieldName + '>' + text;
193 else if ( flags & LessThan )
194 return fieldName + '<' + text;
195 else if ( flags & GreaterThanOrEqualTo )
196 return fieldName + ">=" + text;
197 else if ( flags & LessThanOrEqualTo )
198 return fieldName + "<=" + text;
199 break;
200 }
201
202 case QMetaType::Type::QDate:
203 case QMetaType::Type::QDateTime:
204 case QMetaType::Type::QTime:
205 {
206 if ( flags & EqualTo )
207 return fieldName + "='" + text + '\'';
208 else if ( flags & NotEqualTo )
209 return fieldName + "<>'" + text + '\'';
210 else if ( flags & GreaterThan )
211 return fieldName + ">'" + text + '\'';
212 else if ( flags & LessThan )
213 return fieldName + "<'" + text + '\'';
214 else if ( flags & GreaterThanOrEqualTo )
215 return fieldName + ">='" + text + '\'';
216 else if ( flags & LessThanOrEqualTo )
217 return fieldName + "<='" + text + '\'';
218 break;
219 }
220
221 case QMetaType::Type::QString:
222 {
223 // case insensitive!
224 if ( flags & EqualTo || flags & NotEqualTo )
225 {
226 if ( mCheckbox && mCheckbox->isChecked() )
227 return fieldName + ( ( flags & EqualTo ) ? "=" : "<>" )
228 + QgsExpression::quotedString( mLineEdit->text() );
229 else
230 return QStringLiteral( "lower(%1)" ).arg( fieldName )
231 + ( ( flags & EqualTo ) ? "=" : "<>" ) + QStringLiteral( "lower(%1)" ).arg( QgsExpression::quotedString( mLineEdit->text() ) );
232 }
233 else if ( flags & Contains || flags & DoesNotContain || flags & StartsWith || flags & EndsWith )
234 {
235 QString exp = fieldName + ( mCheckbox && mCheckbox->isChecked() ? " LIKE " : " ILIKE " );
236 QString value = QgsExpression::quotedString( mLineEdit->text() );
237 value.chop( 1 );
238 value = value.remove( 0, 1 );
239 exp += '\'';
240 if ( !flags.testFlag( StartsWith ) )
241 exp += '%';
242 exp += value;
243 if ( !flags.testFlag( EndsWith ) )
244 exp += '%';
245 exp += '\'';
246 if ( flags & DoesNotContain )
247 exp.prepend( "NOT (" ).append( ')' );
248 return exp;
249 }
250
251 break;
252 }
253
254 default:
255 break;
256 }
257
258 return QString();
259}
260
262{
263 mLineEdit->setText( QString() );
264}
265
267{
268 mLineEdit->setEnabled( enabled );
269 if ( mCheckbox )
270 mCheckbox->setEnabled( enabled );
271}
272
274{
275 mContainer = widget;
276 mContainer->setLayout( new QHBoxLayout() );
277 mContainer->layout()->setContentsMargins( 0, 0, 0, 0 );
278 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
279
280 if ( fldType == QMetaType::Type::QString )
281 {
282 mLineEdit = new QgsFieldValuesLineEdit();
283 static_cast<QgsFieldValuesLineEdit *>( mLineEdit )->setLayer( layer() );
284 static_cast<QgsFieldValuesLineEdit *>( mLineEdit )->setAttributeIndex( mFieldIdx );
285 }
286 else
287 {
288 mLineEdit = new QgsFilterLineEdit();
289 }
290 mContainer->layout()->addWidget( mLineEdit );
291 mContainer->setFocusProxy( mLineEdit );
292
293 if ( fldType == QMetaType::Type::QString )
294 {
295 mCheckbox = new QCheckBox( QStringLiteral( "Case sensitive" ) );
296 mContainer->layout()->addWidget( mCheckbox );
297 connect( mCheckbox, &QCheckBox::stateChanged, this, &QgsDefaultSearchWidgetWrapper::setCaseString );
298 mCheckbox->setChecked( Qt::Unchecked );
299 }
300
301 connect( mLineEdit, &QLineEdit::textChanged, this, &QgsDefaultSearchWidgetWrapper::textChanged );
302 connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsDefaultSearchWidgetWrapper::filterChanged );
303 connect( mLineEdit, &QLineEdit::textEdited, this, &QgsSearchWidgetWrapper::valueChanged );
304
305 mCaseString = QStringLiteral( "ILIKE" );
306}
307
309{
310 return true;
311}
312
317
319{
320 return mCheckbox;
321}
322
323void QgsDefaultSearchWidgetWrapper::filterChanged()
324{
326}
327
328void QgsDefaultSearchWidgetWrapper::textChanged( const QString &text )
329{
330 if ( text.isEmpty() )
331 emit valueCleared();
332
333 setExpression( text );
334}
static QString nullRepresentation()
Returns the string used to represent the value NULL throughout QGIS.
QString createExpression(QgsSearchWidgetWrapper::FilterFlags flags) const override
Creates a filter expression based on the current state of the search widget and the specified filter ...
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 double toDouble(const QString &input, bool *ok)
Converts input string to double value.
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.
QMetaType::Type type
Definition qgsfield.h:61
QString name
Definition qgsfield.h:63
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
@ 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.
@ 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.
QgsSearchWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Create a new widget wrapper.
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.
QFlags< FilterFlag > FilterFlags
static bool isNumericType(QMetaType::Type metaType)
Returns true if the specified metaType is a numeric type.
Represents a vector layer which manages a vector based dataset.
QWidget * widget()
Access the widget managed by this wrapper.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.