46#include <QRandomGenerator>
47#include <QStyledItemDelegate>
49#include "moc_qgsdiagramproperties.cpp"
53 QgsExpressionContext expContext;
56 expContext = mMapCanvas->createExpressionContext();
73 , mMapCanvas( canvas )
90 mDiagramOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect,
false );
93 mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
94 mDiagramOptionsListWidget->setIconSize( QSize( iconSize, iconSize ) );
96 mBarSpacingSpinBox->setClearValue( 0 );
101 mDiagramTypeComboBox->blockSignals(
true );
110 mDiagramTypeComboBox->blockSignals(
false );
113 mAxisLineStyleButton->setDialogTitle( tr(
"Axis Line Symbol" ) );
115 mScaleRangeWidget->setMapCanvas( mMapCanvas );
116 mSizeFieldExpressionWidget->registerExpressionContextGenerator(
this );
118 mBackgroundColorButton->setColorDialogTitle( tr(
"Select Background Color" ) );
119 mBackgroundColorButton->setAllowOpacity(
true );
120 mBackgroundColorButton->setContext( QStringLiteral(
"symbology" ) );
121 mBackgroundColorButton->setShowNoColor(
true );
122 mBackgroundColorButton->setNoColorString( tr(
"Transparent Background" ) );
123 mDiagramPenColorButton->setColorDialogTitle( tr(
"Select Pen Color" ) );
124 mDiagramPenColorButton->setAllowOpacity(
true );
125 mDiagramPenColorButton->setContext( QStringLiteral(
"symbology" ) );
126 mDiagramPenColorButton->setShowNoColor(
true );
127 mDiagramPenColorButton->setNoColorString( tr(
"Transparent Stroke" ) );
129 mMaxValueSpinBox->setShowClearButton(
false );
130 mSizeSpinBox->setClearValue( 5 );
132 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnAttributeExpression,
new EditBlockerDelegate(
this ) );
133 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnColor,
new QgsColorSwatchDelegate(
this ) );
135 mDiagramAttributesTreeWidget->setColumnWidth( ColumnColor,
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 6.6 );
146 mDiagramTypeComboBox->setEnabled(
false );
147 mOptionsTab->setEnabled(
false );
148 mDiagramFrame->setEnabled(
false );
156 stackedPlacement->setCurrentWidget( pagePoint );
157 mLinePlacementFrame->setVisible(
false );
160 stackedPlacement->setCurrentWidget( pageLine );
161 mLinePlacementFrame->setVisible(
true );
164 stackedPlacement->setCurrentWidget( pagePolygon );
165 mLinePlacementFrame->setVisible(
false );
174 mPlacePointBtnGrp =
new QButtonGroup(
this );
175 mPlacePointBtnGrp->addButton( radAroundPoint );
176 mPlacePointBtnGrp->addButton( radOverPoint );
177 mPlacePointBtnGrp->setExclusive(
true );
181 mPlaceLineBtnGrp =
new QButtonGroup(
this );
182 mPlaceLineBtnGrp->addButton( radAroundLine );
183 mPlaceLineBtnGrp->addButton( radOverLine );
184 mPlaceLineBtnGrp->setExclusive(
true );
188 mPlacePolygonBtnGrp =
new QButtonGroup(
this );
189 mPlacePolygonBtnGrp->addButton( radAroundCentroid );
190 mPlacePolygonBtnGrp->addButton( radOverCentroid );
191 mPlacePolygonBtnGrp->addButton( radPolygonPerimeter );
192 mPlacePolygonBtnGrp->addButton( radInsidePolygon );
193 mPlacePolygonBtnGrp->setExclusive(
true );
199 mScaleDependencyComboBox->addItem( tr(
"Area" ),
true );
200 mScaleDependencyComboBox->addItem( tr(
"Diameter" ),
false );
202 mAngleOffsetComboBox->addItem( tr(
"Top" ), 270 );
203 mAngleOffsetComboBox->addItem( tr(
"Right" ), 0 );
204 mAngleOffsetComboBox->addItem( tr(
"Bottom" ), 90 );
205 mAngleOffsetComboBox->addItem( tr(
"Left" ), 180 );
213 QSizePolicy policy( mDiagramOptionsListFrame->sizePolicy() );
214 policy.setHorizontalStretch( 0 );
215 mDiagramOptionsListFrame->setSizePolicy( policy );
216 if ( !settings.
contains( QStringLiteral(
"/Windows/Diagrams/OptionsSplitState" ) ) )
219 QList<int> splitsizes;
221 mDiagramOptionsSplitter->setSizes( splitsizes );
225 mDiagramOptionsSplitter->restoreState( settings.
value( QStringLiteral(
"Windows/Diagrams/OptionsSplitState" ) ).toByteArray() );
226 mDiagramOptionsListWidget->setCurrentRow( settings.
value( QStringLiteral(
"Windows/Diagrams/Tab" ), 0 ).toInt() );
229 whileBlocking( mOptionsTab )->setCurrentIndex( mDiagramStackedWidget->currentIndex() );
230 mOptionsTab->tabBar()->setUsesScrollButtons(
true );
233 mSizeFieldExpressionWidget->setLayer( mLayer );
237 mSizeFieldExpressionWidget->setGeomCalculator( myDa );
241 for (
int idx = 0; idx < layerFields.
count(); ++idx )
243 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mAttributesTreeWidget );
244 const QString name = QStringLiteral(
"\"%1\"" ).arg( layerFields.
at( idx ).
name() );
245 newItem->setText( 0, name );
246 newItem->setData( 0, RoleAttributeExpression, name );
247 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
251 mPaintEffect->setEnabled(
false );
264 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
282 QList<QWidget *> widgets;
283 widgets << chkLineAbove;
284 widgets << chkLineBelow;
285 widgets << chkLineOn;
286 widgets << chkLineOrientationDependent;
287 widgets << mAngleDirectionComboBox;
288 widgets << mAngleOffsetComboBox;
289 widgets << mAttributeBasedScalingRadio;
290 widgets << mAxisLineStyleButton;
291 widgets << mBackgroundColorButton;
292 widgets << mBarSpacingSpinBox;
293 widgets << mBarSpacingUnitComboBox;
294 widgets << mBarWidthSpinBox;
295 widgets << mCheckBoxAttributeLegend;
296 widgets << mDiagramAttributesTreeWidget;
297 widgets << mDiagramDistanceSpinBox;
298 widgets << mDiagramFontButton;
299 widgets << mDiagramPenColorButton;
300 widgets << mDiagramSizeSpinBox;
301 widgets << mDiagramLineUnitComboBox;
302 widgets << mDiagramTypeComboBox;
303 widgets << mDiagramUnitComboBox;
304 widgets << mEnableDiagramCheckBox;
305 widgets << mFixedSizeRadio;
306 widgets << mIncreaseMinimumSizeSpinBox;
307 widgets << mIncreaseSmallDiagramsGroupBox;
308 widgets << mLabelPlacementComboBox;
309 widgets << mMaxValueSpinBox;
310 widgets << mPaintEffectWidget;
311 widgets << mPenWidthSpinBox;
312 widgets << mPrioritySlider;
313 widgets << mOpacityWidget;
314 widgets << mOrientationDownButton;
315 widgets << mOrientationLeftButton;
316 widgets << mOrientationRightButton;
317 widgets << mOrientationUpButton;
318 widgets << mScaleDependencyComboBox;
319 widgets << mScaleRangeWidget;
320 widgets << mScaleVisibilityGroupBox;
321 widgets << mShowAllCheckBox;
322 widgets << mShowAxisGroupBox;
323 widgets << mSizeFieldExpressionWidget;
324 widgets << mSizeSpinBox;
325 widgets << mZIndexSpinBox;
326 widgets << radAroundCentroid;
327 widgets << radAroundLine;
328 widgets << radAroundPoint;
329 widgets << radInsidePolygon;
330 widgets << radOverCentroid;
331 widgets << radOverLine;
332 widgets << radOverPoint;
333 widgets << radPolygonPerimeter;
335 connectValueChanged( widgets );
341 mOptionsTab->setVisible(
dockMode );
342 mOptionsTab->setTabToolTip( 0, tr(
"Attributes" ) );
343 mOptionsTab->setTabToolTip( 1, tr(
"Rendering" ) );
344 mOptionsTab->setTabToolTip( 2, tr(
"Size" ) );
345 mOptionsTab->setTabToolTip( 3, tr(
"Placement" ) );
346 mOptionsTab->setTabToolTip( 4, tr(
"Options" ) );
347 mOptionsTab->setTabToolTip( 5, tr(
"Legend" ) );
348 mDiagramOptionsListFrame->setVisible( !
dockMode );
353 mDiagramType = diagramType;
355 mDiagramTypeComboBox->setVisible(
false );
356 mDiagramTypeComboBox->blockSignals(
true );
357 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
358 mDiagramTypeComboBox->blockSignals(
false );
364void QgsDiagramProperties::insertDefaults()
366 mFixedSizeRadio->setChecked(
true );
369 mLabelPlacementComboBox->setCurrentIndex( mLabelPlacementComboBox->findText( tr(
"x-height" ) ) );
370 mDiagramSizeSpinBox->setEnabled(
true );
371 mDiagramSizeSpinBox->setValue( 15 );
372 mLinearScaleFrame->setEnabled(
false );
373 mBarWidthSpinBox->setValue( 5 );
376 mShowAllCheckBox->setChecked(
true );
377 mCheckBoxAttributeLegend->setChecked(
true );
382 radAroundPoint->setChecked(
true );
386 radAroundLine->setChecked(
true );
387 chkLineAbove->setChecked(
true );
388 chkLineBelow->setChecked(
false );
389 chkLineOn->setChecked(
false );
390 chkLineOrientationDependent->setChecked(
false );
394 radOverCentroid->setChecked(
true );
395 mDiagramDistanceLabel->setEnabled(
false );
396 mDiagramDistanceSpinBox->setEnabled(
false );
397 mDistanceDDBtn->setEnabled(
false );
404 mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
405 mDiagramPenColorButton->setColor( QColor( 0, 0, 0, 255 ) );
410void QgsDiagramProperties::updateDataDefinedButtons()
412 const QList<QgsPropertyOverrideButton *> propertyOverrideButtons { findChildren<QgsPropertyOverrideButton *>() };
413 for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
415 updateDataDefinedButton( button );
428 whileBlocking( button )->setToProperty( mDataDefinedProperties.property( key ) );
441 renderer = stackedRenderer->
renderer( 0 );
452 mDiagramAttributesTreeWidget->clear();
463 mFixedSizeRadio->setChecked(
true );
467 mAttributeBasedScalingRadio->setChecked(
true );
469 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
470 mLinearScaleFrame->setEnabled( mAttributeBasedScalingRadio->isChecked() );
475 if ( !settingList.isEmpty() )
477 setDiagramEnabled( settingList.at( 0 ).enabled );
478 mDiagramFontButton->setCurrentFont( settingList.at( 0 ).font );
479 const QSizeF size = settingList.at( 0 ).size;
480 mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
481 mOpacityWidget->setOpacity( settingList.at( 0 ).opacity );
482 mDiagramPenColorButton->setColor( settingList.at( 0 ).penColor );
483 mPenWidthSpinBox->setValue( settingList.at( 0 ).penWidth );
484 mDiagramSizeSpinBox->setValue( ( size.width() + size.height() ) / 2.0 );
485 mScaleRangeWidget->setScaleRange( ( settingList.at( 0 ).minimumScale > 0 ? settingList.at( 0 ).minimumScale : mLayer->minimumScale() ), ( settingList.at( 0 ).maximumScale > 0 ? settingList.at( 0 ).maximumScale : mLayer->maximumScale() ) );
486 mScaleVisibilityGroupBox->setChecked( settingList.at( 0 ).scaleBasedVisibility );
487 mDiagramUnitComboBox->setUnit( settingList.at( 0 ).sizeType );
488 mDiagramUnitComboBox->setMapUnitScale( settingList.at( 0 ).sizeScale );
489 mDiagramLineUnitComboBox->setUnit( settingList.at( 0 ).lineSizeUnit );
490 mDiagramLineUnitComboBox->setMapUnitScale( settingList.at( 0 ).lineSizeScale );
494 mLabelPlacementComboBox->setCurrentIndex( 0 );
498 mLabelPlacementComboBox->setCurrentIndex( 1 );
501 if ( settingList.at( 0 ).paintEffect() )
502 mPaintEffect.reset( settingList.at( 0 ).paintEffect()->clone() );
504 mAngleOffsetComboBox->setCurrentIndex( mAngleOffsetComboBox->findData( settingList.at( 0 ).rotationOffset ) );
505 mAngleDirectionComboBox->setCurrentIndex( mAngleDirectionComboBox->findData( settingList.at( 0 ).direction() ) );
507 switch ( settingList.at( 0 ).diagramOrientation )
510 mOrientationLeftButton->setChecked(
true );
514 mOrientationRightButton->setChecked(
true );
518 mOrientationUpButton->setChecked(
true );
522 mOrientationDownButton->setChecked(
true );
526 mBarWidthSpinBox->setValue( settingList.at( 0 ).barWidth );
527 mBarSpacingSpinBox->setValue( settingList.at( 0 ).spacing() );
528 mBarSpacingUnitComboBox->setUnit( settingList.at( 0 ).spacingUnit() );
529 mBarSpacingUnitComboBox->setMapUnitScale( settingList.at( 0 ).spacingMapUnitScale() );
531 mShowAxisGroupBox->setChecked( settingList.at( 0 ).showAxis() );
532 if ( settingList.at( 0 ).axisLineSymbol() )
533 mAxisLineStyleButton->setSymbol( settingList.at( 0 ).axisLineSymbol()->clone() );
535 mIncreaseSmallDiagramsGroupBox->setChecked( settingList.at( 0 ).minimumSize != 0 );
536 mIncreaseMinimumSizeSpinBox->setValue( settingList.at( 0 ).minimumSize );
538 if ( settingList.at( 0 ).scaleByArea )
540 mScaleDependencyComboBox->setCurrentIndex( 0 );
544 mScaleDependencyComboBox->setCurrentIndex( 1 );
547 const QList<QColor> categoryColors = settingList.at( 0 ).categoryColors;
548 const QList<QString> categoryAttributes = settingList.at( 0 ).categoryAttributes;
549 const QList<QString> categoryLabels = settingList.at( 0 ).categoryLabels;
550 QList<QString>::const_iterator catIt = categoryAttributes.constBegin();
551 QList<QColor>::const_iterator coIt = categoryColors.constBegin();
552 QList<QString>::const_iterator labIt = categoryLabels.constBegin();
553 for ( ; catIt != categoryAttributes.constEnd(); ++catIt, ++coIt, ++labIt )
555 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
556 newItem->setText( 0, *catIt );
557 newItem->setData( 0, RoleAttributeExpression, *catIt );
558 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
559 newItem->setData( ColumnColor, Qt::EditRole, *coIt );
560 newItem->setText( 2, *labIt );
561 newItem->setFlags( newItem->flags() | Qt::ItemIsEditable );
570 mDiagramSizeSpinBox->setEnabled(
false );
571 mLinearScaleFrame->setEnabled(
true );
572 mMaxValueSpinBox->setValue( lidr->
upperValue() );
573 mSizeSpinBox->setValue( ( lidr->
upperSize().width() + lidr->
upperSize().height() ) / 2 );
591 mDiagramTypeComboBox->blockSignals(
true );
592 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
593 mDiagramTypeComboBox->blockSignals(
false );
598 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
605 mDiagramDistanceSpinBox->setValue( dls->
distance() );
606 mPrioritySlider->setValue( dls->
priority() );
607 mZIndexSpinBox->setValue( dls->
zIndex() );
612 radAroundPoint->setChecked(
true );
613 radAroundCentroid->setChecked(
true );
617 radOverPoint->setChecked(
true );
618 radOverCentroid->setChecked(
true );
622 radAroundLine->setChecked(
true );
623 radPolygonPerimeter->setChecked(
true );
627 radOverLine->setChecked(
true );
628 radInsidePolygon->setChecked(
true );
639 chkLineOrientationDependent->setChecked(
true );
645 updateDataDefinedButtons();
652 settings.
setValue( QStringLiteral(
"Windows/Diagrams/OptionsSplitState" ), mDiagramOptionsSplitter->saveState() );
653 settings.
setValue( QStringLiteral(
"Windows/Diagrams/Tab" ), mDiagramOptionsListWidget->currentRow() );
664void QgsDiagramProperties::updateProperty()
666 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
668 mDataDefinedProperties.setProperty( key, button->
toProperty() );
674 mDiagramType = mDiagramTypeComboBox->itemData( index ).toString();
678 mTextOptionsFrame->show();
679 mBackgroundColorLabel->show();
680 mBackgroundColorButton->show();
681 mBackgroundColorDDBtn->show();
682 mDiagramFontButton->show();
686 mTextOptionsFrame->hide();
687 mBackgroundColorLabel->hide();
688 mBackgroundColorButton->hide();
689 mBackgroundColorDDBtn->hide();
690 mDiagramFontButton->hide();
695 mBarWidthLabel->show();
696 mBarWidthSpinBox->show();
697 mBarSpacingLabel->show();
698 mBarSpacingSpinBox->show();
699 mBarSpacingUnitComboBox->show();
700 mBarOptionsFrame->show();
701 mShowAxisGroupBox->show();
703 mAttributeBasedScalingRadio->setChecked(
true );
706 mLinearlyScalingLabel->setText( tr(
"Bar length: Scale linearly, so that the following value matches the specified bar length:" ) );
707 mSizeLabel->setText( tr(
"Bar length" ) );
708 mFrameIncreaseSize->setVisible(
false );
712 mBarWidthLabel->hide();
713 mBarWidthSpinBox->hide();
714 mBarSpacingLabel->hide();
715 mBarSpacingSpinBox->hide();
716 mBarSpacingUnitComboBox->hide();
717 mShowAxisGroupBox->hide();
718 mBarOptionsFrame->hide();
719 mLinearlyScalingLabel->setText( tr(
"Scale linearly between 0 and the following attribute value / diagram size:" ) );
720 mSizeLabel->setText( tr(
"Size" ) );
721 mAttributeBasedScalingRadio->setEnabled(
true );
722 mFixedSizeRadio->setEnabled(
true );
723 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
724 mFrameIncreaseSize->setVisible(
true );
729 mScaleDependencyComboBox->show();
730 mScaleDependencyLabel->show();
734 mScaleDependencyComboBox->hide();
735 mScaleDependencyLabel->hide();
740 mAngleOffsetComboBox->show();
741 mAngleDirectionComboBox->show();
742 mAngleDirectionLabel->show();
743 mAngleOffsetLabel->show();
744 mStartAngleDDBtn->show();
748 mAngleOffsetComboBox->hide();
749 mAngleDirectionComboBox->hide();
750 mAngleDirectionLabel->hide();
751 mAngleOffsetLabel->hide();
752 mStartAngleDDBtn->hide();
756QString QgsDiagramProperties::guessLegendText(
const QString &expression )
759 QString text = expression.mid( expression.startsWith(
'\"' ) ? 1 : 0 );
760 if ( text.endsWith(
'\"' ) )
767 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
769 newItem->setText( 0, item->text( 0 ) );
770 newItem->setText( 2, guessLegendText( item->text( 0 ) ) );
771 newItem->setData( 0, RoleAttributeExpression, item->data( 0, RoleAttributeExpression ) );
772 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
775 const int red = QRandomGenerator::global()->bounded( 1, 256 );
776 const int green = QRandomGenerator::global()->bounded( 1, 256 );
777 const int blue = QRandomGenerator::global()->bounded( 1, 256 );
778 const QColor randomColor( red, green, blue );
779 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
780 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
785 const auto constSelectedItems = mAttributesTreeWidget->selectedItems();
786 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
800 const auto constSelectedItems = mDiagramAttributesTreeWidget->selectedItems();
801 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
803 delete attributeItem;
812 float maxValue = 0.0;
815 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
833 maxValue = std::max( maxValue, exp.
evaluate( &context ).toFloat() );
843 const int attributeNumber = mLayer->fields().lookupField( sizeFieldNameOrExp );
844 maxValue = mLayer->maximumValue( attributeNumber ).toFloat();
847 mMaxValueSpinBox->setValue( maxValue );
854 case ColumnAttributeExpression:
856 const QString currentExpression = item->data( 0, RoleAttributeExpression ).toString();
858 const QString newExpression = showExpressionBuilder( currentExpression );
859 if ( !newExpression.isEmpty() )
861 item->setData( 0, Qt::DisplayRole, newExpression );
862 item->setData( 0, RoleAttributeExpression, newExpression );
870 case ColumnLegendText:
875std::unique_ptr<QgsDiagram> QgsDiagramProperties::createDiagramObject()
877 std::unique_ptr<QgsDiagram> diagram;
881 diagram = std::make_unique<QgsTextDiagram>();
885 diagram = std::make_unique<QgsPieDiagram>();
889 diagram = std::make_unique<QgsStackedBarDiagram>();
893 diagram = std::make_unique<QgsHistogramDiagram>();
898std::unique_ptr<QgsDiagramSettings> QgsDiagramProperties::createDiagramSettings()
900 auto ds = std::make_unique<QgsDiagramSettings>();
901 ds->enabled = isDiagramEnabled();
902 ds->font = mDiagramFontButton->currentFont();
903 ds->opacity = mOpacityWidget->opacity();
905 QList<QColor> categoryColors;
906 QList<QString> categoryAttributes;
907 QList<QString> categoryLabels;
908 categoryColors.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
909 categoryAttributes.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
910 categoryLabels.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
911 for (
int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
913 QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->data( ColumnColor, Qt::EditRole ).value<QColor>();
914 categoryColors.append( color );
915 categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, RoleAttributeExpression ).toString() );
916 categoryLabels.append( mDiagramAttributesTreeWidget->topLevelItem( i )->text( 2 ) );
918 ds->categoryColors = categoryColors;
919 ds->categoryAttributes = categoryAttributes;
920 ds->categoryLabels = categoryLabels;
921 ds->size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
922 ds->sizeType = mDiagramUnitComboBox->unit();
923 ds->sizeScale = mDiagramUnitComboBox->getMapUnitScale();
924 ds->lineSizeUnit = mDiagramLineUnitComboBox->unit();
925 ds->lineSizeScale = mDiagramLineUnitComboBox->getMapUnitScale();
929 if ( mIncreaseSmallDiagramsGroupBox->isChecked() )
931 ds->minimumSize = mIncreaseMinimumSizeSpinBox->value();
938 ds->backgroundColor = mBackgroundColorButton->color();
939 ds->penColor = mDiagramPenColorButton->color();
940 ds->penWidth = mPenWidthSpinBox->value();
941 ds->minimumScale = mScaleRangeWidget->minimumScale();
942 ds->maximumScale = mScaleRangeWidget->maximumScale();
943 ds->scaleBasedVisibility = mScaleVisibilityGroupBox->isChecked();
946 ds->rotationOffset = mAngleOffsetComboBox->currentData().toInt();
952 ds->barWidth = mBarWidthSpinBox->value();
956 ds->size.setWidth( ds->barWidth );
958 ds->size.setHeight( ds->barWidth );
961 ds->setAxisLineSymbol( mAxisLineStyleButton->clonedSymbol<QgsLineSymbol>() );
962 ds->setShowAxis( mShowAxisGroupBox->isChecked() );
964 ds->setSpacing( mBarSpacingSpinBox->value() );
965 ds->setSpacingUnit( mBarSpacingUnitComboBox->unit() );
966 ds->setSpacingMapUnitScale( mBarSpacingUnitComboBox->getMapUnitScale() );
969 ds->setPaintEffect( mPaintEffect->clone() );
971 ds->setPaintEffect(
nullptr );
976std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRenderer()
978 std::unique_ptr<QgsDiagramSettings> ds = createDiagramSettings();
980 std::unique_ptr<QgsDiagramRenderer> renderer;
981 if ( mFixedSizeRadio->isChecked() )
983 auto dr = std::make_unique<QgsSingleCategoryDiagramRenderer>();
984 dr->setDiagramSettings( *ds );
985 renderer = std::move( dr );
989 auto dr = std::make_unique<QgsLinearlyInterpolatedDiagramRenderer>();
990 dr->setLowerValue( 0.0 );
991 dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
992 dr->setUpperValue( mMaxValueSpinBox->value() );
993 dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
996 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
997 dr->setClassificationAttributeIsExpression( isExpression );
1000 dr->setClassificationAttributeExpression( sizeFieldNameOrExp );
1004 dr->setClassificationField( sizeFieldNameOrExp );
1006 dr->setDiagramSettings( *ds );
1008 dr->setDataDefinedSizeLegend( mSizeLegend ?
new QgsDataDefinedSizeLegend( *mSizeLegend ) :
nullptr );
1010 renderer = std::move( dr );
1013 renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
1015 std::unique_ptr<QgsDiagram> diagram = createDiagramObject();
1016 renderer->setDiagram( diagram.release() );
1023 QgsDiagramLayerSettings dls;
1025 dls.
setDistance( mDiagramDistanceSpinBox->value() );
1027 dls.
setZIndex( mZIndexSpinBox->value() );
1030 QWidget *curWdgt = stackedPlacement->currentWidget();
1031 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
1032 || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1036 else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() )
1037 || ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
1041 else if ( ( curWdgt == pageLine && radAroundLine->isChecked() )
1042 || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
1046 else if ( ( curWdgt == pageLine && radOverLine->isChecked() )
1047 || ( curWdgt == pagePolygon && radInsidePolygon->isChecked() ) )
1053 qFatal(
"Invalid settings" );
1057 if ( chkLineAbove->isChecked() )
1059 if ( chkLineBelow->isChecked() )
1061 if ( chkLineOn->isChecked() )
1063 if ( !chkLineOrientationDependent->isChecked() )
1074 if ( !
dockMode() || !settings.
value( QStringLiteral(
"UI/autoApplyStyling" ),
true ).toBool() )
1076 if ( isDiagramEnabled() && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
1078 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." ) );
1082 std::unique_ptr<QgsDiagramRenderer> renderer = createRenderer();
1083 mLayer->setDiagramRenderer( renderer.release() );
1086 mLayer->setDiagramLayerSettings( dls );
1090 mLayer->triggerRepaint();
1093QString QgsDiagramProperties::showExpressionBuilder(
const QString &initialExpression )
1098 dlg.setWindowTitle( tr(
"Expression Based Attribute" ) );
1103 dlg.setGeomCalculator( myDa );
1105 if ( dlg.exec() == QDialog::Accepted )
1107 return dlg.expressionText();
1118 QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
1119 if ( !selections.empty() )
1121 expression = selections[0]->text( 0 );
1124 const QString newExpression = showExpressionBuilder( expression );
1127 if ( !newExpression.isEmpty() )
1129 QTreeWidgetItem *newItem =
new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1131 newItem->setText( 0, newExpression );
1132 newItem->setText( 2, newExpression );
1133 newItem->setData( 0, RoleAttributeExpression, newExpression );
1134 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
1137 QRandomGenerator colorGenerator;
1138 const int red = colorGenerator.bounded( 1, 256 );
1139 const int green = colorGenerator.bounded( 1, 256 );
1140 const int blue = colorGenerator.bounded( 1, 256 );
1142 const QColor randomColor( red, green, blue );
1143 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
1144 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
1151 mDiagramOptionsListWidget->blockSignals(
true );
1152 mDiagramOptionsListWidget->setCurrentRow( index );
1153 mDiagramOptionsListWidget->blockSignals(
false );
1158 QWidget *curWdgt = stackedPlacement->currentWidget();
1160 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
1161 || ( curWdgt == pageLine && radAroundLine->isChecked() )
1162 || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1164 mDiagramDistanceLabel->setEnabled(
true );
1165 mDiagramDistanceSpinBox->setEnabled(
true );
1166 mDistanceDDBtn->setEnabled(
true );
1170 mDiagramDistanceLabel->setEnabled(
false );
1171 mDiagramDistanceSpinBox->setEnabled(
false );
1172 mDistanceDDBtn->setEnabled(
false );
1175 const bool linePlacementEnabled = mLayer->geometryType() ==
Qgis::GeometryType::Line && ( curWdgt == pageLine && radAroundLine->isChecked() );
1176 chkLineAbove->setEnabled( linePlacementEnabled );
1177 chkLineBelow->setEnabled( linePlacementEnabled );
1178 chkLineOn->setEnabled( linePlacementEnabled );
1179 chkLineOrientationDependent->setEnabled( linePlacementEnabled );
1184 mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
1189 mAllowedToEditDls = allowed;
1191 label_16->setVisible( allowed );
1192 mZIndexSpinBox->setVisible( allowed );
1193 mZOrderDDBtn->setVisible( allowed );
1194 mShowAllCheckBox->setVisible( allowed );
1195 mDlsLabel_1->setVisible( !allowed );
1197 mCoordinatesGrpBox->setVisible( allowed );
1198 mLinePlacementFrame->setVisible( allowed );
1199 mObstaclesGrpBox->setVisible( allowed );
1200 mPlacementFrame->setVisible( allowed );
1201 mPriorityGrpBox->setVisible( allowed );
1202 stackedPlacement->setVisible( allowed );
1203 mDlsLabel_2->setVisible( !allowed );
1208 return mAllowedToEditDls;
1215 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1217 const bool scaleByArea = mScaleDependencyComboBox->currentData().toBool();
1223 dlg.setLayout(
new QVBoxLayout() );
1225 dlg.layout()->addWidget( panel );
1226 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
1227 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1228 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsDiagramProperties::showHelp );
1229 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1230 dlg.layout()->addWidget( buttonBox );
1235void QgsDiagramProperties::showHelp()
1237 QgsHelp::openHelp( QStringLiteral(
"working_with_vector/vector_properties.html#legend" ) );
1240void QgsDiagramProperties::createAuxiliaryField()
1243 if ( !mLayer->auxiliaryLayer() )
1245 QgsNewAuxiliaryLayerDialog dlg( mLayer,
this );
1250 if ( !mLayer->auxiliaryLayer() )
1253 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1258 if ( !mLayer->auxiliaryLayer()->exists( def ) )
1259 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
1264 property.setActive(
true );
1267 mDataDefinedProperties.setProperty( key, button->
toProperty() );
1272void QgsDiagramProperties::connectValueChanged(
const QList<QWidget *> &widgets )
1274 const auto constWidgets = widgets;
1275 for ( QWidget *widget : constWidgets )
1277 if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
1281 else if ( QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( widget ) )
1285 else if ( QgsOpacityWidget *w = qobject_cast<QgsOpacityWidget *>( widget ) )
1289 else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
1293 else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
1297 else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
1301 else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
1305 else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
1309 else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
1313 else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
1317 else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
1321 else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
1325 else if ( QTreeWidget *w = qobject_cast<QTreeWidget *>( widget ) )
1329 else if ( QgsScaleRangeWidget *w = qobject_cast<QgsScaleRangeWidget *>( widget ) )
1333 else if ( QgsEffectStackCompactWidget *w = qobject_cast<QgsEffectStackCompactWidget *>( widget ) )
1337 else if ( QgsFontButton *w = qobject_cast<QgsFontButton *>( widget ) )
1343 QgsLogger::warning( QStringLiteral(
"Could not create connection for widget %1" ).arg( widget->objectName() ) );
1348void QgsDiagramProperties::setDiagramEnabled(
bool enabled )
1350 mEnableDiagramCheckBox->setChecked( enabled );
1353bool QgsDiagramProperties::isDiagramEnabled()
const
1355 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)