46#include <QRandomGenerator>
48#include <QStyledItemDelegate>
50#include "moc_qgsdiagramproperties.cpp"
52using namespace Qt::StringLiterals;
56 QgsExpressionContext expContext;
59 expContext = mMapCanvas->createExpressionContext();
77 , mMapCanvas( canvas )
94 mDiagramOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect,
false );
97 mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
98 mDiagramOptionsListWidget->setIconSize( QSize( iconSize, iconSize ) );
100 mBarSpacingSpinBox->setClearValue( 0 );
101 mBarSpacingUnitComboBox->setUnits(
107 mDiagramTypeComboBox->blockSignals(
true );
116 mDiagramTypeComboBox->blockSignals(
false );
119 mAxisLineStyleButton->setDialogTitle( tr(
"Axis Line Symbol" ) );
121 mScaleRangeWidget->setMapCanvas( mMapCanvas );
122 mSizeFieldExpressionWidget->registerExpressionContextGenerator(
this );
124 mBackgroundColorButton->setColorDialogTitle( tr(
"Select Background Color" ) );
125 mBackgroundColorButton->setAllowOpacity(
true );
126 mBackgroundColorButton->setContext( u
"symbology"_s );
127 mBackgroundColorButton->setShowNoColor(
true );
128 mBackgroundColorButton->setNoColorString( tr(
"Transparent Background" ) );
129 mDiagramPenColorButton->setColorDialogTitle( tr(
"Select Pen Color" ) );
130 mDiagramPenColorButton->setAllowOpacity(
true );
131 mDiagramPenColorButton->setContext( u
"symbology"_s );
132 mDiagramPenColorButton->setShowNoColor(
true );
133 mDiagramPenColorButton->setNoColorString( tr(
"Transparent Stroke" ) );
135 mMaxValueSpinBox->setShowClearButton(
false );
136 mSizeSpinBox->setClearValue( 5 );
138 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnAttributeExpression,
new EditBlockerDelegate(
this ) );
139 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnColor,
new QgsColorSwatchDelegate(
this ) );
141 mDiagramAttributesTreeWidget->setColumnWidth( ColumnColor,
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 6.6 );
152 mDiagramTypeComboBox->setEnabled(
false );
153 mOptionsTab->setEnabled(
false );
154 mDiagramFrame->setEnabled(
false );
162 stackedPlacement->setCurrentWidget( pagePoint );
163 mLinePlacementFrame->setVisible(
false );
166 stackedPlacement->setCurrentWidget( pageLine );
167 mLinePlacementFrame->setVisible(
true );
170 stackedPlacement->setCurrentWidget( pagePolygon );
171 mLinePlacementFrame->setVisible(
false );
180 mPlacePointBtnGrp =
new QButtonGroup(
this );
181 mPlacePointBtnGrp->addButton( radAroundPoint );
182 mPlacePointBtnGrp->addButton( radOverPoint );
183 mPlacePointBtnGrp->setExclusive(
true );
187 mPlaceLineBtnGrp =
new QButtonGroup(
this );
188 mPlaceLineBtnGrp->addButton( radAroundLine );
189 mPlaceLineBtnGrp->addButton( radOverLine );
190 mPlaceLineBtnGrp->setExclusive(
true );
194 mPlacePolygonBtnGrp =
new QButtonGroup(
this );
195 mPlacePolygonBtnGrp->addButton( radAroundCentroid );
196 mPlacePolygonBtnGrp->addButton( radOverCentroid );
197 mPlacePolygonBtnGrp->addButton( radPolygonPerimeter );
198 mPlacePolygonBtnGrp->addButton( radInsidePolygon );
199 mPlacePolygonBtnGrp->setExclusive(
true );
205 mScaleDependencyComboBox->addItem( tr(
"Area" ),
true );
206 mScaleDependencyComboBox->addItem( tr(
"Diameter" ),
false );
208 mAngleOffsetComboBox->addItem( tr(
"Top" ), 270 );
209 mAngleOffsetComboBox->addItem( tr(
"Right" ), 0 );
210 mAngleOffsetComboBox->addItem( tr(
"Bottom" ), 90 );
211 mAngleOffsetComboBox->addItem( tr(
"Left" ), 180 );
219 QSizePolicy policy( mDiagramOptionsListFrame->sizePolicy() );
220 policy.setHorizontalStretch( 0 );
221 mDiagramOptionsListFrame->setSizePolicy( policy );
222 if ( !settings.
contains( u
"/Windows/Diagrams/OptionsSplitState"_s ) )
225 QList<int> splitsizes;
227 mDiagramOptionsSplitter->setSizes( splitsizes );
231 mDiagramOptionsSplitter->restoreState( settings.
value( u
"Windows/Diagrams/OptionsSplitState"_s ).toByteArray() );
232 mDiagramOptionsListWidget->setCurrentRow( settings.
value( u
"Windows/Diagrams/Tab"_s, 0 ).toInt() );
235 whileBlocking( mOptionsTab )->setCurrentIndex( mDiagramStackedWidget->currentIndex() );
236 mOptionsTab->tabBar()->setUsesScrollButtons(
true );
239 mSizeFieldExpressionWidget->setLayer( mLayer );
243 mSizeFieldExpressionWidget->setGeomCalculator( myDa );
247 for (
int idx = 0; idx < layerFields.
count(); ++idx )
249 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mAttributesTreeWidget );
250 const QString name = u
"\"%1\""_s.arg( layerFields.
at( idx ).
name() );
251 newItem->setText( 0, name );
252 newItem->setData( 0, RoleAttributeExpression, name );
253 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
257 mPaintEffect->setEnabled(
false );
270 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
288 QList<QWidget *> widgets;
289 widgets << chkLineAbove;
290 widgets << chkLineBelow;
291 widgets << chkLineOn;
292 widgets << chkLineOrientationDependent;
293 widgets << mAngleDirectionComboBox;
294 widgets << mAngleOffsetComboBox;
295 widgets << mAttributeBasedScalingRadio;
296 widgets << mAxisLineStyleButton;
297 widgets << mBackgroundColorButton;
298 widgets << mBarSpacingSpinBox;
299 widgets << mBarSpacingUnitComboBox;
300 widgets << mBarWidthSpinBox;
301 widgets << mCheckBoxAttributeLegend;
302 widgets << mDiagramAttributesTreeWidget;
303 widgets << mDiagramDistanceSpinBox;
304 widgets << mDiagramFontButton;
305 widgets << mDiagramPenColorButton;
306 widgets << mDiagramSizeSpinBox;
307 widgets << mDiagramLineUnitComboBox;
308 widgets << mDiagramTypeComboBox;
309 widgets << mDiagramUnitComboBox;
310 widgets << mEnableDiagramCheckBox;
311 widgets << mFixedSizeRadio;
312 widgets << mIncreaseMinimumSizeSpinBox;
313 widgets << mIncreaseSmallDiagramsGroupBox;
314 widgets << mLabelPlacementComboBox;
315 widgets << mMaxValueSpinBox;
316 widgets << mPaintEffectWidget;
317 widgets << mPenWidthSpinBox;
318 widgets << mPrioritySlider;
319 widgets << mOpacityWidget;
320 widgets << mOrientationDownButton;
321 widgets << mOrientationLeftButton;
322 widgets << mOrientationRightButton;
323 widgets << mOrientationUpButton;
324 widgets << mScaleDependencyComboBox;
325 widgets << mScaleRangeWidget;
326 widgets << mScaleVisibilityGroupBox;
327 widgets << mShowAllCheckBox;
328 widgets << mShowAxisGroupBox;
329 widgets << mSizeFieldExpressionWidget;
330 widgets << mSizeSpinBox;
331 widgets << mZIndexSpinBox;
332 widgets << radAroundCentroid;
333 widgets << radAroundLine;
334 widgets << radAroundPoint;
335 widgets << radInsidePolygon;
336 widgets << radOverCentroid;
337 widgets << radOverLine;
338 widgets << radOverPoint;
339 widgets << radPolygonPerimeter;
341 connectValueChanged( widgets );
347 mOptionsTab->setVisible(
dockMode );
348 mOptionsTab->setTabToolTip( 0, tr(
"Attributes" ) );
349 mOptionsTab->setTabToolTip( 1, tr(
"Rendering" ) );
350 mOptionsTab->setTabToolTip( 2, tr(
"Size" ) );
351 mOptionsTab->setTabToolTip( 3, tr(
"Placement" ) );
352 mOptionsTab->setTabToolTip( 4, tr(
"Options" ) );
353 mOptionsTab->setTabToolTip( 5, tr(
"Legend" ) );
354 mDiagramOptionsListFrame->setVisible( !
dockMode );
359 mDiagramType = diagramType;
361 mDiagramTypeComboBox->setVisible(
false );
362 mDiagramTypeComboBox->blockSignals(
true );
363 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
364 mDiagramTypeComboBox->blockSignals(
false );
370void QgsDiagramProperties::insertDefaults()
372 mFixedSizeRadio->setChecked(
true );
375 mLabelPlacementComboBox->setCurrentIndex( mLabelPlacementComboBox->findText( tr(
"x-height" ) ) );
376 mDiagramSizeSpinBox->setEnabled(
true );
377 mDiagramSizeSpinBox->setValue( 15 );
378 mLinearScaleFrame->setEnabled(
false );
379 mBarWidthSpinBox->setValue( 5 );
382 mShowAllCheckBox->setChecked(
true );
383 mCheckBoxAttributeLegend->setChecked(
true );
388 radAroundPoint->setChecked(
true );
392 radAroundLine->setChecked(
true );
393 chkLineAbove->setChecked(
true );
394 chkLineBelow->setChecked(
false );
395 chkLineOn->setChecked(
false );
396 chkLineOrientationDependent->setChecked(
false );
400 radOverCentroid->setChecked(
true );
401 mDiagramDistanceLabel->setEnabled(
false );
402 mDiagramDistanceSpinBox->setEnabled(
false );
403 mDistanceDDBtn->setEnabled(
false );
410 mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
411 mDiagramPenColorButton->setColor( QColor( 0, 0, 0, 255 ) );
416void QgsDiagramProperties::updateDataDefinedButtons()
418 const QList<QgsPropertyOverrideButton *> propertyOverrideButtons { findChildren<QgsPropertyOverrideButton *>() };
419 for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
421 updateDataDefinedButton( button );
434 whileBlocking( button )->setToProperty( mDataDefinedProperties.property( key ) );
447 renderer = stackedRenderer->
renderer( 0 );
458 mDiagramAttributesTreeWidget->clear();
469 mFixedSizeRadio->setChecked(
true );
473 mAttributeBasedScalingRadio->setChecked(
true );
475 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
476 mLinearScaleFrame->setEnabled( mAttributeBasedScalingRadio->isChecked() );
481 if ( !settingList.isEmpty() )
483 setDiagramEnabled( settingList.at( 0 ).enabled );
484 mDiagramFontButton->setCurrentFont( settingList.at( 0 ).font );
485 const QSizeF size = settingList.at( 0 ).size;
486 mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
487 mOpacityWidget->setOpacity( settingList.at( 0 ).opacity );
488 mDiagramPenColorButton->setColor( settingList.at( 0 ).penColor );
489 mPenWidthSpinBox->setValue( settingList.at( 0 ).penWidth );
490 mDiagramSizeSpinBox->setValue( ( size.width() + size.height() ) / 2.0 );
491 mScaleRangeWidget->setScaleRange(
492 ( settingList.at( 0 ).minimumScale > 0 ? settingList.at( 0 ).minimumScale : mLayer->minimumScale() ),
493 ( settingList.at( 0 ).maximumScale > 0 ? settingList.at( 0 ).maximumScale : mLayer->maximumScale() )
495 mScaleVisibilityGroupBox->setChecked( settingList.at( 0 ).scaleBasedVisibility );
496 mDiagramUnitComboBox->setUnit( settingList.at( 0 ).sizeType );
497 mDiagramUnitComboBox->setMapUnitScale( settingList.at( 0 ).sizeScale );
498 mDiagramLineUnitComboBox->setUnit( settingList.at( 0 ).lineSizeUnit );
499 mDiagramLineUnitComboBox->setMapUnitScale( settingList.at( 0 ).lineSizeScale );
503 mLabelPlacementComboBox->setCurrentIndex( 0 );
507 mLabelPlacementComboBox->setCurrentIndex( 1 );
510 if ( settingList.at( 0 ).paintEffect() )
511 mPaintEffect.reset( settingList.at( 0 ).paintEffect()->clone() );
513 mAngleOffsetComboBox->setCurrentIndex( mAngleOffsetComboBox->findData( settingList.at( 0 ).rotationOffset ) );
514 mAngleDirectionComboBox->setCurrentIndex( mAngleDirectionComboBox->findData( settingList.at( 0 ).direction() ) );
516 switch ( settingList.at( 0 ).diagramOrientation )
519 mOrientationLeftButton->setChecked(
true );
523 mOrientationRightButton->setChecked(
true );
527 mOrientationUpButton->setChecked(
true );
531 mOrientationDownButton->setChecked(
true );
535 mBarWidthSpinBox->setValue( settingList.at( 0 ).barWidth );
536 mBarSpacingSpinBox->setValue( settingList.at( 0 ).spacing() );
537 mBarSpacingUnitComboBox->setUnit( settingList.at( 0 ).spacingUnit() );
538 mBarSpacingUnitComboBox->setMapUnitScale( settingList.at( 0 ).spacingMapUnitScale() );
540 mShowAxisGroupBox->setChecked( settingList.at( 0 ).showAxis() );
541 if ( settingList.at( 0 ).axisLineSymbol() )
542 mAxisLineStyleButton->setSymbol( settingList.at( 0 ).axisLineSymbol()->clone() );
544 mIncreaseSmallDiagramsGroupBox->setChecked( settingList.at( 0 ).minimumSize != 0 );
545 mIncreaseMinimumSizeSpinBox->setValue( settingList.at( 0 ).minimumSize );
547 if ( settingList.at( 0 ).scaleByArea )
549 mScaleDependencyComboBox->setCurrentIndex( 0 );
553 mScaleDependencyComboBox->setCurrentIndex( 1 );
556 const QList<QColor> categoryColors = settingList.at( 0 ).categoryColors;
557 const QList<QString> categoryAttributes = settingList.at( 0 ).categoryAttributes;
558 const QList<QString> categoryLabels = settingList.at( 0 ).categoryLabels;
559 QList<QString>::const_iterator catIt = categoryAttributes.constBegin();
560 QList<QColor>::const_iterator coIt = categoryColors.constBegin();
561 QList<QString>::const_iterator labIt = categoryLabels.constBegin();
562 for ( ; catIt != categoryAttributes.constEnd(); ++catIt, ++coIt, ++labIt )
564 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
565 newItem->setText( 0, *catIt );
566 newItem->setData( 0, RoleAttributeExpression, *catIt );
567 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
568 newItem->setData( ColumnColor, Qt::EditRole, *coIt );
569 newItem->setText( 2, *labIt );
570 newItem->setFlags( newItem->flags() | Qt::ItemIsEditable );
579 mDiagramSizeSpinBox->setEnabled(
false );
580 mLinearScaleFrame->setEnabled(
true );
581 mMaxValueSpinBox->setValue( lidr->
upperValue() );
582 mSizeSpinBox->setValue( ( lidr->
upperSize().width() + lidr->
upperSize().height() ) / 2 );
600 mDiagramTypeComboBox->blockSignals(
true );
601 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
602 mDiagramTypeComboBox->blockSignals(
false );
607 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
614 mDiagramDistanceSpinBox->setValue( dls->
distance() );
615 mPrioritySlider->setValue( dls->
priority() );
616 mZIndexSpinBox->setValue( dls->
zIndex() );
621 radAroundPoint->setChecked(
true );
622 radAroundCentroid->setChecked(
true );
626 radOverPoint->setChecked(
true );
627 radOverCentroid->setChecked(
true );
631 radAroundLine->setChecked(
true );
632 radPolygonPerimeter->setChecked(
true );
636 radOverLine->setChecked(
true );
637 radInsidePolygon->setChecked(
true );
648 chkLineOrientationDependent->setChecked(
true );
654 updateDataDefinedButtons();
661 settings.
setValue( u
"Windows/Diagrams/OptionsSplitState"_s, mDiagramOptionsSplitter->saveState() );
662 settings.
setValue( u
"Windows/Diagrams/Tab"_s, mDiagramOptionsListWidget->currentRow() );
673void QgsDiagramProperties::updateProperty()
675 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
677 mDataDefinedProperties.setProperty( key, button->
toProperty() );
683 mDiagramType = mDiagramTypeComboBox->itemData( index ).toString();
687 mTextOptionsFrame->show();
688 mBackgroundColorLabel->show();
689 mBackgroundColorButton->show();
690 mBackgroundColorDDBtn->show();
691 mDiagramFontButton->show();
695 mTextOptionsFrame->hide();
696 mBackgroundColorLabel->hide();
697 mBackgroundColorButton->hide();
698 mBackgroundColorDDBtn->hide();
699 mDiagramFontButton->hide();
704 mBarWidthLabel->show();
705 mBarWidthSpinBox->show();
706 mBarSpacingLabel->show();
707 mBarSpacingSpinBox->show();
708 mBarSpacingUnitComboBox->show();
709 mBarOptionsFrame->show();
710 mShowAxisGroupBox->show();
712 mAttributeBasedScalingRadio->setChecked(
true );
715 mLinearlyScalingLabel->setText( tr(
"Bar length: Scale linearly, so that the following value matches the specified bar length:" ) );
716 mSizeLabel->setText( tr(
"Bar length" ) );
717 mFrameIncreaseSize->setVisible(
false );
721 mBarWidthLabel->hide();
722 mBarWidthSpinBox->hide();
723 mBarSpacingLabel->hide();
724 mBarSpacingSpinBox->hide();
725 mBarSpacingUnitComboBox->hide();
726 mShowAxisGroupBox->hide();
727 mBarOptionsFrame->hide();
728 mLinearlyScalingLabel->setText( tr(
"Scale linearly between 0 and the following attribute value / diagram size:" ) );
729 mSizeLabel->setText( tr(
"Size" ) );
730 mAttributeBasedScalingRadio->setEnabled(
true );
731 mFixedSizeRadio->setEnabled(
true );
732 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
733 mFrameIncreaseSize->setVisible(
true );
738 mScaleDependencyComboBox->show();
739 mScaleDependencyLabel->show();
743 mScaleDependencyComboBox->hide();
744 mScaleDependencyLabel->hide();
749 mAngleOffsetComboBox->show();
750 mAngleDirectionComboBox->show();
751 mAngleDirectionLabel->show();
752 mAngleOffsetLabel->show();
753 mStartAngleDDBtn->show();
757 mAngleOffsetComboBox->hide();
758 mAngleDirectionComboBox->hide();
759 mAngleDirectionLabel->hide();
760 mAngleOffsetLabel->hide();
761 mStartAngleDDBtn->hide();
765QString QgsDiagramProperties::guessLegendText(
const QString &expression )
768 QString text = expression.mid( expression.startsWith(
'\"' ) ? 1 : 0 );
769 if ( text.endsWith(
'\"' ) )
776 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
778 newItem->setText( 0, item->text( 0 ) );
779 newItem->setText( 2, guessLegendText( item->text( 0 ) ) );
780 newItem->setData( 0, RoleAttributeExpression, item->data( 0, RoleAttributeExpression ) );
781 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
784 const int red = QRandomGenerator::global()->bounded( 1, 256 );
785 const int green = QRandomGenerator::global()->bounded( 1, 256 );
786 const int blue = QRandomGenerator::global()->bounded( 1, 256 );
787 const QColor randomColor( red, green, blue );
788 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
789 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
794 const auto constSelectedItems = mAttributesTreeWidget->selectedItems();
795 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
809 const auto constSelectedItems = mDiagramAttributesTreeWidget->selectedItems();
810 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
812 delete attributeItem;
821 float maxValue = 0.0;
824 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
843 maxValue = std::max( maxValue, exp.
evaluate( &context ).toFloat() );
853 const int attributeNumber = mLayer->fields().lookupField( sizeFieldNameOrExp );
854 maxValue = mLayer->maximumValue( attributeNumber ).toFloat();
857 mMaxValueSpinBox->setValue( maxValue );
864 case ColumnAttributeExpression:
866 const QString currentExpression = item->data( 0, RoleAttributeExpression ).toString();
868 const QString newExpression = showExpressionBuilder( currentExpression );
869 if ( !newExpression.isEmpty() )
871 item->setData( 0, Qt::DisplayRole, newExpression );
872 item->setData( 0, RoleAttributeExpression, newExpression );
880 case ColumnLegendText:
885std::unique_ptr<QgsDiagram> QgsDiagramProperties::createDiagramObject()
887 std::unique_ptr<QgsDiagram> diagram;
891 diagram = std::make_unique<QgsTextDiagram>();
895 diagram = std::make_unique<QgsPieDiagram>();
899 diagram = std::make_unique<QgsStackedBarDiagram>();
903 diagram = std::make_unique<QgsHistogramDiagram>();
908std::unique_ptr<QgsDiagramSettings> QgsDiagramProperties::createDiagramSettings()
910 auto ds = std::make_unique<QgsDiagramSettings>();
911 ds->enabled = isDiagramEnabled();
912 ds->font = mDiagramFontButton->currentFont();
913 ds->opacity = mOpacityWidget->opacity();
915 QList<QColor> categoryColors;
916 QList<QString> categoryAttributes;
917 QList<QString> categoryLabels;
918 categoryColors.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
919 categoryAttributes.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
920 categoryLabels.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
921 for (
int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
923 QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->data( ColumnColor, Qt::EditRole ).value<QColor>();
924 categoryColors.append( color );
925 categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, RoleAttributeExpression ).toString() );
926 categoryLabels.append( mDiagramAttributesTreeWidget->topLevelItem( i )->text( 2 ) );
928 ds->categoryColors = categoryColors;
929 ds->categoryAttributes = categoryAttributes;
930 ds->categoryLabels = categoryLabels;
931 ds->size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
932 ds->sizeType = mDiagramUnitComboBox->unit();
933 ds->sizeScale = mDiagramUnitComboBox->getMapUnitScale();
934 ds->lineSizeUnit = mDiagramLineUnitComboBox->unit();
935 ds->lineSizeScale = mDiagramLineUnitComboBox->getMapUnitScale();
939 if ( mIncreaseSmallDiagramsGroupBox->isChecked() )
941 ds->minimumSize = mIncreaseMinimumSizeSpinBox->value();
948 ds->backgroundColor = mBackgroundColorButton->color();
949 ds->penColor = mDiagramPenColorButton->color();
950 ds->penWidth = mPenWidthSpinBox->value();
951 ds->minimumScale = mScaleRangeWidget->minimumScale();
952 ds->maximumScale = mScaleRangeWidget->maximumScale();
953 ds->scaleBasedVisibility = mScaleVisibilityGroupBox->isChecked();
956 ds->rotationOffset = mAngleOffsetComboBox->currentData().toInt();
962 ds->barWidth = mBarWidthSpinBox->value();
966 ds->size.setWidth( ds->barWidth );
968 ds->size.setHeight( ds->barWidth );
971 ds->setAxisLineSymbol( mAxisLineStyleButton->clonedSymbol<QgsLineSymbol>() );
972 ds->setShowAxis( mShowAxisGroupBox->isChecked() );
974 ds->setSpacing( mBarSpacingSpinBox->value() );
975 ds->setSpacingUnit( mBarSpacingUnitComboBox->unit() );
976 ds->setSpacingMapUnitScale( mBarSpacingUnitComboBox->getMapUnitScale() );
979 ds->setPaintEffect( mPaintEffect->clone() );
981 ds->setPaintEffect(
nullptr );
986std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRenderer()
988 std::unique_ptr<QgsDiagramSettings> ds = createDiagramSettings();
990 std::unique_ptr<QgsDiagramRenderer> renderer;
991 if ( mFixedSizeRadio->isChecked() )
993 auto dr = std::make_unique<QgsSingleCategoryDiagramRenderer>();
994 dr->setDiagramSettings( *ds );
995 renderer = std::move( dr );
999 auto dr = std::make_unique<QgsLinearlyInterpolatedDiagramRenderer>();
1000 dr->setLowerValue( 0.0 );
1001 dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
1002 dr->setUpperValue( mMaxValueSpinBox->value() );
1003 dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
1006 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1007 dr->setClassificationAttributeIsExpression( isExpression );
1010 dr->setClassificationAttributeExpression( sizeFieldNameOrExp );
1014 dr->setClassificationField( sizeFieldNameOrExp );
1016 dr->setDiagramSettings( *ds );
1018 dr->setDataDefinedSizeLegend( mSizeLegend ?
new QgsDataDefinedSizeLegend( *mSizeLegend ) :
nullptr );
1020 renderer = std::move( dr );
1023 renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
1025 std::unique_ptr<QgsDiagram> diagram = createDiagramObject();
1026 renderer->setDiagram( diagram.release() );
1033 QgsDiagramLayerSettings dls;
1035 dls.
setDistance( mDiagramDistanceSpinBox->value() );
1037 dls.
setZIndex( mZIndexSpinBox->value() );
1040 QWidget *curWdgt = stackedPlacement->currentWidget();
1041 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() ) || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1045 else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() ) || ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
1049 else if ( ( curWdgt == pageLine && radAroundLine->isChecked() ) || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
1053 else if ( ( curWdgt == pageLine && radOverLine->isChecked() ) || ( curWdgt == pagePolygon && radInsidePolygon->isChecked() ) )
1059 qFatal(
"Invalid settings" );
1063 if ( chkLineAbove->isChecked() )
1065 if ( chkLineBelow->isChecked() )
1067 if ( chkLineOn->isChecked() )
1069 if ( !chkLineOrientationDependent->isChecked() )
1080 if ( !
dockMode() || !settings.
value( u
"UI/autoApplyStyling"_s,
true ).toBool() )
1082 if ( isDiagramEnabled() && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
1084 QMessageBox::warning(
this, tr(
"Diagrams: No attributes added." ), tr(
"You did not add any attributes to this diagram layer. Please specify the attributes to visualize on the diagrams or disable diagrams." ) );
1088 std::unique_ptr<QgsDiagramRenderer> renderer = createRenderer();
1089 mLayer->setDiagramRenderer( renderer.release() );
1092 mLayer->setDiagramLayerSettings( dls );
1096 mLayer->triggerRepaint();
1099QString QgsDiagramProperties::showExpressionBuilder(
const QString &initialExpression )
1104 dlg.setWindowTitle( tr(
"Expression Based Attribute" ) );
1109 dlg.setGeomCalculator( myDa );
1111 if ( dlg.exec() == QDialog::Accepted )
1113 return dlg.expressionText();
1124 QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
1125 if ( !selections.empty() )
1127 expression = selections[0]->text( 0 );
1130 const QString newExpression = showExpressionBuilder( expression );
1133 if ( !newExpression.isEmpty() )
1135 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1137 newItem->setText( 0, newExpression );
1138 newItem->setText( 2, newExpression );
1139 newItem->setData( 0, RoleAttributeExpression, newExpression );
1140 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
1143 QRandomGenerator colorGenerator;
1144 const int red = colorGenerator.bounded( 1, 256 );
1145 const int green = colorGenerator.bounded( 1, 256 );
1146 const int blue = colorGenerator.bounded( 1, 256 );
1148 const QColor randomColor( red, green, blue );
1149 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
1150 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
1157 mDiagramOptionsListWidget->blockSignals(
true );
1158 mDiagramOptionsListWidget->setCurrentRow( index );
1159 mDiagramOptionsListWidget->blockSignals(
false );
1164 QWidget *curWdgt = stackedPlacement->currentWidget();
1166 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() ) || ( curWdgt == pageLine && radAroundLine->isChecked() ) || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1168 mDiagramDistanceLabel->setEnabled(
true );
1169 mDiagramDistanceSpinBox->setEnabled(
true );
1170 mDistanceDDBtn->setEnabled(
true );
1174 mDiagramDistanceLabel->setEnabled(
false );
1175 mDiagramDistanceSpinBox->setEnabled(
false );
1176 mDistanceDDBtn->setEnabled(
false );
1179 const bool linePlacementEnabled = mLayer->geometryType() ==
Qgis::GeometryType::Line && ( curWdgt == pageLine && radAroundLine->isChecked() );
1180 chkLineAbove->setEnabled( linePlacementEnabled );
1181 chkLineBelow->setEnabled( linePlacementEnabled );
1182 chkLineOn->setEnabled( linePlacementEnabled );
1183 chkLineOrientationDependent->setEnabled( linePlacementEnabled );
1188 mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
1193 mAllowedToEditDls = allowed;
1195 label_16->setVisible( allowed );
1196 mZIndexSpinBox->setVisible( allowed );
1197 mZOrderDDBtn->setVisible( allowed );
1198 mShowAllCheckBox->setVisible( allowed );
1199 mDlsLabel_1->setVisible( !allowed );
1201 mCoordinatesGrpBox->setVisible( allowed );
1202 mLinePlacementFrame->setVisible( allowed );
1203 mObstaclesGrpBox->setVisible( allowed );
1204 mPlacementFrame->setVisible( allowed );
1205 mPriorityGrpBox->setVisible( allowed );
1206 stackedPlacement->setVisible( allowed );
1207 mDlsLabel_2->setVisible( !allowed );
1212 return mAllowedToEditDls;
1219 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1221 const bool scaleByArea = mScaleDependencyComboBox->currentData().toBool();
1227 dlg.setLayout(
new QVBoxLayout() );
1229 dlg.layout()->addWidget( panel );
1230 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
1231 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1232 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsDiagramProperties::showHelp );
1233 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1234 dlg.layout()->addWidget( buttonBox );
1239void QgsDiagramProperties::showHelp()
1244void QgsDiagramProperties::createAuxiliaryField()
1247 if ( !mLayer->auxiliaryLayer() )
1249 QgsNewAuxiliaryLayerDialog dlg( mLayer,
this );
1254 if ( !mLayer->auxiliaryLayer() )
1257 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1262 if ( !mLayer->auxiliaryLayer()->exists( def ) )
1263 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
1268 property.setActive(
true );
1271 mDataDefinedProperties.setProperty( key, button->
toProperty() );
1276void QgsDiagramProperties::connectValueChanged(
const QList<QWidget *> &widgets )
1278 const auto constWidgets = widgets;
1279 for ( QWidget *widget : constWidgets )
1281 if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
1285 else if ( QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( widget ) )
1289 else if ( QgsOpacityWidget *w = qobject_cast<QgsOpacityWidget *>( widget ) )
1293 else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
1297 else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
1301 else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
1305 else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
1309 else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
1313 else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
1317 else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
1321 else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
1325 else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
1329 else if ( QTreeWidget *w = qobject_cast<QTreeWidget *>( widget ) )
1333 else if ( QgsScaleRangeWidget *w = qobject_cast<QgsScaleRangeWidget *>( widget ) )
1337 else if ( QgsEffectStackCompactWidget *w = qobject_cast<QgsEffectStackCompactWidget *>( widget ) )
1341 else if ( QgsFontButton *w = qobject_cast<QgsFontButton *>( widget ) )
1347 QgsLogger::warning( u
"Could not create connection for widget %1"_s.arg( widget->objectName() ) );
1352void QgsDiagramProperties::setDiagramEnabled(
bool enabled )
1354 mEnableDiagramCheckBox->setChecked( enabled );
1357bool QgsDiagramProperties::isDiagramEnabled()
const
1359 return mEnableDiagramCheckBox->isChecked();
Custom item delegate which prevents editing.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ MetersInMapUnits
Meters value as Map units.
static const double UI_SCALE_FACTOR
UI scaling factor.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
A delegate for showing a color swatch in a list.
Object that keeps configuration of appearance of marker symbol's data-defined size in legend.
Stores the settings for rendering of all diagrams for a layer.
void setZIndex(double index)
Sets the diagram z-index.
Placement placement() const
Returns the diagram placement.
QFlags< LinePlacementFlag > LinePlacementFlags
bool showAllDiagrams() const
Returns whether the layer should show all diagrams, including overlapping diagrams.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the diagram's property collection, used for data defined overrides.
LinePlacementFlags linePlacementFlags() const
Returns the diagram placement flags.
Property
Data definable properties.
@ PositionX
X-coordinate data defined diagram position.
@ Distance
Distance to diagram from feature.
@ PositionY
Y-coordinate data defined diagram position.
@ Show
Whether to show the diagram.
@ Priority
Diagram priority (between 0 and 10).
@ ZIndex
Z-index for diagram ordering.
@ StrokeColor
Stroke color.
@ BackgroundColor
Diagram background color.
@ StartAngle
Angle offset for pie diagram.
@ IsObstacle
Whether diagram features act as obstacles for other diagrams/labels.
@ StrokeWidth
Stroke width.
@ AlwaysShow
Whether the diagram should always be shown, even if it overlaps other diagrams/labels.
void setShowAllDiagrams(bool showAllDiagrams)
Sets whether the layer should show all diagrams, including overlapping diagrams.
void setDistance(double distance)
Sets the distance between the diagram and the feature.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
void setPriority(int value)
Sets the diagram priority.
int priority() const
Returns the diagram priority.
void setPlacement(Placement value)
Sets the diagram placement.
void setLinePlacementFlags(LinePlacementFlags flags)
Sets the the diagram placement flags.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the diagram's property collection, used for data defined overrides.
double zIndex() const
Returns the diagram z-index.
double distance() const
Returns the distance between the diagram and the feature (in mm).
void syncToSettings(const QgsDiagramLayerSettings *dls)
Updates the widget to reflect the diagram layer settings.
void scalingTypeChanged()
void setDockMode(bool dockMode) override
Sets the widget in dock mode.
void mDiagramAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
void mAddCategoryPushButton_clicked()
bool isAllowedToEditDiagramLayerSettings() const
Returns whether this widget is allowed to edit diagram layer settings.
void mDiagramTypeComboBox_currentIndexChanged(int index)
~QgsDiagramProperties() override
void syncToLayer()
Updates the widget to reflect the layer's current diagram settings.
void mRemoveCategoryPushButton_clicked()
QgsDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)
void showSizeLegendDialog()
void setDiagramType(const QString diagramType)
Defines the widget's diagram type and lets it know it should hide the type comboBox.
void addAttribute(QTreeWidgetItem *item)
Adds an attribute from the list of available attributes to the assigned attributes with a random colo...
void mFindMaximumValueButton_clicked()
void showAddAttributeExpressionDialog()
void syncToRenderer(const QgsDiagramRenderer *dr)
Updates the widget to reflect the diagram renderer.
void mAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
void auxiliaryFieldCreated()
void updatePlacementWidgets()
void setAllowedToEditDiagramLayerSettings(bool allowed)
Sets whether the widget should show diagram layer settings.
void mDiagramStackedWidget_currentChanged(int index)
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
virtual QString rendererName() const =0
QgsDiagram * diagram() const
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
bool attributeLegend() const
Returns true if renderer will show legend items for diagram attributes.
DiagramOrientation
Orientation of histogram.
Direction
Angular directions.
@ Counterclockwise
Counter-clockwise orientation.
@ Clockwise
Clockwise orientation.
virtual QString diagramName() const =0
Gets a descriptive name for this diagram type.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
A generic dialog for building expression strings.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
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.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QString evalErrorString() const
Returns evaluation error.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Container of fields for a vector layer.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
static const QString DIAGRAM_NAME_HISTOGRAM
Alters the size of rendered diagrams using linear scaling.
double upperValue() const
QString classificationAttributeExpression() const
QString classificationField() const
Returns the field name used for interpolating the diagram size.
bool classificationAttributeIsExpression() const
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend.
static const QString DIAGRAM_RENDERER_NAME_LINEARLY_INTERPOLATED
static void warning(const QString &msg)
Goes to qWarning.
Map canvas is a class for displaying all GIS data types on a canvas.
QgsCoordinateReferenceSystem crs
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
double minimumScale() const
Returns the minimum map scale (i.e.
double maximumScale() const
Returns the maximum map scale (i.e.
static QgsPaintEffect * defaultStack()
Returns a new effect stack consisting of a sensible selection of default effects.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
static const QString DIAGRAM_NAME_PIE
static QgsProject * instance()
Returns the QgsProject singleton instance.
void setDirty(bool b=true)
Flag the project as dirty (modified).
A store for object properties.
void setTransformer(QgsPropertyTransformer *transformer)
Sets an optional transformer to use for manipulating the calculated values for the property.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
void setField(const QString &field)
Sets the field name the property references.
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static const QString DIAGRAM_RENDERER_NAME_SINGLE_CATEGORY
static const QString DIAGRAM_NAME_STACKED_BAR
Renders diagrams using mixed diagram render types.
static const QString DIAGRAM_RENDERER_NAME_STACKED
const QgsDiagramRenderer * renderer(const int index) const
Returns the renderer at the given index.
int rendererCount() const
Returns the number of sub renderers in the stacked diagram renderer.
static const QString DIAGRAM_NAME_TEXT
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
#define QgsDebugMsgLevel(str, level)