19#include "qgspointcloudexpression.h"
24#include <QDomDocument>
33#include "moc_qgspointcloudquerybuilder.cpp"
35using namespace Qt::StringLiterals;
47 connect( lstAttributes->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsPointCloudQueryBuilder::lstAttributes_currentChanged );
48 connect( lstAttributes, &QListView::doubleClicked,
this, &QgsPointCloudQueryBuilder::lstAttributes_doubleClicked );
49 connect( lstValues, &QListView::doubleClicked,
this, &QgsPointCloudQueryBuilder::lstValues_doubleClicked );
50 connect( btnEqual, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnEqual_clicked );
51 connect( btnLessThan, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnLessThan_clicked );
52 connect( btnGreaterThan, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnGreaterThan_clicked );
53 connect( btnIn, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnIn_clicked );
54 connect( btnNotIn, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnNotIn_clicked );
55 connect( btnLessEqual, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnLessEqual_clicked );
56 connect( btnGreaterEqual, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnGreaterEqual_clicked );
57 connect( btnNotEqual, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnNotEqual_clicked );
58 connect( btnAnd, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnAnd_clicked );
59 connect( btnOr, &QPushButton::clicked,
this, &QgsPointCloudQueryBuilder::btnOr_clicked );
61 QPushButton *pbn =
new QPushButton( tr(
"&Test" ) );
62 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
63 connect( pbn, &QAbstractButton::clicked,
this, &QgsPointCloudQueryBuilder::test );
65 pbn =
new QPushButton( tr(
"&Clear" ) );
66 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
67 connect( pbn, &QAbstractButton::clicked,
this, &QgsPointCloudQueryBuilder::clear );
69 pbn =
new QPushButton( tr(
"&Save…" ) );
70 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
71 pbn->setToolTip( tr(
"Save query to QQF file" ) );
72 connect( pbn, &QAbstractButton::clicked,
this, &QgsPointCloudQueryBuilder::saveQuery );
74 pbn =
new QPushButton( tr(
"&Load…" ) );
75 buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
76 pbn->setToolTip( tr(
"Load query from QQF file" ) );
77 connect( pbn, &QAbstractButton::clicked,
this, &QgsPointCloudQueryBuilder::loadQuery );
79 lblDataUri->setText( tr(
"Set provider filter on %1" ).arg( layer->
name() ) );
85 QDialog::showEvent( event );
88void QgsPointCloudQueryBuilder::setupGuiViews()
91 mModelAttributes =
new QStandardItemModel();
92 mModelValues =
new QStandardItemModel();
95 lstAttributes->setViewMode( QListView::ListMode );
96 lstValues->setViewMode( QListView::ListMode );
97 lstAttributes->setSelectionBehavior( QAbstractItemView::SelectRows );
98 lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
99 lstAttributes->setEditTriggers( QAbstractItemView::NoEditTriggers );
100 lstValues->setEditTriggers( QAbstractItemView::NoEditTriggers );
102 lstAttributes->setUniformItemSizes(
true );
103 lstValues->setUniformItemSizes(
true );
105 lstAttributes->setAlternatingRowColors(
true );
106 lstValues->setAlternatingRowColors(
true );
108 lstAttributes->setModel( mModelAttributes );
109 lstValues->setModel( mModelValues );
112void QgsPointCloudQueryBuilder::populateAttributes()
114 const QgsFields &fields = mLayer->dataProvider()->attributes().toFields();
115 mTxtSql->setFields( fields );
116 for (
int idx = 0; idx < fields.
count(); ++idx )
119 mModelAttributes->insertRow( mModelAttributes->rowCount(), myItem );
123void QgsPointCloudQueryBuilder::lstAttributes_currentChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
127 mModelValues->clear();
128 const QString attribute = current.data().toString();
129 if ( attribute.compare(
"Classification"_L1, Qt::CaseInsensitive ) == 0 )
132 for (
int i = 0; i <= 18; ++i )
134 QStandardItem *item =
new QStandardItem( QString(
"%1: %2" ).arg( i ).arg( codes.value( i ) ) );
135 item->setData( i, Qt::UserRole );
136 mModelValues->insertRow( mModelValues->rowCount(), item );
141 const QgsPointCloudStatistics stats = mLayer->statistics();
142 double value = stats.
minimum( attribute );
143 QString valueString = std::isnan( value ) ? tr(
"n/a" ) : QString::number( value );
144 QStandardItem *item =
new QStandardItem( tr(
"Minimum: %1" ).arg( valueString ) );
145 item->setData( value, Qt::UserRole );
146 mModelValues->insertRow( mModelValues->rowCount(), item );
148 value = stats.
maximum( attribute );
149 valueString = std::isnan( value ) ? tr(
"n/a" ) : QString::number( value );
150 item =
new QStandardItem( tr(
"Maximum: %1" ).arg( valueString ) );
151 item->setData( value, Qt::UserRole );
152 mModelValues->insertRow( mModelValues->rowCount(), item );
154 value = stats.
mean( attribute );
155 valueString = std::isnan( value ) ? tr(
"n/a" ) : QString::number( value );
156 item =
new QStandardItem( tr(
"Mean: %1" ).arg( valueString ) );
157 item->setData( value, Qt::UserRole );
158 mModelValues->insertRow( mModelValues->rowCount(), item );
160 value = stats.
stDev( attribute );
161 valueString = std::isnan( value ) ? tr(
"n/a" ) : QString::number( value );
162 item =
new QStandardItem( tr(
"StdDev: %1" ).arg( valueString ) );
163 item->setData( value, Qt::UserRole );
164 mModelValues->insertRow( mModelValues->rowCount(), item );
168void QgsPointCloudQueryBuilder::lstAttributes_doubleClicked(
const QModelIndex &index )
170 mTxtSql->insertText( u
"%1 "_s.arg( mModelAttributes->data( index ).toString() ) );
174void QgsPointCloudQueryBuilder::lstValues_doubleClicked(
const QModelIndex &index )
176 mTxtSql->insertText( u
"%1 "_s.arg( mModelValues->data( index, Qt::UserRole ).toString() ) );
180void QgsPointCloudQueryBuilder::btnEqual_clicked()
182 mTxtSql->insertText( u
"= "_s );
186void QgsPointCloudQueryBuilder::btnLessThan_clicked()
188 mTxtSql->insertText( u
"< "_s );
192void QgsPointCloudQueryBuilder::btnGreaterThan_clicked()
194 mTxtSql->insertText( u
"> "_s );
198void QgsPointCloudQueryBuilder::btnIn_clicked()
200 mTxtSql->insertText( u
"IN () "_s );
202 mTxtSql->getCursorPosition( &i, &j );
203 mTxtSql->setCursorPosition( i, j - 2 );
207void QgsPointCloudQueryBuilder::btnNotIn_clicked()
209 mTxtSql->insertText( u
"NOT IN () "_s );
211 mTxtSql->getCursorPosition( &i, &j );
212 mTxtSql->setCursorPosition( i, j - 2 );
216void QgsPointCloudQueryBuilder::btnLessEqual_clicked()
218 mTxtSql->insertText( u
"<= "_s );
222void QgsPointCloudQueryBuilder::btnGreaterEqual_clicked()
224 mTxtSql->insertText( u
">= "_s );
228void QgsPointCloudQueryBuilder::btnNotEqual_clicked()
230 mTxtSql->insertText( u
"!= "_s );
234void QgsPointCloudQueryBuilder::btnAnd_clicked()
236 mTxtSql->insertText( u
"AND "_s );
240void QgsPointCloudQueryBuilder::btnOr_clicked()
242 mTxtSql->insertText( u
"OR "_s );
256 mTxtSql->setText( mOrigSubsetString );
261bool QgsPointCloudQueryBuilder::test(
bool skipConfirmation )
263 QgsPointCloudExpression expression( mTxtSql->text() );
264 if ( !expression.isValid() && !mTxtSql->text().isEmpty() )
266 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"An error occurred while parsing the expression:\n%1" ).arg( expression.parserErrorString() ) );
271 const QSet<QString> attributes = expression.referencedAttributes();
273 for (
const auto &attribute : attributes )
275 if ( mLayer->dataProvider() && !mLayer->dataProvider()->attributes().find( attribute, offset ) )
277 QMessageBox::warning(
this, tr(
"Query Result" ), tr(
"\"%1\" not recognized as an available attribute." ).arg( attribute ) );
282 if ( !skipConfirmation )
283 QMessageBox::information(
this, tr(
"Query Result" ), tr(
"The expression was successfully parsed." ) );
288void QgsPointCloudQueryBuilder::clear()
293void QgsPointCloudQueryBuilder::saveQuery()
299void QgsPointCloudQueryBuilder::loadQuery()
305 mTxtSql->insertText( subset );
QString displayNameWithAlias() const
Returns the name to use when displaying this field and adds the alias in parenthesis if it is defined...
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
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 QMap< int, QString > translatedLasClassificationCodes()
Returns the map of LAS classification code to translated string value, corresponding to the ASPRS Sta...
Represents a map layer supporting display of point clouds.
QgsPointCloudQueryBuilder(QgsPointCloudLayer *layer, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
This constructor is used when the query builder is called from the layer properties dialog.
void showEvent(QShowEvent *event) override
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...
double stDev(const QString &attribute) const
Returns the standard deviation value for the attribute attribute If no matching statistic is availabl...
double mean(const QString &attribute) const
Returns the mean value for the attribute attribute If no matching statistic is available then NaN wil...
double minimum(const QString &attribute) const
Returns the minimum value for the attribute attribute If no matching statistic is available then NaN ...
static bool loadQueryFromFile(QString &subset)
Load query from the XML file.
static bool saveQueryToFile(const QString &subset)
Save query to the XML file.
QgsSubsetStringEditorInterface(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Constructor.