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
231 = mTransformerWidget->generatePreviews( breaks, mLayerTreeLayer, mSymbol.get(), minValueSpinBox->value(), maxValueSpinBox->value(), mTransformCurveCheckBox->isChecked() ? &curve :
nullptr );
235 const auto constNodes = nodes;
236 for ( QgsSymbolLegendNode *node : constNodes )
238 const QSize minSize( node->minimumIconSize() );
239 node->setIconSize( minSize );
240 widthMax = std::max( minSize.width(), widthMax );
241 QStandardItem *item =
new QStandardItem( node->data( Qt::DecorationRole ).value<QPixmap>(), QLocale().toString( breaks[i] ) );
242 item->setEditable(
false );
243 mPreviewList.appendRow( item );
249 for (
int i = 0; i < breaks.length(); i++ )
251 const QPixmap img( mPreviewList.item( i )->icon().pixmap( mPreviewList.item( i )->icon().actualSize( QSize( 512, 512 ) ) ) );
252 QPixmap enlarged( widthMax, img.height() );
254 enlarged.fill( Qt::transparent );
255 QPainter p( &enlarged );
256 p.drawPixmap( QPoint( ( widthMax - img.width() ) / 2, 0 ), img );
258 mPreviewList.item( i )->setIcon( enlarged );
262bool QgsPropertyAssistantWidget::computeValuesFromExpression(
const QString &expression,
double &minValue,
double &maxValue )
const
264 QgsExpression e( expression );
266 QgsExpressionContext context;
267 if ( mExpressionContextGenerator )
269 context = mExpressionContextGenerator->createExpressionContext();
276 if ( !e.prepare( &context ) )
279 const QSet<QString> referencedCols( e.referencedColumns() );
281 QgsFeatureIterator fit = mLayer->getFeatures(
286 double min = std::numeric_limits<double>::max();
287 double max = std::numeric_limits<double>::lowest();
294 const double value = e.evaluate( &context ).toDouble( &ok );
297 max = std::max( max, value );
298 min = std::min( min, value );
310bool QgsPropertyAssistantWidget::computeValuesFromField(
const QString &fieldName,
double &minValue,
double &maxValue )
const
312 const int fieldIndex = mLayer->fields().lookupField( fieldName );
313 if ( fieldIndex < 0 )
320 mLayer->minimumAndMaximumValue( fieldIndex, min, max );
323 const double minDouble = min.toDouble( &ok );
327 const double maxDouble = max.toDouble( &ok );
331 minValue = minDouble;
332 maxValue = maxDouble;
343 : QgsPropertyAbstractTransformerWidget( parent, definition )
347 layout()->setContentsMargins( 0, 0, 0, 0 );
362 minSizeSpinBox->setShowClearButton(
false );
363 maxSizeSpinBox->setShowClearButton(
false );
364 nullSizeSpinBox->setShowClearButton(
false );
366 if (
const QgsSizeScaleTransformer *sizeTransform =
dynamic_cast<const QgsSizeScaleTransformer *
>( initialState.
transformer() ) )
368 minSizeSpinBox->setValue( sizeTransform->minSize() );
369 maxSizeSpinBox->setValue( sizeTransform->maxSize() );
370 nullSizeSpinBox->setValue( sizeTransform->nullSize() );
371 exponentSpinBox->setValue( sizeTransform->exponent() );
372 scaleMethodComboBox->setCurrentIndex( scaleMethodComboBox->findData( sizeTransform->type() ) );
377 connect( minSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
378 connect( maxSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
379 connect( nullSizeSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
380 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
381 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
382 connect( scaleMethodComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, [
this] {
387QgsSizeScaleTransformer *QgsPropertySizeAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
393 minSizeSpinBox->value(),
394 maxSizeSpinBox->value(),
395 nullSizeSpinBox->value(),
396 exponentSpinBox->value()
401QList<QgsSymbolLegendNode *> QgsPropertySizeAssistantWidget::generatePreviews(
405 QList<QgsSymbolLegendNode *> nodes;
408 std::unique_ptr<QgsSymbol> tempSymbol;
420 legendSymbol = tempSymbol.get();
425 std::unique_ptr<QgsSizeScaleTransformer> t( createTransformer( minValue, maxValue ) );
429 for (
int i = 0; i < breaks.length(); i++ )
431 std::unique_ptr<QgsSymbolLegendNode> node;
434 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
437 symbolClone->setSize( t->size( breaks[i] ) );
438 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
440 else if (
dynamic_cast<const QgsLineSymbol *
>( legendSymbol ) )
442 std::unique_ptr<QgsLineSymbol> symbolClone(
static_cast<QgsLineSymbol *
>( legendSymbol->
clone() ) );
444 symbolClone->setWidth( t->size( breaks[i] ) );
445 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
448 nodes << node.release();
455 return QList<QgsSymbolLegendNode *>();
458QgsPropertyColorAssistantWidget::QgsPropertyColorAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
459 : QgsPropertyAbstractTransformerWidget( parent, definition )
463 layout()->setContentsMargins( 0, 0, 0, 0 );
466 mNullColorButton->setAllowOpacity( supportsAlpha );
467 mNullColorButton->setShowNoColor(
true );
468 mNullColorButton->setColorDialogTitle( tr(
"Color For Null Values" ) );
469 mNullColorButton->setContext( u
"symbology"_s );
470 mNullColorButton->setNoColorString( tr(
"Transparent" ) );
472 if (
const QgsColorRampTransformer *colorTransform =
dynamic_cast<const QgsColorRampTransformer *
>( initialState.
transformer() ) )
474 mNullColorButton->setColor( colorTransform->nullColor() );
475 if ( colorTransform->colorRamp() )
476 mColorRampButton->setColorRamp( colorTransform->colorRamp() );
482 if ( !mColorRampButton->colorRamp() )
485 std::unique_ptr<QgsColorRamp> colorRamp(
QgsProject::instance()->styleSettings()->defaultColorRamp() );
491 mColorRampButton->setColorRamp( colorRamp.get() );
495QgsColorRampTransformer *QgsPropertyColorAssistantWidget::createTransformer(
double minValue,
double maxValue )
const
501QList<QgsSymbolLegendNode *> QgsPropertyColorAssistantWidget::generatePreviews(
505 QList<QgsSymbolLegendNode *> nodes;
508 std::unique_ptr<QgsMarkerSymbol> tempSymbol;
513 legendSymbol = tempSymbol.get();
518 std::unique_ptr<QgsColorRampTransformer> t( createTransformer( minValue, maxValue ) );
522 for (
int i = 0; i < breaks.length(); i++ )
524 std::unique_ptr<QgsSymbolLegendNode> node;
525 std::unique_ptr<QgsMarkerSymbol> symbolClone(
static_cast<QgsMarkerSymbol *
>( legendSymbol->
clone() ) );
526 symbolClone->setColor( t->color( breaks[i] ) );
527 node = std::make_unique<QgsSymbolLegendNode>( parent,
QgsLegendSymbolItem( symbolClone.get(), QString::number( i ), QString() ) );
529 nodes << node.release();
534QgsPropertyGenericNumericAssistantWidget::QgsPropertyGenericNumericAssistantWidget( QWidget *parent,
const QgsPropertyDefinition &definition,
const QgsProperty &initialState )
535 : QgsPropertyAbstractTransformerWidget( parent, definition )
539 layout()->setContentsMargins( 0, 0, 0, 0 );
541 nullOutputSpinBox->setShowClearButton(
false );
548 minOutputSpinBox->setMaximum( 360.0 );
549 minOutputSpinBox->setValue( 0.0 );
550 minOutputSpinBox->setShowClearButton(
true );
551 minOutputSpinBox->setClearValue( 0.0 );
552 minOutputSpinBox->setSuffix( tr(
" °" ) );
553 maxOutputSpinBox->setMaximum( 360.0 );
554 maxOutputSpinBox->setValue( 360.0 );
555 maxOutputSpinBox->setShowClearButton(
true );
556 maxOutputSpinBox->setClearValue( 360.0 );
557 maxOutputSpinBox->setSuffix( tr(
" °" ) );
558 exponentSpinBox->hide();
559 mExponentLabel->hide();
560 mLabelMinOutput->setText( tr(
"Angle from" ) );
561 mLabelNullOutput->setText( tr(
"Angle when NULL" ) );
568 minOutputSpinBox->setMaximum( 100.0 );
569 minOutputSpinBox->setValue( 0.0 );
570 minOutputSpinBox->setShowClearButton(
true );
571 minOutputSpinBox->setClearValue( 0.0 );
572 minOutputSpinBox->setSuffix( tr(
" %" ) );
573 maxOutputSpinBox->setMaximum( 100.0 );
574 maxOutputSpinBox->setValue( 100.0 );
575 maxOutputSpinBox->setShowClearButton(
true );
576 maxOutputSpinBox->setClearValue( 100.0 );
577 maxOutputSpinBox->setSuffix( tr(
" %" ) );
578 mLabelMinOutput->setText( tr(
"Opacity from" ) );
579 mLabelNullOutput->setText( tr(
"Opacity when NULL" ) );
585 minOutputSpinBox->setMinimum( 0 );
586 maxOutputSpinBox->setMinimum( 0 );
587 minOutputSpinBox->setShowClearButton(
false );
588 maxOutputSpinBox->setShowClearButton(
false );
592 minOutputSpinBox->setMinimum( 1 );
593 maxOutputSpinBox->setMinimum( 1 );
594 minOutputSpinBox->setShowClearButton(
false );
595 maxOutputSpinBox->setShowClearButton(
false );
599 minOutputSpinBox->setMinimum( 0 );
600 maxOutputSpinBox->setMinimum( 0 );
601 minOutputSpinBox->setMaximum( 1 );
602 maxOutputSpinBox->setMaximum( 1 );
603 minOutputSpinBox->setShowClearButton(
false );
604 maxOutputSpinBox->setShowClearButton(
false );
608 minOutputSpinBox->setMinimum( -99999999.000000 );
609 maxOutputSpinBox->setMinimum( -99999999.000000 );
610 minOutputSpinBox->setMaximum( 99999999.000000 );
611 maxOutputSpinBox->setMaximum( 99999999.000000 );
612 minOutputSpinBox->setShowClearButton(
false );
613 maxOutputSpinBox->setShowClearButton(
false );
618 minOutputSpinBox->setShowClearButton(
false );
619 maxOutputSpinBox->setShowClearButton(
false );
624 if (
const QgsGenericNumericTransformer *transform =
dynamic_cast<const QgsGenericNumericTransformer *
>( initialState.
transformer() ) )
626 minOutputSpinBox->setValue( transform->minOutputValue() );
627 maxOutputSpinBox->setValue( transform->maxOutputValue() );
628 nullOutputSpinBox->setValue( transform->nullOutputValue() );
629 exponentSpinBox->setValue( transform->exponent() );
632 connect( minOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
633 connect( maxOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
634 connect( nullOutputSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
635 connect( exponentSpinBox,
static_cast<void ( QgsDoubleSpinBox::* )(
double )
>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsPropertySizeAssistantWidget::widgetChanged );
641 =
new QgsGenericNumericTransformer( minValue, maxValue, minOutputSpinBox->value(), maxOutputSpinBox->value(), nullOutputSpinBox->value(), 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.