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 const auto constValues = values;
157 for (
const QVariant &var : constValues )
162 else if ( var.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
163 value = var.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) );
165 value = var.toString();
167 QStandardItem *myItem =
new QStandardItem( value );
168 myItem->setEditable(
false );
169 myItem->setData( var, Qt::UserRole + 1 );
170 mModelValues->insertRow( mModelValues->rowCount(), myItem );
171 QgsDebugMsg( QStringLiteral(
"Value is null: %1\nvalue: %2" ).arg( var.isNull() ).arg( var.isNull() ? nullValue : var.toString() ) );
175 void QgsQueryBuilder::btnSampleValues_clicked()
177 lstValues->setCursor( Qt::WaitCursor );
180 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
186 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), 25 );
193 lstValues->setCursor( Qt::ArrowCursor );
196 void QgsQueryBuilder::btnGetAllValues_clicked()
198 lstValues->setCursor( Qt::WaitCursor );
201 if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
207 fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), -1 );
214 lstValues->setCursor( Qt::ArrowCursor );
225 mUseUnfilteredLayer->setDisabled( mLayer->
subsetString().isEmpty() );
227 QMessageBox::information(
this,
228 tr(
"Query Result" ),
229 tr(
"The where clause returned %n row(s).",
"returned test rows", mLayer->
featureCount() ) );
233 QMessageBox::warning(
this,
234 tr(
"Query Result" ),
235 tr(
"An error occurred when executing the query." )
236 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
241 QMessageBox::warning(
this,
242 tr(
"Query Result" ),
243 tr(
"An error occurred when executing the query." ) );
249 if ( txtSQL->text() != mOrigSubsetString )
256 QMessageBox::warning(
this,
257 tr(
"Query Result" ),
258 tr(
"An error occurred when executing the query." )
259 + tr(
"\nThe data provider said:\n%1" ).arg( mLayer->
dataProvider()->
errors().join( QStringLiteral(
"\n" ) ) ) );
264 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"Error in query. The subset string could not be set." ) );
282 void QgsQueryBuilder::btnEqual_clicked()
284 txtSQL->insertText( QStringLiteral(
" = " ) );
288 void QgsQueryBuilder::btnLessThan_clicked()
290 txtSQL->insertText( QStringLiteral(
" < " ) );
294 void QgsQueryBuilder::btnGreaterThan_clicked()
296 txtSQL->insertText( QStringLiteral(
" > " ) );
300 void QgsQueryBuilder::btnPct_clicked()
302 txtSQL->insertText( QStringLiteral(
"%" ) );
306 void QgsQueryBuilder::btnIn_clicked()
308 txtSQL->insertText( QStringLiteral(
" IN " ) );
312 void QgsQueryBuilder::btnNotIn_clicked()
314 txtSQL->insertText( QStringLiteral(
" NOT IN " ) );
318 void QgsQueryBuilder::btnLike_clicked()
320 txtSQL->insertText( QStringLiteral(
" LIKE " ) );
326 return txtSQL->text();
331 txtSQL->setText( sqlStatement );
334 void QgsQueryBuilder::lstFields_clicked(
const QModelIndex &index )
336 if ( mPreviousFieldRow != index.row() )
338 mPreviousFieldRow = index.row();
340 btnSampleValues->setEnabled(
true );
341 btnGetAllValues->setEnabled(
true );
343 mModelValues->clear();
344 mFilterLineEdit->clear();
348 void QgsQueryBuilder::lstFields_doubleClicked(
const QModelIndex &index )
350 txtSQL->insertText(
'\"' + mLayer->
fields().
at( mModelFields->data( index, Qt::UserRole + 1 ).toInt() ).name() +
'\"' );
354 void QgsQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
356 QVariant value = index.data( Qt::UserRole + 1 );
357 if ( value.isNull() )
358 txtSQL->insertText( QStringLiteral(
"NULL" ) );
359 else if ( value.type() == QVariant::Date && mLayer->
providerType() == QLatin1String(
"ogr" ) && mLayer->
storageType() == QLatin1String(
"ESRI Shapefile" ) )
360 txtSQL->insertText(
'\'' + value.toDate().toString( QStringLiteral(
"yyyy/MM/dd" ) ) +
'\'' );
361 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong || value.type() == QVariant::Bool )
362 txtSQL->insertText( value.toString() );
364 txtSQL->insertText(
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
369 void QgsQueryBuilder::btnLessEqual_clicked()
371 txtSQL->insertText( QStringLiteral(
" <= " ) );
375 void QgsQueryBuilder::btnGreaterEqual_clicked()
377 txtSQL->insertText( QStringLiteral(
" >= " ) );
381 void QgsQueryBuilder::btnNotEqual_clicked()
383 txtSQL->insertText( QStringLiteral(
" != " ) );
387 void QgsQueryBuilder::btnAnd_clicked()
389 txtSQL->insertText( QStringLiteral(
" AND " ) );
393 void QgsQueryBuilder::btnNot_clicked()
395 txtSQL->insertText( QStringLiteral(
" NOT " ) );
399 void QgsQueryBuilder::btnOr_clicked()
401 txtSQL->insertText( QStringLiteral(
" OR " ) );
405 void QgsQueryBuilder::onTextChanged(
const QString &text )
407 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
408 mProxyValues->setFilterWildcard( text );
415 mUseUnfilteredLayer->setDisabled(
true );
418 void QgsQueryBuilder::btnILike_clicked()
420 txtSQL->insertText( QStringLiteral(
" ILIKE " ) );
426 lblDataUri->setText( uri );
429 void QgsQueryBuilder::showHelp()
431 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)
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