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