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 )
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() );
223 if ( featureCount < 0 )
225 QMessageBox::warning(
this,
226 tr(
"Query Result" ),
227 tr(
"An error occurred when executing the query, please check the expression syntax." ) );
231 QMessageBox::information(
this,
232 tr(
"Query Result" ),
233 tr(
"The where clause returned %n row(s).",
"returned test rows", featureCount ) );
238 QMessageBox::warning(
this,
239 tr(
"Query Result" ),
240 tr(
"An error occurred when executing the query." )
241 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
246 QMessageBox::warning(
this,
247 tr(
"Query Result" ),
248 tr(
"An error occurred when executing the query." ) );
254 if ( txtSQL->text() != mOrigSubsetString )
261 QMessageBox::warning(
this,
262 tr(
"Query Result" ),
263 tr(
"An error occurred when executing the query." )
264 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
269 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"Error in query. The subset string could not be set." ) );
287 void QgsQueryBuilder::btnEqual_clicked()
289 txtSQL->insertText( QStringLiteral(
" = " ) );
293 void QgsQueryBuilder::btnLessThan_clicked()
295 txtSQL->insertText( QStringLiteral(
" < " ) );
299 void QgsQueryBuilder::btnGreaterThan_clicked()
301 txtSQL->insertText( QStringLiteral(
" > " ) );
305 void QgsQueryBuilder::btnPct_clicked()
307 txtSQL->insertText( QStringLiteral(
"%" ) );
311 void QgsQueryBuilder::btnIn_clicked()
313 txtSQL->insertText( QStringLiteral(
" IN " ) );
317 void QgsQueryBuilder::btnNotIn_clicked()
319 txtSQL->insertText( QStringLiteral(
" NOT IN " ) );
323 void QgsQueryBuilder::btnLike_clicked()
325 txtSQL->insertText( QStringLiteral(
" LIKE " ) );
331 return txtSQL->text();
336 txtSQL->setText( sqlStatement );
339 void QgsQueryBuilder::lstFields_clicked(
const QModelIndex &index )
341 if ( mPreviousFieldRow != index.row() )
343 mPreviousFieldRow = index.row();
345 btnSampleValues->setEnabled(
true );
346 btnGetAllValues->setEnabled(
true );
348 mModelValues->clear();
349 mFilterLineEdit->clear();
353 void QgsQueryBuilder::lstFields_doubleClicked(
const QModelIndex &index )
355 txtSQL->insertText(
'\"' + mLayer->
fields().
at( mModelFields->data( index, Qt::UserRole + 1 ).toInt() ).name() +
'\"' );
359 void QgsQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
361 QVariant value = index.data( Qt::UserRole + 1 );
362 if ( value.isNull() )
363 txtSQL->insertText( QStringLiteral(
"NULL" ) );
364 else if ( value.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
365 txtSQL->insertText(
'\'' + value.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) ) +
'\'' );
366 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong || value.type() == QVariant::Bool )
367 txtSQL->insertText( value.toString() );
369 txtSQL->insertText(
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
374 void QgsQueryBuilder::btnLessEqual_clicked()
376 txtSQL->insertText( QStringLiteral(
" <= " ) );
380 void QgsQueryBuilder::btnGreaterEqual_clicked()
382 txtSQL->insertText( QStringLiteral(
" >= " ) );
386 void QgsQueryBuilder::btnNotEqual_clicked()
388 txtSQL->insertText( QStringLiteral(
" != " ) );
392 void QgsQueryBuilder::btnAnd_clicked()
394 txtSQL->insertText( QStringLiteral(
" AND " ) );
398 void QgsQueryBuilder::btnNot_clicked()
400 txtSQL->insertText( QStringLiteral(
" NOT " ) );
404 void QgsQueryBuilder::btnOr_clicked()
406 txtSQL->insertText( QStringLiteral(
" OR " ) );
410 void QgsQueryBuilder::onTextChanged(
const QString &text )
412 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
413 mProxyValues->setFilterWildcard( text );
420 mUseUnfilteredLayer->setDisabled(
true );
423 void QgsQueryBuilder::btnILike_clicked()
425 txtSQL->insertText( QStringLiteral(
" ILIKE " ) );
431 lblDataUri->setText( uri );
434 void QgsQueryBuilder::showHelp()
436 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.
QString displayNameWithAlias() const
Returns the name to use when displaying this field and adds the alias in parenthesis if it is defined...
void showEvent(QShowEvent *event) override