38#include "moc_qgspropertyassistantwidget.cpp"
40using namespace Qt::StringLiterals;
44 , mDefinition( definition )
49 layout()->setContentsMargins( 0, 0, 0, 0 );
53 mLegendPreview->hide();
55 minValueSpinBox->setShowClearButton(
false );
56 maxValueSpinBox->setShowClearButton(
false );
59 mExpressionWidget->setLayer(
const_cast<QgsVectorLayer *
>( mLayer ) );
63 if (
auto *lTransformer = initialState.
transformer() )
65 minValueSpinBox->setValue( lTransformer->minValue() );
66 maxValueSpinBox->setValue( lTransformer->maxValue() );
68 if ( lTransformer->curveTransform() )
70 mTransformCurveCheckBox->setChecked(
true );
71 mTransformCurveCheckBox->setCollapsed(
false );
72 mCurveEditor->setCurve( *lTransformer->curveTransform() );
76 connect( computeValuesButton, &QPushButton::clicked,
this, &QgsPropertyAssistantWidget::computeValuesFromLayer );
81 mRoot.addChildNode( mLayerTreeLayer );
83 mLegendPreview->setModel( &mPreviewList );
84 mLegendPreview->setItemDelegate(
new QgsAssistantPreviewItemDelegate( &mPreviewList ) );
85 mLegendPreview->setHeaderHidden(
true );
86 mLegendPreview->expandAll();
87 mLegendVerticalFrame->setLayout(
new QVBoxLayout() );
88 mLegendVerticalFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
89 mLegendVerticalFrame->hide();
96 mTransformerWidget =
new QgsPropertySizeAssistantWidget(
this, mDefinition, initialState );
97 mLegendPreview->show();
104 mTransformerWidget =
new QgsPropertyColorAssistantWidget(
this, mDefinition, initialState );
105 mLegendPreview->show();
111 mTransformerWidget =
new QgsPropertyGenericNumericAssistantWidget(
this, mDefinition, initialState );
119 mTransformerWidget =
new QgsPropertyGenericNumericAssistantWidget(
this, mDefinition, initialState );
125 if ( mTransformerWidget )
127 mOutputWidget->layout()->addWidget( mTransformerWidget );
130 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
131 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
133 mCurveEditor->setHistogramSource( mLayer, mExpressionWidget->currentField() );
135 mCurveEditor->setHistogramSource( mLayer, expression );
140 mTransformCurveCheckBox->setVisible( mTransformerWidget );
153 mExpressionContextGenerator = generator;
154 mExpressionWidget->registerExpressionContextGenerator( generator );
159 property.setActive( !mExpressionWidget->currentText().isEmpty() );
160 if ( mExpressionWidget->isExpression() )
161 property.setExpressionString( mExpressionWidget->currentField() );
163 property.setField( mExpressionWidget->currentField() );
165 if ( mTransformerWidget )
167 std::unique_ptr<QgsPropertyTransformer> t( mTransformerWidget->createTransformer( minValueSpinBox->value(), maxValueSpinBox->value() ) );
168 if ( mTransformCurveCheckBox->isChecked() )
174 t->setCurveTransform(
nullptr );
176 property.setTransformer( t.release() );
184 if (
dockMode && mLegendVerticalFrame->isHidden() )
186 mLegendVerticalFrame->layout()->addWidget( mLegendPreview );
187 mLegendVerticalFrame->show();
191void QgsPropertyAssistantWidget::computeValuesFromLayer()
196 double minValue = 0.0;
197 double maxValue = 0.0;
199 if ( mExpressionWidget->isExpression() )
201 if ( !computeValuesFromExpression( mExpressionWidget->currentField(), minValue, maxValue ) )
206 if ( !computeValuesFromField( mExpressionWidget->currentField(), minValue, maxValue ) )
213 mCurveEditor->setMinHistogramValueRange( minValueSpinBox->value() );
214 mCurveEditor->setMaxHistogramValueRange( maxValueSpinBox->value() );
219void QgsPropertyAssistantWidget::updatePreview()
221 if ( mLegendPreview->isHidden() || !mTransformerWidget || !mLayer )
224 mLegendPreview->setIconSize( QSize( 512, 512 ) );
225 mPreviewList.clear();
229 QgsCurveTransform curve = mCurveEditor->curve();
230 const QList<QgsSymbolLegendNode *> nodes = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve :
nullptr );
234 const auto constNodes = nodes;
235 for ( QgsSymbolLegendNode *node : constNodes )
237 const QSize minSize( node->minimumIconSize() );
238 node->setIconSize( minSize );
239 widthMax = std::max( minSize.width(), widthMax );
240 QStandardItem *item =
new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
241 item->setEditable(
false );
242 mPreviewList.appendRow( item );
248 for (
int i = 0; i < breaks.length(); i++ )
250 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
251 QPixmap enlarged( widthMax, img.height() );
253 enlarged.fill( Qt::transparent );
254 QPainter p( &enlarged );
255 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
257 mPreviewList.item( i )->setIcon( enlarged );
261bool QgsPropertyAssistantWidget::computeValuesFromExpression(
const QString &expression,
double &minValue,
double &maxValue )
const
263 QgsExpression e( expression );
265 QgsExpressionContext context;
266 if ( mExpressionContextGenerator )
268 context = mExpressionContextGenerator->createExpressionContext();
277 if ( !e.prepare( &context ) )
280 const QSet<QString> referencedCols( e.referencedColumns() );
282 QgsFeatureIterator fit = mLayer->getFeatures(
287 double min = std::numeric_limits<double>::max();
288 double max = std::numeric_limits<double>::lowest();
295 const double value = e.evaluate( &context ).toDouble( &ok );
298 max = std::max( max, value );
299 min = std::min( min, value );
311bool QgsPropertyAssistantWidget::computeValuesFromField(
const QString &fieldName,
double &minValue,
double &maxValue )
const
313 const int fieldIndex = mLayer->fields().lookupField( fieldName );
314 if ( fieldIndex < 0 )
321 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
324 const double minDouble = min.toDouble( &ok );
328 const double maxDouble = max.toDouble( &ok );
332 minValue = minDouble;
333 maxValue = maxDouble;
344 : QgsPropertyAbstractTransformerWidget( parent, definition )
348 layout()->setContentsMargins( 0, 0, 0, 0 );
363 minSizeSpinBox->setShowClearButton(
false );
364 maxSizeSpinBox->setShowClearButton(
false );
365 nullSizeSpinBox->setShowClearButton(
false );
367 if (
const QgsSizeScaleTransformer *sizeTransform =
dynamic_cast<const QgsSizeScaleTransformer *
>( initialState.
transformer() ) )
369 minSizeSpinBox->setValue( sizeTransform->minSize() );
370 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
371 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
372 exponentSpinBox->setValue( sizeTransform->exponent() );
373 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
378 connect( minSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( maxSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
380 connect( nullSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
381 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
382 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
383 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, [
this] {
388QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
394 minSizeSpinBox->value(),
395 maxSizeSpinBox->value(),
396 nullSizeSpinBox->value(),
397 exponentSpinBox->value()
402QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews(
const QList<double> &breaks,
QgsLayerTreeLayer *parent,
const QgsSymbol *symbol,
double minValue,
double maxValue,
QgsCurveTransform *curve )
const
404 QList<QgsSymbolLegendNode *> nodes;
407 std::unique_ptr<QgsSymbol> tempSymbol;
419 legendSymbol = tempSymbol.get();
424 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
428 for (
int i = 0; i < breaks.length(); i++ )
430 std::unique_ptr<QgsSymbolLegendNode> node;
433 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
436 symbolClone->setSize( t->size( breaks[i] ) );
437 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
439 else if (
dynamic_cast<const QgsLineSymbol *
>( legendSymbol ) )
441 std::unique_ptr<QgsLineSymbol> symbolClone(
static_cast<QgsLineSymbol *
>( legendSymbol->
clone() ) );
443 symbolClone->setWidth( t->size( breaks[i] ) );
444 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
447 nodes << node.release();
454 return QList<QgsSymbolLegendNode *>();
457QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
458 : QgsPropertyAbstractTransformerWidget( parent, definition )
462 layout()->setContentsMargins( 0, 0, 0, 0 );
465 mNullColorButton->setAllowOpacity( supportsAlpha );
466 mNullColorButton->setShowNoColor(
true );
467 mNullColorButton->setColorDialogTitle( tr(
"Color For Null Values" ) );
468 mNullColorButton->setContext( u
"symbology"_s );
469 mNullColorButton->setNoColorString( tr(
"Transparent" ) );
471 if (
const QgsColorRampTransformer *colorTransform =
dynamic_cast<const QgsColorRampTransformer *
>( initialState.
transformer() ) )
473 mNullColorButton->setColor( colorTransform->nullColor() );
474 if ( colorTransform->colorRamp() )
475 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
481 if ( !mColorRampButton->colorRamp() )
484 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
490 mColorRampButton->setColorRamp( colorRamp.get() );
494QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
499 mColorRampButton->colorRamp(),
500 mNullColorButton->color(),
501 mColorRampButton->colorRampName()
506QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews(
const QList<double> &breaks,
QgsLayerTreeLayer *parent,
const QgsSymbol *symbol,
double minValue,
double maxValue,
QgsCurveTransform *curve )
const
508 QList<QgsSymbolLegendNode *> nodes;
511 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
516 legendSymbol = tempSymbol.get();
521 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
525 for (
int i = 0; i < breaks.length(); i++ )
527 std::unique_ptr<QgsSymbolLegendNode> node;
528 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
529 symbolClone->setColor( t->color( breaks[i] ) );
530 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
532 nodes << node.release();
537QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
538 : QgsPropertyAbstractTransformerWidget( parent, definition )
542 layout()->setContentsMargins( 0, 0, 0, 0 );
544 nullOutputSpinBox->setShowClearButton(
false );
551 minOutputSpinBox->setMaximum( 360.0 );
552 minOutputSpinBox->setValue( 0.0 );
553 minOutputSpinBox->setShowClearButton(
true );
554 minOutputSpinBox->setClearValue( 0.0 );
555 minOutputSpinBox->setSuffix( tr(
" °" ) );
556 maxOutputSpinBox->setMaximum( 360.0 );
557 maxOutputSpinBox->setValue( 360.0 );
558 maxOutputSpinBox->setShowClearButton(
true );
559 maxOutputSpinBox->setClearValue( 360.0 );
560 maxOutputSpinBox->setSuffix( tr(
" °" ) );
561 exponentSpinBox->hide();
562 mExponentLabel->hide();
563 mLabelMinOutput->setText( tr(
"Angle from" ) );
564 mLabelNullOutput->setText( tr(
"Angle when NULL" ) );
571 minOutputSpinBox->setMaximum( 100.0 );
572 minOutputSpinBox->setValue( 0.0 );
573 minOutputSpinBox->setShowClearButton(
true );
574 minOutputSpinBox->setClearValue( 0.0 );
575 minOutputSpinBox->setSuffix( tr(
" %" ) );
576 maxOutputSpinBox->setMaximum( 100.0 );
577 maxOutputSpinBox->setValue( 100.0 );
578 maxOutputSpinBox->setShowClearButton(
true );
579 maxOutputSpinBox->setClearValue( 100.0 );
580 maxOutputSpinBox->setSuffix( tr(
" %" ) );
581 mLabelMinOutput->setText( tr(
"Opacity from" ) );
582 mLabelNullOutput->setText( tr(
"Opacity when NULL" ) );
588 minOutputSpinBox->setMinimum( 0 );
589 maxOutputSpinBox->setMinimum( 0 );
590 minOutputSpinBox->setShowClearButton(
false );
591 maxOutputSpinBox->setShowClearButton(
false );
595 minOutputSpinBox->setMinimum( 1 );
596 maxOutputSpinBox->setMinimum( 1 );
597 minOutputSpinBox->setShowClearButton(
false );
598 maxOutputSpinBox->setShowClearButton(
false );
602 minOutputSpinBox->setMinimum( 0 );
603 maxOutputSpinBox->setMinimum( 0 );
604 minOutputSpinBox->setMaximum( 1 );
605 maxOutputSpinBox->setMaximum( 1 );
606 minOutputSpinBox->setShowClearButton(
false );
607 maxOutputSpinBox->setShowClearButton(
false );
611 minOutputSpinBox->setMinimum( -99999999.000000 );
612 maxOutputSpinBox->setMinimum( -99999999.000000 );
613 minOutputSpinBox->setMaximum( 99999999.000000 );
614 maxOutputSpinBox->setMaximum( 99999999.000000 );
615 minOutputSpinBox->setShowClearButton(
false );
616 maxOutputSpinBox->setShowClearButton(
false );
621 minOutputSpinBox->setShowClearButton(
false );
622 maxOutputSpinBox->setShowClearButton(
false );
627 if (
const QgsGenericNumericTransformer *transform =
dynamic_cast<const QgsGenericNumericTransformer *
>( initialState.
transformer() ) )
629 minOutputSpinBox->setValue( transform->minOutputValue() );
630 maxOutputSpinBox->setValue( transform->maxOutputValue() );
631 nullOutputSpinBox->setValue( transform->nullOutputValue() );
632 exponentSpinBox->setValue( transform->exponent() );
635 connect( minOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
636 connect( maxOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
637 connect( nullOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
638 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
646 minOutputSpinBox->value(),
647 maxOutputSpinBox->value(),
648 nullOutputSpinBox->value(),
649 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.