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 mBackgroundColorButton->setOpaqueColorString( tr(
"Opaque Background" ) );
130 mDiagramPenColorButton->setColorDialogTitle( tr(
"Select Pen Color" ) );
131 mDiagramPenColorButton->setAllowOpacity(
true );
132 mDiagramPenColorButton->setContext( u
"symbology"_s );
133 mDiagramPenColorButton->setShowNoColor(
true );
134 mDiagramPenColorButton->setNoColorString( tr(
"Transparent Stroke" ) );
135 mDiagramPenColorButton->setOpaqueColorString( tr(
"Opaque Stroke" ) );
137 mMaxValueSpinBox->setShowClearButton(
false );
138 mSizeSpinBox->setClearValue( 5 );
140 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnAttributeExpression,
new EditBlockerDelegate(
this ) );
141 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnColor,
new QgsColorSwatchDelegate(
this ) );
143 mDiagramAttributesTreeWidget->setColumnWidth( ColumnColor,
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 6.6 );
154 mDiagramTypeComboBox->setEnabled(
false );
155 mOptionsTab->setEnabled(
false );
156 mDiagramFrame->setEnabled(
false );
164 stackedPlacement->setCurrentWidget( pagePoint );
165 mLinePlacementFrame->setVisible(
false );
168 stackedPlacement->setCurrentWidget( pageLine );
169 mLinePlacementFrame->setVisible(
true );
172 stackedPlacement->setCurrentWidget( pagePolygon );
173 mLinePlacementFrame->setVisible(
false );
182 mPlacePointBtnGrp =
new QButtonGroup(
this );
183 mPlacePointBtnGrp->addButton( radAroundPoint );
184 mPlacePointBtnGrp->addButton( radOverPoint );
185 mPlacePointBtnGrp->setExclusive(
true );
189 mPlaceLineBtnGrp =
new QButtonGroup(
this );
190 mPlaceLineBtnGrp->addButton( radAroundLine );
191 mPlaceLineBtnGrp->addButton( radOverLine );
192 mPlaceLineBtnGrp->setExclusive(
true );
196 mPlacePolygonBtnGrp =
new QButtonGroup(
this );
197 mPlacePolygonBtnGrp->addButton( radAroundCentroid );
198 mPlacePolygonBtnGrp->addButton( radOverCentroid );
199 mPlacePolygonBtnGrp->addButton( radPolygonPerimeter );
200 mPlacePolygonBtnGrp->addButton( radInsidePolygon );
201 mPlacePolygonBtnGrp->setExclusive(
true );
207 mScaleDependencyComboBox->addItem( tr(
"Area" ),
true );
208 mScaleDependencyComboBox->addItem( tr(
"Diameter" ),
false );
210 mAngleOffsetComboBox->addItem( tr(
"Top" ), 270 );
211 mAngleOffsetComboBox->addItem( tr(
"Right" ), 0 );
212 mAngleOffsetComboBox->addItem( tr(
"Bottom" ), 90 );
213 mAngleOffsetComboBox->addItem( tr(
"Left" ), 180 );
221 QSizePolicy policy( mDiagramOptionsListFrame->sizePolicy() );
222 policy.setHorizontalStretch( 0 );
223 mDiagramOptionsListFrame->setSizePolicy( policy );
224 if ( !settings.
contains( u
"/Windows/Diagrams/OptionsSplitState"_s ) )
227 QList<int> splitsizes;
229 mDiagramOptionsSplitter->setSizes( splitsizes );
233 mDiagramOptionsSplitter->restoreState( settings.
value( u
"Windows/Diagrams/OptionsSplitState"_s ).toByteArray() );
234 mDiagramOptionsListWidget->setCurrentRow( settings.
value( u
"Windows/Diagrams/Tab"_s, 0 ).toInt() );
237 whileBlocking( mOptionsTab )->setCurrentIndex( mDiagramStackedWidget->currentIndex() );
238 mOptionsTab->tabBar()->setUsesScrollButtons(
true );
241 mSizeFieldExpressionWidget->setLayer( mLayer );
245 mSizeFieldExpressionWidget->setGeomCalculator( myDa );
249 for (
int idx = 0; idx < layerFields.
count(); ++idx )
251 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mAttributesTreeWidget );
252 const QString name = u
"\"%1\""_s.arg( layerFields.
at( idx ).
name() );
253 newItem->setText( 0, name );
254 newItem->setData( 0, RoleAttributeExpression, name );
255 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
259 mPaintEffect->setEnabled(
false );
272 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
290 QList<QWidget *> widgets;
291 widgets << chkLineAbove;
292 widgets << chkLineBelow;
293 widgets << chkLineOn;
294 widgets << chkLineOrientationDependent;
295 widgets << mAngleDirectionComboBox;
296 widgets << mAngleOffsetComboBox;
297 widgets << mAttributeBasedScalingRadio;
298 widgets << mAxisLineStyleButton;
299 widgets << mBackgroundColorButton;
300 widgets << mBarSpacingSpinBox;
301 widgets << mBarSpacingUnitComboBox;
302 widgets << mBarWidthSpinBox;
303 widgets << mCheckBoxAttributeLegend;
304 widgets << mDiagramAttributesTreeWidget;
305 widgets << mDiagramDistanceSpinBox;
306 widgets << mDiagramFontButton;
307 widgets << mDiagramPenColorButton;
308 widgets << mDiagramSizeSpinBox;
309 widgets << mDiagramLineUnitComboBox;
310 widgets << mDiagramTypeComboBox;
311 widgets << mDiagramUnitComboBox;
312 widgets << mEnableDiagramCheckBox;
313 widgets << mFixedSizeRadio;
314 widgets << mIncreaseMinimumSizeSpinBox;
315 widgets << mIncreaseSmallDiagramsGroupBox;
316 widgets << mLabelPlacementComboBox;
317 widgets << mMaxValueSpinBox;
318 widgets << mPaintEffectWidget;
319 widgets << mPenWidthSpinBox;
320 widgets << mPrioritySlider;
321 widgets << mOpacityWidget;
322 widgets << mOrientationDownButton;
323 widgets << mOrientationLeftButton;
324 widgets << mOrientationRightButton;
325 widgets << mOrientationUpButton;
326 widgets << mScaleDependencyComboBox;
327 widgets << mScaleRangeWidget;
328 widgets << mScaleVisibilityGroupBox;
329 widgets << mShowAllCheckBox;
330 widgets << mShowAxisGroupBox;
331 widgets << mSizeFieldExpressionWidget;
332 widgets << mSizeSpinBox;
333 widgets << mZIndexSpinBox;
334 widgets << radAroundCentroid;
335 widgets << radAroundLine;
336 widgets << radAroundPoint;
337 widgets << radInsidePolygon;
338 widgets << radOverCentroid;
339 widgets << radOverLine;
340 widgets << radOverPoint;
341 widgets << radPolygonPerimeter;
343 connectValueChanged( widgets );
349 mOptionsTab->setVisible(
dockMode );
350 mOptionsTab->setTabToolTip( 0, tr(
"Attributes" ) );
351 mOptionsTab->setTabToolTip( 1, tr(
"Rendering" ) );
352 mOptionsTab->setTabToolTip( 2, tr(
"Size" ) );
353 mOptionsTab->setTabToolTip( 3, tr(
"Placement" ) );
354 mOptionsTab->setTabToolTip( 4, tr(
"Options" ) );
355 mOptionsTab->setTabToolTip( 5, tr(
"Legend" ) );
356 mDiagramOptionsListFrame->setVisible( !
dockMode );
361 mDiagramType = diagramType;
363 mDiagramTypeComboBox->setVisible(
false );
364 mDiagramTypeComboBox->blockSignals(
true );
365 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
366 mDiagramTypeComboBox->blockSignals(
false );
372void QgsDiagramProperties::insertDefaults()
374 mFixedSizeRadio->setChecked(
true );
377 mLabelPlacementComboBox->setCurrentIndex( mLabelPlacementComboBox->findText( tr(
"x-height" ) ) );
378 mDiagramSizeSpinBox->setEnabled(
true );
379 mDiagramSizeSpinBox->setValue( 15 );
380 mLinearScaleFrame->setEnabled(
false );
381 mBarWidthSpinBox->setValue( 5 );
384 mShowAllCheckBox->setChecked(
true );
385 mCheckBoxAttributeLegend->setChecked(
true );
390 radAroundPoint->setChecked(
true );
394 radAroundLine->setChecked(
true );
395 chkLineAbove->setChecked(
true );
396 chkLineBelow->setChecked(
false );
397 chkLineOn->setChecked(
false );
398 chkLineOrientationDependent->setChecked(
false );
402 radOverCentroid->setChecked(
true );
403 mDiagramDistanceLabel->setEnabled(
false );
404 mDiagramDistanceSpinBox->setEnabled(
false );
405 mDistanceDDBtn->setEnabled(
false );
412 mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
413 mDiagramPenColorButton->setColor( QColor( 0, 0, 0, 255 ) );
418void QgsDiagramProperties::updateDataDefinedButtons()
420 const QList<QgsPropertyOverrideButton *> propertyOverrideButtons { findChildren<QgsPropertyOverrideButton *>() };
421 for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
423 updateDataDefinedButton( button );
436 whileBlocking( button )->setToProperty( mDataDefinedProperties.property( key ) );
449 renderer = stackedRenderer->
renderer( 0 );
460 mDiagramAttributesTreeWidget->clear();
471 mFixedSizeRadio->setChecked(
true );
475 mAttributeBasedScalingRadio->setChecked(
true );
477 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
478 mLinearScaleFrame->setEnabled( mAttributeBasedScalingRadio->isChecked() );
483 if ( !settingList.isEmpty() )
485 setDiagramEnabled( settingList.at( 0 ).enabled );
486 mDiagramFontButton->setCurrentFont( settingList.at( 0 ).font );
487 const QSizeF size = settingList.at( 0 ).size;
488 mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
489 mOpacityWidget->setOpacity( settingList.at( 0 ).opacity );
490 mDiagramPenColorButton->setColor( settingList.at( 0 ).penColor );
491 mPenWidthSpinBox->setValue( settingList.at( 0 ).penWidth );
492 mDiagramSizeSpinBox->setValue( ( size.width() + size.height() ) / 2.0 );
493 mScaleRangeWidget->setScaleRange(
494 ( settingList.at( 0 ).minimumScale > 0 ? settingList.at( 0 ).minimumScale : mLayer->minimumScale() ),
495 ( settingList.at( 0 ).maximumScale > 0 ? settingList.at( 0 ).maximumScale : mLayer->maximumScale() )
497 mScaleVisibilityGroupBox->setChecked( settingList.at( 0 ).scaleBasedVisibility );
498 mDiagramUnitComboBox->setUnit( settingList.at( 0 ).sizeType );
499 mDiagramUnitComboBox->setMapUnitScale( settingList.at( 0 ).sizeScale );
500 mDiagramLineUnitComboBox->setUnit( settingList.at( 0 ).lineSizeUnit );
501 mDiagramLineUnitComboBox->setMapUnitScale( settingList.at( 0 ).lineSizeScale );
505 mLabelPlacementComboBox->setCurrentIndex( 0 );
509 mLabelPlacementComboBox->setCurrentIndex( 1 );
512 if ( settingList.at( 0 ).paintEffect() )
513 mPaintEffect.reset( settingList.at( 0 ).paintEffect()->clone() );
515 mAngleOffsetComboBox->setCurrentIndex( mAngleOffsetComboBox->findData( settingList.at( 0 ).rotationOffset ) );
516 mAngleDirectionComboBox->setCurrentIndex( mAngleDirectionComboBox->findData( settingList.at( 0 ).direction() ) );
518 switch ( settingList.at( 0 ).diagramOrientation )
521 mOrientationLeftButton->setChecked(
true );
525 mOrientationRightButton->setChecked(
true );
529 mOrientationUpButton->setChecked(
true );
533 mOrientationDownButton->setChecked(
true );
537 mBarWidthSpinBox->setValue( settingList.at( 0 ).barWidth );
538 mBarSpacingSpinBox->setValue( settingList.at( 0 ).spacing() );
539 mBarSpacingUnitComboBox->setUnit( settingList.at( 0 ).spacingUnit() );
540 mBarSpacingUnitComboBox->setMapUnitScale( settingList.at( 0 ).spacingMapUnitScale() );
542 mShowAxisGroupBox->setChecked( settingList.at( 0 ).showAxis() );
543 if ( settingList.at( 0 ).axisLineSymbol() )
544 mAxisLineStyleButton->setSymbol( settingList.at( 0 ).axisLineSymbol()->clone() );
546 mIncreaseSmallDiagramsGroupBox->setChecked( settingList.at( 0 ).minimumSize != 0 );
547 mIncreaseMinimumSizeSpinBox->setValue( settingList.at( 0 ).minimumSize );
549 if ( settingList.at( 0 ).scaleByArea )
551 mScaleDependencyComboBox->setCurrentIndex( 0 );
555 mScaleDependencyComboBox->setCurrentIndex( 1 );
558 const QList<QColor> categoryColors = settingList.at( 0 ).categoryColors;
559 const QList<QString> categoryAttributes = settingList.at( 0 ).categoryAttributes;
560 const QList<QString> categoryLabels = settingList.at( 0 ).categoryLabels;
561 QList<QString>::const_iterator catIt = categoryAttributes.constBegin();
562 QList<QColor>::const_iterator coIt = categoryColors.constBegin();
563 QList<QString>::const_iterator labIt = categoryLabels.constBegin();
564 for ( ; catIt != categoryAttributes.constEnd(); ++catIt, ++coIt, ++labIt )
566 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
567 newItem->setText( 0, *catIt );
568 newItem->setData( 0, RoleAttributeExpression, *catIt );
569 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
570 newItem->setData( ColumnColor, Qt::EditRole, *coIt );
571 newItem->setText( 2, *labIt );
572 newItem->setFlags( newItem->flags() | Qt::ItemIsEditable );
581 mDiagramSizeSpinBox->setEnabled(
false );
582 mLinearScaleFrame->setEnabled(
true );
583 mMaxValueSpinBox->setValue( lidr->
upperValue() );
584 mSizeSpinBox->setValue( ( lidr->
upperSize().width() + lidr->
upperSize().height() ) / 2 );
602 mDiagramTypeComboBox->blockSignals(
true );
603 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
604 mDiagramTypeComboBox->blockSignals(
false );
609 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
616 mDiagramDistanceSpinBox->setValue( dls->
distance() );
617 mPrioritySlider->setValue( dls->
priority() );
618 mZIndexSpinBox->setValue( dls->
zIndex() );
623 radAroundPoint->setChecked(
true );
624 radAroundCentroid->setChecked(
true );
628 radOverPoint->setChecked(
true );
629 radOverCentroid->setChecked(
true );
633 radAroundLine->setChecked(
true );
634 radPolygonPerimeter->setChecked(
true );
638 radOverLine->setChecked(
true );
639 radInsidePolygon->setChecked(
true );
650 chkLineOrientationDependent->setChecked(
true );
656 updateDataDefinedButtons();
663 settings.
setValue( u
"Windows/Diagrams/OptionsSplitState"_s, mDiagramOptionsSplitter->saveState() );
664 settings.
setValue( u
"Windows/Diagrams/Tab"_s, mDiagramOptionsListWidget->currentRow() );
675void QgsDiagramProperties::updateProperty()
677 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
679 mDataDefinedProperties.setProperty( key, button->
toProperty() );
685 mDiagramType = mDiagramTypeComboBox->itemData( index ).toString();
689 mTextOptionsFrame->show();
690 mBackgroundColorLabel->show();
691 mBackgroundColorButton->show();
692 mBackgroundColorDDBtn->show();
693 mDiagramFontButton->show();
697 mTextOptionsFrame->hide();
698 mBackgroundColorLabel->hide();
699 mBackgroundColorButton->hide();
700 mBackgroundColorDDBtn->hide();
701 mDiagramFontButton->hide();
706 mBarWidthLabel->show();
707 mBarWidthSpinBox->show();
708 mBarSpacingLabel->show();
709 mBarSpacingSpinBox->show();
710 mBarSpacingUnitComboBox->show();
711 mBarOptionsFrame->show();
712 mShowAxisGroupBox->show();
714 mAttributeBasedScalingRadio->setChecked(
true );
717 mLinearlyScalingLabel->setText( tr(
"Bar length: Scale linearly, so that the following value matches the specified bar length:" ) );
718 mSizeLabel->setText( tr(
"Bar length" ) );
719 mFrameIncreaseSize->setVisible(
false );
723 mBarWidthLabel->hide();
724 mBarWidthSpinBox->hide();
725 mBarSpacingLabel->hide();
726 mBarSpacingSpinBox->hide();
727 mBarSpacingUnitComboBox->hide();
728 mShowAxisGroupBox->hide();
729 mBarOptionsFrame->hide();
730 mLinearlyScalingLabel->setText( tr(
"Scale linearly between 0 and the following attribute value / diagram size:" ) );
731 mSizeLabel->setText( tr(
"Size" ) );
732 mAttributeBasedScalingRadio->setEnabled(
true );
733 mFixedSizeRadio->setEnabled(
true );
734 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
735 mFrameIncreaseSize->setVisible(
true );
740 mScaleDependencyComboBox->show();
741 mScaleDependencyLabel->show();
745 mScaleDependencyComboBox->hide();
746 mScaleDependencyLabel->hide();
751 mAngleOffsetComboBox->show();
752 mAngleDirectionComboBox->show();
753 mAngleDirectionLabel->show();
754 mAngleOffsetLabel->show();
755 mStartAngleDDBtn->show();
759 mAngleOffsetComboBox->hide();
760 mAngleDirectionComboBox->hide();
761 mAngleDirectionLabel->hide();
762 mAngleOffsetLabel->hide();
763 mStartAngleDDBtn->hide();
767QString QgsDiagramProperties::guessLegendText(
const QString &expression )
770 QString text = expression.mid( expression.startsWith(
'\"' ) ? 1 : 0 );
771 if ( text.endsWith(
'\"' ) )
778 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
780 newItem->setText( 0, item->text( 0 ) );
781 newItem->setText( 2, guessLegendText( item->text( 0 ) ) );
782 newItem->setData( 0, RoleAttributeExpression, item->data( 0, RoleAttributeExpression ) );
783 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
786 const int red = QRandomGenerator::global()->bounded( 1, 256 );
787 const int green = QRandomGenerator::global()->bounded( 1, 256 );
788 const int blue = QRandomGenerator::global()->bounded( 1, 256 );
789 const QColor randomColor( red, green, blue );
790 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
791 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
796 const auto constSelectedItems = mAttributesTreeWidget->selectedItems();
797 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
811 const auto constSelectedItems = mDiagramAttributesTreeWidget->selectedItems();
812 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
814 delete attributeItem;
823 float maxValue = 0.0;
826 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
845 maxValue = std::max( maxValue, exp.
evaluate( &context ).toFloat() );
855 const int attributeNumber = mLayer->fields().lookupField( sizeFieldNameOrExp );
856 maxValue = mLayer->maximumValue( attributeNumber ).toFloat();
859 mMaxValueSpinBox->setValue( maxValue );
866 case ColumnAttributeExpression:
868 const QString currentExpression = item->data( 0, RoleAttributeExpression ).toString();
870 const QString newExpression = showExpressionBuilder( currentExpression );
871 if ( !newExpression.isEmpty() )
873 item->setData( 0, Qt::DisplayRole, newExpression );
874 item->setData( 0, RoleAttributeExpression, newExpression );
882 case ColumnLegendText:
887std::unique_ptr<QgsDiagram> QgsDiagramProperties::createDiagramObject()
889 std::unique_ptr<QgsDiagram> diagram;
893 diagram = std::make_unique<QgsTextDiagram>();
897 diagram = std::make_unique<QgsPieDiagram>();
901 diagram = std::make_unique<QgsStackedBarDiagram>();
905 diagram = std::make_unique<QgsHistogramDiagram>();
910std::unique_ptr<QgsDiagramSettings> QgsDiagramProperties::createDiagramSettings()
912 auto ds = std::make_unique<QgsDiagramSettings>();
913 ds->enabled = isDiagramEnabled();
914 ds->font = mDiagramFontButton->currentFont();
915 ds->opacity = mOpacityWidget->opacity();
917 QList<QColor> categoryColors;
918 QList<QString> categoryAttributes;
919 QList<QString> categoryLabels;
920 categoryColors.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
921 categoryAttributes.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
922 categoryLabels.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
923 for (
int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
925 QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->data( ColumnColor, Qt::EditRole ).value<QColor>();
926 categoryColors.append( color );
927 categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, RoleAttributeExpression ).toString() );
928 categoryLabels.append( mDiagramAttributesTreeWidget->topLevelItem( i )->text( 2 ) );
930 ds->categoryColors = categoryColors;
931 ds->categoryAttributes = categoryAttributes;
932 ds->categoryLabels = categoryLabels;
933 ds->size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
934 ds->sizeType = mDiagramUnitComboBox->unit();
935 ds->sizeScale = mDiagramUnitComboBox->getMapUnitScale();
936 ds->lineSizeUnit = mDiagramLineUnitComboBox->unit();
937 ds->lineSizeScale = mDiagramLineUnitComboBox->getMapUnitScale();
941 if ( mIncreaseSmallDiagramsGroupBox->isChecked() )
943 ds->minimumSize = mIncreaseMinimumSizeSpinBox->value();
950 ds->backgroundColor = mBackgroundColorButton->color();
951 ds->penColor = mDiagramPenColorButton->color();
952 ds->penWidth = mPenWidthSpinBox->value();
953 ds->minimumScale = mScaleRangeWidget->minimumScale();
954 ds->maximumScale = mScaleRangeWidget->maximumScale();
955 ds->scaleBasedVisibility = mScaleVisibilityGroupBox->isChecked();
958 ds->rotationOffset = mAngleOffsetComboBox->currentData().toInt();
964 ds->barWidth = mBarWidthSpinBox->value();
968 ds->size.setWidth( ds->barWidth );
970 ds->size.setHeight( ds->barWidth );
973 ds->setAxisLineSymbol( mAxisLineStyleButton->clonedSymbol<QgsLineSymbol>() );
974 ds->setShowAxis( mShowAxisGroupBox->isChecked() );
976 ds->setSpacing( mBarSpacingSpinBox->value() );
977 ds->setSpacingUnit( mBarSpacingUnitComboBox->unit() );
978 ds->setSpacingMapUnitScale( mBarSpacingUnitComboBox->getMapUnitScale() );
981 ds->setPaintEffect( mPaintEffect->clone() );
983 ds->setPaintEffect(
nullptr );
988std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRenderer()
990 std::unique_ptr<QgsDiagramSettings> ds = createDiagramSettings();
992 std::unique_ptr<QgsDiagramRenderer> renderer;
993 if ( mFixedSizeRadio->isChecked() )
995 auto dr = std::make_unique<QgsSingleCategoryDiagramRenderer>();
996 dr->setDiagramSettings( *ds );
997 renderer = std::move( dr );
1001 auto dr = std::make_unique<QgsLinearlyInterpolatedDiagramRenderer>();
1002 dr->setLowerValue( 0.0 );
1003 dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
1004 dr->setUpperValue( mMaxValueSpinBox->value() );
1005 dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
1008 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1009 dr->setClassificationAttributeIsExpression( isExpression );
1012 dr->setClassificationAttributeExpression( sizeFieldNameOrExp );
1016 dr->setClassificationField( sizeFieldNameOrExp );
1018 dr->setDiagramSettings( *ds );
1020 dr->setDataDefinedSizeLegend( mSizeLegend ?
new QgsDataDefinedSizeLegend( *mSizeLegend ) :
nullptr );
1022 renderer = std::move( dr );
1025 renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
1027 std::unique_ptr<QgsDiagram> diagram = createDiagramObject();
1028 renderer->setDiagram( diagram.release() );
1035 QgsDiagramLayerSettings dls;
1037 dls.
setDistance( mDiagramDistanceSpinBox->value() );
1039 dls.
setZIndex( mZIndexSpinBox->value() );
1042 QWidget *curWdgt = stackedPlacement->currentWidget();
1043 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() ) || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1047 else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() ) || ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
1051 else if ( ( curWdgt == pageLine && radAroundLine->isChecked() ) || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
1055 else if ( ( curWdgt == pageLine && radOverLine->isChecked() ) || ( curWdgt == pagePolygon && radInsidePolygon->isChecked() ) )
1061 qFatal(
"Invalid settings" );
1065 if ( chkLineAbove->isChecked() )
1067 if ( chkLineBelow->isChecked() )
1069 if ( chkLineOn->isChecked() )
1071 if ( !chkLineOrientationDependent->isChecked() )
1082 if ( !
dockMode() || !settings.
value( u
"UI/autoApplyStyling"_s,
true ).toBool() )
1084 if ( isDiagramEnabled() && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
1086 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." ) );
1090 std::unique_ptr<QgsDiagramRenderer> renderer = createRenderer();
1091 mLayer->setDiagramRenderer( renderer.release() );
1094 mLayer->setDiagramLayerSettings( dls );
1098 mLayer->triggerRepaint();
1101QString QgsDiagramProperties::showExpressionBuilder(
const QString &initialExpression )
1106 dlg.setWindowTitle( tr(
"Expression Based Attribute" ) );
1111 dlg.setGeomCalculator( myDa );
1113 if ( dlg.exec() == QDialog::Accepted )
1115 return dlg.expressionText();
1126 QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
1127 if ( !selections.empty() )
1129 expression = selections[0]->text( 0 );
1132 const QString newExpression = showExpressionBuilder( expression );
1135 if ( !newExpression.isEmpty() )
1137 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1139 newItem->setText( 0, newExpression );
1140 newItem->setText( 2, newExpression );
1141 newItem->setData( 0, RoleAttributeExpression, newExpression );
1142 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
1145 QRandomGenerator colorGenerator;
1146 const int red = colorGenerator.bounded( 1, 256 );
1147 const int green = colorGenerator.bounded( 1, 256 );
1148 const int blue = colorGenerator.bounded( 1, 256 );
1150 const QColor randomColor( red, green, blue );
1151 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
1152 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
1159 mDiagramOptionsListWidget->blockSignals(
true );
1160 mDiagramOptionsListWidget->setCurrentRow( index );
1161 mDiagramOptionsListWidget->blockSignals(
false );
1166 QWidget *curWdgt = stackedPlacement->currentWidget();
1168 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() ) || ( curWdgt == pageLine && radAroundLine->isChecked() ) || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1170 mDiagramDistanceLabel->setEnabled(
true );
1171 mDiagramDistanceSpinBox->setEnabled(
true );
1172 mDistanceDDBtn->setEnabled(
true );
1176 mDiagramDistanceLabel->setEnabled(
false );
1177 mDiagramDistanceSpinBox->setEnabled(
false );
1178 mDistanceDDBtn->setEnabled(
false );
1181 const bool linePlacementEnabled = mLayer->geometryType() ==
Qgis::GeometryType::Line && ( curWdgt == pageLine && radAroundLine->isChecked() );
1182 chkLineAbove->setEnabled( linePlacementEnabled );
1183 chkLineBelow->setEnabled( linePlacementEnabled );
1184 chkLineOn->setEnabled( linePlacementEnabled );
1185 chkLineOrientationDependent->setEnabled( linePlacementEnabled );
1190 mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
1195 mAllowedToEditDls = allowed;
1197 label_16->setVisible( allowed );
1198 mZIndexSpinBox->setVisible( allowed );
1199 mZOrderDDBtn->setVisible( allowed );
1200 mShowAllCheckBox->setVisible( allowed );
1201 mDlsLabel_1->setVisible( !allowed );
1203 mCoordinatesGrpBox->setVisible( allowed );
1204 mLinePlacementFrame->setVisible( allowed );
1205 mObstaclesGrpBox->setVisible( allowed );
1206 mPlacementFrame->setVisible( allowed );
1207 mPriorityGrpBox->setVisible( allowed );
1208 stackedPlacement->setVisible( allowed );
1209 mDlsLabel_2->setVisible( !allowed );
1214 return mAllowedToEditDls;
1221 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1223 const bool scaleByArea = mScaleDependencyComboBox->currentData().toBool();
1229 dlg.setLayout(
new QVBoxLayout() );
1231 dlg.layout()->addWidget( panel );
1232 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
1233 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1234 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsDiagramProperties::showHelp );
1235 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1236 dlg.layout()->addWidget( buttonBox );
1241void QgsDiagramProperties::showHelp()
1246void QgsDiagramProperties::createAuxiliaryField()
1249 if ( !mLayer->auxiliaryLayer() )
1251 QgsNewAuxiliaryLayerDialog dlg( mLayer,
this );
1256 if ( !mLayer->auxiliaryLayer() )
1259 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1264 if ( !mLayer->auxiliaryLayer()->exists( def ) )
1265 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
1270 property.setActive(
true );
1273 mDataDefinedProperties.setProperty( key, button->
toProperty() );
1278void QgsDiagramProperties::connectValueChanged(
const QList<QWidget *> &widgets )
1280 const auto constWidgets = widgets;
1281 for ( QWidget *widget : constWidgets )
1283 if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
1287 else if ( QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( widget ) )
1291 else if ( QgsOpacityWidget *w = qobject_cast<QgsOpacityWidget *>( widget ) )
1295 else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
1299 else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
1303 else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
1307 else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
1311 else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
1315 else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
1319 else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
1323 else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
1327 else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
1331 else if ( QTreeWidget *w = qobject_cast<QTreeWidget *>( widget ) )
1335 else if ( QgsScaleRangeWidget *w = qobject_cast<QgsScaleRangeWidget *>( widget ) )
1339 else if ( QgsEffectStackCompactWidget *w = qobject_cast<QgsEffectStackCompactWidget *>( widget ) )
1343 else if ( QgsFontButton *w = qobject_cast<QgsFontButton *>( widget ) )
1349 QgsLogger::warning( u
"Could not create connection for widget %1"_s.arg( widget->objectName() ) );
1354void QgsDiagramProperties::setDiagramEnabled(
bool enabled )
1356 mEnableDiagramCheckBox->setChecked( enabled );
1359bool QgsDiagramProperties::isDiagramEnabled()
const
1361 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.
@ OverPoint
Point / Polygon.
@ AroundPoint
Point / Polygon.
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)