mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-18 00:03:05 -04:00
251 lines
9.5 KiB
C++
251 lines
9.5 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"
|
|
|
|
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() );
|
|
}
|
|
|
|
connect( computeValuesButton, &QPushButton::clicked, this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
|
|
|
|
switch ( definition.standardTemplate() )
|
|
{
|
|
case QgsPropertyDefinition::Size:
|
|
{
|
|
mTransformerWidget = new QgsPropertySizeAssistantWidget( this, mDefinition, initialState );
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( mTransformerWidget )
|
|
{
|
|
mOutputWidget->layout()->addWidget( mTransformerWidget );
|
|
connect( mTransformerWidget, &QgsPropertyAbstractTransformerWidget::widgetChanged, this, &QgsPropertyAssistantWidget::widgetChanged );
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
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 )
|
|
property.setTransformer( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
|
|
}
|
|
|
|
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 );
|
|
emit widgetChanged();
|
|
}
|
|
|
|
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 = DBL_MAX;
|
|
double max = -DBL_MAX;
|
|
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 = qMax( max, value );
|
|
min = qMin( 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;
|
|
}
|
|
|
|
|
|
//
|
|
// 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 );
|
|
|
|
scaleMethodComboBox->addItem( tr( "Flannery" ), QgsSizeScaleTransformer::Flannery );
|
|
scaleMethodComboBox->addItem( tr( "Surface" ), QgsSizeScaleTransformer::Area );
|
|
scaleMethodComboBox->addItem( tr( "Radius" ), QgsSizeScaleTransformer::Linear );
|
|
scaleMethodComboBox->addItem( tr( "Exponential" ), QgsSizeScaleTransformer::Exponential );
|
|
|
|
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 );
|
|
}
|
|
);
|
|
}
|
|
|
|
QgsPropertyTransformer* 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;
|
|
}
|