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