34#include "moc_qgsfieldexpressionwidget.cpp"
36using namespace Qt::StringLiterals;
40 , mExpressionDialogTitle( tr(
"Expression Builder" ) )
41 , mDistanceArea( nullptr )
44 QHBoxLayout *layout =
new QHBoxLayout(
this );
45 layout->setContentsMargins( 0, 0, 0, 0 );
47 mCombo =
new QComboBox(
this );
48 mCombo->setEditable(
true );
49 mCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
50 const int width = mCombo->minimumSizeHint().width();
51 mCombo->setMinimumWidth( width );
54 mFieldProxyModel->sourceFieldModel()->setAllowExpression(
true );
55 mCombo->setModel( mFieldProxyModel );
57 mButton =
new QToolButton(
this );
58 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
61 layout->addWidget( mCombo );
62 layout->addWidget( mButton );
68 connect( mFieldProxyModel, &QAbstractItemModel::modelAboutToBeReset,
this, &QgsFieldExpressionWidget::beforeResetModel );
69 connect( mFieldProxyModel, &QAbstractItemModel::modelReset,
this, &QgsFieldExpressionWidget::afterResetModel );
75 mCombo->installEventFilter(
this );
80 mExpressionDialogTitle = title;
85 mFieldProxyModel->setFilters(
filters );
90 mCombo->lineEdit()->setClearButtonEnabled( allowEmpty );
91 mFieldProxyModel->sourceFieldModel()->setAllowEmptyFieldName( allowEmpty );
96 return mFieldProxyModel->sourceFieldModel()->allowEmptyFieldName();
101 QHBoxLayout *layout =
dynamic_cast<QHBoxLayout *
>( this->layout() );
107 QLayoutItem *item = layout->takeAt( 1 );
108 layout->insertWidget( 0, item->widget() );
111 layout->addWidget( mCombo );
116 mDistanceArea = std::shared_ptr<const QgsDistanceArea>(
new QgsDistanceArea( da ) );
121 return mCombo->currentText();
142 return !mFieldProxyModel->sourceFieldModel()->isField(
currentText() );
163 return mFieldProxyModel->sourceFieldModel()->layer();
168 mExpressionContextGenerator = generator;
173 mCustomPreviewLabel = label;
174 mCustomChoices = choices;
175 mPreviewContextGenerator = previewContextGenerator;
182 if ( mFieldProxyModel->sourceFieldModel()->layer() )
190 mFieldProxyModel->sourceFieldModel()->setLayer( vl );
192 if ( mFieldProxyModel->sourceFieldModel()->layer() )
193 connect( mFieldProxyModel->sourceFieldModel()->layer(), &
QgsVectorLayer::updatedFields,
this, &QgsFieldExpressionWidget::reloadLayer, Qt::UniqueConnection );
198 if ( fieldName.isEmpty() )
206 if ( fieldName.size() > mCombo->lineEdit()->maxLength() )
208 mCombo->lineEdit()->setMaxLength( fieldName.size() );
211 QModelIndex idx = mFieldProxyModel->sourceFieldModel()->indexFromName( fieldName );
212 if ( !idx.isValid() )
215 QString simpleFieldName = fieldName.trimmed();
216 if ( simpleFieldName.startsWith(
'"' ) && simpleFieldName.endsWith(
'"' ) )
218 simpleFieldName.remove( 0, 1 ).chop( 1 );
219 idx = mFieldProxyModel->sourceFieldModel()->indexFromName( simpleFieldName );
222 if ( !idx.isValid() )
225 mFieldProxyModel->sourceFieldModel()->setExpression( fieldName );
226 idx = mFieldProxyModel->sourceFieldModel()->indexFromName( fieldName );
229 const QModelIndex proxyIndex = mFieldProxyModel->mapFromSource( idx );
230 mCombo->setCurrentIndex( proxyIndex.row() );
236 mFieldProxyModel->sourceFieldModel()->setFields( fields );
249 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
256 dlg.setWindowTitle( mExpressionDialogTitle );
259 if ( !mCustomChoices.isEmpty() )
282 const QString
expression = mCombo->lineEdit()->text();
283 mFieldProxyModel->sourceFieldModel()->setExpression(
expression );
284 const QModelIndex idx = mFieldProxyModel->sourceFieldModel()->indexFromName(
expression );
285 const QModelIndex proxyIndex = mFieldProxyModel->mapFromSource( idx );
286 mCombo->setCurrentIndex( proxyIndex.row() );
292 if ( event->type() == QEvent::EnabledChange )
298void QgsFieldExpressionWidget::reloadLayer()
303void QgsFieldExpressionWidget::beforeResetModel()
306 mBackupExpression = mCombo->currentText();
309void QgsFieldExpressionWidget::afterResetModel()
312 mCombo->lineEdit()->setText( mBackupExpression );
317 if ( watched == mCombo && event->type() == QEvent::KeyPress )
319 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>( event );
320 if ( keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return )
326 return QObject::eventFilter( watched, event );
331 return mAllowEvalErrors;
346 return mButton->isVisibleTo(
this );
354 mButton->setVisible( visible );
366 const QFontMetrics metrics( mCombo->lineEdit()->font() );
367 if ( metrics.boundingRect( fieldName ).width() > mCombo->lineEdit()->width() )
369 mCombo->setToolTip( fieldName );
373 mCombo->setToolTip( QString() );
385 stylesheet = u
"QLineEdit { color: %1; }"_s.arg( QColor( Qt::gray ).name() );
399 QFont font = mCombo->lineEdit()->font();
401 font.setItalic(
false );
402 mCombo->lineEdit()->setFont( font );
406 stylesheet = u
"QLineEdit { color: %1; }"_s.arg( QColor( Qt::red ).name() );
409 mCombo->lineEdit()->setStyleSheet( stylesheet );
421 mExpressionContext.appendScope( scope );
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QFont getMonospaceFont()
Returns the monospaced font to use for code editors.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
A generic dialog for building expression strings.
void setGeomCalculator(const QgsDistanceArea &da)
Sets geometry calculator used in distance/area calculations.
QgsExpressionBuilderWidget * expressionBuilder()
The builder widget that is used by the dialog.
void setAllowEvalErrors(bool allowEvalErrors)
Allow accepting expressions with evaluation errors.
Abstract interface for generating an expression context.
Single scope for storing variables and functions for use within a QgsExpressionContext.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void loadFieldNames(const QgsFields &fields)
This allows loading fields without specifying a layer.
Handles parsing and evaluation of expressions (formerly called "search strings").
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
static bool checkExpression(const QString &text, const QgsExpressionContext *context, QString &errorMessage)
Tests whether a string is a valid expression.
A proxy model to filter the list of fields of a layer.
QgsFieldModel * sourceFieldModel()
Returns the QgsFieldModel used in this QSortFilterProxyModel.
Container of fields for a vector layer.
Base class for all map layer types.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Represents a vector layer which manages a vector based dataset.
QgsExpressionContext createExpressionContext() const final
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void updatedFields()
Emitted whenever the fields available from this layer have been changed.