QGIS API Documentation 3.40.0-Bratislava (b56115d8743)
Loading...
Searching...
No Matches
qgsquerybuilder.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsquerybuilder.cpp - Query Builder
3 --------------------------------------
4 Date : 2004-11-19
5 Copyright : (C) 2004 by Gary E.Sherman
6 Email : sherman at mrcc.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#include "qgsquerybuilder.h"
16#include "qgslogger.h"
17#include "qgssettings.h"
18#include "qgsvectorlayer.h"
20#include "qgsapplication.h"
21#include "qgshelp.h"
22#include "qgsgui.h"
23#include "qgsfieldproxymodel.h"
24#include "qgsfieldmodel.h"
25
26#include <QDomDocument>
27#include <QDomElement>
28#include <QFileDialog>
29#include <QInputDialog>
30#include <QListView>
31#include <QMessageBox>
32#include <QPushButton>
33#include <QTextStream>
34
35
36// constructor used when the query builder must make its own
37// connection to the database
39 QWidget *parent, Qt::WindowFlags fl )
40 : QgsSubsetStringEditorInterface( parent, fl )
41 , mPreviousFieldRow( -1 )
42 , mLayer( layer )
43{
44 setupUi( this );
46 connect( btnEqual, &QPushButton::clicked, this, &QgsQueryBuilder::btnEqual_clicked );
47 connect( btnLessThan, &QPushButton::clicked, this, &QgsQueryBuilder::btnLessThan_clicked );
48 connect( btnGreaterThan, &QPushButton::clicked, this, &QgsQueryBuilder::btnGreaterThan_clicked );
49 connect( btnPct, &QPushButton::clicked, this, &QgsQueryBuilder::btnPct_clicked );
50 connect( btnIn, &QPushButton::clicked, this, &QgsQueryBuilder::btnIn_clicked );
51 connect( btnNotIn, &QPushButton::clicked, this, &QgsQueryBuilder::btnNotIn_clicked );
52 connect( btnLike, &QPushButton::clicked, this, &QgsQueryBuilder::btnLike_clicked );
53 connect( btnILike, &QPushButton::clicked, this, &QgsQueryBuilder::btnILike_clicked );
54 connect( lstFields, &QListView::clicked, this, &QgsQueryBuilder::lstFields_clicked );
55 connect( lstFields, &QListView::doubleClicked, this, &QgsQueryBuilder::lstFields_doubleClicked );
56 connect( lstValues, &QListView::doubleClicked, this, &QgsQueryBuilder::lstValues_doubleClicked );
57 connect( btnLessEqual, &QPushButton::clicked, this, &QgsQueryBuilder::btnLessEqual_clicked );
58 connect( btnGreaterEqual, &QPushButton::clicked, this, &QgsQueryBuilder::btnGreaterEqual_clicked );
59 connect( btnNotEqual, &QPushButton::clicked, this, &QgsQueryBuilder::btnNotEqual_clicked );
60 connect( btnAnd, &QPushButton::clicked, this, &QgsQueryBuilder::btnAnd_clicked );
61 connect( btnNot, &QPushButton::clicked, this, &QgsQueryBuilder::btnNot_clicked );
62 connect( btnOr, &QPushButton::clicked, this, &QgsQueryBuilder::btnOr_clicked );
63 connect( btnGetAllValues, &QPushButton::clicked, this, &QgsQueryBuilder::btnGetAllValues_clicked );
64 connect( btnSampleValues, &QPushButton::clicked, this, &QgsQueryBuilder::btnSampleValues_clicked );
65 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsQueryBuilder::showHelp );
66
67 QPushButton *pbn = new QPushButton( tr( "&Test" ) );
68 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
69 connect( pbn, &QAbstractButton::clicked, this, &QgsQueryBuilder::test );
70
71 pbn = new QPushButton( tr( "&Clear" ) );
72 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
73 connect( pbn, &QAbstractButton::clicked, this, &QgsQueryBuilder::clear );
74
75 pbn = new QPushButton( tr( "&Save…" ) );
76 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
77 pbn->setToolTip( tr( "Save query to QQF file" ) );
78 connect( pbn, &QAbstractButton::clicked, this, &QgsQueryBuilder::saveQuery );
79
80 pbn = new QPushButton( tr( "&Load…" ) );
81 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
82 pbn->setToolTip( tr( "Load query from QQF file" ) );
83 connect( pbn, &QAbstractButton::clicked, this, &QgsQueryBuilder::loadQuery );
84
85 setupGuiViews();
86
87 mModelFields = new QgsFieldProxyModel();
89 mModelFields->sourceFieldModel()->setLayer( layer );
90 lstFields->setModel( mModelFields );
91
92 mOrigSubsetString = layer->subsetString();
93 connect( layer, &QgsVectorLayer::subsetStringChanged, this, &QgsQueryBuilder::layerSubsetStringChanged );
94 layerSubsetStringChanged();
95
96 QString subsetStringDialect;
97 QString subsetStringHelpUrl;
98
99 if ( QgsDataProvider *provider = layer->dataProvider() )
100 {
101 lblDataUri->setText( tr( "Set provider filter on %1 (provider: %2)" ).arg( layer->name(), provider->name() ) );
102 subsetStringDialect = provider->subsetStringDialect();
103 subsetStringHelpUrl = provider->subsetStringHelpUrl();
104 }
105 else
106 {
107 lblDataUri->setText( tr( "Set provider filter on %1 (provider: %2)" ).arg( layer->name(), layer->providerType() ) );
108 }
109
110 if ( !subsetStringDialect.isEmpty() && !subsetStringHelpUrl.isEmpty() )
111 {
112 lblProviderFilterInfo->setOpenExternalLinks( true );
113 lblProviderFilterInfo->setText( tr( "Enter a <a href=\"%1\">%2</a> to filter the layer" ).arg( subsetStringHelpUrl ).arg( subsetStringDialect ) ) ;
114 }
115 else if ( !subsetStringDialect.isEmpty() )
116 {
117 lblProviderFilterInfo->setText( tr( "Enter a %1 to filter the layer" ).arg( subsetStringDialect ) ) ;
118 }
119 else
120 {
121 lblProviderFilterInfo->hide();
122 }
123
124 mTxtSql->setText( mOrigSubsetString );
125
126 mFilterLineEdit->setShowSearchIcon( true );
127 mFilterLineEdit->setPlaceholderText( tr( "Search…" ) );
128 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged, this, &QgsQueryBuilder::onTextChanged );
129}
130
131void QgsQueryBuilder::showEvent( QShowEvent *event )
132{
133 mTxtSql->setFocus();
134 QDialog::showEvent( event );
135}
136
137void QgsQueryBuilder::setupGuiViews()
138{
139 //Initialize the models
140 mModelValues = new QStandardItemModel();
141 mProxyValues = new QSortFilterProxyModel();
142 mProxyValues->setSourceModel( mModelValues );
143 // Modes
144 lstFields->setViewMode( QListView::ListMode );
145 lstValues->setViewMode( QListView::ListMode );
146 lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
147 lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
148 // Performance tip since Qt 4.1
149 lstFields->setUniformItemSizes( true );
150 lstValues->setUniformItemSizes( true );
151 // Colored rows
152 lstFields->setAlternatingRowColors( true );
153 lstValues->setAlternatingRowColors( true );
154 lstValues->setModel( mProxyValues );
155}
156
157void QgsQueryBuilder::fillValues( const QString &field, int limit )
158{
159 // clear the model
160 mModelValues->clear();
161
162 const int fieldIndex = mLayer->fields().lookupField( field );
163
164 // determine the field type
165 QList<QVariant> values = qgis::setToList( mLayer->uniqueValues( fieldIndex, limit ) );
166 std::sort( values.begin(), values.end() );
167
168 const QString nullValue = QgsApplication::nullRepresentation();
169
170 QgsDebugMsgLevel( QStringLiteral( "nullValue: %1" ).arg( nullValue ), 2 );
171
172 const auto constValues = values;
173 for ( const QVariant &var : constValues )
174 {
175 QString value;
176 if ( QgsVariantUtils::isNull( var ) )
177 value = nullValue;
178 else if ( var.userType() == QMetaType::Type::QDate && mLayer->providerType() == QLatin1String( "ogr" ) && mLayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
179 value = var.toDate().toString( QStringLiteral( "yyyy/MM/dd" ) );
180 else if ( var.userType() == QMetaType::Type::QVariantList || var.userType() == QMetaType::Type::QStringList )
181 {
182 const QVariantList list = var.toList();
183 for ( const QVariant &val : list )
184 {
185 if ( !value.isEmpty() )
186 value.append( ", " );
187 value.append( QgsVariantUtils::isNull( val ) ? nullValue : val.toString() );
188 }
189 }
190 else
191 value = var.toString();
192
193 QStandardItem *myItem = new QStandardItem( value );
194 myItem->setEditable( false );
195 myItem->setData( var, Qt::UserRole + 1 );
196 mModelValues->insertRow( mModelValues->rowCount(), myItem );
197 QgsDebugMsgLevel( QStringLiteral( "Value is null: %1\nvalue: %2" ).arg( QgsVariantUtils::isNull( var ) ).arg( QgsVariantUtils::isNull( var ) ? nullValue : var.toString() ), 2 );
198 }
199}
200
201void QgsQueryBuilder::btnSampleValues_clicked()
202{
203 lstValues->setCursor( Qt::WaitCursor );
204
205 const QString prevSubsetString = mLayer->subsetString();
206 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
207 {
208 mIgnoreLayerSubsetStringChangedSignal = true;
209 mLayer->setSubsetString( QString() );
210 }
211
212 //Clear and fill the mModelValues
213 fillValues( mModelFields->data( lstFields->currentIndex(), static_cast< int >( QgsFieldModel::CustomRole::FieldName ) ).toString(), 25 );
214
215 if ( prevSubsetString != mLayer->subsetString() )
216 {
217 mLayer->setSubsetString( prevSubsetString );
218 mIgnoreLayerSubsetStringChangedSignal = false;
219 }
220
221 lstValues->setCursor( Qt::ArrowCursor );
222}
223
224void QgsQueryBuilder::btnGetAllValues_clicked()
225{
226 lstValues->setCursor( Qt::WaitCursor );
227
228 const QString prevSubsetString = mLayer->subsetString();
229 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
230 {
231 mIgnoreLayerSubsetStringChangedSignal = true;
232 mLayer->setSubsetString( QString() );
233 }
234
235 //Clear and fill the mModelValues
236 fillValues( mModelFields->data( lstFields->currentIndex(), static_cast< int >( QgsFieldModel::CustomRole::FieldName ) ).toString(), -1 );
237
238 if ( prevSubsetString != mLayer->subsetString() )
239 {
240 mLayer->setSubsetString( prevSubsetString );
241 mIgnoreLayerSubsetStringChangedSignal = false;
242 }
243
244 lstValues->setCursor( Qt::ArrowCursor );
245}
246
248{
249 // test the sql statement to see if it works
250 // by counting the number of records that would be
251 // returned
252
253 if ( mLayer->setSubsetString( mTxtSql->text() ) )
254 {
255 const long long featureCount { mLayer->featureCount() };
256 // Check for errors
257 if ( featureCount < 0 )
258 {
259 QMessageBox::warning( this,
260 tr( "Query Result" ),
261 tr( "An error occurred when executing the query, please check the expression syntax." ) );
262 }
263 else
264 {
265 QMessageBox::information( this,
266 tr( "Query Result" ),
267 tr( "The where clause returned %n row(s).", "returned test rows", featureCount ) );
268 }
269 }
270 else if ( mLayer->dataProvider()->hasErrors() )
271 {
272 QMessageBox::warning( this,
273 tr( "Query Result" ),
274 tr( "An error occurred when executing the query." )
275 + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( QLatin1Char( '\n' ) ) ) );
276 mLayer->dataProvider()->clearErrors();
277 }
278 else
279 {
280 QMessageBox::warning( this,
281 tr( "Query Result" ),
282 tr( "An error occurred when executing the query." ) );
283 }
284}
285
287{
288 if ( mTxtSql->text() != mOrigSubsetString )
289 {
290 if ( !mLayer->setSubsetString( mTxtSql->text() ) )
291 {
292 //error in query - show the problem
293 if ( mLayer->dataProvider()->hasErrors() )
294 {
295 QMessageBox::warning( this,
296 tr( "Query Result" ),
297 tr( "An error occurred when executing the query." )
298 + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( QLatin1Char( '\n' ) ) ) );
299 mLayer->dataProvider()->clearErrors();
300 }
301 else
302 {
303 QMessageBox::warning( this, tr( "Query Result" ), tr( "Error in query. The subset string could not be set." ) );
304 }
305
306 return;
307 }
308 }
309
310 QDialog::accept();
311}
312
314{
315 if ( mLayer->subsetString() != mOrigSubsetString )
316 mLayer->setSubsetString( mOrigSubsetString );
317
318 QDialog::reject();
319}
320
321void QgsQueryBuilder::btnEqual_clicked()
322{
323 mTxtSql->insertText( QStringLiteral( " = " ) );
324 mTxtSql->setFocus();
325}
326
327void QgsQueryBuilder::btnLessThan_clicked()
328{
329 mTxtSql->insertText( QStringLiteral( " < " ) );
330 mTxtSql->setFocus();
331}
332
333void QgsQueryBuilder::btnGreaterThan_clicked()
334{
335 mTxtSql->insertText( QStringLiteral( " > " ) );
336 mTxtSql->setFocus();
337}
338
339void QgsQueryBuilder::btnPct_clicked()
340{
341 mTxtSql->insertText( QStringLiteral( "%" ) );
342 mTxtSql->setFocus();
343}
344
345void QgsQueryBuilder::btnIn_clicked()
346{
347 mTxtSql->insertText( QStringLiteral( " IN " ) );
348 mTxtSql->setFocus();
349}
350
351void QgsQueryBuilder::btnNotIn_clicked()
352{
353 mTxtSql->insertText( QStringLiteral( " NOT IN " ) );
354 mTxtSql->setFocus();
355}
356
357void QgsQueryBuilder::btnLike_clicked()
358{
359 mTxtSql->insertText( QStringLiteral( " LIKE " ) );
360 mTxtSql->setFocus();
361}
362
363QString QgsQueryBuilder::sql() const
364{
365 return mTxtSql->text();
366}
367
368void QgsQueryBuilder::setSql( const QString &sqlStatement )
369{
370 mTxtSql->setText( sqlStatement );
371}
372
373void QgsQueryBuilder::lstFields_clicked( const QModelIndex &index )
374{
375 if ( mPreviousFieldRow != index.row() )
376 {
377 mPreviousFieldRow = index.row();
378
379 btnSampleValues->setEnabled( true );
380 btnGetAllValues->setEnabled( true );
381
382 mModelValues->clear();
383 mFilterLineEdit->clear();
384 }
385}
386
387void QgsQueryBuilder::lstFields_doubleClicked( const QModelIndex &index )
388{
389 mTxtSql->insertText( '\"' + mModelFields->data( index, static_cast< int >( QgsFieldModel::CustomRole::FieldName ) ).toString() + '\"' );
390 mTxtSql->setFocus();
391}
392
393void QgsQueryBuilder::lstValues_doubleClicked( const QModelIndex &index )
394{
395 const QVariant value = index.data( Qt::UserRole + 1 );
396 if ( QgsVariantUtils::isNull( value ) )
397 mTxtSql->insertText( QStringLiteral( "NULL" ) );
398 else if ( value.userType() == QMetaType::Type::QDate && mLayer->providerType() == QLatin1String( "ogr" ) && mLayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
399 mTxtSql->insertText( '\'' + value.toDate().toString( QStringLiteral( "yyyy/MM/dd" ) ) + '\'' );
400 else if ( value.userType() == QMetaType::Type::Int || value.userType() == QMetaType::Type::Double || value.userType() == QMetaType::Type::LongLong || value.userType() == QMetaType::Type::Bool )
401 mTxtSql->insertText( value.toString() );
402 else
403 mTxtSql->insertText( '\'' + value.toString().replace( '\'', QLatin1String( "''" ) ) + '\'' );
404
405 mTxtSql->setFocus();
406}
407
408void QgsQueryBuilder::btnLessEqual_clicked()
409{
410 mTxtSql->insertText( QStringLiteral( " <= " ) );
411 mTxtSql->setFocus();
412}
413
414void QgsQueryBuilder::btnGreaterEqual_clicked()
415{
416 mTxtSql->insertText( QStringLiteral( " >= " ) );
417 mTxtSql->setFocus();
418}
419
420void QgsQueryBuilder::btnNotEqual_clicked()
421{
422 mTxtSql->insertText( QStringLiteral( " != " ) );
423 mTxtSql->setFocus();
424}
425
426void QgsQueryBuilder::btnAnd_clicked()
427{
428 mTxtSql->insertText( QStringLiteral( " AND " ) );
429 mTxtSql->setFocus();
430}
431
432void QgsQueryBuilder::btnNot_clicked()
433{
434 mTxtSql->insertText( QStringLiteral( " NOT " ) );
435 mTxtSql->setFocus();
436}
437
438void QgsQueryBuilder::btnOr_clicked()
439{
440 mTxtSql->insertText( QStringLiteral( " OR " ) );
441 mTxtSql->setFocus();
442}
443
444void QgsQueryBuilder::onTextChanged( const QString &text )
445{
446 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
447 mProxyValues->setFilterWildcard( text );
448}
449
451{
452 mTxtSql->clear();
453 mLayer->setSubsetString( QString() );
454}
455
456void QgsQueryBuilder::btnILike_clicked()
457{
458 mTxtSql->insertText( QStringLiteral( " ILIKE " ) );
459 mTxtSql->setFocus();
460}
461
463{
464 lblDataUri->setText( uri );
465}
466
467void QgsQueryBuilder::showHelp()
468{
469 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#query-builder" ) );
470}
471
473{
474 const bool ok = saveQueryToFile( mTxtSql->text() );
475 Q_UNUSED( ok )
476}
477
478bool QgsQueryBuilder::saveQueryToFile( const QString &subset )
479{
480 QgsSettings s;
481 const QString lastQueryFileDir = s.value( QStringLiteral( "/UI/lastQueryFileDir" ), QDir::homePath() ).toString();
482 //save as qqf (QGIS query file)
483 QString saveFileName = QFileDialog::getSaveFileName( nullptr, tr( "Save Query to File" ), lastQueryFileDir, tr( "Query files (*.qqf *.QQF)" ) );
484 if ( saveFileName.isNull() )
485 {
486 return false;
487 }
488
489 if ( !saveFileName.endsWith( QLatin1String( ".qqf" ), Qt::CaseInsensitive ) )
490 {
491 saveFileName += QLatin1String( ".qqf" );
492 }
493
494 QFile saveFile( saveFileName );
495 if ( !saveFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
496 {
497 QMessageBox::critical( nullptr, tr( "Save Query to File" ), tr( "Could not open file for writing." ) );
498 return false ;
499 }
500
501 QDomDocument xmlDoc;
502 QDomElement queryElem = xmlDoc.createElement( QStringLiteral( "Query" ) );
503 const QDomText queryTextNode = xmlDoc.createTextNode( subset );
504 queryElem.appendChild( queryTextNode );
505 xmlDoc.appendChild( queryElem );
506
507 QTextStream fileStream( &saveFile );
508 xmlDoc.save( fileStream, 2 );
509
510 const QFileInfo fi( saveFile );
511 s.setValue( QStringLiteral( "/UI/lastQueryFileDir" ), fi.absolutePath() );
512 return true;
513}
514
516{
517 QString subset;
518 if ( loadQueryFromFile( subset ) )
519 {
520 mTxtSql->clear();
521 mTxtSql->insertText( subset );
522 }
523}
524
526{
527 const QgsSettings s;
528 const QString lastQueryFileDir = s.value( QStringLiteral( "/UI/lastQueryFileDir" ), QDir::homePath() ).toString();
529
530 const QString queryFileName = QFileDialog::getOpenFileName( nullptr, tr( "Load Query from File" ), lastQueryFileDir, tr( "Query files" ) + " (*.qqf);;" + tr( "All files" ) + " (*)" );
531 if ( queryFileName.isNull() )
532 {
533 return false;
534 }
535
536 QFile queryFile( queryFileName );
537 if ( !queryFile.open( QIODevice::ReadOnly ) )
538 {
539 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "Could not open file for reading." ) );
540 return false;
541 }
542 QDomDocument queryDoc;
543 if ( !queryDoc.setContent( &queryFile ) )
544 {
545 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "File is not a valid xml document." ) );
546 return false;
547 }
548
549 const QDomElement queryElem = queryDoc.firstChildElement( QStringLiteral( "Query" ) );
550 if ( queryElem.isNull() )
551 {
552 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "File is not a valid query document." ) );
553 return false;
554 }
555
556 subset = queryElem.text();
557 return true;
558}
559
560void QgsQueryBuilder::layerSubsetStringChanged()
561{
562 if ( mIgnoreLayerSubsetStringChangedSignal )
563 return;
564 mUseUnfilteredLayer->setDisabled( mLayer->subsetString().isEmpty() );
565}
static QString nullRepresentation()
Returns the string used to represent the value NULL throughout QGIS.
Abstract base class for spatial data provider implementations.
@ FieldName
Return field name if index corresponds to a field.
void setLayer(QgsVectorLayer *layer)
Set the layer from which fields are displayed.
The QgsFieldProxyModel class provides an easy to use model to display the list of fields of a layer.
QgsFieldModel * sourceFieldModel()
Returns the QgsFieldModel used in this QSortFilterProxyModel.
@ AllTypes
All field types.
@ OriginProvider
Fields with a provider origin, since QGIS 3.38.
QgsFieldProxyModel * setFilters(QgsFieldProxyModel::Filters filters)
Set flags that affect how fields are filtered in the model.
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:208
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
QString name
Definition qgsmaplayer.h:80
QString providerType() const
Returns the provider type (provider key) for this layer.
static bool loadQueryFromFile(QString &subset)
Load query from the XML file.
void loadQuery()
Load query from the XML file.
void saveQuery()
Save query to the XML file.
void accept() override
void reject() override
void setDatasourceDescription(const QString &uri)
void setSql(const QString &sqlStatement)
Set the sql statement to display in the dialog.
virtual void test()
The default implementation tests that the constructed sql statement to see if the vector layer data p...
static bool saveQueryToFile(const QString &subset)
Save query to the XML file.
void showEvent(QShowEvent *event) override
QgsQueryBuilder(QgsVectorLayer *layer, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
This constructor is used when the query builder is called from the vector layer properties dialog.
QString sql() const
Returns the sql statement entered in the dialog.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Interface for a dialog that can edit subset strings.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
void clearErrors()
Clear recorded errors.
QStringList errors() const
Gets recorded errors.
bool hasErrors() const
Provider has errors to report.
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39