QGIS API Documentation 3.29.0-Master (da8bb1db43)
qgsdiagramproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdiagramproperties.cpp
3 Adjust the properties for diagrams
4 -------------------
5 begin : August 2012
6 copyright : (C) Matthias Kuhn
7 email : matthias at opengis dot ch
8
9 ***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
22
23#include "qgsproject.h"
24#include "qgsapplication.h"
28#include "qgsdiagramrenderer.h"
30#include "qgsmessagebar.h"
33#include "qgsfeatureiterator.h"
34#include "qgscolordialog.h"
35#include "qgsguiutils.h"
37#include "qgsstyle.h"
38#include "qgsmapcanvas.h"
40#include "qgslogger.h"
41#include "qgssettings.h"
43#include "qgsauxiliarystorage.h"
47#include "qgspainteffect.h"
48#include "qgslinesymbol.h"
49
50#include <QList>
51#include <QMessageBox>
52#include <QStyledItemDelegate>
53#include <QRandomGenerator>
54
55QgsExpressionContext QgsDiagramProperties::createExpressionContext() const
56{
57 QgsExpressionContext expContext;
63
64 return expContext;
65}
66
68 : QWidget( parent )
69 , mMapCanvas( canvas )
70{
71 mLayer = layer;
72 if ( !layer )
73 {
74 return;
75 }
76
77 setupUi( this );
78 connect( mDiagramTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsDiagramProperties::mDiagramTypeComboBox_currentIndexChanged );
79 connect( mAddCategoryPushButton, &QPushButton::clicked, this, &QgsDiagramProperties::mAddCategoryPushButton_clicked );
80 connect( mAttributesTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsDiagramProperties::mAttributesTreeWidget_itemDoubleClicked );
81 connect( mFindMaximumValueButton, &QPushButton::clicked, this, &QgsDiagramProperties::mFindMaximumValueButton_clicked );
82 connect( mRemoveCategoryPushButton, &QPushButton::clicked, this, &QgsDiagramProperties::mRemoveCategoryPushButton_clicked );
83 connect( mDiagramAttributesTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsDiagramProperties::mDiagramAttributesTreeWidget_itemDoubleClicked );
84 connect( mEngineSettingsButton, &QPushButton::clicked, this, &QgsDiagramProperties::mEngineSettingsButton_clicked );
85 connect( mDiagramStackedWidget, &QStackedWidget::currentChanged, this, &QgsDiagramProperties::mDiagramStackedWidget_currentChanged );
86
87 // get rid of annoying outer focus rect on Mac
88 mDiagramOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
89
90 mBarSpacingSpinBox->setClearValue( 0 );
93
94 mDiagramFontButton->setMode( QgsFontButton::ModeQFont );
95
96 mDiagramTypeComboBox->blockSignals( true );
97 QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "diagramNone.svg" ) );
98 mDiagramTypeComboBox->addItem( icon, tr( "No Diagrams" ), "None" );
99 icon = QgsApplication::getThemeIcon( QStringLiteral( "pie-chart.svg" ) );
100 mDiagramTypeComboBox->addItem( icon, tr( "Pie Chart" ), DIAGRAM_NAME_PIE );
101 icon = QgsApplication::getThemeIcon( QStringLiteral( "text.svg" ) );
102 mDiagramTypeComboBox->addItem( icon, tr( "Text Diagram" ), DIAGRAM_NAME_TEXT );
103 icon = QgsApplication::getThemeIcon( QStringLiteral( "histogram.svg" ) );
104 mDiagramTypeComboBox->addItem( icon, tr( "Histogram" ), DIAGRAM_NAME_HISTOGRAM );
105 icon = QgsApplication::getThemeIcon( QStringLiteral( "stacked-bar.svg" ) );
106 mDiagramTypeComboBox->addItem( icon, tr( "Stacked Bars" ), DIAGRAM_NAME_STACKED );
107 mDiagramTypeComboBox->blockSignals( false );
108
109 mAxisLineStyleButton->setSymbolType( Qgis::SymbolType::Line );
110 mAxisLineStyleButton->setDialogTitle( tr( "Axis Line Symbol" ) );
111
112 mScaleRangeWidget->setMapCanvas( mMapCanvas );
113 mSizeFieldExpressionWidget->registerExpressionContextGenerator( this );
114
115 mBackgroundColorButton->setColorDialogTitle( tr( "Select Background Color" ) );
116 mBackgroundColorButton->setAllowOpacity( true );
117 mBackgroundColorButton->setContext( QStringLiteral( "symbology" ) );
118 mBackgroundColorButton->setShowNoColor( true );
119 mBackgroundColorButton->setNoColorString( tr( "Transparent Background" ) );
120 mDiagramPenColorButton->setColorDialogTitle( tr( "Select Pen Color" ) );
121 mDiagramPenColorButton->setAllowOpacity( true );
122 mDiagramPenColorButton->setContext( QStringLiteral( "symbology" ) );
123 mDiagramPenColorButton->setShowNoColor( true );
124 mDiagramPenColorButton->setNoColorString( tr( "Transparent Stroke" ) );
125
126 mMaxValueSpinBox->setShowClearButton( false );
127 mSizeSpinBox->setClearValue( 5 );
128
129 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnAttributeExpression, new EditBlockerDelegate( this ) );
130 mDiagramAttributesTreeWidget->setItemDelegateForColumn( ColumnColor, new QgsColorSwatchDelegate( this ) );
131
132 mDiagramAttributesTreeWidget->setColumnWidth( ColumnColor, Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 6.6 );
133
134 connect( mFixedSizeRadio, &QRadioButton::toggled, this, &QgsDiagramProperties::scalingTypeChanged );
135 connect( mAttributeBasedScalingRadio, &QRadioButton::toggled, this, &QgsDiagramProperties::scalingTypeChanged );
136
141
142 const QgsWkbTypes::GeometryType layerType = layer->geometryType();
143 if ( layerType == QgsWkbTypes::UnknownGeometry || layerType == QgsWkbTypes::NullGeometry )
144 {
145 mDiagramTypeComboBox->setEnabled( false );
146 mDiagramFrame->setEnabled( false );
147 }
148
149 // set placement methods page based on geometry type
150
151 switch ( layerType )
152 {
154 stackedPlacement->setCurrentWidget( pagePoint );
155 mLinePlacementFrame->setVisible( false );
156 break;
158 stackedPlacement->setCurrentWidget( pageLine );
159 mLinePlacementFrame->setVisible( true );
160 break;
162 stackedPlacement->setCurrentWidget( pagePolygon );
163 mLinePlacementFrame->setVisible( false );
164 break;
167 break;
168 }
169
170 //insert placement options
171 // setup point placement button group
172 mPlacePointBtnGrp = new QButtonGroup( this );
173 mPlacePointBtnGrp->addButton( radAroundPoint );
174 mPlacePointBtnGrp->addButton( radOverPoint );
175 mPlacePointBtnGrp->setExclusive( true );
176 connect( mPlacePointBtnGrp, qOverload< QAbstractButton * >( &QButtonGroup::buttonClicked ), this, &QgsDiagramProperties::updatePlacementWidgets );
177
178 // setup line placement button group
179 mPlaceLineBtnGrp = new QButtonGroup( this );
180 mPlaceLineBtnGrp->addButton( radAroundLine );
181 mPlaceLineBtnGrp->addButton( radOverLine );
182 mPlaceLineBtnGrp->setExclusive( true );
183 connect( mPlaceLineBtnGrp, qOverload< QAbstractButton * >( &QButtonGroup::buttonClicked ), this, &QgsDiagramProperties::updatePlacementWidgets );
184
185 // setup polygon placement button group
186 mPlacePolygonBtnGrp = new QButtonGroup( this );
187 mPlacePolygonBtnGrp->addButton( radAroundCentroid );
188 mPlacePolygonBtnGrp->addButton( radOverCentroid );
189 mPlacePolygonBtnGrp->addButton( radPolygonPerimeter );
190 mPlacePolygonBtnGrp->addButton( radInsidePolygon );
191 mPlacePolygonBtnGrp->setExclusive( true );
192 connect( mPlacePolygonBtnGrp, qOverload< QAbstractButton * >( &QButtonGroup::buttonClicked ), this, &QgsDiagramProperties::updatePlacementWidgets );
193
194 mLabelPlacementComboBox->addItem( tr( "Height" ), QgsDiagramSettings::Height );
195 mLabelPlacementComboBox->addItem( tr( "x-height" ), QgsDiagramSettings::XHeight );
196
197 mScaleDependencyComboBox->addItem( tr( "Area" ), true );
198 mScaleDependencyComboBox->addItem( tr( "Diameter" ), false );
199
200 mAngleOffsetComboBox->addItem( tr( "Top" ), 270 );
201 mAngleOffsetComboBox->addItem( tr( "Right" ), 0 );
202 mAngleOffsetComboBox->addItem( tr( "Bottom" ), 90 );
203 mAngleOffsetComboBox->addItem( tr( "Left" ), 180 );
204
205 mAngleDirectionComboBox->addItem( tr( "Clockwise" ), QgsDiagramSettings::Clockwise );
206 mAngleDirectionComboBox->addItem( tr( "Counter-clockwise" ), QgsDiagramSettings::Counterclockwise );
207
208 const QgsSettings settings;
209
210 // reset horiz stretch of left side of options splitter (set to 1 for previewing in Qt Designer)
211 QSizePolicy policy( mDiagramOptionsListFrame->sizePolicy() );
212 policy.setHorizontalStretch( 0 );
213 mDiagramOptionsListFrame->setSizePolicy( policy );
214 if ( !settings.contains( QStringLiteral( "/Windows/Diagrams/OptionsSplitState" ) ) )
215 {
216 // set left list widget width on initial showing
217 QList<int> splitsizes;
218 splitsizes << 115;
219 mDiagramOptionsSplitter->setSizes( splitsizes );
220 }
221
222 // restore dialog, splitters and current tab
223 mDiagramOptionsSplitter->restoreState( settings.value( QStringLiteral( "Windows/Diagrams/OptionsSplitState" ) ).toByteArray() );
224 mDiagramOptionsListWidget->setCurrentRow( settings.value( QStringLiteral( "Windows/Diagrams/Tab" ), 0 ).toInt() );
225
226 // field combo and expression button
227 mSizeFieldExpressionWidget->setLayer( mLayer );
228 QgsDistanceArea myDa;
230 myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
231 mSizeFieldExpressionWidget->setGeomCalculator( myDa );
232
233 //insert all attributes into the combo boxes
234 const QgsFields &layerFields = layer->fields();
235 for ( int idx = 0; idx < layerFields.count(); ++idx )
236 {
237 QTreeWidgetItem *newItem = new QTreeWidgetItem( mAttributesTreeWidget );
238 const QString name = QStringLiteral( "\"%1\"" ).arg( layerFields.at( idx ).name() );
239 newItem->setText( 0, name );
240 newItem->setData( 0, RoleAttributeExpression, name );
241 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
242 }
243
244 mPaintEffect.reset( QgsPaintEffectRegistry::defaultStack() );
245 mPaintEffect->setEnabled( false );
246
247 syncToLayer();
248
249 connect( mAddAttributeExpression, &QPushButton::clicked, this, &QgsDiagramProperties::showAddAttributeExpressionDialog );
250 registerDataDefinedButton( mBackgroundColorDDBtn, QgsDiagramLayerSettings::BackgroundColor );
251 registerDataDefinedButton( mLineColorDDBtn, QgsDiagramLayerSettings::StrokeColor );
252 registerDataDefinedButton( mLineWidthDDBtn, QgsDiagramLayerSettings::StrokeWidth );
253 registerDataDefinedButton( mCoordXDDBtn, QgsDiagramLayerSettings::PositionX );
254 registerDataDefinedButton( mCoordYDDBtn, QgsDiagramLayerSettings::PositionY );
255 registerDataDefinedButton( mDistanceDDBtn, QgsDiagramLayerSettings::Distance );
256 registerDataDefinedButton( mPriorityDDBtn, QgsDiagramLayerSettings::Priority );
257 registerDataDefinedButton( mZOrderDDBtn, QgsDiagramLayerSettings::ZIndex );
258 registerDataDefinedButton( mShowDiagramDDBtn, QgsDiagramLayerSettings::Show );
259 registerDataDefinedButton( mAlwaysShowDDBtn, QgsDiagramLayerSettings::AlwaysShow );
260 registerDataDefinedButton( mIsObstacleDDBtn, QgsDiagramLayerSettings::IsObstacle );
261 registerDataDefinedButton( mStartAngleDDBtn, QgsDiagramLayerSettings::StartAngle );
262
263 connect( mButtonSizeLegendSettings, &QPushButton::clicked, this, &QgsDiagramProperties::showSizeLegendDialog );
264}
265
267{
268 mDiagramAttributesTreeWidget->clear();
269
270 const QgsDiagramRenderer *dr = mLayer->diagramRenderer();
271 if ( !dr ) //no diagram renderer yet, insert reasonable default
272 {
273 mDiagramTypeComboBox->blockSignals( true );
274 mDiagramTypeComboBox->setCurrentIndex( 0 );
275 mDiagramTypeComboBox->blockSignals( false );
276 mFixedSizeRadio->setChecked( true );
277 mDiagramUnitComboBox->setUnit( QgsUnitTypes::RenderMillimeters );
278 mDiagramLineUnitComboBox->setUnit( QgsUnitTypes::RenderMillimeters );
279 mLabelPlacementComboBox->setCurrentIndex( mLabelPlacementComboBox->findText( tr( "x-height" ) ) );
280 mDiagramSizeSpinBox->setEnabled( true );
281 mDiagramSizeSpinBox->setValue( 15 );
282 mLinearScaleFrame->setEnabled( false );
283 mIncreaseMinimumSizeSpinBox->setEnabled( false );
284 mIncreaseMinimumSizeLabel->setEnabled( false );
285 mBarWidthSpinBox->setValue( 5 );
286 mScaleVisibilityGroupBox->setChecked( mLayer->hasScaleBasedVisibility() );
287 mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
288 mShowAllCheckBox->setChecked( true );
289 mCheckBoxAttributeLegend->setChecked( true );
290
291 switch ( mLayer->geometryType() )
292 {
294 radAroundPoint->setChecked( true );
295 break;
296
298 radAroundLine->setChecked( true );
299 chkLineAbove->setChecked( true );
300 chkLineBelow->setChecked( false );
301 chkLineOn->setChecked( false );
302 chkLineOrientationDependent->setChecked( false );
303 break;
304
306 radOverCentroid->setChecked( true );
307 mDiagramDistanceLabel->setEnabled( false );
308 mDiagramDistanceSpinBox->setEnabled( false );
309 mDistanceDDBtn->setEnabled( false );
310 break;
311
314 break;
315 }
316 mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
317 //force a refresh of widget status to match diagram type
318 mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
319
320 }
321 else // already a diagram renderer present
322 {
323 //single category renderer or interpolated one?
324 if ( dr->rendererName() == QLatin1String( "SingleCategory" ) )
325 {
326 mFixedSizeRadio->setChecked( true );
327 }
328 else
329 {
330 mAttributeBasedScalingRadio->setChecked( true );
331 }
332 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
333 mLinearScaleFrame->setEnabled( mAttributeBasedScalingRadio->isChecked() );
334 mCheckBoxAttributeLegend->setChecked( dr->attributeLegend() );
335
336 //assume single category or linearly interpolated diagram renderer for now
337 const QList<QgsDiagramSettings> settingList = dr->diagramSettings();
338 if ( !settingList.isEmpty() )
339 {
340 mDiagramFrame->setEnabled( settingList.at( 0 ).enabled );
341 mDiagramFontButton->setCurrentFont( settingList.at( 0 ).font );
342 const QSizeF size = settingList.at( 0 ).size;
343 mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
344 mOpacityWidget->setOpacity( settingList.at( 0 ).opacity );
345 mDiagramPenColorButton->setColor( settingList.at( 0 ).penColor );
346 mPenWidthSpinBox->setValue( settingList.at( 0 ).penWidth );
347 mDiagramSizeSpinBox->setValue( ( size.width() + size.height() ) / 2.0 );
348 mScaleRangeWidget->setScaleRange( ( settingList.at( 0 ).minimumScale > 0 ? settingList.at( 0 ).minimumScale : mLayer->minimumScale() ),
349 ( settingList.at( 0 ).maximumScale > 0 ? settingList.at( 0 ).maximumScale : mLayer->maximumScale() ) );
350 mScaleVisibilityGroupBox->setChecked( settingList.at( 0 ).scaleBasedVisibility );
351 mDiagramUnitComboBox->setUnit( settingList.at( 0 ).sizeType );
352 mDiagramUnitComboBox->setMapUnitScale( settingList.at( 0 ).sizeScale );
353 mDiagramLineUnitComboBox->setUnit( settingList.at( 0 ).lineSizeUnit );
354 mDiagramLineUnitComboBox->setMapUnitScale( settingList.at( 0 ).lineSizeScale );
355
356 if ( settingList.at( 0 ).labelPlacementMethod == QgsDiagramSettings::Height )
357 {
358 mLabelPlacementComboBox->setCurrentIndex( 0 );
359 }
360 else
361 {
362 mLabelPlacementComboBox->setCurrentIndex( 1 );
363 }
364
365 if ( settingList.at( 0 ).paintEffect() )
366 mPaintEffect.reset( settingList.at( 0 ).paintEffect()->clone() );
367
368 mAngleOffsetComboBox->setCurrentIndex( mAngleOffsetComboBox->findData( settingList.at( 0 ).rotationOffset ) );
369 mAngleDirectionComboBox->setCurrentIndex( mAngleDirectionComboBox->findData( settingList.at( 0 ).direction() ) );
370
371 mOrientationLeftButton->setProperty( "direction", QgsDiagramSettings::Left );
372 mOrientationRightButton->setProperty( "direction", QgsDiagramSettings::Right );
373 mOrientationUpButton->setProperty( "direction", QgsDiagramSettings::Up );
374 mOrientationDownButton->setProperty( "direction", QgsDiagramSettings::Down );
375 switch ( settingList.at( 0 ).diagramOrientation )
376 {
378 mOrientationLeftButton->setChecked( true );
379 break;
380
382 mOrientationRightButton->setChecked( true );
383 break;
384
386 mOrientationUpButton->setChecked( true );
387 break;
388
390 mOrientationDownButton->setChecked( true );
391 break;
392 }
393
394 mBarWidthSpinBox->setValue( settingList.at( 0 ).barWidth );
395 mBarSpacingSpinBox->setValue( settingList.at( 0 ).spacing() );
396 mBarSpacingUnitComboBox->setUnit( settingList.at( 0 ).spacingUnit() );
397 mBarSpacingUnitComboBox->setMapUnitScale( settingList.at( 0 ).spacingMapUnitScale() );
398
399 mShowAxisGroupBox->setChecked( settingList.at( 0 ).showAxis() );
400 if ( settingList.at( 0 ).axisLineSymbol() )
401 mAxisLineStyleButton->setSymbol( settingList.at( 0 ).axisLineSymbol()->clone() );
402
403 mIncreaseSmallDiagramsCheck->setChecked( settingList.at( 0 ).minimumSize != 0 );
404 mIncreaseMinimumSizeSpinBox->setEnabled( mIncreaseSmallDiagramsCheck->isChecked() );
405 mIncreaseMinimumSizeLabel->setEnabled( mIncreaseSmallDiagramsCheck->isChecked() );
406
407 mIncreaseMinimumSizeSpinBox->setValue( settingList.at( 0 ).minimumSize );
408
409 if ( settingList.at( 0 ).scaleByArea )
410 {
411 mScaleDependencyComboBox->setCurrentIndex( 0 );
412 }
413 else
414 {
415 mScaleDependencyComboBox->setCurrentIndex( 1 );
416 }
417
418 const QList< QColor > categoryColors = settingList.at( 0 ).categoryColors;
419 const QList< QString > categoryAttributes = settingList.at( 0 ).categoryAttributes;
420 const QList< QString > categoryLabels = settingList.at( 0 ).categoryLabels;
421 QList< QString >::const_iterator catIt = categoryAttributes.constBegin();
422 QList< QColor >::const_iterator coIt = categoryColors.constBegin();
423 QList< QString >::const_iterator labIt = categoryLabels.constBegin();
424 for ( ; catIt != categoryAttributes.constEnd(); ++catIt, ++coIt, ++labIt )
425 {
426 QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
427 newItem->setText( 0, *catIt );
428 newItem->setData( 0, RoleAttributeExpression, *catIt );
429 newItem->setFlags( newItem->flags() & ~Qt::ItemIsDropEnabled );
430 newItem->setData( ColumnColor, Qt::EditRole, *coIt );
431 newItem->setText( 2, *labIt );
432 newItem->setFlags( newItem->flags() | Qt::ItemIsEditable );
433 }
434 }
435
436 if ( dr->rendererName() == QLatin1String( "LinearlyInterpolated" ) )
437 {
439 if ( lidr )
440 {
441 mDiagramSizeSpinBox->setEnabled( false );
442 mLinearScaleFrame->setEnabled( true );
443 mMaxValueSpinBox->setValue( lidr->upperValue() );
444 mSizeSpinBox->setValue( ( lidr->upperSize().width() + lidr->upperSize().height() ) / 2 );
446 {
447 mSizeFieldExpressionWidget->setField( lidr->classificationAttributeExpression() );
448 }
449 else
450 {
451 mSizeFieldExpressionWidget->setField( lidr->classificationField() );
452 }
453
454 mSizeLegend.reset( lidr->dataDefinedSizeLegend() ? new QgsDataDefinedSizeLegend( *lidr->dataDefinedSizeLegend() ) : nullptr );
455 }
456 }
457
458 const QgsDiagramLayerSettings *dls = mLayer->diagramLayerSettings();
459 if ( dls )
460 {
461 mDiagramDistanceSpinBox->setValue( dls->distance() );
462 mPrioritySlider->setValue( dls->priority() );
463 mZIndexSpinBox->setValue( dls->zIndex() );
464
465 switch ( dls->placement() )
466 {
468 radAroundPoint->setChecked( true );
469 radAroundCentroid->setChecked( true );
470 break;
471
473 radOverPoint->setChecked( true );
474 radOverCentroid->setChecked( true );
475 break;
476
478 radAroundLine->setChecked( true );
479 radPolygonPerimeter->setChecked( true );
480 break;
481
483 radOverLine->setChecked( true );
484 radInsidePolygon->setChecked( true );
485 break;
486
487 default:
488 break;
489 }
490
491 chkLineAbove->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::AboveLine );
492 chkLineBelow->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::BelowLine );
493 chkLineOn->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::OnLine );
495 chkLineOrientationDependent->setChecked( true );
497
498 mShowAllCheckBox->setChecked( dls->showAllDiagrams() );
499
500 mDataDefinedProperties = dls->dataDefinedProperties();
501 }
502
503 if ( dr->diagram() )
504 {
505 mDiagramType = dr->diagram()->diagramName();
506
507 mDiagramTypeComboBox->blockSignals( true );
508 mDiagramTypeComboBox->setCurrentIndex( settingList.at( 0 ).enabled ? mDiagramTypeComboBox->findData( mDiagramType ) : 0 );
509 mDiagramTypeComboBox->blockSignals( false );
510 //force a refresh of widget status to match diagram type
511 mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
512 if ( mDiagramTypeComboBox->currentIndex() == -1 )
513 {
514 QMessageBox::warning( this, tr( "Diagram Properties" ),
515 tr( "The diagram type '%1' is unknown. A default type is selected for you." ).arg( mDiagramType ), QMessageBox::Ok );
516 mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( DIAGRAM_NAME_PIE ) );
517 }
518 }
519 }
520 mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
521}
522
524{
525 QgsSettings settings;
526 settings.setValue( QStringLiteral( "Windows/Diagrams/OptionsSplitState" ), mDiagramOptionsSplitter->saveState() );
527 settings.setValue( QStringLiteral( "Windows/Diagrams/Tab" ), mDiagramOptionsListWidget->currentRow() );
528}
529
530void QgsDiagramProperties::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsDiagramLayerSettings::Property key )
531{
532 button->init( key, mDataDefinedProperties, QgsDiagramLayerSettings::propertyDefinitions(), mLayer, true );
533 connect( button, &QgsPropertyOverrideButton::changed, this, &QgsDiagramProperties::updateProperty );
534 connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsDiagramProperties::createAuxiliaryField );
536}
537
538void QgsDiagramProperties::updateProperty()
539{
540 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
542 mDataDefinedProperties.setProperty( key, button->toProperty() );
543}
544
546{
547 if ( index == 0 )
548 {
549 mDiagramFrame->setEnabled( false );
550 }
551 else
552 {
553 mDiagramFrame->setEnabled( true );
554
555 mDiagramType = mDiagramTypeComboBox->itemData( index ).toString();
556
557 if ( DIAGRAM_NAME_TEXT == mDiagramType )
558 {
559 mTextOptionsFrame->show();
560 mBackgroundColorLabel->show();
561 mBackgroundColorButton->show();
562 mBackgroundColorDDBtn->show();
563 mDiagramFontButton->show();
564 }
565 else
566 {
567 mTextOptionsFrame->hide();
568 mBackgroundColorLabel->hide();
569 mBackgroundColorButton->hide();
570 mBackgroundColorDDBtn->hide();
571 mDiagramFontButton->hide();
572 }
573
574 if ( DIAGRAM_NAME_HISTOGRAM == mDiagramType || DIAGRAM_NAME_STACKED == mDiagramType )
575 {
576 mBarWidthLabel->show();
577 mBarWidthSpinBox->show();
578 mBarSpacingLabel->show();
579 mBarSpacingSpinBox->show();
580 mBarSpacingUnitComboBox->show();
581 mBarOptionsFrame->show();
582 mShowAxisGroupBox->show();
583 if ( DIAGRAM_NAME_HISTOGRAM == mDiagramType )
584 mAttributeBasedScalingRadio->setChecked( true );
585 mFixedSizeRadio->setEnabled( DIAGRAM_NAME_STACKED == mDiagramType );
586 mDiagramSizeSpinBox->setEnabled( DIAGRAM_NAME_STACKED == mDiagramType );
587 mLinearlyScalingLabel->setText( tr( "Bar length: Scale linearly, so that the following value matches the specified bar length:" ) );
588 mSizeLabel->setText( tr( "Bar length" ) );
589 mFrameIncreaseSize->setVisible( false );
590 }
591 else
592 {
593 mBarWidthLabel->hide();
594 mBarWidthSpinBox->hide();
595 mBarSpacingLabel->hide();
596 mBarSpacingSpinBox->hide();
597 mBarSpacingUnitComboBox->hide();
598 mShowAxisGroupBox->hide();
599 mBarOptionsFrame->hide();
600 mLinearlyScalingLabel->setText( tr( "Scale linearly between 0 and the following attribute value / diagram size:" ) );
601 mSizeLabel->setText( tr( "Size" ) );
602 mAttributeBasedScalingRadio->setEnabled( true );
603 mFixedSizeRadio->setEnabled( true );
604 mDiagramSizeSpinBox->setEnabled( mFixedSizeRadio->isChecked() );
605 mFrameIncreaseSize->setVisible( true );
606 }
607
608 if ( DIAGRAM_NAME_TEXT == mDiagramType || DIAGRAM_NAME_PIE == mDiagramType )
609 {
610 mScaleDependencyComboBox->show();
611 mScaleDependencyLabel->show();
612 }
613 else
614 {
615 mScaleDependencyComboBox->hide();
616 mScaleDependencyLabel->hide();
617 }
618
619 if ( DIAGRAM_NAME_PIE == mDiagramType )
620 {
621 mAngleOffsetComboBox->show();
622 mAngleDirectionComboBox->show();
623 mAngleDirectionLabel->show();
624 mAngleOffsetLabel->show();
625 mStartAngleDDBtn->show();
626 }
627 else
628 {
629 mAngleOffsetComboBox->hide();
630 mAngleDirectionComboBox->hide();
631 mAngleDirectionLabel->hide();
632 mAngleOffsetLabel->hide();
633 mStartAngleDDBtn->hide();
634 }
635 }
636}
637QString QgsDiagramProperties::guessLegendText( const QString &expression )
638{
639 //trim unwanted characters from expression text for legend
640 QString text = expression.mid( expression.startsWith( '\"' ) ? 1 : 0 );
641 if ( text.endsWith( '\"' ) )
642 text.chop( 1 );
643 return text;
644}
645
646void QgsDiagramProperties::addAttribute( QTreeWidgetItem *item )
647{
648 QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
649
650 newItem->setText( 0, item->text( 0 ) );
651 newItem->setText( 2, guessLegendText( item->text( 0 ) ) );
652 newItem->setData( 0, RoleAttributeExpression, item->data( 0, RoleAttributeExpression ) );
653 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
654
655 //set initial color for diagram category
656 QRandomGenerator colorGenerator;
657 const int red = colorGenerator.bounded( 1, 256 );
658 const int green = colorGenerator.bounded( 1, 256 );
659 const int blue = colorGenerator.bounded( 1, 256 );
660 const QColor randomColor( red, green, blue );
661 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
662 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
663}
664
666{
667 const auto constSelectedItems = mAttributesTreeWidget->selectedItems();
668 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
669 {
670 addAttribute( attributeItem );
671 }
672}
673
675{
676 Q_UNUSED( column )
677 addAttribute( item );
678}
679
681{
682 const auto constSelectedItems = mDiagramAttributesTreeWidget->selectedItems();
683 for ( QTreeWidgetItem *attributeItem : constSelectedItems )
684 {
685 delete attributeItem;
686 }
687}
688
690{
691 if ( !mLayer )
692 return;
693
694 float maxValue = 0.0;
695
696 bool isExpression;
697 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
698 if ( isExpression )
699 {
700 QgsExpression exp( sizeFieldNameOrExp );
701 QgsExpressionContext context;
706
707 exp.prepare( &context );
708 if ( !exp.hasEvalError() )
709 {
710 QgsFeature feature;
711 QgsFeatureIterator features = mLayer->getFeatures();
712 while ( features.nextFeature( *&feature ) )
713 {
714 context.setFeature( feature );
715 maxValue = std::max( maxValue, exp.evaluate( &context ).toFloat() );
716 }
717 }
718 else
719 {
720 QgsDebugMsgLevel( "Prepare error:" + exp.evalErrorString(), 4 );
721 }
722 }
723 else
724 {
725 const int attributeNumber = mLayer->fields().lookupField( sizeFieldNameOrExp );
726 maxValue = mLayer->maximumValue( attributeNumber ).toFloat();
727 }
728
729 mMaxValueSpinBox->setValue( maxValue );
730}
731
733{
734 switch ( column )
735 {
736 case ColumnAttributeExpression:
737 {
738 const QString currentExpression = item->data( 0, RoleAttributeExpression ).toString();
739
740 const QString newExpression = showExpressionBuilder( currentExpression );
741 if ( !newExpression.isEmpty() )
742 {
743 item->setData( 0, Qt::DisplayRole, newExpression );
744 item->setData( 0, RoleAttributeExpression, newExpression );
745 }
746 break;
747 }
748
749 case ColumnColor:
750 break;
751
752 case ColumnLegendText:
753 break;
754 }
755}
756
758{
760 if ( panel && panel->dockMode() )
761 {
762 QgsLabelEngineConfigWidget *widget = new QgsLabelEngineConfigWidget( mMapCanvas );
764 panel->openPanel( widget );
765 }
766 else
767 {
768 QgsLabelEngineConfigDialog dialog( mMapCanvas, this );
769 dialog.exec();
770 // reactivate button's window
771 activateWindow();
772 }
773}
774
776{
777 const int index = mDiagramTypeComboBox->currentIndex();
778 const bool diagramsEnabled = ( index != 0 );
779
780 std::unique_ptr< QgsDiagram > diagram;
781
782 if ( diagramsEnabled && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
783 {
784 QMessageBox::warning( this, tr( "Diagrams: No attributes added." ),
785 tr( "You did not add any attributes to this diagram layer. Please specify the attributes to visualize on the diagrams or disable diagrams." ) );
786 }
787
788 if ( mDiagramType == DIAGRAM_NAME_TEXT )
789 {
790 diagram = std::make_unique< QgsTextDiagram >();
791 }
792 else if ( mDiagramType == DIAGRAM_NAME_PIE )
793 {
794 diagram = std::make_unique< QgsPieDiagram >();
795 }
796 else if ( mDiagramType == DIAGRAM_NAME_STACKED )
797 {
798 diagram = std::make_unique< QgsStackedBarDiagram >();
799 }
800 else // if ( diagramType == DIAGRAM_NAME_HISTOGRAM )
801 {
802 diagram = std::make_unique< QgsHistogramDiagram >();
803 }
804
806 ds.enabled = ( mDiagramTypeComboBox->currentIndex() != 0 );
807 ds.font = mDiagramFontButton->currentFont();
808 ds.opacity = mOpacityWidget->opacity();
809
810 QList<QColor> categoryColors;
811 QList<QString> categoryAttributes;
812 QList<QString> categoryLabels;
813 categoryColors.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
814 categoryAttributes.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
815 categoryLabels.reserve( mDiagramAttributesTreeWidget->topLevelItemCount() );
816 for ( int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
817 {
818 QColor color = mDiagramAttributesTreeWidget->topLevelItem( i )->data( ColumnColor, Qt::EditRole ).value<QColor>();
819 categoryColors.append( color );
820 categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, RoleAttributeExpression ).toString() );
821 categoryLabels.append( mDiagramAttributesTreeWidget->topLevelItem( i )->text( 2 ) );
822 }
823 ds.categoryColors = categoryColors;
824 ds.categoryAttributes = categoryAttributes;
825 ds.categoryLabels = categoryLabels;
826 ds.size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
827 ds.sizeType = mDiagramUnitComboBox->unit();
828 ds.sizeScale = mDiagramUnitComboBox->getMapUnitScale();
829 ds.lineSizeUnit = mDiagramLineUnitComboBox->unit();
830 ds.lineSizeScale = mDiagramLineUnitComboBox->getMapUnitScale();
831 ds.labelPlacementMethod = static_cast<QgsDiagramSettings::LabelPlacementMethod>( mLabelPlacementComboBox->currentData().toInt() );
832 ds.scaleByArea = ( mDiagramType == DIAGRAM_NAME_STACKED ) ? false : mScaleDependencyComboBox->currentData().toBool();
833
834 if ( mIncreaseSmallDiagramsCheck->isChecked() )
835 {
836 ds.minimumSize = mIncreaseMinimumSizeSpinBox->value();
837 }
838 else
839 {
840 ds.minimumSize = 0;
841 }
842
843 ds.backgroundColor = mBackgroundColorButton->color();
844 ds.penColor = mDiagramPenColorButton->color();
845 ds.penWidth = mPenWidthSpinBox->value();
846 ds.minimumScale = mScaleRangeWidget->minimumScale();
847 ds.maximumScale = mScaleRangeWidget->maximumScale();
848 ds.scaleBasedVisibility = mScaleVisibilityGroupBox->isChecked();
849
850 // Diagram angle offset (pie)
851 ds.rotationOffset = mAngleOffsetComboBox->currentData().toInt();
852 ds.setDirection( static_cast< QgsDiagramSettings::Direction>( mAngleDirectionComboBox->currentData().toInt() ) );
853
854 // Diagram orientation (histogram)
855 ds.diagramOrientation = static_cast<QgsDiagramSettings::DiagramOrientation>( mOrientationButtonGroup->checkedButton()->property( "direction" ).toInt() );
856
857 ds.barWidth = mBarWidthSpinBox->value();
858
859 ds.setAxisLineSymbol( mAxisLineStyleButton->clonedSymbol< QgsLineSymbol >() );
860 ds.setShowAxis( mShowAxisGroupBox->isChecked() );
861
862 ds.setSpacing( mBarSpacingSpinBox->value() );
863 ds.setSpacingUnit( mBarSpacingUnitComboBox->unit() );
864 ds.setSpacingMapUnitScale( mBarSpacingUnitComboBox->getMapUnitScale() );
865
866 if ( mPaintEffect && ( !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect.get() ) || mPaintEffect->enabled() ) )
867 ds.setPaintEffect( mPaintEffect->clone() );
868 else
869 ds.setPaintEffect( nullptr );
870
871 QgsDiagramRenderer *renderer = nullptr;
872 if ( mFixedSizeRadio->isChecked() )
873 {
875 dr->setDiagramSettings( ds );
876 renderer = dr;
877 }
878 else
879 {
881 dr->setLowerValue( 0.0 );
882 dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
883 dr->setUpperValue( mMaxValueSpinBox->value() );
884 dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
885
886 bool isExpression;
887 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
888 dr->setClassificationAttributeIsExpression( isExpression );
889 if ( isExpression )
890 {
891 dr->setClassificationAttributeExpression( sizeFieldNameOrExp );
892 }
893 else
894 {
895 dr->setClassificationField( sizeFieldNameOrExp );
896 }
897 dr->setDiagramSettings( ds );
898
899 dr->setDataDefinedSizeLegend( mSizeLegend ? new QgsDataDefinedSizeLegend( *mSizeLegend ) : nullptr );
900
901 renderer = dr;
902 }
903 renderer->setDiagram( diagram.release() );
904 renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
905 mLayer->setDiagramRenderer( renderer );
906
908 dls.setDataDefinedProperties( mDataDefinedProperties );
909 dls.setDistance( mDiagramDistanceSpinBox->value() );
910 dls.setPriority( mPrioritySlider->value() );
911 dls.setZIndex( mZIndexSpinBox->value() );
912 dls.setShowAllDiagrams( mShowAllCheckBox->isChecked() );
913
914 QWidget *curWdgt = stackedPlacement->currentWidget();
915 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
916 || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
917 {
919 }
920 else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() )
921 || ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
922 {
924 }
925 else if ( ( curWdgt == pageLine && radAroundLine->isChecked() )
926 || ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
927 {
929 }
930 else if ( ( curWdgt == pageLine && radOverLine->isChecked() )
931 || ( curWdgt == pagePolygon && radInsidePolygon->isChecked() ) )
932 {
934 }
935 else
936 {
937 qFatal( "Invalid settings" );
938 }
939
940 QgsDiagramLayerSettings::LinePlacementFlags flags = QgsDiagramLayerSettings::LinePlacementFlags();
941 if ( chkLineAbove->isChecked() )
943 if ( chkLineBelow->isChecked() )
945 if ( chkLineOn->isChecked() )
947 if ( ! chkLineOrientationDependent->isChecked() )
949 dls.setLinePlacementFlags( flags );
950
951 mLayer->setDiagramLayerSettings( dls );
952
953 // refresh
955 mLayer->triggerRepaint();
956}
957
958QString QgsDiagramProperties::showExpressionBuilder( const QString &initialExpression )
959{
960 QgsExpressionContext context;
966
967 QgsExpressionBuilderDialog dlg( mLayer, initialExpression, this, QStringLiteral( "generic" ), context );
968 dlg.setWindowTitle( tr( "Expression Based Attribute" ) );
969
970 QgsDistanceArea myDa;
972 myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
973 dlg.setGeomCalculator( myDa );
974
975 if ( dlg.exec() == QDialog::Accepted )
976 {
977 return dlg.expressionText();
978 }
979 else
980 {
981 return QString();
982 }
983}
984
986{
987 QString expression;
988 QList<QTreeWidgetItem *> selections = mAttributesTreeWidget->selectedItems();
989 if ( !selections.empty() )
990 {
991 expression = selections[0]->text( 0 );
992 }
993
994 const QString newExpression = showExpressionBuilder( expression );
995
996 //Only add the expression if the user has entered some text.
997 if ( !newExpression.isEmpty() )
998 {
999 QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1000
1001 newItem->setText( 0, newExpression );
1002 newItem->setText( 2, newExpression );
1003 newItem->setData( 0, RoleAttributeExpression, newExpression );
1004 newItem->setFlags( ( newItem->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled );
1005
1006 //set initial color for diagram category
1007 QRandomGenerator colorGenerator;
1008 const int red = colorGenerator.bounded( 1, 256 );
1009 const int green = colorGenerator.bounded( 1, 256 );
1010 const int blue = colorGenerator.bounded( 1, 256 );
1011
1012 const QColor randomColor( red, green, blue );
1013 newItem->setData( ColumnColor, Qt::EditRole, randomColor );
1014 mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
1015 }
1016 activateWindow(); // set focus back parent
1017}
1018
1020{
1021 mDiagramOptionsListWidget->blockSignals( true );
1022 mDiagramOptionsListWidget->setCurrentRow( index );
1023 mDiagramOptionsListWidget->blockSignals( false );
1024}
1025
1027{
1028 QWidget *curWdgt = stackedPlacement->currentWidget();
1029
1030 if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
1031 || ( curWdgt == pageLine && radAroundLine->isChecked() )
1032 || ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
1033 {
1034 mDiagramDistanceLabel->setEnabled( true );
1035 mDiagramDistanceSpinBox->setEnabled( true );
1036 mDistanceDDBtn->setEnabled( true );
1037 }
1038 else
1039 {
1040 mDiagramDistanceLabel->setEnabled( false );
1041 mDiagramDistanceSpinBox->setEnabled( false );
1042 mDistanceDDBtn->setEnabled( false );
1043 }
1044
1045 const bool linePlacementEnabled = mLayer->geometryType() == QgsWkbTypes::LineGeometry && ( curWdgt == pageLine && radAroundLine->isChecked() );
1046 chkLineAbove->setEnabled( linePlacementEnabled );
1047 chkLineBelow->setEnabled( linePlacementEnabled );
1048 chkLineOn->setEnabled( linePlacementEnabled );
1049 chkLineOrientationDependent->setEnabled( linePlacementEnabled );
1050}
1051
1053{
1054 mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
1055}
1056
1058{
1059 // prepare size transformer
1060 bool isExpression;
1061 const QString sizeFieldNameOrExp = mSizeFieldExpressionWidget->currentField( &isExpression );
1062 QgsProperty ddSize = isExpression ? QgsProperty::fromExpression( sizeFieldNameOrExp ) : QgsProperty::fromField( sizeFieldNameOrExp );
1063 const bool scaleByArea = mScaleDependencyComboBox->currentData().toBool();
1065 0.0, mMaxValueSpinBox->value(), 0.0, mSizeSpinBox->value() ) );
1066
1067 QgsDataDefinedSizeLegendWidget *panel = new QgsDataDefinedSizeLegendWidget( mSizeLegend.get(), ddSize, nullptr, mMapCanvas );
1068
1069 QDialog dlg;
1070 dlg.setLayout( new QVBoxLayout() );
1071 dlg.setWindowTitle( panel->panelTitle() );
1072 dlg.layout()->addWidget( panel );
1073 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
1074 connect( buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
1075 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsDiagramProperties::showHelp );
1076 connect( buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
1077 dlg.layout()->addWidget( buttonBox );
1078 if ( dlg.exec() )
1079 mSizeLegend.reset( panel->dataDefinedSizeLegend() );
1080}
1081
1082void QgsDiagramProperties::showHelp()
1083{
1084 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#legend" ) );
1085}
1086
1087void QgsDiagramProperties::createAuxiliaryField()
1088{
1089 // try to create an auxiliary layer if not yet created
1090 if ( !mLayer->auxiliaryLayer() )
1091 {
1092 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
1093 dlg.exec();
1094 }
1095
1096 // return if still not exists
1097 if ( !mLayer->auxiliaryLayer() )
1098 return;
1099
1100 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1103
1104 // create property in auxiliary storage if necessary
1105 if ( !mLayer->auxiliaryLayer()->exists( def ) )
1106 mLayer->auxiliaryLayer()->addAuxiliaryField( def );
1107
1108 // update property with join field name from auxiliary storage
1109 QgsProperty property = button->toProperty();
1110 property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
1111 property.setActive( true );
1112 button->updateFieldLists();
1113 button->setToProperty( property );
1114 mDataDefinedProperties.setProperty( key, button->toProperty() );
1115
1116 emit auxiliaryFieldCreated();
1117}
@ Line
Line symbol.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:2861
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.
bool addAuxiliaryField(const QgsPropertyDefinition &definition)
Adds an auxiliary field for the given property.
bool exists(const QgsPropertyDefinition &definition) const
Returns true if the property is stored in the layer already, false otherwise.
A delegate for showing a color swatch in a list.
Widget for configuration of appearance of legend for marker symbols with data-defined size.
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration as set up in the dialog (may be nullptr). Ownership is passed to the caller.
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.
Property
Data definable properties.
@ StartAngle
Angle offset for pie diagram.
@ Distance
Distance to diagram from feature.
@ IsObstacle
Whether diagram features act as obstacles for other diagrams/labels.
@ PositionX
X-coordinate data defined diagram position.
@ Priority
Diagram priority (between 0 and 10)
@ AlwaysShow
Whether the diagram should always be shown, even if it overlaps other diagrams/labels.
@ Show
Whether to show the diagram.
@ ZIndex
Z-index for diagram ordering.
@ BackgroundColor
Diagram background color.
@ PositionY
Y-coordinate data defined diagram position.
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.
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 mDiagramAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
void mDiagramTypeComboBox_currentIndexChanged(int index)
void syncToLayer()
Updates the widget to reflect the layer's current diagram settings.
QgsDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)
void addAttribute(QTreeWidgetItem *item)
Adds an attribute from the list of available attributes to the assigned attributes with a random colo...
void mAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
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
void setAttributeLegend(bool enabled)
Sets whether the renderer will show legend items for diagram attributes.
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.
void setDiagram(QgsDiagram *d)
Stores the settings for rendering a single diagram.
QgsUnitTypes::RenderUnit sizeType
Diagram size unit.
void setDirection(Direction direction)
Sets the chart's angular direction.
DiagramOrientation
Orientation of histogram.
LabelPlacementMethod labelPlacementMethod
double opacity
Opacity, from 0 (transparent) to 1.0 (opaque)
QList< QString > categoryAttributes
QList< QString > categoryLabels
DiagramOrientation diagramOrientation
QgsMapUnitScale lineSizeScale
Line unit scale.
QList< QColor > categoryColors
double rotationOffset
Rotation offset, in degrees clockwise from horizontal.
QgsMapUnitScale sizeScale
Diagram size unit scale.
double minimumScale
The minimum map scale (i.e.
void setSpacing(double spacing)
Sets the spacing between diagram contents.
double maximumScale
The maximum map scale (i.e.
void setAxisLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol to use for rendering axis in diagrams.
QgsUnitTypes::RenderUnit lineSizeUnit
Line unit index.
void setSpacingMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the content spacing.
double minimumSize
Scale diagrams smaller than mMinimumSize to mMinimumSize.
Direction
Angular directions.
@ Counterclockwise
Counter-clockwise orientation.
@ Clockwise
Clockwise orientation.
void setShowAxis(bool showAxis)
Sets whether the diagram axis should be shown.
void setPaintEffect(QgsPaintEffect *effect)
Sets the paint effect to use while rendering diagrams.
void setSpacingUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the content spacing.
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.
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.
Class for 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)
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QString name
Definition: qgsfield.h:60
Container of fields for a vector layer.
Definition: qgsfields.h:45
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
@ ModeQFont
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:63
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:38
Dialog for configuring the labeling engine.
Widget for configuring the labeling engine.
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgslinesymbol.h:30
void setDiagramSettings(const QgsDiagramSettings &s)
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend.
QString classificationField() const
Returns the field name used for interpolating the diagram size.
void setClassificationAttributeExpression(const QString &expression)
void setClassificationField(const QString &field)
Sets the field name used for interpolating the diagram size.
void setClassificationAttributeIsExpression(bool isExpression)
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:90
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
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.
A dialog to create a new auxiliary layer.
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.
Base class for any widget that can be shown as a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
QString panelTitle()
The title of the panel.
void widgetChanged()
Emitted when the widget state changes.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:112
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:592
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition for a property.
Definition: qgsproperty.h:46
A button for controlling property overrides which may apply to a widget.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
void updateFieldLists()
Updates list of fields.
void changed()
Emitted when property definition changes.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout).
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
int propertyKey() const
Returns the property key linked to the button.
void setToProperty(const QgsProperty &property)
Sets the widget to reflect the current state of a QgsProperty.
void createAuxiliaryField()
Emitted when creating a new auxiliary field.
A store for object properties.
Definition: qgsproperty.h:230
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.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
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.
Renders the diagrams for all features with the same settings.
void setDiagramSettings(const QgsDiagramSettings &s)
QgsPropertyTransformer subclass for scaling a value into a size according to various scaling methods.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:240
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderInches
Inches.
Definition: qgsunittypes.h:174
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
Represents a vector layer which manages a vector based data sets.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
const QgsDiagramLayerSettings * diagramLayerSettings() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
void setDiagramRenderer(QgsDiagramRenderer *r)
Sets diagram rendering object (takes ownership)
const QgsDiagramRenderer * diagramRenderer() const
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
#define DIAGRAM_NAME_HISTOGRAM
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define DIAGRAM_NAME_PIE
Definition: qgspiediagram.h:18
#define DIAGRAM_NAME_STACKED
#define DIAGRAM_NAME_TEXT