52  connect( mNewFieldGroupBox, &QGroupBox::toggled, 
this, &QgsFieldCalculator::mNewFieldGroupBox_toggled );
 
   53  connect( mUpdateExistingGroupBox, &QGroupBox::toggled, 
this, &QgsFieldCalculator::mUpdateExistingGroupBox_toggled );
 
   54  connect( mCreateVirtualFieldCheckbox, &QCheckBox::stateChanged, 
this, &QgsFieldCalculator::mCreateVirtualFieldCheckbox_stateChanged );
 
   55  connect( mOutputFieldNameLineEdit, &QLineEdit::textChanged, 
this, &QgsFieldCalculator::mOutputFieldNameLineEdit_textChanged );
 
   56  connect( mOutputFieldTypeComboBox, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::activated ), 
this, &QgsFieldCalculator::mOutputFieldTypeComboBox_activated );
 
   76  populateOutputFieldTypes();
 
   79  connect( mOutputFieldWidthSpinBox, &QAbstractSpinBox::editingFinished, 
this, &QgsFieldCalculator::setPrecisionMinMax );
 
   80  connect( mButtonBox, &QDialogButtonBox::helpRequested, 
this, &QgsFieldCalculator::showHelp );
 
   85  builder->setGeomCalculator( myDa );
 
   88  mOutputFieldWidthSpinBox->setValue( 10 );
 
   89  mOutputFieldWidthSpinBox->setClearValue( 10 );
 
   90  mOutputFieldPrecisionSpinBox->setValue( 3 );
 
   91  mOutputFieldPrecisionSpinBox->setClearValue( 3 );
 
   96    mOutputFieldNameLineEdit->setMaxLength( 10 );
 
   99  if ( !mCanAddAttribute )
 
  101    mCreateVirtualFieldCheckbox->setChecked( 
true );
 
  102    mCreateVirtualFieldCheckbox->setEnabled( 
false );
 
  103    mOnlyVirtualFieldsInfoLabel->setVisible( 
true );
 
  104    mInfoIcon->setVisible( 
true );
 
  108    mOnlyVirtualFieldsInfoLabel->setVisible( 
false );
 
  109    mInfoIcon->setVisible( 
false );
 
  112  if ( !mCanChangeAttributeValue )
 
  114    mUpdateExistingGroupBox->setEnabled( 
false );
 
  115    mCreateVirtualFieldCheckbox->setChecked( 
true );
 
  116    mCreateVirtualFieldCheckbox->setEnabled( 
false );
 
  119  Q_ASSERT( mNewFieldGroupBox->isEnabled() || mUpdateExistingGroupBox->isEnabled() );
 
  121  if ( mNewFieldGroupBox->isEnabled() )
 
  123    mNewFieldGroupBox->setChecked( 
true );
 
  127    mNewFieldGroupBox->setToolTip( tr( 
"Not available for layer" ) );
 
  128    mUpdateExistingGroupBox->setChecked( 
true );
 
  129    mUpdateExistingGroupBox->setCheckable( 
false );
 
  132  if ( mUpdateExistingGroupBox->isEnabled() )
 
  134    mUpdateExistingGroupBox->setChecked( !mNewFieldGroupBox->isEnabled() );
 
  138    mUpdateExistingGroupBox->setToolTip( tr( 
"Not available for layer" ) );
 
  139    mNewFieldGroupBox->setChecked( 
true );
 
  140    mNewFieldGroupBox->setCheckable( 
false );
 
  143  if ( ( mNewFieldGroupBox->isChecked() && mCreateVirtualFieldCheckbox->isChecked() ) || mVectorLayer->
isEditable() )
 
  145    mEditModeAutoTurnOnLabel->setVisible( 
false );
 
  146    mInfoIcon->setVisible( 
false );
 
  150    mInfoIcon->setVisible( 
true );
 
  154  mOnlyUpdateSelectedCheckBox->setChecked( mCanChangeAttributeValue && hasselection );
 
  155  mOnlyUpdateSelectedCheckBox->setEnabled( mCanChangeAttributeValue && hasselection );
 
  156  mOnlyUpdateSelectedCheckBox->setText( tr( 
"Only update %n selected feature(s)", 
nullptr, vl->
selectedFeatureCount() ) );
 
  158  builder->initWithLayer( vl, expContext, QStringLiteral( 
"fieldcalc" ) );
 
  160  mInfoIcon->setPixmap( style()->standardPixmap( QStyle::SP_MessageBoxInformation ) );
 
  162  setWindowTitle( tr( 
"%1 — Field Calculator" ).arg( mVectorLayer->
name() ) );
 
 
  169  builder->expressionTree()->saveToRecent( builder->expressionText(), QStringLiteral( 
"fieldcalc" ) );
 
  180  const QString calcString = builder->expressionText();
 
  188  if ( !exp.
prepare( &expContext ) )
 
  190    QMessageBox::critical( 
nullptr, tr( 
"Evaluation Error" ), exp.
evalErrorString() );
 
  194  bool updatingGeom = 
false;
 
  200  if ( ! mUpdateExistingGroupBox->isChecked() && mCreateVirtualFieldCheckbox->isChecked() )
 
  214    if ( mUpdateExistingGroupBox->isChecked() || !mNewFieldGroupBox->isEnabled() )
 
  216      if ( mExistingFieldComboBox->currentData().toString() == QLatin1String( 
"geom" ) )
 
  225        const int id = mExistingFieldComboBox->currentData().toInt( &ok );
 
  233      const QgsField newField = fieldDefinition();
 
  238        QMessageBox::critical( 
nullptr, tr( 
"Create New Field" ), tr( 
"Could not add the new field to the provider." ) );
 
  246      for ( 
int idx = 0; idx < fields.
count(); ++idx )
 
  248        if ( fields.
at( idx ).
name() == mOutputFieldNameLineEdit->text() )
 
  257      if ( ! exp.
prepare( &expContext ) )
 
  260        QMessageBox::critical( 
nullptr, tr( 
"Evaluation Error" ), exp.
evalErrorString() );
 
  265    if ( mAttributeId == -1 && !updatingGeom )
 
  273    bool calculationSuccess = 
true;
 
  281    const bool newField = !mUpdateExistingGroupBox->isChecked();
 
  282    QVariant emptyAttribute;
 
  288    referencedColumns.insert( field.
name() ); 
 
  290    if ( mOnlyUpdateSelectedCheckBox->isChecked() )
 
  296    std::unique_ptr< QgsScopedProxyProgressTask > task = std::make_unique< QgsScopedProxyProgressTask >( tr( 
"Calculating field" ) );
 
  302      task->setProgress( i / 
static_cast< double >( count ) * 100 );
 
  307      QVariant value = exp.
evaluate( &expContext );
 
  310        calculationSuccess = 
false;
 
  314      else if ( updatingGeom )
 
  316        if ( value.userType() == QMetaType::type( 
"QgsGeometry" ) )
 
  331    if ( !calculationSuccess )
 
  335      QMessageBox::critical( 
nullptr, tr( 
"Evaluation Error" ), tr( 
"An error occurred while evaluating the calculation string:\n%1" ).arg( error ) );
 
 
  345void QgsFieldCalculator::populateOutputFieldTypes()
 
  358  const int oldDataType = mOutputFieldTypeComboBox->currentData( Qt::UserRole + 
FTC_TYPE_ROLE_IDX ).toInt();
 
  360  mOutputFieldTypeComboBox->blockSignals( 
true );
 
  363  const QList< QgsVectorDataProvider::NativeType > &typelist = mCreateVirtualFieldCheckbox->isChecked() ?
 
  364      ( QList< QgsVectorDataProvider::NativeType >()
 
  378      provider->nativeTypes();
 
  380  mOutputFieldTypeComboBox->clear();
 
  381  for ( 
int i = 0; i < typelist.size(); i++ )
 
  383    mOutputFieldTypeComboBox->addItem( 
QgsFields::iconForFieldType( typelist[i].mType, typelist[i].mSubType, typelist[i].mTypeName ), typelist[i].mTypeDesc );
 
  384    mOutputFieldTypeComboBox->setItemData( i, 
static_cast<int>( typelist[i].mType ), Qt::UserRole + 
FTC_TYPE_ROLE_IDX );
 
  385    mOutputFieldTypeComboBox->setItemData( i, typelist[i].mTypeName, Qt::UserRole + 
FTC_TYPE_NAME_IDX );
 
  386    mOutputFieldTypeComboBox->setItemData( i, typelist[i].mMinLen, Qt::UserRole + 
FTC_MINLEN_IDX );
 
  387    mOutputFieldTypeComboBox->setItemData( i, typelist[i].mMaxLen, Qt::UserRole + 
FTC_MAXLEN_IDX );
 
  388    mOutputFieldTypeComboBox->setItemData( i, typelist[i].mMinPrec, Qt::UserRole + 
FTC_MINPREC_IDX );
 
  389    mOutputFieldTypeComboBox->setItemData( i, typelist[i].mMaxPrec, Qt::UserRole + 
FTC_MAXPREC_IDX );
 
  390    mOutputFieldTypeComboBox->setItemData( i, 
static_cast<int>( typelist[i].mSubType ), Qt::UserRole + 
FTC_SUBTYPE_IDX );
 
  392  mOutputFieldTypeComboBox->blockSignals( 
false );
 
  394  const int idx = mOutputFieldTypeComboBox->findData( oldDataType, Qt::UserRole + 
FTC_TYPE_ROLE_IDX );
 
  397    mOutputFieldTypeComboBox->setCurrentIndex( idx );
 
  398    mOutputFieldTypeComboBox_activated( idx );
 
  402    mOutputFieldTypeComboBox->setCurrentIndex( 0 );
 
  403    mOutputFieldTypeComboBox_activated( 0 );
 
  407void QgsFieldCalculator::mNewFieldGroupBox_toggled( 
bool on )
 
  409  mUpdateExistingGroupBox->setChecked( !on );
 
  410  if ( on && !mCanAddAttribute )
 
  412    mOnlyVirtualFieldsInfoLabel->setVisible( 
true );
 
  416    mOnlyVirtualFieldsInfoLabel->setVisible( 
false );
 
  419  if ( ( mNewFieldGroupBox->isChecked() && mCreateVirtualFieldCheckbox->isChecked() ) || mVectorLayer->
isEditable() )
 
  421    mEditModeAutoTurnOnLabel->setVisible( 
false );
 
  425    mEditModeAutoTurnOnLabel->setVisible( 
true );
 
  428  mInfoIcon->setVisible( mOnlyVirtualFieldsInfoLabel->isVisible() || mEditModeAutoTurnOnLabel->isVisible() );
 
  431void QgsFieldCalculator::mUpdateExistingGroupBox_toggled( 
bool on )
 
  433  mNewFieldGroupBox->setChecked( !on );
 
  442    mCreateVirtualFieldCheckbox_stateChanged( mCreateVirtualFieldCheckbox->checkState() );
 
  446void QgsFieldCalculator::mCreateVirtualFieldCheckbox_stateChanged( 
int state )
 
  448  mOnlyUpdateSelectedCheckBox->setChecked( 
false );
 
  449  mOnlyUpdateSelectedCheckBox->setEnabled( state != Qt::Checked && mVectorLayer->
selectedFeatureCount() > 0 );
 
  451  if ( ( mNewFieldGroupBox->isChecked() && mCreateVirtualFieldCheckbox->isChecked() ) || mVectorLayer->
isEditable() )
 
  453    mEditModeAutoTurnOnLabel->setVisible( 
false );
 
  457    mEditModeAutoTurnOnLabel->setVisible( 
true );
 
  459  populateOutputFieldTypes();
 
  460  mInfoIcon->setVisible( mOnlyVirtualFieldsInfoLabel->isVisible() || mEditModeAutoTurnOnLabel->isVisible() );
 
  464void QgsFieldCalculator::mOutputFieldNameLineEdit_textChanged( 
const QString &text )
 
  471void QgsFieldCalculator::mOutputFieldTypeComboBox_activated( 
int index )
 
  473  mOutputFieldWidthSpinBox->setMinimum( mOutputFieldTypeComboBox->itemData( index, Qt::UserRole + 
FTC_MINLEN_IDX ).toInt() );
 
  474  mOutputFieldWidthSpinBox->setMaximum( mOutputFieldTypeComboBox->itemData( index, Qt::UserRole + 
FTC_MAXLEN_IDX ).toInt() );
 
  475  mOutputFieldWidthSpinBox->setEnabled( mOutputFieldWidthSpinBox->minimum() < mOutputFieldWidthSpinBox->maximum() );
 
  476  if ( mOutputFieldWidthSpinBox->value() < mOutputFieldWidthSpinBox->minimum() )
 
  477    mOutputFieldWidthSpinBox->setValue( mOutputFieldWidthSpinBox->minimum() );
 
  478  if ( mOutputFieldWidthSpinBox->value() > mOutputFieldWidthSpinBox->maximum() )
 
  479    mOutputFieldWidthSpinBox->setValue( mOutputFieldWidthSpinBox->maximum() );
 
  481  setPrecisionMinMax();
 
  484void QgsFieldCalculator::populateFields()
 
  490  for ( 
int idx = 0; idx < fields.
count(); ++idx )
 
  522    const QString fieldName = fields.
at( idx ).
name();
 
  525    mExistingFieldComboBox->addItem( fields.
iconForField( idx ), fieldName, idx );
 
  530    mExistingFieldComboBox->addItem( tr( 
"<geometry>" ), 
"geom" );
 
  532    QFont font = mExistingFieldComboBox->itemData( mExistingFieldComboBox->count() - 1, Qt::FontRole ).value<QFont>();
 
  533    font.setItalic( 
true );
 
  534    mExistingFieldComboBox->setItemData( mExistingFieldComboBox->count() - 1, font, Qt::FontRole );
 
  536  mExistingFieldComboBox->setCurrentIndex( -1 );
 
  539void QgsFieldCalculator::setOkButtonState()
 
  541  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
 
  543  if ( ( mNewFieldGroupBox->isChecked() || !mUpdateExistingGroupBox->isEnabled() )
 
  544       && mOutputFieldNameLineEdit->text().isEmpty() )
 
  546    okButton->setToolTip( tr( 
"Please enter a field name" ) );
 
  547    okButton->setEnabled( 
false );
 
  551  if ( !builder->isExpressionValid() )
 
  553    okButton->setToolTip( okButton->toolTip() + tr( 
"\n The expression is invalid see (more info) for details" ) );
 
  554    okButton->setEnabled( 
false );
 
  558  okButton->setToolTip( QString() );
 
  559  okButton->setEnabled( 
true );
 
  562void QgsFieldCalculator::setPrecisionMinMax()
 
  564  const int idx = mOutputFieldTypeComboBox->currentIndex();
 
  565  const int minPrecType = mOutputFieldTypeComboBox->itemData( idx, Qt::UserRole + 
FTC_MINPREC_IDX ).toInt();
 
  566  const int maxPrecType = mOutputFieldTypeComboBox->itemData( idx, Qt::UserRole + 
FTC_MAXPREC_IDX ).toInt();
 
  567  const bool precisionIsEnabled = minPrecType < maxPrecType;
 
  568  mOutputFieldPrecisionSpinBox->setEnabled( precisionIsEnabled );
 
  572  if ( precisionIsEnabled )
 
  574    mOutputFieldPrecisionSpinBox->setMinimum( minPrecType );
 
  575    mOutputFieldPrecisionSpinBox->setMaximum( std::max( minPrecType, std::min( maxPrecType, mOutputFieldWidthSpinBox->value() ) ) );
 
  579void QgsFieldCalculator::showHelp()
 
  581  QgsHelp::openHelp( QStringLiteral( 
"working_with_vector/attribute_table.html#editing-attribute-values" ) );
 
  584QgsField QgsFieldCalculator::fieldDefinition()
 
  586  return QgsField( mOutputFieldNameLineEdit->text(),
 
  587                   static_cast< QMetaType::Type 
>( mOutputFieldTypeComboBox->currentData( Qt::UserRole + 
FTC_TYPE_ROLE_IDX ).toInt() ),
 
  588                   mOutputFieldTypeComboBox->currentData( Qt::UserRole + 
FTC_TYPE_NAME_IDX ).toString(),
 
  589                   mOutputFieldWidthSpinBox->value(),
 
  590                   mOutputFieldPrecisionSpinBox->isEnabled() ? mOutputFieldPrecisionSpinBox->value() : 0,
 
  592                   static_cast< QMetaType::Type >( mOutputFieldTypeComboBox->currentData( Qt::UserRole + 
FTC_SUBTYPE_IDX ).toInt() )
 
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
 
@ NoFlags
No flags are set.
 
@ Provider
Field originates from the underlying data provider of the vector layer.
 
@ Edit
Field has been temporarily added in editing mode.
 
@ Unknown
The field origin has not been specified.
 
@ Expression
Field is calculated from an expression.
 
@ Join
Field originates from a joined layer.
 
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
 
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
 
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
 
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
 
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
 
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
 
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
 
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
 
Class for parsing and evaluation of expressions (formerly called "search strings").
 
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
 
QString evalErrorString() const
Returns evaluation error.
 
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
 
void setDistanceUnits(Qgis::DistanceUnit unit)
Sets the desired distance units for calculations involving geomCalculator(), e.g.,...
 
void setAreaUnits(Qgis::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
 
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
 
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
 
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
 
QVariant evaluate()
Evaluate the feature and return the result.
 
Wrapper for iterator of features from vector data provider or vector layer.
 
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
 
This class wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
 
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
 
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
QgsFieldCalculator(QgsVectorLayer *vl, QWidget *parent=nullptr)
 
Encapsulate a field in an attribute table or data source.
 
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
 
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
 
Container of fields for a vector layer.
 
static QIcon iconForFieldType(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType, const QString &typeString=QString())
Returns an icon corresponding to a field type.
 
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
QIcon iconForField(int fieldIdx, bool considerOrigin=false) const
Returns an icon corresponding to a field index, based on the field's type and source.
 
A geometry is the spatial representation of a feature.
 
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.
 
QString providerType() const
Returns the provider type (provider key) for this layer.
 
QgsCoordinateReferenceSystem crs
 
static QgsProject * instance()
Returns the QgsProject singleton instance.
 
QgsCoordinateTransformContext transformContext
 
Temporarily sets a cursor override for the QApplication for the lifetime of the object.
 
void release()
Releases the cursor override early (i.e.
 
static QString typeToDisplayString(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
 
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
 
This is the base class for vector data providers.
 
@ AddAttributes
Allows addition of new attributes (fields)
 
@ ChangeAttributeValues
Allows modification of attribute values.
 
QFlags< Capability > Capabilities
 
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
 
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
 
Defines left outer join from our vector layer to some other vector layer.
 
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
 
Represents a vector layer which manages a vector based data sets.
 
int addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
 
Q_INVOKABLE bool startEditing()
Makes the layer editable.
 
Q_INVOKABLE bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes an attribute value for a feature (but does not immediately commit the changes).
 
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
 
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
 
void endEditCommand()
Finish edit command and add it to undo/redo stack.
 
void destroyEditCommand()
Destroy active command and reverts all changes in it.
 
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
 
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
 
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
 
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
 
QgsVectorLayerJoinBuffer * joinBuffer()
Returns the join buffer object.
 
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
 
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
 
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
 
constexpr int FTC_TYPE_NAME_IDX
 
constexpr int FTC_MINLEN_IDX
 
constexpr int FTC_TYPE_ROLE_IDX
 
constexpr int FTC_MAXLEN_IDX
 
constexpr int FTC_MAXPREC_IDX
 
constexpr int FTC_MINPREC_IDX
 
constexpr int FTC_SUBTYPE_IDX
 
Single variable definition for use within a QgsExpressionContextScope.