void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
{
  mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
  mIntSpinBox = qobject_cast<QSpinBox *>( editor );

  mDial = qobject_cast<QDial *>( editor );
  mSlider = qobject_cast<QSlider *>( editor );
  mQgsDial = qobject_cast<QgsDial *>( editor );
  mQgsSlider = qobject_cast<QgsSlider *>( editor );

  bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();

  QVariant min( config( QStringLiteral( "Min" ) ) );
  QVariant max( config( QStringLiteral( "Max" ) ) );
  QVariant step( config( QStringLiteral( "Step" ) ) );

  if ( mDoubleSpinBox )
  {
    // set the precision if field is integer
    int precision = layer()->fields().at( fieldIdx() ).precision();
    if ( precision > 0 )
    {
      mDoubleSpinBox->setDecimals( layer()->fields().at( fieldIdx() ).precision() );
    }

    double minval = min.toDouble();
    double stepval = step.toDouble();
    QgsDoubleSpinBox *qgsWidget = dynamic_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );
    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    if ( allowNull )
    {
      if ( precision > 0 )
      {
        minval -= 10 ^ -precision;
      }
      else
      {
        minval -= stepval;
      }
      mDoubleSpinBox->setValue( minval );
      mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
    }
    mDoubleSpinBox->setMinimum( min.isValid() ? min.toDouble() : std::numeric_limits<double>::min() );
    mDoubleSpinBox->setMaximum( max.isValid() ? max.toDouble() : std::numeric_limits<double>::max() );
    mDoubleSpinBox->setSingleStep( step.isValid() ? step.toDouble() : 1.0 );
    if ( config( QStringLiteral( "Suffix" ) ).isValid() )
      mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );

    connect( mDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
             this, static_cast < void ( QgsEditorWidgetWrapper::* )( double ) > ( &QgsEditorWidgetWrapper::valueChanged ) );
  }
  else if ( mIntSpinBox )
  {
    QgsSpinBox *qgsWidget = dynamic_cast<QgsSpinBox *>( mIntSpinBox );
    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    if ( allowNull )
    {
      int minval = min.toInt();
      int stepval = step.toInt();
      minval -= stepval;
      mIntSpinBox->setValue( minval );
      mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
    }
    setupIntEditor( min, max, step, mIntSpinBox, this );
    if ( config( QStringLiteral( "Suffix" ) ).isValid() )
      mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
  }
  else
  {
    field().convertCompatible( min );
    field().convertCompatible( max );
    field().convertCompatible( step );
    if ( mQgsDial ) setupIntEditor( min, max, step, mQgsDial, this );
    else if ( mQgsSlider ) setupIntEditor( min, max, step, mQgsSlider, this );
    else if ( mDial ) setupIntEditor( min, max, step, mDial, this );
    else if ( mSlider ) setupIntEditor( min, max, step, mSlider, this );
  }
}
void QgsRangeWidgetWrapper::initWidget( QWidget* editor )
{
  mDoubleSpinBox = qobject_cast<QDoubleSpinBox*>( editor );
  mIntSpinBox = qobject_cast<QSpinBox*>( editor );
  mDial = qobject_cast<QDial*>( editor );
  mSlider = qobject_cast<QSlider*>( editor );
  mQgsDial = qobject_cast<QgsDial*>( editor );
  mQgsSlider = qobject_cast<QgsSlider*>( editor );

  bool allowNull = config( "AllowNull" ).toBool();

  QVariant min( config( "Min" ) );
  QVariant max( config( "Max" ) );
  QVariant step( config( "Step" ) );

  if ( mDoubleSpinBox )
  {
    // set the precision if field is integer
    int precision = layer()->fields()[fieldIdx()].precision();
    if ( precision > 0 )
    {
      mDoubleSpinBox->setDecimals( layer()->fields()[fieldIdx()].precision() );
    }

    double minval = min.toDouble();
    double stepval = step.toDouble();
    QgsDoubleSpinBox* qgsWidget = dynamic_cast<QgsDoubleSpinBox*>( mDoubleSpinBox );
    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    if ( allowNull )
    {
      if ( precision > 0 )
      {
        minval -= 10 ^ -precision;
      }
      else
      {
        minval -= stepval;
      }
      mDoubleSpinBox->setValue( minval );
      mDoubleSpinBox->setSpecialValueText( QSettings().value( "qgis/nullValue", "NULL" ).toString() );
    }
    if ( min.isValid() )
      mDoubleSpinBox->setMinimum( min.toDouble() );
    if ( max.isValid() )
      mDoubleSpinBox->setMaximum( max.toDouble() );
    if ( step.isValid() )
      mDoubleSpinBox->setSingleStep( step.toDouble() );
    if ( config( "Suffix" ).isValid() )
      mDoubleSpinBox->setSuffix( config( "Suffix" ).toString() );

    connect( mDoubleSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( valueChanged( double ) ) );
  }

  if ( mIntSpinBox )
  {
    int minval = min.toInt();
    int stepval = step.toInt();
    QgsSpinBox* qgsWidget = dynamic_cast<QgsSpinBox*>( mIntSpinBox );
    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    if ( allowNull )
    {
      minval -= stepval;
      mIntSpinBox->setValue( minval );
      mIntSpinBox->setSpecialValueText( QSettings().value( "qgis/nullValue", "NULL" ).toString() );
    }
    if ( min.isValid() )
      mIntSpinBox->setMinimum( min.toInt() );
    if ( max.isValid() )
      mIntSpinBox->setMaximum( max.toInt() );
    if ( step.isValid() )
      mIntSpinBox->setSingleStep( step.toInt() );
    if ( config( "Suffix" ).isValid() )
      mIntSpinBox->setSuffix( config( "Suffix" ).toString() );
    connect( mIntSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( valueChanged( int ) ) );
  }


  if ( mQgsDial || mQgsSlider )
  {
    field().convertCompatible( min );
    field().convertCompatible( max );
    field().convertCompatible( step );

    if ( mQgsSlider )
    {
      if ( min.isValid() )
        mQgsSlider->setMinimum( min );
      if ( max.isValid() )
        mQgsSlider->setMaximum( max );
      if ( step.isValid() )
        mQgsSlider->setSingleStep( step );
    }

    if ( mQgsDial )
    {
      if ( min.isValid() )
        mQgsDial->setMinimum( min );
      if ( max.isValid() )
        mQgsDial->setMaximum( max );
      if ( step.isValid() )
        mQgsDial->setSingleStep( step );
    }

    connect( editor, SIGNAL( valueChanged( QVariant ) ), this, SLOT( valueChanged( QVariant ) ) );
  }
  else if ( mDial )
  {
    if ( min.isValid() )
      mDial->setMinimum( min.toInt() );
    if ( max.isValid() )
      mDial->setMaximum( max.toInt() );
    if ( step.isValid() )
      mDial->setSingleStep( step.toInt() );
    connect( mDial, SIGNAL( valueChanged( int ) ), this, SLOT( valueChanged( int ) ) );
  }
  else if ( mSlider )
void QgsRangeWidgetWrapper::initWidget( QWidget *editor )
{
  mDoubleSpinBox = qobject_cast<QDoubleSpinBox *>( editor );
  mIntSpinBox = qobject_cast<QSpinBox *>( editor );

  mDial = qobject_cast<QDial *>( editor );
  mSlider = qobject_cast<QSlider *>( editor );
  mQgsDial = qobject_cast<QgsDial *>( editor );
  mQgsSlider = qobject_cast<QgsSlider *>( editor );

  bool allowNull = config( QStringLiteral( "AllowNull" ), true ).toBool();

  QVariant min( config( QStringLiteral( "Min" ) ) );
  QVariant max( config( QStringLiteral( "Max" ) ) );
  QVariant step( config( QStringLiteral( "Step" ) ) );
  QVariant precision( config( QStringLiteral( "Precision" ) ) );

  if ( mDoubleSpinBox )
  {
    double stepval = step.isValid() ? step.toDouble() : 1.0;
    double minval = min.isValid() ? min.toDouble() : std::numeric_limits<double>::lowest();
    double maxval  = max.isValid() ? max.toDouble() : std::numeric_limits<double>::max();
    int precisionval = precision.isValid() ? precision.toInt() : layer()->fields().at( fieldIdx() ).precision();

    mDoubleSpinBox->setDecimals( precisionval );

    QgsDoubleSpinBox *qgsWidget = qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox );


    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    // Make room for null value: lower the minimum to allow for NULL special values
    if ( allowNull )
    {
      double decr;
      if ( precisionval > 0 )
      {
        decr = std::pow( 10, -precisionval );
      }
      else
      {
        decr = stepval;
      }
      minval -= decr;
      // Note: call setMinimum here or setValue won't work
      mDoubleSpinBox->setMinimum( minval );
      mDoubleSpinBox->setValue( minval );
      QgsDoubleSpinBox *doubleSpinBox( qobject_cast<QgsDoubleSpinBox *>( mDoubleSpinBox ) );
      if ( doubleSpinBox )
        doubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
      else
        mDoubleSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
    }
    mDoubleSpinBox->setMinimum( minval );
    mDoubleSpinBox->setMaximum( maxval );
    mDoubleSpinBox->setSingleStep( stepval );
    if ( config( QStringLiteral( "Suffix" ) ).isValid() )
      mDoubleSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );

    connect( mDoubleSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ),
    this, [ = ]( double ) { emitValueChanged(); } );
  }
  else if ( mIntSpinBox )
  {
    QgsSpinBox *qgsWidget = qobject_cast<QgsSpinBox *>( mIntSpinBox );
    if ( qgsWidget )
      qgsWidget->setShowClearButton( allowNull );
    int minval = min.toInt();
    if ( allowNull )
    {
      int stepval = step.isValid() ? step.toInt() : 1;
      minval -= stepval;
      mIntSpinBox->setValue( minval );
      QgsSpinBox *intSpinBox( qobject_cast<QgsSpinBox *>( mIntSpinBox ) );
      if ( intSpinBox )
        intSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
      else
        mIntSpinBox->setSpecialValueText( QgsApplication::nullRepresentation() );
    }
    setupIntEditor( minval, max, step, mIntSpinBox, this );
    if ( config( QStringLiteral( "Suffix" ) ).isValid() )
      mIntSpinBox->setSuffix( config( QStringLiteral( "Suffix" ) ).toString() );
  }
  else
  {
    ( void )field().convertCompatible( min );
    ( void )field().convertCompatible( max );
    ( void )field().convertCompatible( step );
    if ( mQgsDial )
      setupIntEditor( min, max, step, mQgsDial, this );
    else if ( mQgsSlider )
      setupIntEditor( min, max, step, mQgsSlider, this );
    else if ( mDial )
      setupIntEditor( min, max, step, mDial, this );
    else if ( mSlider )
      setupIntEditor( min, max, step, mSlider, this );
  }
}