QGIS/src/gui/qgspropertyassistantwidget.cpp
Nyall Dawson 62268e2b89 Use unique_ptr for owned object, and cleanup include in header
which was causing of cascade of unnecessary includes
2020-05-20 12:40:40 +10:00

588 lines
23 KiB
C++

/***************************************************************************
qgspropertyassistantwidget.cpp
------------------------------
begin : February, 2017
copyright : (C) 2017 Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgspropertyassistantwidget.h"
#include "qgsproject.h"
#include "qgsmapsettings.h"
#include "qgsvectorlayer.h"
#include "qgslayertreelayer.h"
#include "qgssymbollayerutils.h"
#include "qgsexpressioncontextutils.h"
#include "qgsstyle.h"
QgsPropertyAssistantWidget::QgsPropertyAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition, const QgsProperty &initialState,
const QgsVectorLayer *layer )
: QgsPanelWidget( parent )
, mDefinition( definition )
, mLayer( layer )
{
setupUi( this );
layout()->setContentsMargins( 0, 0, 0, 0 );
layout()->setMargin( 0 );
setPanelTitle( mDefinition.description() );
mLegendPreview->hide();
minValueSpinBox->setShowClearButton( false );
maxValueSpinBox->setShowClearButton( false );
// TODO expression widget shouldn't require a non-const layer
mExpressionWidget->setLayer( const_cast< QgsVectorLayer * >( mLayer ) );
mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );
mExpressionWidget->setField( initialState.propertyType() == QgsProperty::ExpressionBasedProperty ? initialState.expressionString() : initialState.field() );
if ( initialState.transformer() )
{
minValueSpinBox->setValue( initialState.transformer()->minValue() );
maxValueSpinBox->setValue( initialState.transformer()->maxValue() );
if ( initialState.transformer()->curveTransform() )
{
mTransformCurveCheckBox->setChecked( true );
mTransformCurveCheckBox->setCollapsed( false );
mCurveEditor->setCurve( *initialState.transformer()->curveTransform() );
}
}
connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
if ( mLayer )
{
mLayerTreeLayer = new QgsLayerTreeLayer( const_cast< QgsVectorLayer * >( mLayer ) );
mRoot.addChildNode( mLayerTreeLayer ); // takes ownership
}
mLegendPreview->setModel( &mPreviewList );
mLegendPreview->setItemDelegate( new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
mLegendPreview->setHeaderHidden( true );
mLegendPreview->expandAll();
mLegendVerticalFrame->setLayout( new QVBoxLayout() );
mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
mLegendVerticalFrame->layout()->setMargin( 0 );
mLegendVerticalFrame->hide();
switch ( definition.standardTemplate() )
{
case QgsPropertyDefinition::Size:
case QgsPropertyDefinition::StrokeWidth:
{
mTransformerWidget = new QgsPropertySizeAssistantWidget( this, mDefinition, initialState );
mLegendPreview->show();
break;
}
case QgsPropertyDefinition::ColorNoAlpha:
case QgsPropertyDefinition::ColorWithAlpha:
{
mTransformerWidget = new QgsPropertyColorAssistantWidget( this, mDefinition, initialState );
mLegendPreview->show();
break;
}
case QgsPropertyDefinition::Rotation:
{
mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
break;
}
default:
{
if ( mDefinition.dataType() == QgsPropertyDefinition::DataTypeNumeric )
{
mTransformerWidget = new QgsPropertyGenericNumericAssistantWidget( this, mDefinition, initialState );
}
break;
}
}
if ( mTransformerWidget )
{
mOutputWidget->layout()->addWidget( mTransformerWidget );
connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ]( const QString & expression )
{
mCurveEditor->setHistogramSource( mLayer, expression );
}
);
connect( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMinHistogramValueRange );
connect( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), mCurveEditor, &QgsCurveEditorWidget::setMaxHistogramValueRange );
}
mTransformCurveCheckBox->setVisible( mTransformerWidget );
connect( minValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
connect( maxValueSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
connect( mExpressionWidget, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) > ( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsPropertyAssistantWidget::widgetChanged );
connect( mCurveEditor, &QgsCurveEditorWidget::changed, this, &QgsPropertyAssistantWidget::widgetChanged );
connect( this, &QgsPropertyAssistantWidget::widgetChanged, this, &QgsPropertyAssistantWidget::updatePreview );
updatePreview();
}
void QgsPropertyAssistantWidget::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator )
{
mExpressionContextGenerator = generator;
mExpressionWidget->registerExpressionContextGenerator( generator );
}
void QgsPropertyAssistantWidget::updateProperty( QgsProperty &property )
{
property.setActive( !mExpressionWidget->currentText().isEmpty() );
if ( mExpressionWidget->isExpression() )
property.setExpressionString( mExpressionWidget->currentField() );
else
property.setField( mExpressionWidget->currentField() );
if ( mTransformerWidget )
{
std::unique_ptr< QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
if ( mTransformCurveCheckBox->isChecked() )
{
t->setCurveTransform( new QgsCurveTransform( mCurveEditor->curve() ) );
}
else
{
t->setCurveTransform( nullptr );
}
property.setTransformer( t.release() );
}
}
void QgsPropertyAssistantWidget::setDockMode( bool dockMode )
{
QgsPanelWidget::setDockMode( dockMode );
if ( dockMode && mLegendVerticalFrame->isHidden() )
{
mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
mLegendVerticalFrame->show();
}
}
void QgsPropertyAssistantWidget::computeValuesFromLayer()
{
if ( !mLayer )
return;
double minValue = 0.0;
double maxValue = 0.0;
if ( mExpressionWidget->isExpression() )
{
if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
return;
}
else
{
if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
return;
}
whileBlocking( minValueSpinBox )->setValue( minValue );
whileBlocking( maxValueSpinBox )->setValue( maxValue );
mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
emit widgetChanged();
}
void QgsPropertyAssistantWidget::updatePreview()
{
if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer ) // TODO - make this work OK without a layer
return;
mLegendPreview->setIconSize( QSize( 512, 512 ) );
mPreviewList.clear();
QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( minValueSpinBox->value(),
maxValueSpinBox->value(), 8 );
QgsCurveTransform curve = mCurveEditor->curve();
QList< QgsSymbolLegendNode * > nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(),
maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve : nullptr );
int widthMax = 0;
int i = 0;
const auto constNodes = nodes;
for ( QgsSymbolLegendNode *node : constNodes )
{
const QSize minSize( node->minimumIconSize() );
node->setIconSize( minSize );
widthMax = std::max( minSize.width(), widthMax );
QStandardItem *item = new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QString::number( breaks[i] ) );
item->setEditable( false );
mPreviewList.appendRow( item );
delete node;
i++;
}
// center icon and align text left by giving icons the same width
// TODO maybe add some space so that icons don't touch
for ( int i = 0; i < breaks.length(); i++ )
{
QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
QPixmap enlarged( widthMax, img.height() );
// fill transparent and add original image
enlarged.fill( Qt::transparent );
QPainter p( &enlarged );
p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
p.end();
mPreviewList.item( i )->setIcon( enlarged );
}
}
bool QgsPropertyAssistantWidget::computeValuesFromExpression( const QString &expression, double &minValue, double &maxValue ) const
{
QgsExpression e( expression );
QgsExpressionContext context;
if ( mExpressionContextGenerator )
{
context = mExpressionContextGenerator->createExpressionContext();
}
else
{
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::layerScope( mLayer );
}
if ( !e.prepare( &context ) )
return false;
QSet<QString> referencedCols( e.referencedColumns() );
QgsFeatureIterator fit = mLayer->getFeatures(
QgsFeatureRequest().setFlags( e.needsGeometry()
? QgsFeatureRequest::NoFlags
: QgsFeatureRequest::NoGeometry )
.setSubsetOfAttributes( referencedCols, mLayer->fields() ) );
// create list of non-null attribute values
double min = std::numeric_limits<double>::max();
double max = std::numeric_limits<double>::lowest();
QgsFeature f;
bool found = false;
while ( fit.nextFeature( f ) )
{
bool ok;
context.setFeature( f );
const double value = e.evaluate( &context ).toDouble( &ok );
if ( ok )
{
max = std::max( max, value );
min = std::min( min, value );
found = true;
}
}
if ( found )
{
minValue = min;
maxValue = max;
}
return found;
}
bool QgsPropertyAssistantWidget::computeValuesFromField( const QString &fieldName, double &minValue, double &maxValue ) const
{
int fieldIndex = mLayer->fields().lookupField( fieldName );
if ( fieldIndex < 0 )
{
return false;
}
bool ok = false;
double minDouble = mLayer->minimumValue( fieldIndex ).toDouble( &ok );
if ( !ok )
return false;
double maxDouble = mLayer->maximumValue( fieldIndex ).toDouble( &ok );
if ( !ok )
return false;
minValue = minDouble;
maxValue = maxDouble;
return true;
}
///@cond PRIVATE
//
// QgsPropertySizeAssistantWidget
//
QgsPropertySizeAssistantWidget::QgsPropertySizeAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
: QgsPropertyAbstractTransformerWidget( parent, definition )
{
setupUi( this );
layout()->setContentsMargins( 0, 0, 0, 0 );
layout()->setMargin( 0 );
if ( definition.standardTemplate() == QgsPropertyDefinition::Size )
{
scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
}
else if ( definition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
{
scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
scaleMethodComboBox->addItem( tr( "Linear" ), QgsSizeScaleTransformer::Linear );
}
minSizeSpinBox->setShowClearButton( false );
maxSizeSpinBox->setShowClearButton( false );
nullSizeSpinBox->setShowClearButton( false );
if ( const QgsSizeScaleTransformer *sizeTransform = dynamic_cast< const QgsSizeScaleTransformer * >( initialState.transformer() ) )
{
minSizeSpinBox->setValue( sizeTransform->minSize() );
maxSizeSpinBox->setValue( sizeTransform->maxSize() );
nullSizeSpinBox->setValue( sizeTransform->nullSize() );
exponentSpinBox->setValue( sizeTransform->exponent() );
scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
}
exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
connect( minSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( maxSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( nullSizeSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( scaleMethodComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::currentIndexChanged ), this,
[ = ]
{
exponentSpinBox->setEnabled( scaleMethodComboBox->currentData().toInt() == QgsSizeScaleTransformer::Exponential );
}
);
}
QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer( double minValue, double maxValue ) const
{
QgsSizeScaleTransformer *transformer = new QgsSizeScaleTransformer(
static_cast< QgsSizeScaleTransformer::ScaleType >( scaleMethodComboBox->currentData().toInt() ),
minValue,
maxValue,
minSizeSpinBox->value(),
maxSizeSpinBox->value(),
nullSizeSpinBox->value(),
exponentSpinBox->value() );
return transformer;
}
QList< QgsSymbolLegendNode * > QgsPropertySizeAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
{
QList< QgsSymbolLegendNode * > nodes;
const QgsSymbol *legendSymbol = symbol;
std::unique_ptr< QgsSymbol > tempSymbol;
if ( !legendSymbol )
{
if ( mDefinition.standardTemplate() == QgsPropertyDefinition::Size )
{
tempSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
}
else if ( mDefinition.standardTemplate() == QgsPropertyDefinition::StrokeWidth )
{
tempSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
}
legendSymbol = tempSymbol.get();
}
if ( !legendSymbol )
return nodes;
std::unique_ptr< QgsSizeScaleTransformer > t( createTransformer( minValue, maxValue ) );
if ( curve )
t->setCurveTransform( new QgsCurveTransform( *curve ) );
for ( int i = 0; i < breaks.length(); i++ )
{
std::unique_ptr< QgsSymbolLegendNode > node;
if ( dynamic_cast<const QgsMarkerSymbol *>( legendSymbol ) )
{
std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
symbolClone->setDataDefinedSize( QgsProperty() );
symbolClone->setDataDefinedAngle( QgsProperty() ); // to avoid symbol not being drawn
symbolClone->setSize( t->size( breaks[i] ) );
node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
}
else if ( dynamic_cast<const QgsLineSymbol *>( legendSymbol ) )
{
std::unique_ptr< QgsLineSymbol > symbolClone( static_cast<QgsLineSymbol *>( legendSymbol->clone() ) );
symbolClone->setDataDefinedWidth( QgsProperty() );
symbolClone->setWidth( t->size( breaks[i] ) );
node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
}
if ( node )
nodes << node.release();
}
return nodes;
}
QList<QgsSymbolLegendNode *> QgsPropertyAbstractTransformerWidget::generatePreviews( const QList<double> &, QgsLayerTreeLayer *, const QgsSymbol *, double, double, QgsCurveTransform * ) const
{
return QList< QgsSymbolLegendNode * >();
}
QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
: QgsPropertyAbstractTransformerWidget( parent, definition )
{
setupUi( this );
layout()->setContentsMargins( 0, 0, 0, 0 );
layout()->setMargin( 0 );
bool supportsAlpha = definition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha;
mNullColorButton->setAllowOpacity( supportsAlpha );
mNullColorButton->setShowNoColor( true );
mNullColorButton->setColorDialogTitle( tr( "Color For Null Values" ) );
mNullColorButton->setContext( QStringLiteral( "symbology" ) );
mNullColorButton->setNoColorString( tr( "Transparent" ) );
if ( const QgsColorRampTransformer *colorTransform = dynamic_cast< const QgsColorRampTransformer * >( initialState.transformer() ) )
{
mNullColorButton->setColor( colorTransform->nullColor() );
if ( colorTransform->colorRamp() )
mColorRampButton->setColorRamp( colorTransform->colorRamp() );
}
connect( mNullColorButton, &QgsColorButton::colorChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
connect( mColorRampButton, &QgsColorRampButton::colorRampChanged, this, &QgsPropertyColorAssistantWidget::widgetChanged );
if ( !mColorRampButton->colorRamp() )
{
// set a default ramp
QString defaultRampName = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/ColorRamp" ), QString() );
std::unique_ptr< QgsColorRamp > defaultRamp( QgsStyle::defaultStyle()->colorRamp( !defaultRampName.isEmpty() ? defaultRampName : QStringLiteral( "Blues" ) ) );
if ( defaultRamp )
mColorRampButton->setColorRamp( defaultRamp.get() );
}
}
QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer( double minValue, double maxValue ) const
{
QgsColorRampTransformer *transformer = new QgsColorRampTransformer(
minValue,
maxValue,
mColorRampButton->colorRamp(),
mNullColorButton->color() );
return transformer;
}
QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews( const QList<double> &breaks, QgsLayerTreeLayer *parent, const QgsSymbol *symbol, double minValue, double maxValue, QgsCurveTransform *curve ) const
{
QList< QgsSymbolLegendNode * > nodes;
const QgsMarkerSymbol *legendSymbol = dynamic_cast<const QgsMarkerSymbol *>( symbol );
std::unique_ptr< QgsMarkerSymbol > tempSymbol;
if ( !legendSymbol )
{
tempSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
legendSymbol = tempSymbol.get();
}
if ( !legendSymbol )
return nodes;
std::unique_ptr< QgsColorRampTransformer > t( createTransformer( minValue, maxValue ) );
if ( curve )
t->setCurveTransform( new QgsCurveTransform( *curve ) );
for ( int i = 0; i < breaks.length(); i++ )
{
std::unique_ptr< QgsSymbolLegendNode > node;
std::unique_ptr< QgsMarkerSymbol > symbolClone( static_cast<QgsMarkerSymbol *>( legendSymbol->clone() ) );
symbolClone->setColor( t->color( breaks[i] ) );
node.reset( new QgsSymbolLegendNode( parent, QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) ) );
if ( node )
nodes << node.release();
}
return nodes;
}
QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent, const QgsPropertyDefinition &definition, const QgsProperty &initialState )
: QgsPropertyAbstractTransformerWidget( parent, definition )
{
setupUi( this );
layout()->setContentsMargins( 0, 0, 0, 0 );
layout()->setMargin( 0 );
nullOutputSpinBox->setShowClearButton( false );
if ( definition.standardTemplate() == QgsPropertyDefinition::Rotation )
{
// tweak dialog for rotation
minOutputSpinBox->setMaximum( 360.0 );
minOutputSpinBox->setValue( 0.0 );
minOutputSpinBox->setShowClearButton( true );
minOutputSpinBox->setClearValue( 0.0 );
minOutputSpinBox->setSuffix( tr( " °" ) );
maxOutputSpinBox->setMaximum( 360.0 );
maxOutputSpinBox->setValue( 360.0 );
maxOutputSpinBox->setShowClearButton( true );
maxOutputSpinBox->setClearValue( 360.0 );
maxOutputSpinBox->setSuffix( tr( " °" ) );
exponentSpinBox->hide();
mExponentLabel->hide();
mLabelMinOutput->setText( tr( "Angle from" ) );
mLabelNullOutput->setText( tr( "Angle when NULL" ) );
}
else
{
minOutputSpinBox->setShowClearButton( false );
maxOutputSpinBox->setShowClearButton( false );
}
if ( const QgsGenericNumericTransformer *transform = dynamic_cast< const QgsGenericNumericTransformer * >( initialState.transformer() ) )
{
minOutputSpinBox->setValue( transform->minOutputValue() );
maxOutputSpinBox->setValue( transform->maxOutputValue() );
nullOutputSpinBox->setValue( transform->nullOutputValue() );
exponentSpinBox->setValue( transform->exponent() );
}
connect( minOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( maxOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( nullOutputSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
connect( exponentSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsPropertySizeAssistantWidget::widgetChanged );
}
QgsGenericNumericTransformer *QgsPropertyGenericNumericAssistantWidget::createTransformer( double minValue, double maxValue ) const
{
QgsGenericNumericTransformer *transformer = new QgsGenericNumericTransformer(
minValue,
maxValue,
minOutputSpinBox->value(),
maxOutputSpinBox->value(),
nullOutputSpinBox->value(),
exponentSpinBox->value() );
return transformer;
}
///@endcond PRIVATE