QGIS API Documentation 3.41.0-Master (af5edcb665c)
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 "moc_qgsquerybuilder.cpp"
17#include "qgslogger.h"
18#include "qgssettings.h"
19#include "qgsvectorlayer.h"
21#include "qgsapplication.h"
22#include "qgshelp.h"
23#include "qgsgui.h"
24#include "qgsfieldproxymodel.h"
25#include "qgsfieldmodel.h"
26
27#include <QDomDocument>
28#include <QDomElement>
29#include <QFileDialog>
30#include <QInputDialog>
31#include <QListView>
32#include <QMessageBox>
33#include <QPushButton>
34#include <QTextStream>
35
36
37// constructor used when the query builder must make its own
38// connection to the database
39QgsQueryBuilder::QgsQueryBuilder( QgsVectorLayer *layer, 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, tr( "Query Result" ), tr( "An error occurred when executing the query, please check the expression syntax." ) );
260 }
261 else
262 {
263 QMessageBox::information( this, tr( "Query Result" ), tr( "The where clause returned %n row(s).", "returned test rows", featureCount ) );
264 }
265 }
266 else if ( mLayer->dataProvider()->hasErrors() )
267 {
268 QMessageBox::warning( this, tr( "Query Result" ), tr( "An error occurred when executing the query." ) + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( QLatin1Char( '\n' ) ) ) );
269 mLayer->dataProvider()->clearErrors();
270 }
271 else
272 {
273 QMessageBox::warning( this, tr( "Query Result" ), tr( "An error occurred when executing the query." ) );
274 }
275}
276
278{
279 if ( mTxtSql->text() != mOrigSubsetString )
280 {
281 if ( !mLayer->setSubsetString( mTxtSql->text() ) )
282 {
283 //error in query - show the problem
284 if ( mLayer->dataProvider()->hasErrors() )
285 {
286 QMessageBox::warning( this, tr( "Query Result" ), tr( "An error occurred when executing the query." ) + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( QLatin1Char( '\n' ) ) ) );
287 mLayer->dataProvider()->clearErrors();
288 }
289 else
290 {
291 QMessageBox::warning( this, tr( "Query Result" ), tr( "Error in query. The subset string could not be set." ) );
292 }
293
294 return;
295 }
296 }
297
298 QDialog::accept();
299}
300
302{
303 if ( mLayer->subsetString() != mOrigSubsetString )
304 mLayer->setSubsetString( mOrigSubsetString );
305
306 QDialog::reject();
307}
308
309void QgsQueryBuilder::btnEqual_clicked()
310{
311 mTxtSql->insertText( QStringLiteral( " = " ) );
312 mTxtSql->setFocus();
313}
314
315void QgsQueryBuilder::btnLessThan_clicked()
316{
317 mTxtSql->insertText( QStringLiteral( " < " ) );
318 mTxtSql->setFocus();
319}
320
321void QgsQueryBuilder::btnGreaterThan_clicked()
322{
323 mTxtSql->insertText( QStringLiteral( " > " ) );
324 mTxtSql->setFocus();
325}
326
327void QgsQueryBuilder::btnPct_clicked()
328{
329 mTxtSql->insertText( QStringLiteral( "%" ) );
330 mTxtSql->setFocus();
331}
332
333void QgsQueryBuilder::btnIn_clicked()
334{
335 mTxtSql->insertText( QStringLiteral( " IN " ) );
336 mTxtSql->setFocus();
337}
338
339void QgsQueryBuilder::btnNotIn_clicked()
340{
341 mTxtSql->insertText( QStringLiteral( " NOT IN " ) );
342 mTxtSql->setFocus();
343}
344
345void QgsQueryBuilder::btnLike_clicked()
346{
347 mTxtSql->insertText( QStringLiteral( " LIKE " ) );
348 mTxtSql->setFocus();
349}
350
351QString QgsQueryBuilder::sql() const
352{
353 return mTxtSql->text();
354}
355
356void QgsQueryBuilder::setSql( const QString &sqlStatement )
357{
358 mTxtSql->setText( sqlStatement );
359}
360
361void QgsQueryBuilder::lstFields_clicked( const QModelIndex &index )
362{
363 if ( mPreviousFieldRow != index.row() )
364 {
365 mPreviousFieldRow = index.row();
366
367 btnSampleValues->setEnabled( true );
368 btnGetAllValues->setEnabled( true );
369
370 mModelValues->clear();
371 mFilterLineEdit->clear();
372 }
373}
374
375void QgsQueryBuilder::lstFields_doubleClicked( const QModelIndex &index )
376{
377 mTxtSql->insertText( '\"' + mModelFields->data( index, static_cast<int>( QgsFieldModel::CustomRole::FieldName ) ).toString() + '\"' );
378 mTxtSql->setFocus();
379}
380
381void QgsQueryBuilder::lstValues_doubleClicked( const QModelIndex &index )
382{
383 const QVariant value = index.data( Qt::UserRole + 1 );
384 if ( QgsVariantUtils::isNull( value ) )
385 mTxtSql->insertText( QStringLiteral( "NULL" ) );
386 else if ( value.userType() == QMetaType::Type::QDate && mLayer->providerType() == QLatin1String( "ogr" ) && mLayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
387 mTxtSql->insertText( '\'' + value.toDate().toString( QStringLiteral( "yyyy/MM/dd" ) ) + '\'' );
388 else if ( value.userType() == QMetaType::Type::Int || value.userType() == QMetaType::Type::Double || value.userType() == QMetaType::Type::LongLong || value.userType() == QMetaType::Type::Bool )
389 mTxtSql->insertText( value.toString() );
390 else
391 mTxtSql->insertText( '\'' + value.toString().replace( '\'', QLatin1String( "''" ) ) + '\'' );
392
393 mTxtSql->setFocus();
394}
395
396void QgsQueryBuilder::btnLessEqual_clicked()
397{
398 mTxtSql->insertText( QStringLiteral( " <= " ) );
399 mTxtSql->setFocus();
400}
401
402void QgsQueryBuilder::btnGreaterEqual_clicked()
403{
404 mTxtSql->insertText( QStringLiteral( " >= " ) );
405 mTxtSql->setFocus();
406}
407
408void QgsQueryBuilder::btnNotEqual_clicked()
409{
410 mTxtSql->insertText( QStringLiteral( " != " ) );
411 mTxtSql->setFocus();
412}
413
414void QgsQueryBuilder::btnAnd_clicked()
415{
416 mTxtSql->insertText( QStringLiteral( " AND " ) );
417 mTxtSql->setFocus();
418}
419
420void QgsQueryBuilder::btnNot_clicked()
421{
422 mTxtSql->insertText( QStringLiteral( " NOT " ) );
423 mTxtSql->setFocus();
424}
425
426void QgsQueryBuilder::btnOr_clicked()
427{
428 mTxtSql->insertText( QStringLiteral( " OR " ) );
429 mTxtSql->setFocus();
430}
431
432void QgsQueryBuilder::onTextChanged( const QString &text )
433{
434 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
435 mProxyValues->setFilterWildcard( text );
436}
437
439{
440 mTxtSql->clear();
441 mLayer->setSubsetString( QString() );
442}
443
444void QgsQueryBuilder::btnILike_clicked()
445{
446 mTxtSql->insertText( QStringLiteral( " ILIKE " ) );
447 mTxtSql->setFocus();
448}
449
451{
452 lblDataUri->setText( uri );
453}
454
455void QgsQueryBuilder::showHelp()
456{
457 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#query-builder" ) );
458}
459
461{
462 const bool ok = saveQueryToFile( mTxtSql->text() );
463 Q_UNUSED( ok )
464}
465
466bool QgsQueryBuilder::saveQueryToFile( const QString &subset )
467{
468 QgsSettings s;
469 const QString lastQueryFileDir = s.value( QStringLiteral( "/UI/lastQueryFileDir" ), QDir::homePath() ).toString();
470 //save as qqf (QGIS query file)
471 QString saveFileName = QFileDialog::getSaveFileName( nullptr, tr( "Save Query to File" ), lastQueryFileDir, tr( "Query files (*.qqf *.QQF)" ) );
472 if ( saveFileName.isNull() )
473 {
474 return false;
475 }
476
477 if ( !saveFileName.endsWith( QLatin1String( ".qqf" ), Qt::CaseInsensitive ) )
478 {
479 saveFileName += QLatin1String( ".qqf" );
480 }
481
482 QFile saveFile( saveFileName );
483 if ( !saveFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
484 {
485 QMessageBox::critical( nullptr, tr( "Save Query to File" ), tr( "Could not open file for writing." ) );
486 return false;
487 }
488
489 QDomDocument xmlDoc;
490 QDomElement queryElem = xmlDoc.createElement( QStringLiteral( "Query" ) );
491 const QDomText queryTextNode = xmlDoc.createTextNode( subset );
492 queryElem.appendChild( queryTextNode );
493 xmlDoc.appendChild( queryElem );
494
495 QTextStream fileStream( &saveFile );
496 xmlDoc.save( fileStream, 2 );
497
498 const QFileInfo fi( saveFile );
499 s.setValue( QStringLiteral( "/UI/lastQueryFileDir" ), fi.absolutePath() );
500 return true;
501}
502
504{
505 QString subset;
506 if ( loadQueryFromFile( subset ) )
507 {
508 mTxtSql->clear();
509 mTxtSql->insertText( subset );
510 }
511}
512
514{
515 const QgsSettings s;
516 const QString lastQueryFileDir = s.value( QStringLiteral( "/UI/lastQueryFileDir" ), QDir::homePath() ).toString();
517
518 const QString queryFileName = QFileDialog::getOpenFileName( nullptr, tr( "Load Query from File" ), lastQueryFileDir, tr( "Query files" ) + " (*.qqf);;" + tr( "All files" ) + " (*)" );
519 if ( queryFileName.isNull() )
520 {
521 return false;
522 }
523
524 QFile queryFile( queryFileName );
525 if ( !queryFile.open( QIODevice::ReadOnly ) )
526 {
527 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "Could not open file for reading." ) );
528 return false;
529 }
530 QDomDocument queryDoc;
531 if ( !queryDoc.setContent( &queryFile ) )
532 {
533 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "File is not a valid xml document." ) );
534 return false;
535 }
536
537 const QDomElement queryElem = queryDoc.firstChildElement( QStringLiteral( "Query" ) );
538 if ( queryElem.isNull() )
539 {
540 QMessageBox::critical( nullptr, tr( "Load Query from File" ), tr( "File is not a valid query document." ) );
541 return false;
542 }
543
544 subset = queryElem.text();
545 return true;
546}
547
548void QgsQueryBuilder::layerSubsetStringChanged()
549{
550 if ( mIgnoreLayerSubsetStringChangedSignal )
551 return;
552 mUseUnfilteredLayer->setDisabled( mLayer->subsetString().isEmpty() );
553}
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:210
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