23 #include <QMessageBox> 25 #include <QPushButton> 30 QWidget *parent, Qt::WindowFlags fl )
31 : QDialog( parent, fl )
32 , mPreviousFieldRow( -1 )
36 connect( btnEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnEqual_clicked );
37 connect( btnLessThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessThan_clicked );
38 connect( btnGreaterThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterThan_clicked );
39 connect( btnPct, &QPushButton::clicked,
this, &QgsQueryBuilder::btnPct_clicked );
40 connect( btnIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnIn_clicked );
41 connect( btnNotIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotIn_clicked );
42 connect( btnLike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLike_clicked );
43 connect( btnILike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnILike_clicked );
44 connect( lstFields, &QListView::clicked,
this, &QgsQueryBuilder::lstFields_clicked );
45 connect( lstFields, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstFields_doubleClicked );
46 connect( lstValues, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstValues_doubleClicked );
47 connect( btnLessEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessEqual_clicked );
48 connect( btnGreaterEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterEqual_clicked );
49 connect( btnNotEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotEqual_clicked );
50 connect( btnAnd, &QPushButton::clicked,
this, &QgsQueryBuilder::btnAnd_clicked );
51 connect( btnNot, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNot_clicked );
52 connect( btnOr, &QPushButton::clicked,
this, &QgsQueryBuilder::btnOr_clicked );
53 connect( btnGetAllValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGetAllValues_clicked );
54 connect( btnSampleValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnSampleValues_clicked );
55 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsQueryBuilder::showHelp );
58 restoreGeometry( settings.
value( QStringLiteral(
"Windows/QueryBuilder/geometry" ) ).toByteArray() );
60 QPushButton *pbn =
new QPushButton( tr(
"&Test" ) );
61 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
64 pbn =
new QPushButton( tr(
"&Clear" ) );
65 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
72 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
74 lblDataUri->setText( tr(
"Set provider filter on %1" ).arg( layer->
name() ) );
75 txtSQL->setText( mOrigSubsetString );
77 mFilterLineEdit->setShowSearchIcon(
true );
78 mFilterLineEdit->setPlaceholderText( tr(
"Search…" ) );
79 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged,
this, &QgsQueryBuilder::onTextChanged );
93 QDialog::showEvent( event );
96 void QgsQueryBuilder::populateFields()
99 for (
int idx = 0; idx < fields.
count(); ++idx )
106 QStandardItem *myItem =
new QStandardItem( fields.
at( idx ).
name() );
107 myItem->setData( idx );
108 myItem->setEditable(
false );
109 mModelFields->insertRow( mModelFields->rowCount(), myItem );
113 setupLstFieldsModel();
116 void QgsQueryBuilder::setupLstFieldsModel()
118 lstFields->setModel( mModelFields );
121 void QgsQueryBuilder::setupGuiViews()
124 mModelFields =
new QStandardItemModel();
125 mModelValues =
new QStandardItemModel();
126 mProxyValues =
new QSortFilterProxyModel();
127 mProxyValues->setSourceModel( mModelValues );
129 lstFields->setViewMode( QListView::ListMode );
130 lstValues->setViewMode( QListView::ListMode );
131 lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
132 lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
134 lstFields->setUniformItemSizes(
true );
135 lstValues->setUniformItemSizes(
true );
137 lstFields->setAlternatingRowColors(
true );
138 lstValues->setAlternatingRowColors(
true );
139 lstValues->setModel( mProxyValues );
142 void QgsQueryBuilder::fillValues(
int idx,
int limit )
145 mModelValues->clear();
148 QList<QVariant> values = mLayer->
uniqueValues( idx, limit ).toList();
149 std::sort( values.begin(), values.end() );
153 QgsDebugMsg( QStringLiteral(
"nullValue: %1" ).arg( nullValue ) );
155 Q_FOREACH (
const QVariant &var, values )
160 else if ( var.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
161 value = var.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) );
163 value = var.toString();
165 QStandardItem *myItem =
new QStandardItem( value );
166 myItem->setEditable(
false );
167 myItem->setData( var, Qt::UserRole + 1 );
168 mModelValues->insertRow( mModelValues->rowCount(), myItem );
169 QgsDebugMsg( QStringLiteral(
"Value is null: %1\nvalue: %2" ).arg( var.isNull() ).arg( var.isNull() ? nullValue : var.toString() ) );
173 void QgsQueryBuilder::btnSampleValues_clicked()
175 lstValues->setCursor( Qt::WaitCursor );
178 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
184 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), 25 );
191 lstValues->setCursor( Qt::ArrowCursor );
194 void QgsQueryBuilder::btnGetAllValues_clicked()
196 lstValues->setCursor( Qt::WaitCursor );
199 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
205 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), -1 );
212 lstValues->setCursor( Qt::ArrowCursor );
223 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
225 QMessageBox::information(
this,
226 tr(
"Query Result" ),
227 tr(
"The where clause returned %n row(s).",
"returned test rows", mLayer->
featureCount() ) );
231 QMessageBox::warning(
this,
232 tr(
"Query Result" ),
233 tr(
"An error occurred when executing the query." )
234 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
239 QMessageBox::warning(
this,
240 tr(
"Query Result" ),
241 tr(
"An error occurred when executing the query." ) );
247 if ( txtSQL->text() != mOrigSubsetString )
254 QMessageBox::warning(
this,
255 tr(
"Query Result" ),
256 tr(
"An error occurred when executing the query." )
257 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
262 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"Error in query. The subset string could not be set." ) );
280 void QgsQueryBuilder::btnEqual_clicked()
282 txtSQL->insertText( QStringLiteral(
" = " ) );
286 void QgsQueryBuilder::btnLessThan_clicked()
288 txtSQL->insertText( QStringLiteral(
" < " ) );
292 void QgsQueryBuilder::btnGreaterThan_clicked()
294 txtSQL->insertText( QStringLiteral(
" > " ) );
298 void QgsQueryBuilder::btnPct_clicked()
300 txtSQL->insertText( QStringLiteral(
"%" ) );
304 void QgsQueryBuilder::btnIn_clicked()
306 txtSQL->insertText( QStringLiteral(
" IN " ) );
310 void QgsQueryBuilder::btnNotIn_clicked()
312 txtSQL->insertText( QStringLiteral(
" NOT IN " ) );
316 void QgsQueryBuilder::btnLike_clicked()
318 txtSQL->insertText( QStringLiteral(
" LIKE " ) );
324 return txtSQL->text();
329 txtSQL->setText( sqlStatement );
332 void QgsQueryBuilder::lstFields_clicked(
const QModelIndex &index )
334 if ( mPreviousFieldRow != index.row() )
336 mPreviousFieldRow = index.row();
338 btnSampleValues->setEnabled(
true );
339 btnGetAllValues->setEnabled(
true );
341 mModelValues->clear();
342 mFilterLineEdit->clear();
346 void QgsQueryBuilder::lstFields_doubleClicked(
const QModelIndex &index )
348 txtSQL->insertText(
'\"' + mLayer->
fields().
at( mModelFields->data( index, Qt::UserRole + 1 ).toInt() ).name() +
'\"' );
352 void QgsQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
354 QVariant value = index.data( Qt::DisplayRole );
355 if ( value.isNull() )
356 txtSQL->insertText( QStringLiteral(
"NULL" ) );
357 else if ( value.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
358 txtSQL->insertText(
'\'' + value.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) ) +
'\'' );
359 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
360 txtSQL->insertText( value.toString() );
362 txtSQL->insertText(
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
367 void QgsQueryBuilder::btnLessEqual_clicked()
369 txtSQL->insertText( QStringLiteral(
" <= " ) );
373 void QgsQueryBuilder::btnGreaterEqual_clicked()
375 txtSQL->insertText( QStringLiteral(
" >= " ) );
379 void QgsQueryBuilder::btnNotEqual_clicked()
381 txtSQL->insertText( QStringLiteral(
" != " ) );
385 void QgsQueryBuilder::btnAnd_clicked()
387 txtSQL->insertText( QStringLiteral(
" AND " ) );
391 void QgsQueryBuilder::btnNot_clicked()
393 txtSQL->insertText( QStringLiteral(
" NOT " ) );
397 void QgsQueryBuilder::btnOr_clicked()
399 txtSQL->insertText( QStringLiteral(
" OR " ) );
403 void QgsQueryBuilder::onTextChanged(
const QString &text )
405 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
406 mProxyValues->setFilterWildcard( text );
413 mUseUnfilteredLayer->setDisabled(
true );
416 void QgsQueryBuilder::btnILike_clicked()
418 txtSQL->insertText( QStringLiteral(
" ILIKE " ) );
424 lblDataUri->setText( uri );
427 void QgsQueryBuilder::showHelp()
429 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/vector_properties.html#query-builder" ) );
void test()
Test the constructed sql statement to see if the vector layer data provider likes it...
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Container of fields for a vector layer.
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
~QgsQueryBuilder() override
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
void setSql(const QString &sqlStatement)
QgsFields fields() const FINAL
Returns the list of fields of this layer.
bool hasErrors() const
Provider has errors to report.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void clearErrors()
Clear recorded errors.
int count() const
Returns number of items.
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 providerType() const
Returns the provider type for this layer.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void setDatasourceDescription(const QString &uri)
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field's origin (value from an enumeration)
QStringList errors() const
Gets recorded errors.
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
virtual bool setSubsetString(const QString &subset)
Set the string (typically sql) used to define a subset of the layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider.
Represents a vector layer which manages a vector based data sets.
void showEvent(QShowEvent *event) override
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.