33#include "moc_qgsfieldexpressionwidget.cpp"
37 , mExpressionDialogTitle( tr(
"Expression Builder" ) )
38 , mDistanceArea( nullptr )
41 QHBoxLayout *layout =
new QHBoxLayout(
this );
42 layout->setContentsMargins( 0, 0, 0, 0 );
44 mCombo =
new QComboBox(
this );
45 mCombo->setEditable(
true );
46 mCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
47 const int width = mCombo->minimumSizeHint().width();
48 mCombo->setMinimumWidth( width );
51 mFieldProxyModel->sourceFieldModel()->setAllowExpression(
true );
52 mCombo->setModel( mFieldProxyModel );
54 mButton =
new QToolButton(
this );
55 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
58 layout->addWidget( mCombo );
59 layout->addWidget( mButton );
65 connect( mFieldProxyModel, &QAbstractItemModel::modelAboutToBeReset,
this, &QgsFieldExpressionWidget::beforeResetModel );
66 connect( mFieldProxyModel, &QAbstractItemModel::modelReset,
this, &QgsFieldExpressionWidget::afterResetModel );
72 mCombo->installEventFilter(
this );
77 mExpressionDialogTitle = title;
82 mFieldProxyModel->setFilters(
filters );
87 mCombo->lineEdit()->setClearButtonEnabled( allowEmpty );
88 mFieldProxyModel->sourceFieldModel()->setAllowEmptyFieldName( allowEmpty );
93 return mFieldProxyModel->sourceFieldModel()->allowEmptyFieldName();
98 QHBoxLayout *layout =
dynamic_cast<QHBoxLayout *
>( this->layout() );
104 QLayoutItem *item = layout->takeAt( 1 );
105 layout->insertWidget( 0, item->widget() );
108 layout->addWidget( mCombo );
113 mDistanceArea = std::shared_ptr<const QgsDistanceArea>(
new QgsDistanceArea( da ) );
118 return mCombo->currentText();
139 return !mFieldProxyModel->sourceFieldModel()->isField(
currentText() );
160 return mFieldProxyModel->sourceFieldModel()->layer();
165 mExpressionContextGenerator = generator;
170 mCustomPreviewLabel = label;
171 mCustomChoices = choices;
172 mPreviewContextGenerator = previewContextGenerator;
179 if ( mFieldProxyModel->sourceFieldModel()->layer() )
187 mFieldProxyModel->sourceFieldModel()->setLayer( vl );
189 if ( mFieldProxyModel->sourceFieldModel()->layer() )
190 connect( mFieldProxyModel->sourceFieldModel()->layer(), &
QgsVectorLayer::updatedFields,
this, &QgsFieldExpressionWidget::reloadLayer, Qt::UniqueConnection );
195 if ( fieldName.isEmpty() )
203 if ( fieldName.size() > mCombo->lineEdit()->maxLength() )
205 mCombo->lineEdit()->setMaxLength( fieldName.size() );
208 QModelIndex idx = mFieldProxyModel->sourceFieldModel()->indexFromName( fieldName );
209 if ( !idx.isValid() )
212 QString simpleFieldName = fieldName.trimmed();
213 if ( simpleFieldName.startsWith(
'"' ) && simpleFieldName.endsWith(
'"' ) )
215 simpleFieldName.remove( 0, 1 ).chop( 1 );
216 idx = mFieldProxyModel->sourceFieldModel()->indexFromName( simpleFieldName );
219 if ( !idx.isValid() )
222 mFieldProxyModel->sourceFieldModel()->setExpression( fieldName );
223 idx = mFieldProxyModel->sourceFieldModel()->indexFromName( fieldName );
226 const QModelIndex proxyIndex = mFieldProxyModel->mapFromSource( idx );
227 mCombo->setCurrentIndex( proxyIndex.row() );
233 mFieldProxyModel->sourceFieldModel()->setFields( fields );
246 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
253 dlg.setWindowTitle( mExpressionDialogTitle );
256 if ( !mCustomChoices.isEmpty() )
279 const QString
expression = mCombo->lineEdit()->text();
280 mFieldProxyModel->sourceFieldModel()->setExpression(
expression );
281 const QModelIndex idx = mFieldProxyModel->sourceFieldModel()->indexFromName(
expression );
282 const QModelIndex proxyIndex = mFieldProxyModel->mapFromSource( idx );
283 mCombo->setCurrentIndex( proxyIndex.row() );
289 if ( event->type() == QEvent::EnabledChange )
295void QgsFieldExpressionWidget::reloadLayer()
300void QgsFieldExpressionWidget::beforeResetModel()
303 mBackupExpression = mCombo->currentText();
306void QgsFieldExpressionWidget::afterResetModel()
309 mCombo->lineEdit()->setText( mBackupExpression );
314 if ( watched == mCombo && event->type() == QEvent::KeyPress )
316 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>( event );
317 if ( keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return )
323 return QObject::eventFilter( watched, event );
328 return mAllowEvalErrors;
343 return mButton->isVisibleTo(
this );
351 mButton->setVisible( visible );
363 const QFontMetrics metrics( mCombo->lineEdit()->font() );
364 if ( metrics.boundingRect( fieldName ).width() > mCombo->lineEdit()->width() )
366 mCombo->setToolTip( fieldName );
370 mCombo->setToolTip( QString() );
382 stylesheet = QStringLiteral(
"QLineEdit { color: %1; }" ).arg( QColor( Qt::gray ).name() );
396 QFont font = mCombo->lineEdit()->font();
398 font.setItalic(
false );
399 mCombo->lineEdit()->setFont( font );
403 stylesheet = QStringLiteral(
"QLineEdit { color: %1; }" ).arg( QColor( Qt::red ).name() );
406 mCombo->lineEdit()->setStyleSheet( stylesheet );
418 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.