26 #include <QMessageBox> 28 #include <QPushButton> 33 QWidget *parent, Qt::WindowFlags fl )
34 : QDialog( parent, fl )
35 , mPreviousFieldRow( -1 )
40 connect( btnEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnEqual_clicked );
41 connect( btnLessThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessThan_clicked );
42 connect( btnGreaterThan, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterThan_clicked );
43 connect( btnPct, &QPushButton::clicked,
this, &QgsQueryBuilder::btnPct_clicked );
44 connect( btnIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnIn_clicked );
45 connect( btnNotIn, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotIn_clicked );
46 connect( btnLike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLike_clicked );
47 connect( btnILike, &QPushButton::clicked,
this, &QgsQueryBuilder::btnILike_clicked );
48 connect( lstFields, &QListView::clicked,
this, &QgsQueryBuilder::lstFields_clicked );
49 connect( lstFields, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstFields_doubleClicked );
50 connect( lstValues, &QListView::doubleClicked,
this, &QgsQueryBuilder::lstValues_doubleClicked );
51 connect( btnLessEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnLessEqual_clicked );
52 connect( btnGreaterEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGreaterEqual_clicked );
53 connect( btnNotEqual, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNotEqual_clicked );
54 connect( btnAnd, &QPushButton::clicked,
this, &QgsQueryBuilder::btnAnd_clicked );
55 connect( btnNot, &QPushButton::clicked,
this, &QgsQueryBuilder::btnNot_clicked );
56 connect( btnOr, &QPushButton::clicked,
this, &QgsQueryBuilder::btnOr_clicked );
57 connect( btnGetAllValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnGetAllValues_clicked );
58 connect( btnSampleValues, &QPushButton::clicked,
this, &QgsQueryBuilder::btnSampleValues_clicked );
59 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsQueryBuilder::showHelp );
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 );
88 QDialog::showEvent( event );
91 void QgsQueryBuilder::populateFields()
94 for (
int idx = 0; idx < fields.
count(); ++idx )
101 QStandardItem *myItem =
new QStandardItem( fields.
at( idx ).
name() );
102 myItem->setData( idx );
103 myItem->setEditable(
false );
104 mModelFields->insertRow( mModelFields->rowCount(), myItem );
108 setupLstFieldsModel();
111 void QgsQueryBuilder::setupLstFieldsModel()
113 lstFields->setModel( mModelFields );
116 void QgsQueryBuilder::setupGuiViews()
119 mModelFields =
new QStandardItemModel();
120 mModelValues =
new QStandardItemModel();
121 mProxyValues =
new QSortFilterProxyModel();
122 mProxyValues->setSourceModel( mModelValues );
124 lstFields->setViewMode( QListView::ListMode );
125 lstValues->setViewMode( QListView::ListMode );
126 lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
127 lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
129 lstFields->setUniformItemSizes(
true );
130 lstValues->setUniformItemSizes(
true );
132 lstFields->setAlternatingRowColors(
true );
133 lstValues->setAlternatingRowColors(
true );
134 lstValues->setModel( mProxyValues );
137 void QgsQueryBuilder::fillValues(
int idx,
int limit )
140 mModelValues->clear();
143 QList<QVariant> values = mLayer->
uniqueValues( idx, limit ).toList();
144 std::sort( values.begin(), values.end() );
148 QgsDebugMsg( QStringLiteral(
"nullValue: %1" ).arg( nullValue ) );
150 const auto constValues = values;
151 for (
const QVariant &var : constValues )
156 else if ( var.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
157 value = var.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) );
159 value = var.toString();
161 QStandardItem *myItem =
new QStandardItem( value );
162 myItem->setEditable(
false );
163 myItem->setData( var, Qt::UserRole + 1 );
164 mModelValues->insertRow( mModelValues->rowCount(), myItem );
165 QgsDebugMsg( QStringLiteral(
"Value is null: %1\nvalue: %2" ).arg( var.isNull() ).arg( var.isNull() ? nullValue : var.toString() ) );
169 void QgsQueryBuilder::btnSampleValues_clicked()
171 lstValues->setCursor( Qt::WaitCursor );
174 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
180 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), 25 );
187 lstValues->setCursor( Qt::ArrowCursor );
190 void QgsQueryBuilder::btnGetAllValues_clicked()
192 lstValues->setCursor( Qt::WaitCursor );
195 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
201 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), -1 );
208 lstValues->setCursor( Qt::ArrowCursor );
219 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
221 QMessageBox::information(
this,
222 tr(
"Query Result" ),
223 tr(
"The where clause returned %n row(s).",
"returned test rows", mLayer->
featureCount() ) );
227 QMessageBox::warning(
this,
228 tr(
"Query Result" ),
229 tr(
"An error occurred when executing the query." )
230 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
235 QMessageBox::warning(
this,
236 tr(
"Query Result" ),
237 tr(
"An error occurred when executing the query." ) );
243 if ( txtSQL->text() != mOrigSubsetString )
250 QMessageBox::warning(
this,
251 tr(
"Query Result" ),
252 tr(
"An error occurred when executing the query." )
253 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
258 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"Error in query. The subset string could not be set." ) );
276 void QgsQueryBuilder::btnEqual_clicked()
278 txtSQL->insertText( QStringLiteral(
" = " ) );
282 void QgsQueryBuilder::btnLessThan_clicked()
284 txtSQL->insertText( QStringLiteral(
" < " ) );
288 void QgsQueryBuilder::btnGreaterThan_clicked()
290 txtSQL->insertText( QStringLiteral(
" > " ) );
294 void QgsQueryBuilder::btnPct_clicked()
296 txtSQL->insertText( QStringLiteral(
"%" ) );
300 void QgsQueryBuilder::btnIn_clicked()
302 txtSQL->insertText( QStringLiteral(
" IN " ) );
306 void QgsQueryBuilder::btnNotIn_clicked()
308 txtSQL->insertText( QStringLiteral(
" NOT IN " ) );
312 void QgsQueryBuilder::btnLike_clicked()
314 txtSQL->insertText( QStringLiteral(
" LIKE " ) );
320 return txtSQL->text();
325 txtSQL->setText( sqlStatement );
328 void QgsQueryBuilder::lstFields_clicked(
const QModelIndex &index )
330 if ( mPreviousFieldRow != index.row() )
332 mPreviousFieldRow = index.row();
334 btnSampleValues->setEnabled(
true );
335 btnGetAllValues->setEnabled(
true );
337 mModelValues->clear();
338 mFilterLineEdit->clear();
342 void QgsQueryBuilder::lstFields_doubleClicked(
const QModelIndex &index )
344 txtSQL->insertText(
'\"' + mLayer->
fields().
at( mModelFields->data( index, Qt::UserRole + 1 ).toInt() ).name() +
'\"' );
348 void QgsQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
350 QVariant value = index.data( Qt::UserRole + 1 );
351 if ( value.isNull() )
352 txtSQL->insertText( QStringLiteral(
"NULL" ) );
353 else if ( value.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
354 txtSQL->insertText(
'\'' + value.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) ) +
'\'' );
355 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong || value.type() == QVariant::Bool )
356 txtSQL->insertText( value.toString() );
358 txtSQL->insertText(
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
363 void QgsQueryBuilder::btnLessEqual_clicked()
365 txtSQL->insertText( QStringLiteral(
" <= " ) );
369 void QgsQueryBuilder::btnGreaterEqual_clicked()
371 txtSQL->insertText( QStringLiteral(
" >= " ) );
375 void QgsQueryBuilder::btnNotEqual_clicked()
377 txtSQL->insertText( QStringLiteral(
" != " ) );
381 void QgsQueryBuilder::btnAnd_clicked()
383 txtSQL->insertText( QStringLiteral(
" AND " ) );
387 void QgsQueryBuilder::btnNot_clicked()
389 txtSQL->insertText( QStringLiteral(
" NOT " ) );
393 void QgsQueryBuilder::btnOr_clicked()
395 txtSQL->insertText( QStringLiteral(
" OR " ) );
399 void QgsQueryBuilder::onTextChanged(
const QString &text )
401 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
402 mProxyValues->setFilterWildcard( text );
409 mUseUnfilteredLayer->setDisabled(
true );
412 void QgsQueryBuilder::btnILike_clicked()
414 txtSQL->insertText( QStringLiteral(
" ILIKE " ) );
420 lblDataUri->setText( uri );
423 void QgsQueryBuilder::showHelp()
425 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...
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
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 ...
static QgsGui * instance()
Returns a pointer to the singleton instance.
int count() const
Returns number of items.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
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 setDatasourceDescription(const QString &uri)
bool hasErrors() const
Provider has errors to report.
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...
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)
Sets the string (typically sql) used to define a subset of the layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Represents a vector layer which manages a vector based data sets.
void showEvent(QShowEvent *event) override