36#include "moc_qgspropertyassistantwidget.cpp"
40 , mDefinition( definition )
45 layout()->setContentsMargins( 0, 0, 0, 0 );
49 mLegendPreview->hide();
51 minValueSpinBox->setShowClearButton(
false );
52 maxValueSpinBox->setShowClearButton(
false );
55 mExpressionWidget->setLayer(
const_cast<QgsVectorLayer *
>( mLayer ) );
59 if (
auto *lTransformer = initialState.
transformer() )
61 minValueSpinBox->setValue( lTransformer->minValue() );
62 maxValueSpinBox->setValue( lTransformer->maxValue() );
64 if ( lTransformer->curveTransform() )
66 mTransformCurveCheckBox->setChecked(
true );
67 mTransformCurveCheckBox->setCollapsed(
false );
68 mCurveEditor->setCurve( *lTransformer->curveTransform() );
72 connect( computeValuesButton, &QPushButton::clicked,
this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
77 mRoot.addChildNode( mLayerTreeLayer );
79 mLegendPreview->setModel( &mPreviewList );
80 mLegendPreview->setItemDelegate(
new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
81 mLegendPreview->setHeaderHidden(
true );
82 mLegendPreview->expandAll();
83 mLegendVerticalFrame->setLayout(
new QVBoxLayout() );
84 mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
85 mLegendVerticalFrame->hide();
92 mTransformerWidget =
new QgsPropertySizeAssistantWidget(
this, mDefinition, initialState );
93 mLegendPreview->show();
100 mTransformerWidget =
new QgsPropertyColorAssistantWidget(
this, mDefinition, initialState );
101 mLegendPreview->show();
107 mTransformerWidget =
new QgsPropertyGenericNumericAssistantWidget(
this, mDefinition, initialState );
115 mTransformerWidget =
new QgsPropertyGenericNumericAssistantWidget(
this, mDefinition, initialState );
121 if ( mTransformerWidget )
123 mOutputWidget->layout()->addWidget( mTransformerWidget );
126 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
127 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
129 mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
131 mCurveEditor->setHistogramSource( mLayer, expression );
136 mTransformCurveCheckBox->setVisible( mTransformerWidget );
149 mExpressionContextGenerator = generator;
150 mExpressionWidget->registerExpressionContextGenerator( generator );
155 property.setActive( !mExpressionWidget->currentText().isEmpty() );
156 if ( mExpressionWidget->isExpression() )
157 property.setExpressionString( mExpressionWidget->currentField() );
159 property.setField( mExpressionWidget->currentField() );
161 if ( mTransformerWidget )
163 std::unique_ptr<QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
164 if ( mTransformCurveCheckBox->isChecked() )
170 t->setCurveTransform(
nullptr );
172 property.setTransformer( t.release() );
180 if (
dockMode && mLegendVerticalFrame->isHidden() )
182 mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
183 mLegendVerticalFrame->show();
187void QgsPropertyAssistantWidget::computeValuesFromLayer()
192 double minValue = 0.0;
193 double maxValue = 0.0;
195 if ( mExpressionWidget->isExpression() )
197 if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
202 if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
209 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
210 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
215void QgsPropertyAssistantWidget::updatePreview()
217 if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer )
220 mLegendPreview->setIconSize( QSize( 512, 512 ) );
221 mPreviewList.clear();
225 QgsCurveTransform curve = mCurveEditor->curve();
226 const QList<QgsSymbolLegendNode *> nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve :
nullptr );
230 const auto constNodes = nodes;
231 for ( QgsSymbolLegendNode *node : constNodes )
233 const QSize minSize( node->minimumIconSize() );
234 node->setIconSize( minSize );
235 widthMax = std::max( minSize.width(), widthMax );
236 QStandardItem *item =
new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
237 item->setEditable(
false );
238 mPreviewList.appendRow( item );
244 for (
int i = 0; i < breaks.length(); i++ )
246 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
247 QPixmap enlarged( widthMax, img.height() );
249 enlarged.fill( Qt::transparent );
250 QPainter p( &enlarged );
251 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
253 mPreviewList.item( i )->setIcon( enlarged );
257bool QgsPropertyAssistantWidget::computeValuesFromExpression(
const QString &expression,
double &minValue,
double &maxValue )
const
259 QgsExpression e( expression );
261 QgsExpressionContext context;
262 if ( mExpressionContextGenerator )
264 context = mExpressionContextGenerator->createExpressionContext();
273 if ( !e.prepare( &context ) )
276 const QSet<QString> referencedCols( e.referencedColumns() );
278 QgsFeatureIterator fit = mLayer->getFeatures(
283 double min = std::numeric_limits<double>::max();
284 double max = std::numeric_limits<double>::lowest();
291 const double value = e.evaluate( &context ).toDouble( &ok );
294 max = std::max( max, value );
295 min = std::min( min, value );
307bool QgsPropertyAssistantWidget::computeValuesFromField(
const QString &fieldName,
double &minValue,
double &maxValue )
const
309 const int fieldIndex = mLayer->fields().lookupField( fieldName );
310 if ( fieldIndex < 0 )
317 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
320 const double minDouble = min.toDouble( &ok );
324 const double maxDouble = max.toDouble( &ok );
328 minValue = minDouble;
329 maxValue = maxDouble;
340 : QgsPropertyAbstractTransformerWidget( parent, definition )
344 layout()->setContentsMargins( 0, 0, 0, 0 );
359 minSizeSpinBox->setShowClearButton(
false );
360 maxSizeSpinBox->setShowClearButton(
false );
361 nullSizeSpinBox->setShowClearButton(
false );
363 if (
const QgsSizeScaleTransformer *sizeTransform =
dynamic_cast<const QgsSizeScaleTransformer *
>( initialState.
transformer() ) )
365 minSizeSpinBox->setValue( sizeTransform->minSize() );
366 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
367 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
368 exponentSpinBox->setValue( sizeTransform->exponent() );
369 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
374 connect( minSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
375 connect( maxSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
376 connect( nullSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
377 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
378 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, [
this] {
384QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
390 minSizeSpinBox->value(),
391 maxSizeSpinBox->value(),
392 nullSizeSpinBox->value(),
393 exponentSpinBox->value()
398QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews(
const QList<double> &breaks,
QgsLayerTreeLayer *parent,
const QgsSymbol *symbol,
double minValue,
double maxValue,
QgsCurveTransform *curve )
const
400 QList<QgsSymbolLegendNode *> nodes;
403 std::unique_ptr<QgsSymbol> tempSymbol;
415 legendSymbol = tempSymbol.get();
420 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
424 for (
int i = 0; i < breaks.length(); i++ )
426 std::unique_ptr<QgsSymbolLegendNode> node;
429 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
432 symbolClone->setSize( t->size( breaks[i] ) );
433 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
435 else if (
dynamic_cast<const QgsLineSymbol *
>( legendSymbol ) )
437 std::unique_ptr<QgsLineSymbol> symbolClone(
static_cast<QgsLineSymbol *
>( legendSymbol->
clone() ) );
439 symbolClone->setWidth( t->size( breaks[i] ) );
440 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
443 nodes << node.release();
450 return QList<QgsSymbolLegendNode *>();
453QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
454 : QgsPropertyAbstractTransformerWidget( parent, definition )
458 layout()->setContentsMargins( 0, 0, 0, 0 );
461 mNullColorButton->setAllowOpacity( supportsAlpha );
462 mNullColorButton->setShowNoColor(
true );
463 mNullColorButton->setColorDialogTitle( tr(
"Color For Null Values" ) );
464 mNullColorButton->setContext( QStringLiteral(
"symbology" ) );
465 mNullColorButton->setNoColorString( tr(
"Transparent" ) );
467 if (
const QgsColorRampTransformer *colorTransform =
dynamic_cast<const QgsColorRampTransformer *
>( initialState.
transformer() ) )
469 mNullColorButton->setColor( colorTransform->nullColor() );
470 if ( colorTransform->colorRamp() )
471 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
477 if ( !mColorRampButton->colorRamp() )
480 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
486 mColorRampButton->setColorRamp( colorRamp.get() );
490QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
495 mColorRampButton->colorRamp(),
496 mNullColorButton->color(),
497 mColorRampButton->colorRampName()
502QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews(
const QList<double> &breaks,
QgsLayerTreeLayer *parent,
const QgsSymbol *symbol,
double minValue,
double maxValue,
QgsCurveTransform *curve )
const
504 QList<QgsSymbolLegendNode *> nodes;
507 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
512 legendSymbol = tempSymbol.get();
517 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
521 for (
int i = 0; i < breaks.length(); i++ )
523 std::unique_ptr<QgsSymbolLegendNode> node;
524 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
525 symbolClone->setColor( t->color( breaks[i] ) );
526 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
528 nodes << node.release();
533QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
534 : QgsPropertyAbstractTransformerWidget( parent, definition )
538 layout()->setContentsMargins( 0, 0, 0, 0 );
540 nullOutputSpinBox->setShowClearButton(
false );
547 minOutputSpinBox->setMaximum( 360.0 );
548 minOutputSpinBox->setValue( 0.0 );
549 minOutputSpinBox->setShowClearButton(
true );
550 minOutputSpinBox->setClearValue( 0.0 );
551 minOutputSpinBox->setSuffix( tr(
" °" ) );
552 maxOutputSpinBox->setMaximum( 360.0 );
553 maxOutputSpinBox->setValue( 360.0 );
554 maxOutputSpinBox->setShowClearButton(
true );
555 maxOutputSpinBox->setClearValue( 360.0 );
556 maxOutputSpinBox->setSuffix( tr(
" °" ) );
557 exponentSpinBox->hide();
558 mExponentLabel->hide();
559 mLabelMinOutput->setText( tr(
"Angle from" ) );
560 mLabelNullOutput->setText( tr(
"Angle when NULL" ) );
567 minOutputSpinBox->setMaximum( 100.0 );
568 minOutputSpinBox->setValue( 0.0 );
569 minOutputSpinBox->setShowClearButton(
true );
570 minOutputSpinBox->setClearValue( 0.0 );
571 minOutputSpinBox->setSuffix( tr(
" %" ) );
572 maxOutputSpinBox->setMaximum( 100.0 );
573 maxOutputSpinBox->setValue( 100.0 );
574 maxOutputSpinBox->setShowClearButton(
true );
575 maxOutputSpinBox->setClearValue( 100.0 );
576 maxOutputSpinBox->setSuffix( tr(
" %" ) );
577 mLabelMinOutput->setText( tr(
"Opacity from" ) );
578 mLabelNullOutput->setText( tr(
"Opacity when NULL" ) );
584 minOutputSpinBox->setMinimum( 0 );
585 maxOutputSpinBox->setMinimum( 0 );
586 minOutputSpinBox->setShowClearButton(
false );
587 maxOutputSpinBox->setShowClearButton(
false );
591 minOutputSpinBox->setMinimum( 1 );
592 maxOutputSpinBox->setMinimum( 1 );
593 minOutputSpinBox->setShowClearButton(
false );
594 maxOutputSpinBox->setShowClearButton(
false );
598 minOutputSpinBox->setMinimum( 0 );
599 maxOutputSpinBox->setMinimum( 0 );
600 minOutputSpinBox->setMaximum( 1 );
601 maxOutputSpinBox->setMaximum( 1 );
602 minOutputSpinBox->setShowClearButton(
false );
603 maxOutputSpinBox->setShowClearButton(
false );
607 minOutputSpinBox->setMinimum( -99999999.000000 );
608 maxOutputSpinBox->setMinimum( -99999999.000000 );
609 minOutputSpinBox->setMaximum( 99999999.000000 );
610 maxOutputSpinBox->setMaximum( 99999999.000000 );
611 minOutputSpinBox->setShowClearButton(
false );
612 maxOutputSpinBox->setShowClearButton(
false );
617 minOutputSpinBox->setShowClearButton(
false );
618 maxOutputSpinBox->setShowClearButton(
false );
623 if (
const QgsGenericNumericTransformer *transform =
dynamic_cast<const QgsGenericNumericTransformer *
>( initialState.
transformer() ) )
625 minOutputSpinBox->setValue( transform->minOutputValue() );
626 maxOutputSpinBox->setValue( transform->maxOutputValue() );
627 nullOutputSpinBox->setValue( transform->nullOutputValue() );
628 exponentSpinBox->setValue( transform->exponent() );
631 connect( minOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
632 connect( maxOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
633 connect( nullOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
634 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
642 minOutputSpinBox->value(),
643 maxOutputSpinBox->value(),
644 nullOutputSpinBox->value(),
645 exponentSpinBox->value()
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
@ Expression
Expression based property.
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Abstract interface for generating an expression context.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
@ Numeric
All numeric fields.
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Layer tree node points to a map layer.
Stores information about one class/rule of a vector layer renderer in a unified way that can be used ...
A line symbol type, for rendering LineString and MultiLineString geometries.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A marker symbol type, for rendering Point and MultiPoint geometries.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition for a property.
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
@ Double
Double value (including negative values).
@ Double0To1
Double value between 0-1 (inclusive).
@ StrokeWidth
Line stroke width.
@ IntegerPositiveGreaterZero
Non-zero positive integer values.
@ IntegerPositive
Positive integer values (including 0).
@ Opacity
Opacity (0-100).
@ ColorNoAlpha
Color with no alpha channel.
@ Rotation
Rotation (value between 0-360 degrees).
@ Size
1D size (eg marker radius, or square marker height/width)
@ ColorWithAlpha
Color with alpha channel.
@ DoublePositive
Positive double value (including 0).
@ DataTypeNumeric
Property requires a numeric value.
A store for object properties.
QString expressionString() const
Returns the expression used for the property value.
Qgis::PropertyType propertyType() const
Returns the property type.
QString field() const
Returns the current field name the property references.
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property,...
static QString capitalize(const QString &string, Qgis::Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
Abstract base class for all rendered symbols.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
Represents a vector layer which manages a vector based dataset.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.