QGIS API Documentation 3.99.0-Master (d270888f95f)
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#include <QString>
28
29#include "moc_qgsdefaultsearchwidgetwrapper.cpp"
30
31using namespace Qt::StringLiterals;
32
34 : QgsSearchWidgetWrapper( vl, fieldIdx, parent )
35 , mCaseString( u"LIKE"_s )
36{
37}
38
40{
41 return mExpression;
42}
43
44void QgsDefaultSearchWidgetWrapper::setCaseString( int caseSensitiveCheckState )
45{
46 if ( caseSensitiveCheckState == Qt::Checked )
47 {
48 mCaseString = u"LIKE"_s;
49 }
50 else
51 {
52 mCaseString = u"ILIKE"_s;
53 }
54 // need to update also the line edit
55 setExpression( mLineEdit->text() );
56
57 if ( applyDirectly() )
59}
60
62{
63 const QString nullValue = QgsApplication::nullRepresentation();
64 const QString fieldName = layer()->fields().at( mFieldIdx ).name();
65 QString str;
66 if ( expression == nullValue )
67 {
68 str = u"%1 IS NULL"_s.arg( QgsExpression::quotedColumnRef( fieldName ) );
69 }
70 else
71 {
72 QString exp = expression;
73 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
74 const bool isNumeric = QgsVariantUtils::isNumericType( fldType );
75
76 if ( isNumeric )
77 {
78 bool ok = false;
79 const double doubleValue = QgsDoubleValidator::toDouble( exp, &ok );
80 if ( ok )
81 {
82 exp = QString::number( doubleValue );
83 }
84 }
85 str = u"%1 %2 '%3'"_s
86 .arg( QgsExpression::quotedColumnRef( fieldName ), isNumeric ? u"="_s : mCaseString, isNumeric ? exp.replace( '\'', "''"_L1 ) : '%' + exp.replace( '\'', "''"_L1 ) + '%' ); // escape quotes
87 }
88 mExpression = str;
89}
90
92{
93 return new QWidget( parent );
94}
95
97{
98 return false;
99}
100
102{
104
105 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
106 switch ( fldType )
107 {
108 case QMetaType::Type::Int:
109 case QMetaType::Type::UInt:
110 case QMetaType::Type::Double:
111 case QMetaType::Type::LongLong:
112 case QMetaType::Type::ULongLong:
113 case QMetaType::Type::QDate:
114 case QMetaType::Type::QDateTime:
115 case QMetaType::Type::QTime:
117 break;
118
119 case QMetaType::Type::QString:
121 break;
122
123 default:
124 break;
125 }
126 return flags;
127}
128
130{
131 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
132 switch ( fldType )
133 {
134 //numeric
135 case QMetaType::Type::Int:
136 case QMetaType::Type::UInt:
137 case QMetaType::Type::Double:
138 case QMetaType::Type::LongLong:
139 case QMetaType::Type::ULongLong:
140
141 // date
142 case QMetaType::Type::QDate:
143 case QMetaType::Type::QDateTime:
144 case QMetaType::Type::QTime:
145 return EqualTo;
146
147 case QMetaType::Type::QString:
148 return Contains;
149
150 default:
151 break;
152 }
153 return EqualTo;
154}
155
157{
158 //clear any unsupported flags
159 flags &= supportedFlags();
160
161 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
162 const QString fieldName = createFieldIdentifier();
163
164 if ( flags & IsNull )
165 return fieldName + " IS NULL";
166 if ( flags & IsNotNull )
167 return fieldName + " IS NOT NULL";
168
169 QString text = mLineEdit->text();
170
171 if ( QgsVariantUtils::isNumericType( fldType ) )
172 {
173 bool ok = false;
174 const double doubleValue = QgsDoubleValidator::toDouble( text, &ok );
175 if ( ok )
176 {
177 text = QString::number( doubleValue );
178 ;
179 }
180 }
181
182 switch ( fldType )
183 {
184 case QMetaType::Type::Int:
185 case QMetaType::Type::UInt:
186 case QMetaType::Type::Double:
187 case QMetaType::Type::LongLong:
188 case QMetaType::Type::ULongLong:
189 {
190 if ( flags & EqualTo )
191 return fieldName + '=' + text;
192 else if ( flags & NotEqualTo )
193 return fieldName + "<>" + text;
194 else if ( flags & GreaterThan )
195 return fieldName + '>' + text;
196 else if ( flags & LessThan )
197 return fieldName + '<' + text;
198 else if ( flags & GreaterThanOrEqualTo )
199 return fieldName + ">=" + text;
200 else if ( flags & LessThanOrEqualTo )
201 return fieldName + "<=" + text;
202 break;
203 }
204
205 case QMetaType::Type::QDate:
206 case QMetaType::Type::QDateTime:
207 case QMetaType::Type::QTime:
208 {
209 if ( flags & EqualTo )
210 return fieldName + "='" + text + '\'';
211 else if ( flags & NotEqualTo )
212 return fieldName + "<>'" + text + '\'';
213 else if ( flags & GreaterThan )
214 return fieldName + ">'" + text + '\'';
215 else if ( flags & LessThan )
216 return fieldName + "<'" + text + '\'';
217 else if ( flags & GreaterThanOrEqualTo )
218 return fieldName + ">='" + text + '\'';
219 else if ( flags & LessThanOrEqualTo )
220 return fieldName + "<='" + text + '\'';
221 break;
222 }
223
224 case QMetaType::Type::QString:
225 {
226 // case insensitive!
227 if ( flags & EqualTo || flags & NotEqualTo )
228 {
229 if ( mCheckbox && mCheckbox->isChecked() )
230 return fieldName + ( ( flags & EqualTo ) ? "=" : "<>" )
231 + QgsExpression::quotedString( mLineEdit->text() );
232 else
233 return u"lower(%1)"_s.arg( fieldName )
234 + ( ( flags & EqualTo ) ? "=" : "<>" ) + u"lower(%1)"_s.arg( QgsExpression::quotedString( mLineEdit->text() ) );
235 }
236 else if ( flags & Contains || flags & DoesNotContain || flags & StartsWith || flags & EndsWith )
237 {
238 QString exp = fieldName + ( mCheckbox && mCheckbox->isChecked() ? " LIKE " : " ILIKE " );
239 QString value = QgsExpression::quotedString( mLineEdit->text() );
240 value.chop( 1 );
241 value = value.remove( 0, 1 );
242 exp += '\'';
243 if ( !flags.testFlag( StartsWith ) )
244 exp += '%';
245 exp += value;
246 if ( !flags.testFlag( EndsWith ) )
247 exp += '%';
248 exp += '\'';
249 if ( flags & DoesNotContain )
250 exp.prepend( "NOT (" ).append( ')' );
251 return exp;
252 }
253
254 break;
255 }
256
257 default:
258 break;
259 }
260
261 return QString();
262}
263
265{
266 mLineEdit->setText( QString() );
267}
268
270{
271 mLineEdit->setEnabled( enabled );
272 if ( mCheckbox )
273 mCheckbox->setEnabled( enabled );
274}
275
277{
278 mContainer = widget;
279 mContainer->setLayout( new QHBoxLayout() );
280 mContainer->layout()->setContentsMargins( 0, 0, 0, 0 );
281 const QMetaType::Type fldType = layer()->fields().at( mFieldIdx ).type();
282
283 if ( fldType == QMetaType::Type::QString )
284 {
285 mLineEdit = new QgsFieldValuesLineEdit();
286 static_cast<QgsFieldValuesLineEdit *>( mLineEdit )->setLayer( layer() );
287 static_cast<QgsFieldValuesLineEdit *>( mLineEdit )->setAttributeIndex( mFieldIdx );
288 }
289 else
290 {
291 mLineEdit = new QgsFilterLineEdit();
292 }
293 mContainer->layout()->addWidget( mLineEdit );
294 mContainer->setFocusProxy( mLineEdit );
295
296 if ( fldType == QMetaType::Type::QString )
297 {
298 mCheckbox = new QCheckBox( u"Case sensitive"_s );
299 mContainer->layout()->addWidget( mCheckbox );
300 connect( mCheckbox, &QCheckBox::stateChanged, this, &QgsDefaultSearchWidgetWrapper::setCaseString );
301 mCheckbox->setChecked( Qt::Unchecked );
302 }
303
304 connect( mLineEdit, &QLineEdit::textChanged, this, &QgsDefaultSearchWidgetWrapper::textChanged );
305 connect( mLineEdit, &QLineEdit::returnPressed, this, &QgsDefaultSearchWidgetWrapper::filterChanged );
306 connect( mLineEdit, &QLineEdit::textEdited, this, &QgsSearchWidgetWrapper::valueChanged );
307
308 mCaseString = u"ILIKE"_s;
309}
310
312{
313 return true;
314}
315
320
322{
323 return mCheckbox;
324}
325
326void QgsDefaultSearchWidgetWrapper::filterChanged()
327{
329}
330
331void QgsDefaultSearchWidgetWrapper::textChanged( const QString &text )
332{
333 if ( text.isEmpty() )
334 emit valueCleared();
335
336 setExpression( text );
337}
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:63
QString name
Definition qgsfield.h:65
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.