28#include "moc_qgslayoutchartwidget.cpp"
32 , mChartItem( chartItem )
38 mainLayout->addWidget( mItemPropertiesWidget );
41 for (
auto plotTypesIterator = plotTypes.keyValueBegin(); plotTypesIterator != plotTypes.keyValueEnd(); ++plotTypesIterator )
43 mChartTypeComboBox->addItem( plotTypesIterator->second, plotTypesIterator->first );
48 connect( mChartTypeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutChartWidget::mChartTypeComboBox_currentIndexChanged );
49 connect( mChartPropertiesButton, &QPushButton::clicked,
this, &QgsLayoutChartWidget::mChartPropertiesButton_clicked );
50 connect( mFlipAxesCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mFlipAxesCheckBox_stateChanged );
54 connect( mSortCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mSortCheckBox_stateChanged );
56 connect( mSortDirectionButton, &QToolButton::clicked,
this, &QgsLayoutChartWidget::mSortDirectionButton_clicked );
58 connect( mGenerateCategoriesFromRendererCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mGenerateCategoriesFromRendererCheckBox_stateChanged );
59 connect( mApplyRendererStyleCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mApplyRendererStyleCheckBox_stateChanged );
61 connect( mSeriesListWidget, &QListWidget::currentItemChanged,
this, &QgsLayoutChartWidget::mSeriesListWidget_currentItemChanged );
62 connect( mSeriesListWidget, &QListWidget::itemChanged,
this, &QgsLayoutChartWidget::mSeriesListWidget_itemChanged );
63 connect( mAddSeriesPushButton, &QPushButton::clicked,
this, &QgsLayoutChartWidget::mAddSeriesPushButton_clicked );
64 connect( mRemoveSeriesPushButton, &QPushButton::clicked,
this, &QgsLayoutChartWidget::mRemoveSeriesPushButton_clicked );
65 connect( mSeriesPropertiesButton, &QPushButton::clicked,
this, &QgsLayoutChartWidget::mSeriesPropertiesButton_clicked );
67 mLinkedMapComboBox->setCurrentLayout( mChartItem->layout() );
71 connect( mFilterOnlyVisibleFeaturesCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mFilterOnlyVisibleFeaturesCheckBox_stateChanged );
72 connect( mIntersectAtlasCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutChartWidget::mIntersectAtlasCheckBox_stateChanged );
74 setGuiElementValues();
82 if ( mItemPropertiesWidget )
83 mItemPropertiesWidget->setMasterLayout( masterLayout );
96 mChartItem = qobject_cast<QgsLayoutItemChart *>( item );
97 mItemPropertiesWidget->setItem( mChartItem );
104 setGuiElementValues();
109void QgsLayoutChartWidget::setGuiElementValues()
113 whileBlocking( mChartTypeComboBox )->setCurrentIndex( mChartTypeComboBox->findData( mChartItem->plot()->type() ) );
114 whileBlocking( mLayerComboBox )->setLayer( mChartItem->sourceLayer() );
119 mFlipAxesCheckBox->setEnabled(
true );
124 mFlipAxesCheckBox->setEnabled(
false );
128 whileBlocking( mGenerateCategoriesFromRendererCheckBox )->setCheckState( mChartItem->generateCategoriesFromRenderer() ? Qt::Checked : Qt::Unchecked );
129 whileBlocking( mApplyRendererStyleCheckBox )->setCheckState( mChartItem->applyRendererStyle() ? Qt::Checked : Qt::Unchecked );
131 whileBlocking( mSortCheckBox )->setCheckState( mChartItem->sortFeatures() ? Qt::Checked : Qt::Unchecked );
132 whileBlocking( mSortDirectionButton )->setEnabled( mChartItem->sortFeatures() );
133 whileBlocking( mSortDirectionButton )->setArrowType( mChartItem->sortAscending() ? Qt::UpArrow : Qt::DownArrow );
134 whileBlocking( mSortExpressionWidget )->setEnabled( mChartItem->sortFeatures() );
135 whileBlocking( mSortExpressionWidget )->setLayer( mChartItem->sourceLayer() );
136 whileBlocking( mSortExpressionWidget )->setField( mChartItem->sortExpression() );
138 mSeriesListWidget->clear();
139 const QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
140 for (
const QgsLayoutItemChart::SeriesDetails &series : seriesList )
142 addSeriesListItem( series.name() );
145 if ( !seriesList.isEmpty() )
147 mSeriesListWidget->setCurrentRow( 0 );
151 mSeriesPropertiesButton->setEnabled(
false );
154 whileBlocking( mFilterOnlyVisibleFeaturesCheckBox )->setChecked( mChartItem->filterOnlyVisibleFeatures() );
155 mLinkedMapLabel->setEnabled( mFilterOnlyVisibleFeaturesCheckBox->isChecked() );
156 mLinkedMapComboBox->setEnabled( mFilterOnlyVisibleFeaturesCheckBox->isChecked() );
157 whileBlocking( mLinkedMapComboBox )->setItem( mChartItem->map() );
159 whileBlocking( mIntersectAtlasCheckBox )->setChecked( mChartItem->filterToAtlasFeature() );
163 mSeriesListWidget->clear();
167void QgsLayoutChartWidget::mChartTypeComboBox_currentIndexChanged(
int )
174 const QString plotType = mChartTypeComboBox->currentData().toString();
175 if ( mChartItem->plot()->type() == plotType )
180 QgsPlot *oldPlot = mChartItem->plot();
184 Qgs2DXyPlot *newPlot2DXy =
dynamic_cast<Qgs2DXyPlot *
>( newPlot );
187 mFlipAxesCheckBox->setEnabled(
true );
188 mFlipAxesCheckBox->setChecked( newPlot2DXy->
flipAxes() );
192 mFlipAxesCheckBox->setEnabled(
false );
193 mFlipAxesCheckBox->setChecked(
false );
196 mChartItem->beginCommand( tr(
"Change Chart Type" ) );
197 mChartItem->setPlot( newPlot );
198 mChartItem->update();
199 mChartItem->endCommand();
202void QgsLayoutChartWidget::mChartPropertiesButton_clicked()
211 const QString plotType = mChartTypeComboBox->currentData().toString();
213 if ( !abstractMetadata )
225 widget->
setPlot( mChartItem->plot() );
233 mChartItem->beginCommand( tr(
"Modify Chart" ) );
235 mChartItem->endCommand();
236 mChartItem->update();
242void QgsLayoutChartWidget::mFlipAxesCheckBox_stateChanged(
int state )
249 Qgs2DXyPlot *plot2DXy =
dynamic_cast<Qgs2DXyPlot *
>( mChartItem->plot() );
255 mChartItem->beginCommand( tr(
"Modify Chart" ) );
257 mChartItem->endCommand();
258 mChartItem->update();
261void QgsLayoutChartWidget::changeLayer(
QgsMapLayer *layer )
268 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
274 mChartItem->beginCommand( tr(
"Change Chart Source Layer" ) );
275 mChartItem->setSourceLayer( vl );
276 mChartItem->update();
277 mChartItem->endCommand();
278 updateButtonsState();
281void QgsLayoutChartWidget::changeSortExpression(
const QString &expression,
bool )
288 mChartItem->beginCommand( tr(
"Change Chart Source Sort Expression" ) );
289 mChartItem->setSortExpression( expression );
290 mChartItem->update();
291 mChartItem->endCommand();
294void QgsLayoutChartWidget::mSortCheckBox_stateChanged(
int state )
299 if ( state == Qt::Checked )
301 mSortDirectionButton->setEnabled(
true );
302 mSortExpressionWidget->setEnabled(
true );
306 mSortDirectionButton->setEnabled(
false );
307 mSortExpressionWidget->setEnabled(
false );
310 mChartItem->beginCommand( tr(
"Toggle Atlas Sorting" ) );
311 mChartItem->setSortFeatures( state == Qt::Checked );
312 mChartItem->update();
313 mChartItem->endCommand();
316void QgsLayoutChartWidget::mSortDirectionButton_clicked()
323 Qt::ArrowType at = mSortDirectionButton->arrowType();
324 at = ( at == Qt::UpArrow ) ? Qt::DownArrow : Qt::UpArrow;
325 mSortDirectionButton->setArrowType( at );
327 mChartItem->beginCommand( tr(
"Change Chart Source Sort Direction" ) );
328 mChartItem->setSortAscending( at == Qt::UpArrow );
329 mChartItem->update();
330 mChartItem->endCommand();
333QListWidgetItem *QgsLayoutChartWidget::addSeriesListItem(
const QString &name )
335 QListWidgetItem *item =
new QListWidgetItem( name,
nullptr );
336 item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
337 mSeriesListWidget->addItem( item );
341void QgsLayoutChartWidget::mSeriesListWidget_currentItemChanged( QListWidgetItem *current, QListWidgetItem * )
343 mSeriesPropertiesButton->setEnabled(
static_cast<bool>( current ) );
346void QgsLayoutChartWidget::mSeriesListWidget_itemChanged( QListWidgetItem *item )
353 QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
354 const int idx = mSeriesListWidget->row( item );
355 if ( idx >= seriesList.size() )
360 mChartItem->beginCommand( tr(
"Rename Chart Series" ) );
361 seriesList[idx].setName( item->text() );
362 mChartItem->setSeriesList( seriesList );
363 mChartItem->endCommand();
366void QgsLayoutChartWidget::mAddSeriesPushButton_clicked()
373 QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
374 const QString itemName = tr(
"Series %1" ).arg( seriesList.size() + 1 );
375 addSeriesListItem( itemName );
377 mChartItem->beginCommand( tr(
"Add Chart Series" ) );
378 seriesList << QgsLayoutItemChart::SeriesDetails( itemName );
379 mChartItem->setSeriesList( seriesList );
380 mChartItem->endCommand();
381 mChartItem->update();
383 mSeriesListWidget->setCurrentRow( mSeriesListWidget->count() - 1 );
384 mSeriesListWidget_currentItemChanged( mSeriesListWidget->currentItem(),
nullptr );
385 updateButtonsState();
388void QgsLayoutChartWidget::mRemoveSeriesPushButton_clicked()
390 QListWidgetItem *item = mSeriesListWidget->currentItem();
391 if ( !item || !mChartItem )
396 QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
397 const int idx = mSeriesListWidget->row( item );
398 if ( idx >= seriesList.size() )
403 QListWidgetItem *deletedItem = mSeriesListWidget->takeItem( mSeriesListWidget->row( item ) );
406 mChartItem->beginCommand( tr(
"Remove Chart Series" ) );
407 seriesList.removeAt( idx );
408 mChartItem->setSeriesList( seriesList );
409 mChartItem->endCommand();
410 mChartItem->update();
411 updateButtonsState();
414void QgsLayoutChartWidget::mSeriesPropertiesButton_clicked()
416 QListWidgetItem *item = mSeriesListWidget->currentItem();
417 if ( !item || !mChartItem )
422 QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
423 const int idx = mSeriesListWidget->row( item );
424 if ( idx >= seriesList.size() )
429 QgsLayoutChartSeriesDetailsWidget *widget =
new QgsLayoutChartSeriesDetailsWidget( mChartItem->sourceLayer(), idx, seriesList[idx], mGenerateCategoriesFromRendererCheckBox->isChecked(),
this );
438 QList<QgsLayoutItemChart::SeriesDetails> seriesList = mChartItem->seriesList();
439 const int idx = widget->
index();
440 if ( idx >= seriesList.size() )
445 mChartItem->beginCommand( tr(
"Modify Chart Series" ) );
446 seriesList[idx].setXExpression( widget->
xExpression() );
447 seriesList[idx].setYExpression( widget->
yExpression() );
449 mChartItem->setSeriesList( seriesList );
450 mChartItem->endCommand();
451 mChartItem->update();
457void QgsLayoutChartWidget::mLinkedMapComboBox_itemChanged(
QgsLayoutItem *item )
464 mChartItem->beginCommand( tr(
"Change Chart Map Item" ) );
465 mChartItem->setMap( qobject_cast<QgsLayoutItemMap *>( item ) );
466 mChartItem->endCommand();
467 mChartItem->update();
470void QgsLayoutChartWidget::mGenerateCategoriesFromRendererCheckBox_stateChanged(
int state )
477 mChartItem->beginCommand( tr(
"Toggle Generate Categories from Layer Renderer" ) );
478 const bool generateCategoriesFromRenderer = ( state == Qt::Checked );
479 mChartItem->setGenerateCategoriesFromRenderer( generateCategoriesFromRenderer );
480 mChartItem->endCommand();
481 mChartItem->update();
483 mApplyRendererStyleCheckBox->setEnabled( mGenerateCategoriesFromRendererCheckBox->isChecked() );
486void QgsLayoutChartWidget::mApplyRendererStyleCheckBox_stateChanged(
int state )
493 mChartItem->beginCommand( tr(
"Toggle Apply Layer Renderer Style" ) );
494 const bool applyRendererStyle = ( state == Qt::Checked );
495 mChartItem->setApplyRendererStyle( applyRendererStyle );
496 mChartItem->endCommand();
497 mChartItem->update();
500void QgsLayoutChartWidget::mFilterOnlyVisibleFeaturesCheckBox_stateChanged(
int state )
507 mChartItem->beginCommand( tr(
"Toggle Visible Features Only Filter" ) );
508 const bool useOnlyVisibleFeatures = ( state == Qt::Checked );
509 mChartItem->setFilterOnlyVisibleFeatures( useOnlyVisibleFeatures );
510 mChartItem->endCommand();
511 mChartItem->update();
514 mLinkedMapComboBox->setEnabled( state == Qt::Checked );
515 mLinkedMapLabel->setEnabled( state == Qt::Checked );
518void QgsLayoutChartWidget::mIntersectAtlasCheckBox_stateChanged(
int state )
525 mChartItem->beginCommand( tr(
"Toggle Chart Atlas Filter" ) );
526 const bool filterToAtlas = ( state == Qt::Checked );
527 mChartItem->setFilterToAtlasFeature( filterToAtlas );
528 mChartItem->endCommand();
529 mChartItem->update();
532void QgsLayoutChartWidget::updateButtonsState()
539 const bool enable = qobject_cast<QgsVectorLayer *>( mLayerComboBox->currentLayer() ) !=
nullptr;
540 mGenerateCategoriesFromRendererCheckBox->setEnabled( enable );
541 mApplyRendererStyleCheckBox->setEnabled( enable && mGenerateCategoriesFromRendererCheckBox->isChecked() );
542 mSortCheckBox->setEnabled( enable );
543 mAddSeriesPushButton->setEnabled( enable );
544 mRemoveSeriesPushButton->setEnabled( mSeriesListWidget->count() > 0 );
Base class for 2-dimensional plot/chart/graphs with an X and Y axes.
void setFlipAxes(bool flipAxes)
Sets whether the X and Y axes are flipped.
bool flipAxes() const
Returns whether the X and Y axes are flipped.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QgsPlotRegistry * plotRegistry()
Returns the application's plot registry, used for plot types.
static void initPlotWidgets()
Initializes plot widgets.
A layout item subclass that renders chart plots.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
Base class for graphical items within a QgsLayout.
int type() const override
Returns a unique graphics item type identifier.
void changed()
Emitted when the object's properties change.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
Interface for master layout type objects, such as print layouts and reports.
QgsPlot * createPlot(const QString &type) const
Creates a new instance of a plot given the type.
QMap< QString, QString > plotTypes() const
Returns a map of available plot types to translated name.
QgsPlotAbstractMetadata * plotMetadata(const QString &type) const
Returns the metadata for the specified plot type.
virtual void initFromPlot(const QgsPlot *plot)
Initializes properties of this plot from an existing plot, transferring all applicable settings.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.