void QgsPropertyOverrideButton::showExpressionDialog()
{
  QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : QgsExpressionContext();

  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer *>( mVectorLayer ), mProperty.asExpression(), this, QStringLiteral( "generic" ), context );
  if ( d.exec() == QDialog::Accepted )
  {
    mExpressionString = d.expressionText().trimmed();
    mProperty.setExpressionString( mExpressionString );
    mProperty.setTransformer( nullptr );
    setActivePrivate( !mExpressionString.isEmpty() );
    updateGui();
    emit changed();
  }
  activateWindow(); // reset focus to parent window
}
void QgsPropertyOverrideButton::mouseReleaseEvent( QMouseEvent *event )
{
  // Ctrl-click to toggle activated state
  if ( ( event->modifiers() & ( Qt::ControlModifier ) )
       || event->button() == Qt::RightButton )
  {
    setActivePrivate( !mProperty.isActive() );
    updateGui();
    emit changed();
    event->ignore();
    return;
  }

  // pass to default behavior
  QToolButton::mousePressEvent( event );
}
void QgsPropertyOverrideButton::showExpressionDialog()
{
  QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : QgsExpressionContext();

  // build sensible initial expression text - see https://issues.qgis.org/issues/18638
  QString currentExpression = ( mProperty.propertyType() == QgsProperty::StaticProperty && !mProperty.staticValue().isValid() ) ? QString()
                              : mProperty.asExpression();

  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer *>( mVectorLayer ), currentExpression, this, QStringLiteral( "generic" ), context );
  d.setExpectedOutputFormat( mInputDescription );
  if ( d.exec() == QDialog::Accepted )
  {
    mExpressionString = d.expressionText().trimmed();
    mProperty.setExpressionString( mExpressionString );
    mProperty.setTransformer( nullptr );
    setActivePrivate( !mExpressionString.isEmpty() );
    updateSiblingWidgets( isActive() );
    updateGui();
    emit changed();
  }
  activateWindow(); // reset focus to parent window
}
void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
{
  if ( action == mActionActive )
  {
    setActivePrivate( mActionActive->data().toBool() );
    updateGui();
    emit changed();
  }
  else if ( action == mActionDescription )
  {
    showDescriptionDialog();
  }
  else if ( action == mActionExpDialog )
  {
    showExpressionDialog();
  }
  else if ( action == mActionExpression )
  {
    mProperty.setExpressionString( mExpressionString );
    mProperty.setTransformer( nullptr );
    setActivePrivate( true );
    updateSiblingWidgets( isActive() );
    updateGui();
    emit changed();
  }
  else if ( action == mActionCopyExpr )
  {
    QApplication::clipboard()->setText( mExpressionString );
  }
  else if ( action == mActionPasteExpr )
  {
    QString exprString = QApplication::clipboard()->text();
    if ( !exprString.isEmpty() )
    {
      mExpressionString = exprString;
      mProperty.setExpressionString( mExpressionString );
      mProperty.setTransformer( nullptr );
      setActivePrivate( true );
      updateSiblingWidgets( isActive() );
      updateGui();
      emit changed();
    }
  }
  else if ( action == mActionClearExpr )
  {
    setActivePrivate( false );
    mProperty.setStaticValue( QVariant() );
    mProperty.setTransformer( nullptr );
    mExpressionString.clear();
    updateSiblingWidgets( isActive() );
    updateGui();
    emit changed();
  }
  else if ( action == mActionAssistant )
  {
    showAssistant();
  }
  else if ( action == mActionCreateAuxiliaryField )
  {
    emit createAuxiliaryField();
  }
  else if ( mFieldsMenu->actions().contains( action ) )  // a field name clicked
  {
    if ( action->isEnabled() )
    {
      if ( mFieldName != action->text() )
      {
        mFieldName = action->data().toString();
      }
      mProperty.setField( mFieldName );
      mProperty.setTransformer( nullptr );
      setActivePrivate( true );
      updateSiblingWidgets( isActive() );
      updateGui();
      emit changed();
    }
  }
  else if ( mVariablesMenu->actions().contains( action ) )  // a variable name clicked
  {
    if ( mExpressionString != action->text().prepend( "@" ) )
    {
      mExpressionString = action->data().toString().prepend( "@" );
    }
    mProperty.setExpressionString( mExpressionString );
    mProperty.setTransformer( nullptr );
    setActivePrivate( true );
    updateSiblingWidgets( isActive() );
    updateGui();
    emit changed();
  }
}