QGIS API Documentation 3.99.0-Master (357b655ed83)
Loading...
Searching...
No Matches
qgsplotwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsplotwidget.cpp
3 -----------------
4 begin : August 2025
5 copyright : (C) 2025 by Mathieu Pellerin
6 email : mathieu dot opengis dot ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsplotwidget.h"
17
18#include "qgsapplication.h"
19#include "qgsbarchartplot.h"
20#include "qgscolorrampbutton.h"
22#include "qgsfillsymbol.h"
23#include "qgslinechartplot.h"
24#include "qgslinesymbol.h"
26#include "qgspiechartplot.h"
27#include "qgsplotregistry.h"
28
29#include <QString>
30
31#include "moc_qgsplotwidget.cpp"
32
33using namespace Qt::StringLiterals;
34
36{
37 mExpressionContextGenerator = generator;
38}
39
41{
43 if ( mExpressionContextGenerator )
44 {
45 context = mExpressionContextGenerator->createExpressionContext();
46 }
47 else
48 {
50 }
51
52 auto plotScope = std::make_unique<QgsExpressionContextScope>( u"plot"_s );
53 plotScope->addVariable( QgsExpressionContextScope::StaticVariable( u"plot_axis"_s, QString(), true ) );
54 plotScope->addVariable( QgsExpressionContextScope::StaticVariable( u"plot_axis_value"_s, 0.0, true ) );
55 context.appendScope( plotScope.release() );
56
57 auto chartScope = std::make_unique<QgsExpressionContextScope>( u"chart"_s );
58 chartScope->addVariable( QgsExpressionContextScope::StaticVariable( u"chart_category"_s, QString(), true ) );
59 chartScope->addVariable( QgsExpressionContextScope::StaticVariable( u"chart_value"_s, 0.0, true ) );
60 context.appendScope( chartScope.release() );
61
62 context.setHighlightedVariables( { u"plot_axis"_s, u"plot_axis_value"_s, u"chart_category"_s, u"chart_value"_s } );
63
64 return context;
65}
66
68{
69 button->blockSignals( true );
70 button->init( static_cast< int >( key ), mPropertyCollection, QgsPlot::propertyDefinitions(), nullptr );
71 connect( button, &QgsPropertyOverrideButton::changed, this, &QgsPlotWidget::updateProperty );
73 button->blockSignals( false );
74}
75
77{
78 if ( !button )
79 {
80 return;
81 }
82
83 if ( button->propertyKey() < 0 )
84 {
85 return;
86 }
87
88 const QgsPlot::DataDefinedProperty key = static_cast<QgsPlot::DataDefinedProperty>( button->propertyKey() );
89 whileBlocking( button )->setToProperty( mPropertyCollection.property( key ) );
90}
91
92void QgsPlotWidget::updateProperty()
93{
94 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
95 const QgsPlot::DataDefinedProperty key = static_cast<QgsPlot::DataDefinedProperty>( button->propertyKey() );
97 emit widgetChanged();
98}
99
100
102 : QgsPlotWidget( parent )
103{
104 setupUi( this );
105
106 setPanelTitle( tr( "Bar Chart Plot Properties" ) );
107
108 mSymbolsList->setColumnCount( 2 );
109 mSymbolsList->setSelectionBehavior( QAbstractItemView::SelectRows );
110 mSymbolsList->setSelectionMode( QAbstractItemView::ExtendedSelection );
111 mSymbolsList->setSortingEnabled( false );
112 mSymbolsList->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
113 mSymbolsList->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
114 mSymbolsList->horizontalHeader()->hide();
115 mSymbolsList->verticalHeader()->hide();
116
117 connect( mAddSymbolPushButton, &QPushButton::clicked, this, &QgsBarChartPlotWidget::mAddSymbolPushButton_clicked );
118 connect( mRemoveSymbolPushButton, &QPushButton::clicked, this, &QgsBarChartPlotWidget::mRemoveSymbolPushButton_clicked );
119
120 mSpinMinXAxis->setClearValue( 0 );
121 connect( mSpinMinXAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
122 if ( mBlockChanges )
123 return;
124 emit widgetChanged();
125 } );
126
127 connect( mSpinMaxXAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
128 if ( mBlockChanges )
129 return;
130 emit widgetChanged();
131 } );
132
133 mSpinMinYAxis->setClearValue( 0 );
134 connect( mSpinMinYAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
135 if ( mBlockChanges )
136 return;
137 emit widgetChanged();
138 } );
139
140 mSpinMaxYAxis->setClearValue( 0 );
141 connect( mSpinMaxYAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
142 if ( mBlockChanges )
143 return;
144 emit widgetChanged();
145 } );
146
147 mXAxisMajorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
148 connect( mXAxisMajorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
149 if ( mBlockChanges )
150 return;
151 emit widgetChanged();
152 } );
153 mXAxisMajorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMajorSymbol() );
154
155 mXAxisMinorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
156 connect( mXAxisMinorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
157 if ( mBlockChanges )
158 return;
159 emit widgetChanged();
160 } );
161 mXAxisMinorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMinorSymbol() );
162
163 connect( mXAxisMajorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
164 if ( mBlockChanges )
165 return;
166 emit widgetChanged();
167 } );
168
169 connect( mXAxisMinorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
170 if ( mBlockChanges )
171 return;
172 emit widgetChanged();
173 } );
174
175 connect( mXAxisLabelIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
176 if ( mBlockChanges )
177 return;
178 emit widgetChanged();
179 } );
180
181 mYAxisMajorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
182 connect( mYAxisMajorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
183 if ( mBlockChanges )
184 return;
185 emit widgetChanged();
186 } );
187 mYAxisMajorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMajorSymbol() );
188
189 mYAxisMinorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
190 connect( mYAxisMinorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
191 if ( mBlockChanges )
192 return;
193 emit widgetChanged();
194 } );
195 mYAxisMinorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMinorSymbol() );
196
197 connect( mYAxisLabelIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
198 if ( mBlockChanges )
199 return;
200 emit widgetChanged();
201 } );
202
203 connect( mYAxisMajorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
204 if ( mBlockChanges )
205 return;
206 emit widgetChanged();
207 } );
208
209 connect( mYAxisMinorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
210 if ( mBlockChanges )
211 return;
212 emit widgetChanged();
213 } );
214
215 mChartBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
216 connect( mChartBackgroundSymbolButton, &QgsSymbolButton::changed, this, [this] {
217 if ( mBlockChanges )
218 return;
219 emit widgetChanged();
220 } );
221 mChartBackgroundSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::chartBackgroundSymbol() );
222
223 mChartBorderSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
224 connect( mChartBorderSymbolButton, &QgsSymbolButton::changed, this, [this] {
225 if ( mBlockChanges )
226 return;
227 emit widgetChanged();
228 } );
229 mChartBorderSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::chartBorderSymbol() );
230
231 connect( mXAxisLabelFormatButton, &QPushButton::clicked, this, [this] {
233 widget->setPanelTitle( tr( "X Axis Number Format" ) );
234 widget->setFormat( mXAxisNumericFormat.get() );
235 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
236 mXAxisNumericFormat.reset( widget->format() );
237 emit widgetChanged();
238 } );
239 openPanel( widget );
240 } );
241
242 connect( mYAxisLabelFormatButton, &QPushButton::clicked, this, [this] {
244 widget->setPanelTitle( tr( "Y Axis Number Format" ) );
245 widget->setFormat( mYAxisNumericFormat.get() );
246 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
247 mYAxisNumericFormat.reset( widget->format() );
248 emit widgetChanged();
249 } );
250 openPanel( widget );
251 } );
252
253 mXAxisLabelFontButton->setDialogTitle( tr( "X Axis Label Font" ) );
254 mYAxisLabelFontButton->setDialogTitle( tr( "Y Axis Label Font" ) );
255 mXAxisLabelFontButton->setMode( QgsFontButton::ModeTextRenderer );
256 mYAxisLabelFontButton->setMode( QgsFontButton::ModeTextRenderer );
257
258 connect( mXAxisLabelFontButton, &QgsFontButton::changed, this, [this] {
259 if ( mBlockChanges )
260 return;
261 emit widgetChanged();
262 } );
263
264 connect( mYAxisLabelFontButton, &QgsFontButton::changed, this, [this] {
265 if ( mBlockChanges )
266 return;
267 emit widgetChanged();
268 } );
269
270 mSpinLeftMargin->setClearValue( 0 );
271 connect( mSpinLeftMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
272 if ( mBlockChanges )
273 return;
274 emit widgetChanged();
275 } );
276
277 mSpinRightMargin->setClearValue( 0 );
278 connect( mSpinRightMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
279 if ( mBlockChanges )
280 return;
281 emit widgetChanged();
282 } );
283
284 mSpinTopMargin->setClearValue( 0 );
285 connect( mSpinTopMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
286 if ( mBlockChanges )
287 return;
288 emit widgetChanged();
289 } );
290
291 mSpinBottomMargin->setClearValue( 0 );
292 connect( mSpinBottomMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
293 if ( mBlockChanges )
294 return;
295 emit widgetChanged();
296 } );
297
298 mXAxisTypeCombo->addItem( tr( "Interval" ), QVariant::fromValue( Qgis::PlotAxisType::Interval ) );
299 mXAxisTypeCombo->addItem( tr( "Categorical" ), QVariant::fromValue( Qgis::PlotAxisType::Categorical ) );
300 connect( mXAxisTypeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
301 if ( mBlockChanges )
302 return;
303 emit widgetChanged();
304 } );
305
306 mXAxisLabelsCombo->addItem( tr( "None" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::NoLabels ) );
307 mXAxisLabelsCombo->addItem( tr( "Every Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::EveryLabel ) );
308 mXAxisLabelsCombo->addItem( tr( "First Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstLabel ) );
309 mXAxisLabelsCombo->addItem( tr( "Last Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::LastLabel ) );
310 mXAxisLabelsCombo->addItem( tr( "First and Last Values" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstAndLastLabels ) );
311 connect( mXAxisLabelsCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
312 if ( mBlockChanges )
313 return;
314 emit widgetChanged();
315 } );
316
317 mXAxisMajorLinesSymbolButton->registerExpressionContextGenerator( this );
318 mXAxisMinorLinesSymbolButton->registerExpressionContextGenerator( this );
319 mXAxisLabelFontButton->registerExpressionContextGenerator( this );
320 mYAxisMajorLinesSymbolButton->registerExpressionContextGenerator( this );
321 mYAxisMinorLinesSymbolButton->registerExpressionContextGenerator( this );
322 mYAxisLabelFontButton->registerExpressionContextGenerator( this );
323 mChartBackgroundSymbolButton->registerExpressionContextGenerator( this );
324 mChartBorderSymbolButton->registerExpressionContextGenerator( this );
325
330
337
342}
343
344void QgsBarChartPlotWidget::mAddSymbolPushButton_clicked()
345{
346 const int row = mSymbolsList->rowCount();
347 mSymbolsList->insertRow( row );
348
349 QTableWidgetItem *item = new QTableWidgetItem();
350 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
351 mSymbolsList->setItem( row, 0, item );
352
353 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
354 symbolButton->setSymbolType( Qgis::SymbolType::Fill );
355 symbolButton->setShowNull( true );
357 symbolButton->registerExpressionContextGenerator( this );
358 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
359 if ( mBlockChanges )
360 return;
361 emit widgetChanged();
362 } );
363 mSymbolsList->setCellWidget( row, 1, symbolButton );
364
365 emit widgetChanged();
366}
367
368void QgsBarChartPlotWidget::mRemoveSymbolPushButton_clicked()
369{
370 QTableWidgetItem *item = mSymbolsList->currentItem();
371 if ( !item )
372 {
373 return;
374 }
375
376 mSymbolsList->removeRow( mSymbolsList->row( item ) );
377
378 emit widgetChanged();
379}
380
382{
383 QgsBarChartPlot *chartPlot = dynamic_cast<QgsBarChartPlot *>( plot );
384 if ( !chartPlot )
385 {
386 return;
387 }
388
389 mBlockChanges++;
390
391 mSymbolsList->clear();
392 const int symbolCount = chartPlot->fillSymbolCount();
393 for ( int i = 0; i < symbolCount; i++ )
394 {
395 const int row = mSymbolsList->rowCount();
396 mSymbolsList->insertRow( row );
397
398 QTableWidgetItem *item = new QTableWidgetItem();
399 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
400 mSymbolsList->setItem( row, 0, item );
401
402 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
403 symbolButton->setSymbolType( Qgis::SymbolType::Fill );
404 symbolButton->setShowNull( true );
405 symbolButton->setSymbol( chartPlot->fillSymbolAt( i )->clone() );
406 symbolButton->registerExpressionContextGenerator( this );
407 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
408 if ( mBlockChanges )
409 return;
410 emit widgetChanged();
411 } );
412 mSymbolsList->setCellWidget( row, 1, symbolButton );
413 }
414
415 mSpinMinXAxis->setValue( chartPlot->xMinimum() );
416 mSpinMaxXAxis->setValue( chartPlot->xMaximum() );
417 mSpinMinYAxis->setValue( chartPlot->yMinimum() );
418 mSpinMaxYAxis->setValue( chartPlot->yMaximum() );
419
420 if ( chartPlot->xAxis().gridMajorSymbol() )
421 mXAxisMajorLinesSymbolButton->setSymbol( chartPlot->xAxis().gridMajorSymbol()->clone() );
422 if ( chartPlot->xAxis().gridMinorSymbol() )
423 mXAxisMinorLinesSymbolButton->setSymbol( chartPlot->xAxis().gridMinorSymbol()->clone() );
424 if ( chartPlot->yAxis().gridMajorSymbol() )
425 mYAxisMajorLinesSymbolButton->setSymbol( chartPlot->yAxis().gridMajorSymbol()->clone() );
426 if ( chartPlot->yAxis().gridMinorSymbol() )
427 mYAxisMinorLinesSymbolButton->setSymbol( chartPlot->yAxis().gridMinorSymbol()->clone() );
428
429 mXAxisLabelFontButton->setTextFormat( chartPlot->xAxis().textFormat() );
430 mXAxisNumericFormat.reset( chartPlot->xAxis().numericFormat()->clone() );
431 mYAxisLabelFontButton->setTextFormat( chartPlot->yAxis().textFormat() );
432 mYAxisNumericFormat.reset( chartPlot->yAxis().numericFormat()->clone() );
433
434 mXAxisTypeCombo->setCurrentIndex( mXAxisTypeCombo->findData( QVariant::fromValue( chartPlot->xAxis().type() ) ) );
435 mXAxisLabelsCombo->setCurrentIndex( mXAxisLabelsCombo->findData( QVariant::fromValue( chartPlot->xAxis().labelSuffixPlacement() ) ) );
436
437 mXAxisMajorIntervalSpin->setValue( chartPlot->xAxis().gridIntervalMajor() );
438 mXAxisMinorIntervalSpin->setValue( chartPlot->xAxis().gridIntervalMinor() );
439 mXAxisLabelIntervalSpin->setValue( chartPlot->xAxis().labelInterval() );
440
441 mYAxisMajorIntervalSpin->setValue( chartPlot->yAxis().gridIntervalMajor() );
442 mYAxisMinorIntervalSpin->setValue( chartPlot->yAxis().gridIntervalMinor() );
443 mYAxisLabelIntervalSpin->setValue( chartPlot->yAxis().labelInterval() );
444
445 if ( chartPlot->chartBackgroundSymbol() )
446 mChartBackgroundSymbolButton->setSymbol( chartPlot->chartBackgroundSymbol()->clone() );
447 if ( chartPlot->chartBorderSymbol() )
448 mChartBorderSymbolButton->setSymbol( chartPlot->chartBorderSymbol()->clone() );
449
450 mSpinLeftMargin->setValue( chartPlot->margins().left() );
451 mSpinRightMargin->setValue( chartPlot->margins().right() );
452 mSpinTopMargin->setValue( chartPlot->margins().top() );
453 mSpinBottomMargin->setValue( chartPlot->margins().bottom() );
454
456
457 updateDataDefinedButton( mDDBtnMinXAxis );
458 updateDataDefinedButton( mDDBtnMaxXAxis );
459 updateDataDefinedButton( mDDBtnMinYAxis );
460 updateDataDefinedButton( mDDBtnMaxYAxis );
461
462 updateDataDefinedButton( mDDBtnXAxisMajorInterval );
463 updateDataDefinedButton( mDDBtnXAxisMinorInterval );
464 updateDataDefinedButton( mDDBtnXAxisLabelInterval );
465 updateDataDefinedButton( mDDBtnYAxisMajorInterval );
466 updateDataDefinedButton( mDDBtnYAxisMinorInterval );
467 updateDataDefinedButton( mDDBtnYAxisLabelInterval );
468
469 updateDataDefinedButton( mDDBtnLeftMargin );
470 updateDataDefinedButton( mDDBtnRightMargin );
471 updateDataDefinedButton( mDDBtnTopMargin );
472 updateDataDefinedButton( mDDBtnBottomMargin );
473
474 mBlockChanges--;
475}
476
477
479{
480 QgsPlot *plot = QgsApplication::plotRegistry()->createPlot( u"bar"_s );
481 QgsBarChartPlot *chartPlot = dynamic_cast<QgsBarChartPlot *>( plot );
482 if ( !chartPlot )
483 {
484 return nullptr;
485 }
486
487 const int rowCount = mSymbolsList->rowCount();
488 for ( int i = 0; i < rowCount; i++ )
489 {
490 QgsSymbolButton *symbolButton = dynamic_cast<QgsSymbolButton *>( mSymbolsList->cellWidget( i, 1 ) );
491 if ( symbolButton )
492 {
493 chartPlot->setFillSymbolAt( i, symbolButton->clonedSymbol<QgsFillSymbol>() );
494 }
495 }
496
497 chartPlot->setXMinimum( mSpinMinXAxis->value() );
498 chartPlot->setXMaximum( mSpinMaxXAxis->value() );
499 chartPlot->setYMinimum( mSpinMinYAxis->value() );
500 chartPlot->setYMaximum( mSpinMaxYAxis->value() );
501
502 chartPlot->xAxis().setGridMajorSymbol( mXAxisMajorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
503 chartPlot->xAxis().setGridMinorSymbol( mXAxisMinorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
504 chartPlot->yAxis().setGridMajorSymbol( mYAxisMajorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
505 chartPlot->yAxis().setGridMinorSymbol( mYAxisMinorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
506
507 chartPlot->xAxis().setTextFormat( mXAxisLabelFontButton->textFormat() );
508 chartPlot->xAxis().setNumericFormat( mXAxisNumericFormat.get()->clone() );
509 chartPlot->yAxis().setTextFormat( mYAxisLabelFontButton->textFormat() );
510 chartPlot->yAxis().setNumericFormat( mYAxisNumericFormat.get()->clone() );
511
512 chartPlot->xAxis().setType( mXAxisTypeCombo->currentData().value<Qgis::PlotAxisType>() );
513 chartPlot->xAxis().setLabelSuffixPlacement( mXAxisLabelsCombo->currentData().value<Qgis::PlotAxisSuffixPlacement>() );
514
515 chartPlot->xAxis().setGridIntervalMajor( mXAxisMajorIntervalSpin->value() );
516 chartPlot->xAxis().setGridIntervalMinor( mXAxisMinorIntervalSpin->value() );
517 chartPlot->xAxis().setLabelInterval( mXAxisLabelIntervalSpin->value() );
518
519 chartPlot->yAxis().setGridIntervalMajor( mYAxisMajorIntervalSpin->value() );
520 chartPlot->yAxis().setGridIntervalMinor( mYAxisMinorIntervalSpin->value() );
521 chartPlot->yAxis().setLabelInterval( mYAxisLabelIntervalSpin->value() );
522
523 chartPlot->setChartBackgroundSymbol( mChartBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
524 chartPlot->setChartBorderSymbol( mChartBorderSymbolButton->clonedSymbol<QgsFillSymbol>() );
525
526 QgsMargins margins;
527 margins.setLeft( mSpinLeftMargin->value() );
528 margins.setRight( mSpinRightMargin->value() );
529 margins.setTop( mSpinTopMargin->value() );
530 margins.setBottom( mSpinBottomMargin->value() );
531 chartPlot->setMargins( margins );
532
534
535 return plot;
536}
537
538
540 : QgsPlotWidget( parent )
541{
542 setupUi( this );
543
544 setPanelTitle( tr( "Line Chart Plot Properties" ) );
545
546 mSymbolsList->setColumnCount( 3 );
547 mSymbolsList->setSelectionBehavior( QAbstractItemView::SelectRows );
548 mSymbolsList->setSelectionMode( QAbstractItemView::ExtendedSelection );
549 mSymbolsList->setSortingEnabled( false );
550 mSymbolsList->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
551 mSymbolsList->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
552 mSymbolsList->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::Stretch );
553 mSymbolsList->horizontalHeader()->hide();
554 mSymbolsList->verticalHeader()->hide();
555
556 connect( mAddSymbolPushButton, &QPushButton::clicked, this, &QgsLineChartPlotWidget::mAddSymbolPushButton_clicked );
557 connect( mRemoveSymbolPushButton, &QPushButton::clicked, this, &QgsLineChartPlotWidget::mRemoveSymbolPushButton_clicked );
558
559 mSpinMinXAxis->setClearValue( 0 );
560 connect( mSpinMinXAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
561 if ( mBlockChanges )
562 return;
563 emit widgetChanged();
564 } );
565
566 connect( mSpinMaxXAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
567 if ( mBlockChanges )
568 return;
569 emit widgetChanged();
570 } );
571
572 mSpinMinYAxis->setClearValue( 0 );
573 connect( mSpinMinYAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
574 if ( mBlockChanges )
575 return;
576 emit widgetChanged();
577 } );
578
579 mSpinMaxYAxis->setClearValue( 0 );
580 connect( mSpinMaxYAxis, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
581 if ( mBlockChanges )
582 return;
583 emit widgetChanged();
584 } );
585
586 mXAxisMajorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
587 connect( mXAxisMajorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
588 if ( mBlockChanges )
589 return;
590 emit widgetChanged();
591 } );
592 mXAxisMajorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMajorSymbol() );
593
594 mXAxisMinorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
595 connect( mXAxisMinorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
596 if ( mBlockChanges )
597 return;
598 emit widgetChanged();
599 } );
600 mXAxisMinorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMinorSymbol() );
601
602 connect( mXAxisMajorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
603 if ( mBlockChanges )
604 return;
605 emit widgetChanged();
606 } );
607
608 connect( mXAxisMinorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
609 if ( mBlockChanges )
610 return;
611 emit widgetChanged();
612 } );
613
614 connect( mXAxisLabelIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
615 if ( mBlockChanges )
616 return;
617 emit widgetChanged();
618 } );
619
620 mYAxisMajorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
621 connect( mYAxisMajorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
622 if ( mBlockChanges )
623 return;
624 emit widgetChanged();
625 } );
626 mYAxisMajorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMajorSymbol() );
627
628 mYAxisMinorLinesSymbolButton->setSymbolType( Qgis::SymbolType::Line );
629 connect( mYAxisMinorLinesSymbolButton, &QgsSymbolButton::changed, this, [this] {
630 if ( mBlockChanges )
631 return;
632 emit widgetChanged();
633 } );
634 mYAxisMinorLinesSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::axisGridMinorSymbol() );
635
636 connect( mYAxisLabelIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
637 if ( mBlockChanges )
638 return;
639 emit widgetChanged();
640 } );
641
642 connect( mYAxisMajorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
643 if ( mBlockChanges )
644 return;
645 emit widgetChanged();
646 } );
647
648 connect( mYAxisMinorIntervalSpin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
649 if ( mBlockChanges )
650 return;
651 emit widgetChanged();
652 } );
653
654 mChartBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
655 connect( mChartBackgroundSymbolButton, &QgsSymbolButton::changed, this, [this] {
656 if ( mBlockChanges )
657 return;
658 emit widgetChanged();
659 } );
660 mChartBackgroundSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::chartBackgroundSymbol() );
661
662 mChartBorderSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
663 connect( mChartBorderSymbolButton, &QgsSymbolButton::changed, this, [this] {
664 if ( mBlockChanges )
665 return;
666 emit widgetChanged();
667 } );
668 mChartBorderSymbolButton->setDefaultSymbol( QgsPlotDefaultSettings::chartBorderSymbol() );
669
670 connect( mXAxisLabelFormatButton, &QPushButton::clicked, this, [this] {
672 widget->setPanelTitle( tr( "X Axis Number Format" ) );
673 widget->setFormat( mXAxisNumericFormat.get() );
674 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
675 mXAxisNumericFormat.reset( widget->format() );
676 emit widgetChanged();
677 } );
678 openPanel( widget );
679 } );
680
681 connect( mYAxisLabelFormatButton, &QPushButton::clicked, this, [this] {
683 widget->setPanelTitle( tr( "Y Axis Number Format" ) );
684 widget->setFormat( mYAxisNumericFormat.get() );
685 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
686 mYAxisNumericFormat.reset( widget->format() );
687 emit widgetChanged();
688 } );
689 openPanel( widget );
690 } );
691
692 mXAxisLabelFontButton->setDialogTitle( tr( "X Axis Label Font" ) );
693 mYAxisLabelFontButton->setDialogTitle( tr( "Y Axis Label Font" ) );
694 mXAxisLabelFontButton->setMode( QgsFontButton::ModeTextRenderer );
695 mYAxisLabelFontButton->setMode( QgsFontButton::ModeTextRenderer );
696
697 connect( mXAxisLabelFontButton, &QgsFontButton::changed, this, [this] {
698 if ( mBlockChanges )
699 return;
700 emit widgetChanged();
701 } );
702
703 connect( mYAxisLabelFontButton, &QgsFontButton::changed, this, [this] {
704 if ( mBlockChanges )
705 return;
706 emit widgetChanged();
707 } );
708
709 mSpinLeftMargin->setClearValue( 0 );
710 connect( mSpinLeftMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
711 if ( mBlockChanges )
712 return;
713 emit widgetChanged();
714 } );
715
716 mSpinRightMargin->setClearValue( 0 );
717 connect( mSpinRightMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
718 if ( mBlockChanges )
719 return;
720 emit widgetChanged();
721 } );
722
723 mSpinTopMargin->setClearValue( 0 );
724 connect( mSpinTopMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
725 if ( mBlockChanges )
726 return;
727 emit widgetChanged();
728 } );
729
730 mSpinBottomMargin->setClearValue( 0 );
731 connect( mSpinBottomMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
732 if ( mBlockChanges )
733 return;
734 emit widgetChanged();
735 } );
736
737 mXAxisTypeCombo->addItem( tr( "Interval" ), QVariant::fromValue( Qgis::PlotAxisType::Interval ) );
738 mXAxisTypeCombo->addItem( tr( "Categorical" ), QVariant::fromValue( Qgis::PlotAxisType::Categorical ) );
739 connect( mXAxisTypeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
740 if ( mBlockChanges )
741 return;
742 emit widgetChanged();
743 } );
744
745 mXAxisLabelsCombo->addItem( tr( "None" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::NoLabels ) );
746 mXAxisLabelsCombo->addItem( tr( "Every Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::EveryLabel ) );
747 mXAxisLabelsCombo->addItem( tr( "First Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstLabel ) );
748 mXAxisLabelsCombo->addItem( tr( "Last Value" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::LastLabel ) );
749 mXAxisLabelsCombo->addItem( tr( "First and Last Values" ), QVariant::fromValue( Qgis::PlotAxisSuffixPlacement::FirstAndLastLabels ) );
750 connect( mXAxisLabelsCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
751 if ( mBlockChanges )
752 return;
753 emit widgetChanged();
754 } );
755
756 mXAxisMajorLinesSymbolButton->registerExpressionContextGenerator( this );
757 mXAxisMinorLinesSymbolButton->registerExpressionContextGenerator( this );
758 mXAxisLabelFontButton->registerExpressionContextGenerator( this );
759 mYAxisMajorLinesSymbolButton->registerExpressionContextGenerator( this );
760 mYAxisMinorLinesSymbolButton->registerExpressionContextGenerator( this );
761 mYAxisLabelFontButton->registerExpressionContextGenerator( this );
762 mChartBackgroundSymbolButton->registerExpressionContextGenerator( this );
763 mChartBorderSymbolButton->registerExpressionContextGenerator( this );
764
769
776
781}
782
783void QgsLineChartPlotWidget::mAddSymbolPushButton_clicked()
784{
785 const int row = mSymbolsList->rowCount();
786 mSymbolsList->insertRow( row );
787
788 QTableWidgetItem *item = new QTableWidgetItem();
789 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
790 mSymbolsList->setItem( row, 0, item );
791
792 // Line
793 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
794 symbolButton->setSymbolType( Qgis::SymbolType::Line );
795 symbolButton->setShowNull( true );
797 symbolButton->registerExpressionContextGenerator( this );
798 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
799 if ( mBlockChanges )
800 return;
801 emit widgetChanged();
802 } );
803 mSymbolsList->setCellWidget( row, 1, symbolButton );
804
805 // Marker
806 symbolButton = new QgsSymbolButton( this );
807 symbolButton->setFixedSizeConstraints( false );
809 symbolButton->setShowNull( true );
811 symbolButton->registerExpressionContextGenerator( this );
812 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
813 if ( mBlockChanges )
814 return;
815 emit widgetChanged();
816 } );
817 mSymbolsList->setCellWidget( row, 2, symbolButton );
818
819 emit widgetChanged();
820}
821
822void QgsLineChartPlotWidget::mRemoveSymbolPushButton_clicked()
823{
824 QTableWidgetItem *item = mSymbolsList->currentItem();
825 if ( !item )
826 {
827 return;
828 }
829
830 mSymbolsList->removeRow( mSymbolsList->row( item ) );
831
832 emit widgetChanged();
833}
834
836{
837 QgsLineChartPlot *chartPlot = dynamic_cast<QgsLineChartPlot *>( plot );
838 if ( !chartPlot )
839 {
840 return;
841 }
842
843 mBlockChanges++;
844
845 mSymbolsList->clear();
846 const int symbolCount = std::max( chartPlot->markerSymbolCount(), chartPlot->lineSymbolCount() );
847 for ( int i = 0; i < symbolCount; i++ )
848 {
849 const int row = mSymbolsList->rowCount();
850 mSymbolsList->insertRow( row );
851
852 QTableWidgetItem *item = new QTableWidgetItem();
853 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
854 mSymbolsList->setItem( row, 0, item );
855
856 // Line
857 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
858 symbolButton->setSymbolType( Qgis::SymbolType::Line );
859 symbolButton->setShowNull( true );
860 symbolButton->setSymbol( i < chartPlot->lineSymbolCount() ? chartPlot->lineSymbolAt( i )->clone() : nullptr );
861 symbolButton->registerExpressionContextGenerator( this );
862 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
863 if ( mBlockChanges )
864 return;
865 emit widgetChanged();
866 } );
867 mSymbolsList->setCellWidget( row, 1, symbolButton );
868
869 // Marker
870 symbolButton = new QgsSymbolButton( this );
871 symbolButton->setFixedSizeConstraints( false );
873 symbolButton->setShowNull( true );
874 symbolButton->setSymbol( i < chartPlot->markerSymbolCount() ? chartPlot->markerSymbolAt( i )->clone() : nullptr );
875 symbolButton->registerExpressionContextGenerator( this );
876 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
877 if ( mBlockChanges )
878 return;
879 emit widgetChanged();
880 } );
881 mSymbolsList->setCellWidget( row, 2, symbolButton );
882 }
883
884 mSpinMinXAxis->setValue( chartPlot->xMinimum() );
885 mSpinMaxXAxis->setValue( chartPlot->xMaximum() );
886 mSpinMinYAxis->setValue( chartPlot->yMinimum() );
887 mSpinMaxYAxis->setValue( chartPlot->yMaximum() );
888
889 if ( chartPlot->xAxis().gridMajorSymbol() )
890 mXAxisMajorLinesSymbolButton->setSymbol( chartPlot->xAxis().gridMajorSymbol()->clone() );
891 if ( chartPlot->xAxis().gridMinorSymbol() )
892 mXAxisMinorLinesSymbolButton->setSymbol( chartPlot->xAxis().gridMinorSymbol()->clone() );
893 if ( chartPlot->yAxis().gridMajorSymbol() )
894 mYAxisMajorLinesSymbolButton->setSymbol( chartPlot->yAxis().gridMajorSymbol()->clone() );
895 if ( chartPlot->yAxis().gridMinorSymbol() )
896 mYAxisMinorLinesSymbolButton->setSymbol( chartPlot->yAxis().gridMinorSymbol()->clone() );
897
898 mXAxisLabelFontButton->setTextFormat( chartPlot->xAxis().textFormat() );
899 mYAxisLabelFontButton->setTextFormat( chartPlot->yAxis().textFormat() );
900
901 mXAxisTypeCombo->setCurrentIndex( mXAxisTypeCombo->findData( QVariant::fromValue( chartPlot->xAxis().type() ) ) );
902 mXAxisLabelsCombo->setCurrentIndex( mXAxisLabelsCombo->findData( QVariant::fromValue( chartPlot->xAxis().labelSuffixPlacement() ) ) );
903
904 mXAxisMajorIntervalSpin->setValue( chartPlot->xAxis().gridIntervalMajor() );
905 mXAxisMinorIntervalSpin->setValue( chartPlot->xAxis().gridIntervalMinor() );
906 mXAxisLabelIntervalSpin->setValue( chartPlot->xAxis().labelInterval() );
907
908 mYAxisMajorIntervalSpin->setValue( chartPlot->yAxis().gridIntervalMajor() );
909 mYAxisMinorIntervalSpin->setValue( chartPlot->yAxis().gridIntervalMinor() );
910 mYAxisLabelIntervalSpin->setValue( chartPlot->yAxis().labelInterval() );
911
912 if ( chartPlot->chartBackgroundSymbol() )
913 mChartBackgroundSymbolButton->setSymbol( chartPlot->chartBackgroundSymbol()->clone() );
914 if ( chartPlot->chartBorderSymbol() )
915 mChartBorderSymbolButton->setSymbol( chartPlot->chartBorderSymbol()->clone() );
916
917 mSpinLeftMargin->setValue( chartPlot->margins().left() );
918 mSpinRightMargin->setValue( chartPlot->margins().right() );
919 mSpinTopMargin->setValue( chartPlot->margins().top() );
920 mSpinBottomMargin->setValue( chartPlot->margins().bottom() );
921
923
924 updateDataDefinedButton( mDDBtnMinXAxis );
925 updateDataDefinedButton( mDDBtnMaxXAxis );
926 updateDataDefinedButton( mDDBtnMinYAxis );
927 updateDataDefinedButton( mDDBtnMaxYAxis );
928
929 updateDataDefinedButton( mDDBtnXAxisMajorInterval );
930 updateDataDefinedButton( mDDBtnXAxisMinorInterval );
931 updateDataDefinedButton( mDDBtnXAxisLabelInterval );
932 updateDataDefinedButton( mDDBtnYAxisMajorInterval );
933 updateDataDefinedButton( mDDBtnYAxisMinorInterval );
934 updateDataDefinedButton( mDDBtnYAxisLabelInterval );
935
936 updateDataDefinedButton( mDDBtnLeftMargin );
937 updateDataDefinedButton( mDDBtnRightMargin );
938 updateDataDefinedButton( mDDBtnTopMargin );
939 updateDataDefinedButton( mDDBtnBottomMargin );
940
941 mBlockChanges--;
942}
943
944
946{
947 QgsPlot *plot = QgsApplication::plotRegistry()->createPlot( u"line"_s );
948 QgsLineChartPlot *chartPlot = dynamic_cast<QgsLineChartPlot *>( plot );
949 if ( !chartPlot )
950 {
951 return nullptr;
952 }
953
954 const int rowCount = mSymbolsList->rowCount();
955 for ( int i = 0; i < rowCount; i++ )
956 {
957 QgsSymbolButton *symbolButton = dynamic_cast<QgsSymbolButton *>( mSymbolsList->cellWidget( i, 1 ) );
958 if ( symbolButton )
959 {
960 chartPlot->setLineSymbolAt( i, symbolButton->clonedSymbol<QgsLineSymbol>() );
961 }
962
963 symbolButton = dynamic_cast<QgsSymbolButton *>( mSymbolsList->cellWidget( i, 2 ) );
964 if ( symbolButton )
965 {
966 chartPlot->setMarkerSymbolAt( i, symbolButton->clonedSymbol<QgsMarkerSymbol>() );
967 }
968 }
969
970 chartPlot->setXMinimum( mSpinMinXAxis->value() );
971 chartPlot->setXMaximum( mSpinMaxXAxis->value() );
972 chartPlot->setYMinimum( mSpinMinYAxis->value() );
973 chartPlot->setYMaximum( mSpinMaxYAxis->value() );
974
975 chartPlot->xAxis().setGridMajorSymbol( mXAxisMajorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
976 chartPlot->xAxis().setGridMinorSymbol( mXAxisMinorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
977 chartPlot->yAxis().setGridMajorSymbol( mYAxisMajorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
978 chartPlot->yAxis().setGridMinorSymbol( mYAxisMinorLinesSymbolButton->clonedSymbol<QgsLineSymbol>() );
979
980 chartPlot->xAxis().setTextFormat( mXAxisLabelFontButton->textFormat() );
981 chartPlot->yAxis().setTextFormat( mYAxisLabelFontButton->textFormat() );
982
983 chartPlot->xAxis().setType( mXAxisTypeCombo->currentData().value<Qgis::PlotAxisType>() );
984 chartPlot->xAxis().setLabelSuffixPlacement( mXAxisLabelsCombo->currentData().value<Qgis::PlotAxisSuffixPlacement>() );
985
986 chartPlot->xAxis().setGridIntervalMajor( mXAxisMajorIntervalSpin->value() );
987 chartPlot->xAxis().setGridIntervalMinor( mXAxisMinorIntervalSpin->value() );
988 chartPlot->xAxis().setLabelInterval( mXAxisLabelIntervalSpin->value() );
989
990 chartPlot->yAxis().setGridIntervalMajor( mYAxisMajorIntervalSpin->value() );
991 chartPlot->yAxis().setGridIntervalMinor( mYAxisMinorIntervalSpin->value() );
992 chartPlot->yAxis().setLabelInterval( mYAxisLabelIntervalSpin->value() );
993
994 chartPlot->setChartBackgroundSymbol( mChartBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
995 chartPlot->setChartBorderSymbol( mChartBorderSymbolButton->clonedSymbol<QgsFillSymbol>() );
996
997 QgsMargins margins;
998 margins.setLeft( mSpinLeftMargin->value() );
999 margins.setRight( mSpinRightMargin->value() );
1000 margins.setTop( mSpinTopMargin->value() );
1001 margins.setBottom( mSpinBottomMargin->value() );
1002 chartPlot->setMargins( margins );
1003
1005
1006 return plot;
1007}
1008
1009
1011 : QgsPlotWidget( parent )
1012{
1013 setupUi( this );
1014
1015 setPanelTitle( tr( "Pie Chart Plot Properties" ) );
1016
1017 mSymbolsList->setColumnCount( 3 );
1018 mSymbolsList->setSelectionBehavior( QAbstractItemView::SelectRows );
1019 mSymbolsList->setSelectionMode( QAbstractItemView::ExtendedSelection );
1020 mSymbolsList->setSortingEnabled( false );
1021 mSymbolsList->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
1022 mSymbolsList->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
1023 mSymbolsList->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::Stretch );
1024 mSymbolsList->horizontalHeader()->hide();
1025 mSymbolsList->verticalHeader()->hide();
1026
1027 mLabelCombo->addItem( tr( "None" ), QVariant::fromValue( Qgis::PieChartLabelType::NoLabels ) );
1028 mLabelCombo->addItem( tr( "Category Labels" ), QVariant::fromValue( Qgis::PieChartLabelType::Categories ) );
1029 mLabelCombo->addItem( tr( "Value Labels" ), QVariant::fromValue( Qgis::PieChartLabelType::Values ) );
1030 connect( mLabelCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this]( int ) {
1031 if ( mBlockChanges )
1032 return;
1033 emit widgetChanged();
1034 } );
1035
1036 mLabelFontButton->setDialogTitle( tr( "Chart Label Font" ) );
1037 mLabelFontButton->setMode( QgsFontButton::ModeTextRenderer );
1038 connect( mLabelFontButton, &QgsFontButton::changed, this, [this] {
1039 if ( mBlockChanges )
1040 return;
1041 emit widgetChanged();
1042 } );
1043
1044 connect( mLabelFormatButton, &QPushButton::clicked, this, [this] {
1046 widget->setPanelTitle( tr( "Chart Number Format" ) );
1047 widget->setFormat( mNumericFormat.get() );
1048 connect( widget, &QgsNumericFormatSelectorWidget::changed, this, [this, widget] {
1049 mNumericFormat.reset( widget->format() );
1050 emit widgetChanged();
1051 } );
1052 openPanel( widget );
1053 } );
1054
1055 mSpinLeftMargin->setClearValue( 0 );
1056 connect( mSpinLeftMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
1057 if ( mBlockChanges )
1058 return;
1059 emit widgetChanged();
1060 } );
1061
1062 mSpinRightMargin->setClearValue( 0 );
1063 connect( mSpinRightMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
1064 if ( mBlockChanges )
1065 return;
1066 emit widgetChanged();
1067 } );
1068
1069 mSpinTopMargin->setClearValue( 0 );
1070 connect( mSpinTopMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
1071 if ( mBlockChanges )
1072 return;
1073 emit widgetChanged();
1074 } );
1075
1076 mSpinBottomMargin->setClearValue( 0 );
1077 connect( mSpinBottomMargin, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, [this]( double ) {
1078 if ( mBlockChanges )
1079 return;
1080 emit widgetChanged();
1081 } );
1082
1083 connect( mAddSymbolPushButton, &QPushButton::clicked, this, &QgsPieChartPlotWidget::mAddSymbolPushButton_clicked );
1084 connect( mRemoveSymbolPushButton, &QPushButton::clicked, this, &QgsPieChartPlotWidget::mRemoveSymbolPushButton_clicked );
1085
1086 mLabelFontButton->registerExpressionContextGenerator( this );
1087
1092}
1093
1094void QgsPieChartPlotWidget::mAddSymbolPushButton_clicked()
1095{
1096 const int row = mSymbolsList->rowCount();
1097 mSymbolsList->insertRow( row );
1098
1099 QTableWidgetItem *item = new QTableWidgetItem();
1100 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
1101 mSymbolsList->setItem( row, 0, item );
1102
1103 // Fill
1104 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
1105 symbolButton->setSymbolType( Qgis::SymbolType::Fill );
1106 symbolButton->setShowNull( true );
1108 symbolButton->registerExpressionContextGenerator( this );
1109 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
1110 if ( mBlockChanges )
1111 return;
1112 emit widgetChanged();
1113 } );
1114 mSymbolsList->setCellWidget( row, 1, symbolButton );
1115
1116 // Color ramp
1117 QgsColorRampButton *colorRampButton = new QgsColorRampButton( this );
1118 colorRampButton->setShowNull( true );
1120 connect( colorRampButton, &QgsColorRampButton::colorRampChanged, this, [this] {
1121 if ( mBlockChanges )
1122 return;
1123 emit widgetChanged();
1124 } );
1125 mSymbolsList->setCellWidget( row, 2, colorRampButton );
1126
1127 emit widgetChanged();
1128}
1129
1130void QgsPieChartPlotWidget::mRemoveSymbolPushButton_clicked()
1131{
1132 QTableWidgetItem *item = mSymbolsList->currentItem();
1133 if ( !item )
1134 {
1135 return;
1136 }
1137
1138 mSymbolsList->removeRow( mSymbolsList->row( item ) );
1139
1140 emit widgetChanged();
1141}
1142
1144{
1145 QgsPieChartPlot *chartPlot = dynamic_cast<QgsPieChartPlot *>( plot );
1146 if ( !chartPlot )
1147 {
1148 return;
1149 }
1150
1151 mBlockChanges++;
1152
1153 mSymbolsList->clear();
1154 const int symbolCount = std::max( chartPlot->fillSymbolCount(), chartPlot->colorRampCount() );
1155 for ( int i = 0; i < symbolCount; i++ )
1156 {
1157 const int row = mSymbolsList->rowCount();
1158 mSymbolsList->insertRow( row );
1159
1160 QTableWidgetItem *item = new QTableWidgetItem();
1161 item->setData( Qt::DisplayRole, tr( "Symbol" ) );
1162 mSymbolsList->setItem( row, 0, item );
1163
1164 // Fill
1165 QgsSymbolButton *symbolButton = new QgsSymbolButton( this );
1166 symbolButton->setSymbolType( Qgis::SymbolType::Fill );
1167 symbolButton->setShowNull( true );
1168 symbolButton->setSymbol( i < chartPlot->fillSymbolCount() ? chartPlot->fillSymbolAt( i )->clone() : nullptr );
1169 symbolButton->registerExpressionContextGenerator( this );
1170 connect( symbolButton, &QgsSymbolButton::changed, this, [this] {
1171 if ( mBlockChanges )
1172 return;
1173 emit widgetChanged();
1174 } );
1175 mSymbolsList->setCellWidget( row, 1, symbolButton );
1176
1177 // Color ramp
1178 QgsColorRampButton *colorRampButton = new QgsColorRampButton( this );
1179 colorRampButton->setShowNull( true );
1180 colorRampButton->setColorRamp( i < chartPlot->colorRampCount() ? chartPlot->colorRampAt( i )->clone() : nullptr );
1181 connect( colorRampButton, &QgsColorRampButton::colorRampChanged, this, [this] {
1182 if ( mBlockChanges )
1183 return;
1184 emit widgetChanged();
1185 } );
1186 mSymbolsList->setCellWidget( row, 2, colorRampButton );
1187 }
1188
1189 mNumericFormat.reset( chartPlot->numericFormat()->clone() );
1190 mLabelFontButton->setTextFormat( chartPlot->textFormat() );
1191
1192 mLabelCombo->setCurrentIndex( mLabelCombo->findData( QVariant::fromValue( chartPlot->labelType() ) ) );
1193
1195
1196 updateDataDefinedButton( mDDBtnLeftMargin );
1197 updateDataDefinedButton( mDDBtnRightMargin );
1198 updateDataDefinedButton( mDDBtnTopMargin );
1199 updateDataDefinedButton( mDDBtnBottomMargin );
1200
1201 mBlockChanges--;
1202}
1203
1205{
1206 QgsPlot *plot = QgsApplication::plotRegistry()->createPlot( u"pie"_s );
1207 QgsPieChartPlot *chartPlot = dynamic_cast<QgsPieChartPlot *>( plot );
1208 if ( !chartPlot )
1209 {
1210 return nullptr;
1211 }
1212
1213 const int rowCount = mSymbolsList->rowCount();
1214 for ( int i = 0; i < rowCount; i++ )
1215 {
1216 QgsSymbolButton *symbolButton = dynamic_cast<QgsSymbolButton *>( mSymbolsList->cellWidget( i, 1 ) );
1217 if ( symbolButton )
1218 {
1219 chartPlot->setFillSymbolAt( i, symbolButton->clonedSymbol<QgsFillSymbol>() );
1220 }
1221
1222 QgsColorRampButton *colorRampButton = dynamic_cast<QgsColorRampButton *>( mSymbolsList->cellWidget( i, 2 ) );
1223 if ( colorRampButton )
1224 {
1225 chartPlot->setColorRampAt( i, colorRampButton->colorRamp()->clone() );
1226 }
1227 }
1228
1229 chartPlot->setNumericFormat( mNumericFormat.get()->clone() );
1230 chartPlot->setTextFormat( mLabelFontButton->textFormat() );
1231 chartPlot->setLabelType( mLabelCombo->currentData().value<Qgis::PieChartLabelType>() );
1232
1233 QgsMargins margins;
1234 margins.setLeft( mSpinLeftMargin->value() );
1235 margins.setRight( mSpinRightMargin->value() );
1236 margins.setTop( mSpinTopMargin->value() );
1237 margins.setBottom( mSpinBottomMargin->value() );
1238 chartPlot->setMargins( margins );
1239
1241
1242 return plot;
1243}
PieChartLabelType
Pie chart label types.
Definition qgis.h:3417
@ Categories
Category labels are drawn.
Definition qgis.h:3419
@ Values
Value labels are drawn.
Definition qgis.h:3420
@ NoLabels
Labels are not drawn.
Definition qgis.h:3418
PlotAxisSuffixPlacement
Placement options for suffixes in the labels for axis of plots.
Definition qgis.h:3389
@ FirstAndLastLabels
Place suffix after the first and last label values only.
Definition qgis.h:3394
@ EveryLabel
Place suffix after every value label.
Definition qgis.h:3391
@ FirstLabel
Place suffix after the first label value only.
Definition qgis.h:3392
@ LastLabel
Place suffix after the last label value only.
Definition qgis.h:3393
@ NoLabels
Do not place suffixes.
Definition qgis.h:3390
PlotAxisType
Plots axis types.
Definition qgis.h:3405
@ Categorical
The axis represents categories.
Definition qgis.h:3407
@ Interval
The axis represents a range of values.
Definition qgis.h:3406
@ Marker
Marker symbol.
Definition qgis.h:630
@ Line
Line symbol.
Definition qgis.h:631
@ Fill
Fill symbol.
Definition qgis.h:632
const QgsMargins & margins() const
Returns the margins of the plot area (in millimeters).
Definition qgsplot.cpp:296
void setMargins(const QgsMargins &margins)
Sets the margins of the plot area (in millimeters).
Definition qgsplot.cpp:301
void setXMaximum(double maximum)
Sets the maximum value of the x axis.
Definition qgsplot.h:735
double yMaximum() const
Returns the maximum value of the y axis.
Definition qgsplot.h:742
void setYMinimum(double minimum)
Sets the minimum value of the y axis.
Definition qgsplot.h:721
double xMinimum() const
Returns the minimum value of the x axis.
Definition qgsplot.h:700
void setChartBackgroundSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used to render the background of the chart.
Definition qgsplot.cpp:1041
QgsPlotAxis & yAxis()
Returns a reference to the plot's y axis.
Definition qgsplot.h:770
void setChartBorderSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the border of the chart.
Definition qgsplot.cpp:1051
QgsFillSymbol * chartBackgroundSymbol()
Returns the fill symbol used to render the background of the chart.
Definition qgsplot.cpp:1036
void setXMinimum(double minimum)
Sets the minimum value of the x axis.
Definition qgsplot.h:707
QgsPlotAxis & xAxis()
Returns a reference to the plot's x axis.
Definition qgsplot.h:756
QgsFillSymbol * chartBorderSymbol()
Returns the symbol used to render the border of the chart.
Definition qgsplot.cpp:1046
double yMinimum() const
Returns the minimum value of the y axis.
Definition qgsplot.h:714
void setYMaximum(double maximum)
Sets the maximum value of the y axis.
Definition qgsplot.h:749
double xMaximum() const
Returns the maximum value of the x axis.
Definition qgsplot.h:728
static QgsPlotRegistry * plotRegistry()
Returns the application's plot registry, used for plot types.
void setPlot(QgsPlot *plot) override
Sets the widget to match the settings of the plot.
QgsBarChartPlotWidget(QWidget *parent=nullptr)
Constructor for QgsBarChartPlotWidget.
QgsPlot * createPlot() override
Creates a plot defined by the current settings in the widget.
A simple bar chart class.
void setFillSymbolAt(int index, QgsFillSymbol *symbol)
Sets the fill symbol to use for the series with matching index.
int fillSymbolCount() const
Returns the fill symbols list count.
QgsFillSymbol * fillSymbolAt(int index) const
Returns the fill symbol for the series with matching index.
A cross platform button subclass for selecting color ramps.
void setColorRamp(QgsColorRamp *colorramp)
Sets the current color ramp for the button.
QgsColorRamp * colorRamp() const
Returns a copy of the current color ramp.
void setShowNull(bool showNull)
Sets whether a set to null (clear) option is shown in the button's drop-down menu.
void colorRampChanged()
Emitted whenever a new color ramp is set for the button.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
Abstract interface for generating an expression context.
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 appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
@ ModeTextRenderer
Configure font settings for use with QgsTextRenderer.
void changed()
Emitted when the widget's text format settings are changed.
QgsLineChartPlotWidget(QWidget *parent=nullptr)
Constructor for QgsLineChartPlotWidget.
void setPlot(QgsPlot *plot) override
Sets the widget to match the settings of the plot.
QgsPlot * createPlot() override
Creates a plot defined by the current settings in the widget.
A simple line chart class.
QgsMarkerSymbol * markerSymbolAt(int index) const
Returns the marker symbol for the series with matching index.
QgsLineSymbol * lineSymbolAt(int index) const
Returns the line symbol for the series with matching index.
void setLineSymbolAt(int index, QgsLineSymbol *symbol)
Sets the line symbol to use for the series with matching index.
int lineSymbolCount() const
Returns the line symbols list count.
void setMarkerSymbolAt(int index, QgsMarkerSymbol *symbol)
Sets the fill symbol to use for the series with matching index.
int markerSymbolCount() const
Returns the line symbols list count.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Defines the four margins of a rectangle.
Definition qgsmargins.h:40
void setBottom(double bottom)
Sets the bottom margin to bottom.
Definition qgsmargins.h:116
double top() const
Returns the top margin.
Definition qgsmargins.h:80
void setLeft(double left)
Sets the left margin to left.
Definition qgsmargins.h:98
double right() const
Returns the right margin.
Definition qgsmargins.h:86
double bottom() const
Returns the bottom margin.
Definition qgsmargins.h:92
void setRight(double right)
Sets the right margin to right.
Definition qgsmargins.h:110
void setTop(double top)
Sets the top margin to top.
Definition qgsmargins.h:104
double left() const
Returns the left margin.
Definition qgsmargins.h:74
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
A widget which allows choice of numeric formats and the properties of them.
QgsNumericFormat * format() const
Returns a new format object representing the settings currently configured in the widget.
void changed()
Emitted whenever the format configured55 in the widget is changed.
void setFormat(const QgsNumericFormat *format)
Sets the format to show in the widget.
virtual QgsNumericFormat * clone() const =0
Clones the format, returning a new object.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void widgetChanged()
Emitted when the widget state changes.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsPlot * createPlot() override
Creates a plot defined by the current settings in the widget.
void setPlot(QgsPlot *plot) override
Sets the widget to match the settings of the plot.
QgsPieChartPlotWidget(QWidget *parent=nullptr)
Constructor for QgsLineChartPlotWidget.
A simple pie chart class.
void setTextFormat(const QgsTextFormat &format)
Sets the text format used for the pie chart labels.
QgsTextFormat textFormat() const
Returns the text format used for the pie chart labels.
QgsFillSymbol * fillSymbolAt(int index) const
Returns the fill symbol for the series with matching index.
void setNumericFormat(QgsNumericFormat *format)
Sets the numeric format used for the pie chart labels.
QgsColorRamp * colorRampAt(int index) const
Returns the color ramp for the series with matching index.
QgsNumericFormat * numericFormat() const
Returns the numeric format used for the pie chart labels.
void setLabelType(Qgis::PieChartLabelType type)
Sets the pie chart label type.
Qgis::PieChartLabelType labelType() const
Returns the pie chart label type.
int fillSymbolCount() const
Returns the fill symbols list count.
void setColorRampAt(int index, QgsColorRamp *ramp)
Sets the color ramp for the series with matching index.
void setFillSymbolAt(int index, QgsFillSymbol *symbol)
Sets the fill symbol to use for the series with matching index.
int colorRampCount() const
Returns the color ramps list count.
QgsLineSymbol * gridMinorSymbol()
Returns the line symbol used to render the minor lines in the axis grid.
Definition qgsplot.cpp:208
void setGridMajorSymbol(QgsLineSymbol *symbol)
Sets the symbol used to render the major lines in the axis grid.
Definition qgsplot.cpp:203
double gridIntervalMinor() const
Returns the interval of minor grid lines for the axis.
Definition qgsplot.h:389
double gridIntervalMajor() const
Returns the interval of major grid lines for the axis.
Definition qgsplot.h:403
void setType(Qgis::PlotAxisType type)
Sets the axis type.
Definition qgsplot.cpp:112
void setNumericFormat(QgsNumericFormat *format)
Sets the numeric format used for the axis labels.
Definition qgsplot.cpp:173
QgsTextFormat textFormat() const
Returns the text format used for the axis labels.
Definition qgsplot.cpp:218
void setGridIntervalMajor(double interval)
Sets the interval of major grid lines for the axis.
Definition qgsplot.h:410
void setLabelSuffixPlacement(Qgis::PlotAxisSuffixPlacement placement)
Sets the placement for the axis label suffixes.
Definition qgsplot.cpp:193
void setGridIntervalMinor(double interval)
Sets the interval of minor grid lines for the axis.
Definition qgsplot.h:396
void setLabelInterval(double interval)
Sets the interval of labels for the axis.
Definition qgsplot.h:424
Qgis::PlotAxisType type() const
Returns the axis type.
Definition qgsplot.cpp:107
double labelInterval() const
Returns the interval of labels for the axis.
Definition qgsplot.h:417
QgsLineSymbol * gridMajorSymbol()
Returns the line symbol used to render the major lines in the axis grid.
Definition qgsplot.cpp:198
void setTextFormat(const QgsTextFormat &format)
Sets the text format used for the axis labels.
Definition qgsplot.cpp:223
void setGridMinorSymbol(QgsLineSymbol *symbol)
Sets the symbol used to render the minor lines in the axis grid.
Definition qgsplot.cpp:213
QgsNumericFormat * numericFormat() const
Returns the numeric format used for the axis labels.
Definition qgsplot.cpp:168
Qgis::PlotAxisSuffixPlacement labelSuffixPlacement() const
Returns the placement for the axis label suffixes.
Definition qgsplot.cpp:188
static QgsFillSymbol * chartBorderSymbol()
Returns the default fill symbol to use for the chart area border.
Definition qgsplot.cpp:1194
static QgsColorRamp * pieChartColorRamp()
Returns the default color ramp to use for pie charts.
Definition qgsplot.cpp:1224
static QgsFillSymbol * barChartFillSymbol()
Returns the default fill symbol to use for bar charts.
Definition qgsplot.cpp:1212
static QgsLineSymbol * lineChartLineSymbol()
Returns the default line symbol to use for line charts.
Definition qgsplot.cpp:1206
static QgsLineSymbol * axisGridMinorSymbol()
Returns the default line symbol to use for axis minor grid lines.
Definition qgsplot.cpp:1181
static QgsFillSymbol * pieChartFillSymbol()
Returns the default fill symbol to use for pie charts.
Definition qgsplot.cpp:1218
static QgsMarkerSymbol * lineChartMarkerSymbol()
Returns the default marker symbol to use for line charts.
Definition qgsplot.cpp:1200
static QgsFillSymbol * chartBackgroundSymbol()
Returns the default fill symbol to use for the chart area background fill.
Definition qgsplot.cpp:1188
static QgsLineSymbol * axisGridMajorSymbol()
Returns the default line symbol to use for axis major grid lines.
Definition qgsplot.cpp:1174
QgsPlot * createPlot(const QString &type) const
Creates a new instance of a plot given the type.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
QgsPropertyCollection mPropertyCollection
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Initiate a data-defined property button tied to a plot widget.
QgsPlotWidget(QWidget *parent=nullptr)
Constructor for QgsPlotWidget.
void initializeDataDefinedButton(QgsPropertyOverrideButton *button, QgsPlot::DataDefinedProperty key)
Initiate a data-defined property button tied to a plot widget.
Base class for plot/chart/graphs.
Definition qgsplot.h:48
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the plot's property collection, used for data defined overrides.
Definition qgsplot.h:151
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the plot property definitions.
Definition qgsplot.cpp:88
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the plot's property collection, used for data defined overrides.
Definition qgsplot.h:136
DataDefinedProperty
Data defined properties for different plot types.
Definition qgsplot.h:96
@ YAxisMinorInterval
Minor grid line interval for Y axis.
Definition qgsplot.h:105
@ YAxisLabelInterval
Label interval for Y axis.
Definition qgsplot.h:106
@ XAxisMajorInterval
Major grid line interval for X axis.
Definition qgsplot.h:101
@ XAxisMaximum
Maximum X axis value.
Definition qgsplot.h:108
@ XAxisMinimum
Minimum X axis value.
Definition qgsplot.h:107
@ XAxisLabelInterval
Label interval for X axis.
Definition qgsplot.h:103
@ MarginBottom
Bottom margin.
Definition qgsplot.h:100
@ XAxisMinorInterval
Minor grid line interval for X axis.
Definition qgsplot.h:102
@ YAxisMajorInterval
Major grid line interval for Y axis.
Definition qgsplot.h:104
@ YAxisMaximum
Maximum Y axis value.
Definition qgsplot.h:110
@ MarginLeft
Left margin.
Definition qgsplot.h:97
@ MarginRight
Right margin.
Definition qgsplot.h:99
@ YAxisMinimum
Minimum Y axis value.
Definition qgsplot.h:109
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
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 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.
A button for creating and modifying QgsSymbol settings.
void setFixedSizeConstraints(bool fixedSizeConstraints)
Sets whether the widget adopts fixed size constraints.
void setSymbol(QgsSymbol *symbol)
Sets the symbol for the button.
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type which the button requires.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void changed()
Emitted when the symbol's settings are changed.
void setShowNull(bool showNull)
Sets whether a set to null (clear) option is shown in the button's drop-down menu.
SymbolType * clonedSymbol()
Returns a clone of the current symbol (as the specified template type) defined by the button.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6839
Single variable definition for use within a QgsExpressionContextScope.