24 #include <QMessageBox> 26 #include <QPushButton> 31 QWidget *parent, Qt::WindowFlags fl )
32 : QDialog( parent, fl )
33 , mPreviousFieldRow( -1 )
37 connect( btnEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnEqual_clicked );
38 connect( btnLessThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessThan_clicked );
39 connect( btnGreaterThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterThan_clicked );
40 connect( btnPct, &QPushButton::clicked,
this, &QgsQueryBuilder::btnPct_clicked );
41 connect( btnIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnIn_clicked );
42 connect( btnNotIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotIn_clicked );
43 connect( btnLike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLike_clicked );
44 connect( btnILike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnILike_clicked );
45 connect( lstFields, &QListView::clicked,
this, &QgsQueryBuilder::lstFields_clicked );
46 connect( lstFields, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstFields_doubleClicked );
47 connect( lstValues, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstValues_doubleClicked );
48 connect( btnLessEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessEqual_clicked );
49 connect( btnGreaterEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterEqual_clicked );
50 connect( btnNotEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotEqual_clicked );
51 connect( btnAnd, &QPushButton::clicked,
this, &QgsQueryBuilder::btnAnd_clicked );
52 connect( btnNot, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNot_clicked );
53 connect( btnOr, &QPushButton::clicked,
this, &QgsQueryBuilder::btnOr_clicked );
54 connect( btnGetAllValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGetAllValues_clicked );
55 connect( btnSampleValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnSampleValues_clicked );
56 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsQueryBuilder::showHelp );
59 restoreGeometry( settings.
value( QStringLiteral(
"Windows/QueryBuilder/geometry" ) ).toByteArray() );
61 QPushButton *pbn =
new QPushButton( tr(
"&Test" ) );
62 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
65 pbn =
new QPushButton( tr(
"&Clear" ) );
66 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
73 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
75 lblDataUri->setText( tr(
"Set provider filter on %1" ).arg( layer->
name() ) );
76 txtSQL->setText( mOrigSubsetString );
78 mFilterLineEdit->setShowSearchIcon(
true );
79 mFilterLineEdit->setPlaceholderText( tr(
"Search…" ) );
80 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged,
this, &QgsQueryBuilder::onTextChanged );
94 QDialog::showEvent( event );
97 void QgsQueryBuilder::populateFields()
100 for (
int idx = 0; idx < fields.
count(); ++idx )
107 QStandardItem *myItem =
new QStandardItem( fields.
at( idx ).
name() );
108 myItem->setData( idx );
109 myItem->setEditable(
false );
110 mModelFields->insertRow( mModelFields->rowCount(), myItem );
114 setupLstFieldsModel();
117 void QgsQueryBuilder::setupLstFieldsModel()
119 lstFields->setModel( mModelFields );
122 void QgsQueryBuilder::setupGuiViews()
125 mModelFields =
new QStandardItemModel();
126 mModelValues =
new QStandardItemModel();
127 mProxyValues =
new QSortFilterProxyModel();
128 mProxyValues->setSourceModel( mModelValues );
130 lstFields->setViewMode( QListView::ListMode );
131 lstValues->setViewMode( QListView::ListMode );
132 lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
133 lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
135 lstFields->setUniformItemSizes(
true );
136 lstValues->setUniformItemSizes(
true );
138 lstFields->setAlternatingRowColors(
true );
139 lstValues->setAlternatingRowColors(
true );
140 lstValues->setModel( mProxyValues );
143 void QgsQueryBuilder::fillValues(
int idx,
int limit )
146 mModelValues->clear();
149 QList<QVariant> values = mLayer->
uniqueValues( idx, limit ).toList();
150 std::sort( values.begin(), values.end() );
154 QgsDebugMsg( QStringLiteral(
"nullValue: %1" ).arg( nullValue ) );
156 Q_FOREACH (
const QVariant &var, values )
161 else if ( var.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
162 value = var.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) );
164 value = var.toString();
166 QStandardItem *myItem =
new QStandardItem( value );
167 myItem->setEditable(
false );
168 myItem->setData( var, Qt::UserRole + 1 );
169 mModelValues->insertRow( mModelValues->rowCount(), myItem );
170 QgsDebugMsg( QStringLiteral(
"Value is null: %1\nvalue: %2" ).arg( var.isNull() ).arg( var.isNull() ? nullValue : var.toString() ) );
174 void QgsQueryBuilder::btnSampleValues_clicked()
176 lstValues->setCursor( Qt::WaitCursor );
179 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
185 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), 25 );
192 lstValues->setCursor( Qt::ArrowCursor );
195 void QgsQueryBuilder::btnGetAllValues_clicked()
197 lstValues->setCursor( Qt::WaitCursor );
200 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
206 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), -1 );
213 lstValues->setCursor( Qt::ArrowCursor );
224 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
226 QMessageBox::information(
this,
227 tr(
"Query Result" ),
228 tr(
"The where clause returned %n row(s).",
"returned test rows", mLayer->
featureCount() ) );
232 QMessageBox::warning(
this,
233 tr(
"Query Result" ),
234 tr(
"An error occurred when executing the query." )
235 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
240 QMessageBox::warning(
this,
241 tr(
"Query Result" ),
242 tr(
"An error occurred when executing the query." ) );
248 if ( txtSQL->text() != mOrigSubsetString )
255 QMessageBox::warning(
this,
256 tr(
"Query Result" ),
257 tr(
"An error occurred when executing the query." )
258 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
263 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"Error in query. The subset string could not be set." ) );
281 void QgsQueryBuilder::btnEqual_clicked()
283 txtSQL->insertText( QStringLiteral(
" = " ) );
287 void QgsQueryBuilder::btnLessThan_clicked()
289 txtSQL->insertText( QStringLiteral(
" < " ) );
293 void QgsQueryBuilder::btnGreaterThan_clicked()
295 txtSQL->insertText( QStringLiteral(
" > " ) );
299 void QgsQueryBuilder::btnPct_clicked()
301 txtSQL->insertText( QStringLiteral(
"%" ) );
305 void QgsQueryBuilder::btnIn_clicked()
307 txtSQL->insertText( QStringLiteral(
" IN " ) );
311 void QgsQueryBuilder::btnNotIn_clicked()
313 txtSQL->insertText( QStringLiteral(
" NOT IN " ) );
317 void QgsQueryBuilder::btnLike_clicked()
319 txtSQL->insertText( QStringLiteral(
" LIKE " ) );
325 return txtSQL->text();
330 txtSQL->setText( sqlStatement );
333 void QgsQueryBuilder::lstFields_clicked(
const QModelIndex &index )
335 if ( mPreviousFieldRow != index.row() )
337 mPreviousFieldRow = index.row();
339 btnSampleValues->setEnabled(
true );
340 btnGetAllValues->setEnabled(
true );
342 mModelValues->clear();
343 mFilterLineEdit->clear();
347 void QgsQueryBuilder::lstFields_doubleClicked(
const QModelIndex &index )
349 txtSQL->insertText(
'\"' + mLayer->
fields().
at( mModelFields->data( index, Qt::UserRole + 1 ).toInt() ).name() +
'\"' );
353 void QgsQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
355 QVariant value = index.data( Qt::DisplayRole );
356 if ( value.isNull() )
357 txtSQL->insertText( QStringLiteral(
"NULL" ) );
358 else if ( value.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
359 txtSQL->insertText(
'\'' + value.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) ) +
'\'' );
360 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
361 txtSQL->insertText( value.toString() );
363 txtSQL->insertText(
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
368 void QgsQueryBuilder::btnLessEqual_clicked()
370 txtSQL->insertText( QStringLiteral(
" <= " ) );
374 void QgsQueryBuilder::btnGreaterEqual_clicked()
376 txtSQL->insertText( QStringLiteral(
" >= " ) );
380 void QgsQueryBuilder::btnNotEqual_clicked()
382 txtSQL->insertText( QStringLiteral(
" != " ) );
386 void QgsQueryBuilder::btnAnd_clicked()
388 txtSQL->insertText( QStringLiteral(
" AND " ) );
392 void QgsQueryBuilder::btnNot_clicked()
394 txtSQL->insertText( QStringLiteral(
" NOT " ) );
398 void QgsQueryBuilder::btnOr_clicked()
400 txtSQL->insertText( QStringLiteral(
" OR " ) );
404 void QgsQueryBuilder::onTextChanged(
const QString &text )
406 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
407 mProxyValues->setFilterWildcard( text );
414 mUseUnfilteredLayer->setDisabled(
true );
417 void QgsQueryBuilder::btnILike_clicked()
419 txtSQL->insertText( QStringLiteral(
" ILIKE " ) );
425 lblDataUri->setText( uri );
428 void QgsQueryBuilder::showHelp()
430 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/vector_properties.html#query-builder" ) );
FieldOrigin fieldOrigin(int fieldIdx) const
Gets field's origin (value from an enumeration)
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:
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QString providerType() const
Returns the provider type (provider key) for this layer.
Container of fields for a vector layer.
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
int count() const
Returns number of items.
~QgsQueryBuilder() override
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
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.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QStringList errors() const
Gets recorded errors.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void clearErrors()
Clear recorded errors.
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...
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)
bool hasErrors() const
Provider has errors to report.
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, it may be null.
Represents a vector layer which manages a vector based data sets.
void showEvent(QShowEvent *event) override