void QgsExpressionSelectionDialog::on_mActionAddToSelection_triggered()
{
  QgsFeatureIds newSelection = mLayer->selectedFeaturesIds();
  QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() );

  const QgsFields fields = mLayer->fields();

  QgsFeatureIterator features = mLayer->getFeatures();

  expression->prepare( fields );

  QgsFeature feat;
  while ( features.nextFeature( feat ) )
  {
    if ( expression->evaluate( &feat, fields ).toBool() )
    {
      newSelection << feat.id();
    }
  }

  features.close();

  mLayer->setSelectedFeatures( newSelection );

  delete expression;
  saveRecent();
}
void QgsExpressionSelectionDialog::mActionRemoveFromSelection_triggered()
{
  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
                              QgsVectorLayer::RemoveFromSelection );
  pushSelectedFeaturesMessage();
  saveRecent();
}
void QgsExpressionSelectionDialog::on_mActionSelect_triggered()
{
  QgsFeatureIds newSelection;
  QgsExpression* expression = new QgsExpression( mExpressionBuilder->expressionText() );

  QgsExpressionContext context;
  context << QgsExpressionContextUtils::globalScope()
  << QgsExpressionContextUtils::projectScope()
  << QgsExpressionContextUtils::layerScope( mLayer );

  QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( mExpressionBuilder->expressionText() ).setExpressionContext( context );
  QgsFeatureIterator features = mLayer->getFeatures( request );

  QgsFeature feat;
  while ( features.nextFeature( feat ) )
  {
    newSelection << feat.id();
  }

  features.close();

  mLayer->setSelectedFeatures( newSelection );

  delete expression;
  saveRecent();
}
void QgsExpressionSelectionDialog::mButtonZoomToFeatures_clicked()
{
  if ( mExpressionBuilder->expressionText().isEmpty() || !mMapCanvas )
    return;

  QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );

  QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( mExpressionBuilder->expressionText() )
                              .setExpressionContext( context )
                              .setNoAttributes();

  QgsFeatureIterator features = mLayer->getFeatures( request );

  QgsRectangle bbox;
  bbox.setMinimal();
  QgsFeature feat;
  int featureCount = 0;
  while ( features.nextFeature( feat ) )
  {
    QgsGeometry geom = feat.geometry();
    if ( geom.isNull() || geom.constGet()->isEmpty() )
      continue;

    QgsRectangle r = mMapCanvas->mapSettings().layerExtentToOutputExtent( mLayer, geom.boundingBox() );
    bbox.combineExtentWith( r );
    featureCount++;
  }
  features.close();

  QgsSettings settings;
  int timeout = settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
  if ( featureCount > 0 )
  {
    mMapCanvas->zoomToFeatureExtent( bbox );
    if ( mMessageBar )
    {
      mMessageBar->pushMessage( QString(),
                                tr( "Zoomed to %n matching feature(s)", "number of matching features", featureCount ),
                                Qgis::Info,
                                timeout );
    }
  }
  else if ( mMessageBar )
  {
    mMessageBar->pushMessage( QString(),
                              tr( "No matching features found" ),
                              Qgis::Info,
                              timeout );
  }
  saveRecent();
}
void QgsExpressionSelectionDialog::on_mActionSelectIntersect_triggered()
{
  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
                              QgsVectorLayer::IntersectSelection );
  saveRecent();
}
void QgsExpressionSelectionDialog::mActionAddToSelection_triggered()
{
  mLayer->selectByExpression( mExpressionBuilder->expressionText(),
                              QgsVectorLayer::AddToSelection );
  saveRecent();
}