35#include "moc_qgsstackeddiagramproperties.cpp"
37using namespace Qt::StringLiterals;
42 , mMapCanvas( canvas )
50 connect( mSubDiagramsView, &QAbstractItemView::doubleClicked,
this,
static_cast<void (
QgsStackedDiagramProperties::* )(
const QModelIndex & )
>( &QgsStackedDiagramProperties::editSubDiagramRenderer ) );
52 connect( mAddSubDiagramButton, &QPushButton::clicked,
this, &QgsStackedDiagramProperties::addSubDiagramRenderer );
53 connect( mEditSubDiagramButton, &QAbstractButton::clicked,
this,
static_cast<void (
QgsStackedDiagramProperties::* )()
>( &QgsStackedDiagramProperties::editSubDiagramRenderer ) );
54 connect( mRemoveSubDiagramButton, &QPushButton::clicked,
this, &QgsStackedDiagramProperties::removeSubDiagramRenderer );
60 mStackedDiagramSpacingSpinBox->setClearValue( 0 );
61 mStackedDiagramSpacingUnitComboBox->setUnits(
70 mSubDiagramsView->setModel( mModel );
83void QgsStackedDiagramProperties::addSubDiagramRenderer()
86 std::unique_ptr<QgsDiagramRenderer> renderer;
87 auto dr = std::make_unique<QgsSingleCategoryDiagramRenderer>();
88 renderer = std::move( dr );
90 QItemSelectionModel *sel = mSubDiagramsView->selectionModel();
91 const QModelIndex index = sel->currentIndex();
93 if ( index.isValid() )
96 const QModelIndex currentIndex = mSubDiagramsView->selectionModel()->currentIndex();
98 const QModelIndex newIndex = mModel->index( currentIndex.row() + 1, 0 );
99 mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
104 appendSubDiagramRenderer( renderer.release() );
106 editSubDiagramRenderer();
111 const int rows = mModel->rowCount();
112 mModel->insertSubDiagram( rows, dr );
113 const QModelIndex newIndex = mModel->index( rows, 0 );
114 mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
117void QgsStackedDiagramProperties::editSubDiagramRenderer()
119 editSubDiagramRenderer( mSubDiagramsView->selectionModel()->currentIndex() );
122void QgsStackedDiagramProperties::editSubDiagramRenderer(
const QModelIndex &index )
124 if ( !index.isValid() )
127 QgsDiagramRenderer *renderer = mModel->subDiagramForIndex( index );
128 QgsDiagramLayerSettings dls = mModel->diagramLayerSettings();
133 QgsDiagramProperties *widget =
new QgsDiagramProperties( mLayer,
this, mMapCanvas );
135 widget->layout()->setContentsMargins( 0, 0, 0, 0 );
138 if ( !couldBeFirstSubDiagram( index ) )
150 QgsStackedDiagramPropertiesDialog dlg( mLayer,
this, mMapCanvas );
151 dlg.syncToRenderer( renderer );
152 dlg.syncToSettings( &dls );
153 if ( !couldBeFirstSubDiagram( index ) )
155 dlg.setAllowedToEditDiagramLayerSettings(
false );
160 const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
161 if ( dlg.isAllowedToEditDiagramLayerSettings() )
162 mModel->updateDiagramLayerSettings( dlg.diagramLayerSettings() );
165 mModel->updateSubDiagram( index, dlg.renderer() );
169void QgsStackedDiagramProperties::removeSubDiagramRenderer()
171 const QItemSelection sel = mSubDiagramsView->selectionModel()->selection();
172 const auto constSel = sel;
173 for (
const QItemSelectionRange &range : constSel )
175 if ( range.isValid() )
176 mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
179 mSubDiagramsView->selectionModel()->clear();
184 mSubDiagramsView->selectionModel()->clearCurrentIndex();
194 mStackedDiagramModeComboBox->setCurrentIndex( settingList.at( 0 ).stackedDiagramMode );
195 mStackedDiagramSpacingSpinBox->setValue( settingList.at( 0 ).stackedDiagramSpacing() );
196 mStackedDiagramSpacingUnitComboBox->setUnit( settingList.at( 0 ).stackedDiagramSpacingUnit() );
201 const QList<QgsDiagramRenderer *> renderers = stackedDiagramRenderer->
renderers();
204 appendSubDiagramRenderer( renderer->
clone() );
210 appendSubDiagramRenderer( dr->
clone() );
214 mModel->updateDiagramLayerSettings( *dls );
216 mSubDiagramsView->selectionModel()->clear();
222 auto ds = std::make_unique<QgsDiagramSettings>();
224 ds->setStackedDiagramSpacingUnit( mStackedDiagramSpacingUnitComboBox->unit() );
225 ds->setStackedDiagramSpacing( mStackedDiagramSpacingSpinBox->value() );
232 const QList<QgsDiagramRenderer *> renderers = mModel->subRenderers();
236 if ( !ds1.isEmpty() )
238 ds->categoryAttributes += ds1.at( 0 ).categoryAttributes;
239 ds->categoryLabels += ds1.at( 0 ).categoryLabels;
240 ds->categoryColors += ds1.at( 0 ).categoryColors;
246 mLayer->setDiagramRenderer( dr );
250 mLayer->setDiagramLayerSettings( dls );
254 mLayer->triggerRepaint();
257bool QgsStackedDiagramProperties::couldBeFirstSubDiagram(
const QModelIndex &index )
const
259 if ( !index.isValid() )
267 const QList<QgsDiagramRenderer *> renderers = mModel->
subRenderers();
269 for (
int i = 0; i < index.row(); i++ )
273 if ( !ds.isEmpty() && ds.at( 0 ).enabled )
287void QgsStackedDiagramProperties::subDiagramWidgetPanelAccepted(
QgsPanelWidget *panel )
289 QgsDiagramProperties *widget = qobject_cast<QgsDiagramProperties *>( panel );
291 std::unique_ptr<QgsDiagramRenderer> renderer = widget->createRenderer();
293 const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
295 mModel->updateDiagramLayerSettings( widget->createDiagramLayerSettings() );
297 mModel->updateSubDiagram( index, renderer.release() );
300void QgsStackedDiagramProperties::liveUpdateSubDiagramFromPanel()
302 subDiagramWidgetPanelAccepted( qobject_cast<QgsPanelWidget *>( sender() ) );
313 setWindowModality( Qt::WindowModal );
316 QVBoxLayout *layout =
new QVBoxLayout(
this );
318 scrollArea->setFrameShape( QFrame::NoFrame );
319 layout->addWidget( scrollArea );
321 buttonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
323 mPropsWidget->setDockMode(
false );
325 scrollArea->setWidget( mPropsWidget );
326 layout->addWidget( buttonBox );
327 this->setWindowTitle(
"Edit Sub Diagram" );
331 connect( buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
332 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStackedDiagramPropertiesDialog::showHelp );
337 mPropsWidget->syncToRenderer( dr );
342 mPropsWidget->syncToSettings( dls );
348 mRenderer = mPropsWidget->createRenderer();
349 mDiagramLayerSettings = mPropsWidget->createDiagramLayerSettings();
355 return mRenderer.release();
360 return mDiagramLayerSettings;
365 mPropsWidget->setAllowedToEditDiagramLayerSettings( allowed );
370 return mPropsWidget->isAllowedToEditDiagramLayerSettings();
373void QgsStackedDiagramPropertiesDialog::showHelp()
375 QgsHelp::openHelp( u
"working_with_vector/vector_properties.html#diagrams-properties"_s );
381 : QAbstractTableModel( parent )
392 if ( !index.isValid() )
393 return Qt::ItemIsDropEnabled;
395 Qt::ItemFlags
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
397 if ( index.column() == 0 )
398 flags |= Qt::ItemIsUserCheckable;
405 return Qt::MoveAction;
411 types << u
"application/vnd.text.list"_s;
417 QMimeData *
mimeData =
new QMimeData();
418 QByteArray encodedData;
420 QDataStream stream( &encodedData, QIODevice::WriteOnly );
423 QModelIndexList sortedIndexes = indexes;
424 std::sort( sortedIndexes.begin(), sortedIndexes.end() );
426 for (
const QModelIndex &index : std::as_const( sortedIndexes ) )
429 if ( !index.isValid() || index.column() != 0 )
436 QDomElement rootElem = doc.createElement( u
"diagram_mime"_s );
438 doc.appendChild( rootElem );
439 stream << doc.toString( -1 );
443 mimeData->setData( u
"application/vnd.text.list"_s, encodedData );
452 if ( action == Qt::IgnoreAction )
455 if ( !
data->hasFormat( u
"application/vnd.text.list"_s ) )
458 QByteArray encodedData =
data->data( u
"application/vnd.text.list"_s );
459 QDataStream stream( &encodedData, QIODevice::ReadOnly );
468 while ( !stream.atEnd() )
474 if ( !doc.setContent( text ) )
476 const QDomElement rootElem = doc.documentElement();
477 if ( rootElem.tagName() !=
"diagram_mime"_L1 || !rootElem.hasChildNodes() )
479 const QDomElement childElem = rootElem.firstChild().toElement();
482 if ( childElem.nodeName() ==
"SingleCategoryDiagramRenderer"_L1 )
487 else if ( childElem.nodeName() ==
"LinearlyInterpolatedDiagramRenderer"_L1 )
492 else if ( childElem.nodeName() ==
"StackedDiagramRenderer"_L1 )
511 if ( !index.isValid() )
516 if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
518 switch ( index.column() )
525 return tr(
"Pie Chart" );
529 return tr(
"Text Diagram" );
533 return tr(
"Histogram" );
537 return tr(
"Stacked Bars" );
541 return tr(
"Stacked Diagram" );
550 return tr(
"(no diagram)" );
555 return tr(
"(no renderer)" );
560 return tr(
"Fixed" );
562 return tr(
"Scaled" );
564 return tr(
"Unknown" );
576 return tr(
"Right" );
589 else if ( role == Qt::CheckStateRole )
591 if ( index.column() != 0 )
604 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
607 lst << tr(
"Diagram type" ) << tr(
"Size" ) << tr(
"Orientation" );
626 if ( !index.isValid() )
631 if ( role == Qt::CheckStateRole )
636 ds.
enabled = ( value.toInt() == Qt::Checked );
649 emit dataChanged( index, index );
661 beginRemoveRows( parent, row, row + count - 1 );
671 if ( index.isValid() )
678 beginInsertRows( QModelIndex(), index, index );
685 if ( !index.isValid() )
690 emit dataChanged( index, index );
715 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
717 QStyleOption opt( *option );
718 opt.rect.setLeft( 0 );
720 opt.rect.setHeight( 0 );
722 opt.rect.setRight( widget->width() );
723 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
726 QProxyStyle::drawPrimitive( element, option, painter, widget );
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ MetersInMapUnits
Meters value as Map units.
Stores the settings for rendering of all diagrams for a layer.
A widget which configures diagrams for a vector layer.
void syncToSettings(const QgsDiagramLayerSettings *dls)
Updates the widget to reflect the diagram layer settings.
bool isAllowedToEditDiagramLayerSettings() const
Returns whether this widget is allowed to edit diagram layer settings.
void syncToRenderer(const QgsDiagramRenderer *dr)
Updates the widget to reflect the diagram renderer.
void auxiliaryFieldCreated()
void setAllowedToEditDiagramLayerSettings(bool allowed)
Sets whether the widget should show diagram layer settings.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
virtual QString rendererName() const =0
QgsDiagram * diagram() const
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads diagram state from a DOM element.
void setDiagram(QgsDiagram *d)
virtual QgsDiagramRenderer * clone() const =0
Returns new instance that is equivalent to this one.
Stores the settings for rendering a single diagram.
StackedDiagramMode
Orientation of the stacked diagrams.
virtual QString diagramName() const =0
Gets a descriptive name for this diagram type.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
static const QString DIAGRAM_NAME_HISTOGRAM
Alters the size of rendered diagrams using linear scaling.
void setDiagramSettings(const QgsDiagramSettings &s)
static const QString DIAGRAM_RENDERER_NAME_LINEARLY_INTERPOLATED
Map canvas is a class for displaying all GIS data types on a canvas.
static const QString DIAGRAM_NAME_PIE
static QgsProject * instance()
Returns the QgsProject singleton instance.
void setDirty(bool b=true)
Flag the project as dirty (modified).
QgsProxyStyle(QWidget *parent)
Constructor for QgsProxyStyle.
A container for the context for various read/write operations on objects.
Renders the diagrams for all features with the same settings.
void setDiagramSettings(const QgsDiagramSettings &s)
static const QString DIAGRAM_RENDERER_NAME_SINGLE_CATEGORY
static const QString DIAGRAM_NAME_STACKED_BAR
QgsStackedDiagramPropertiesDialog(QgsVectorLayer *layer, QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr)
Constructor for QgsStackedDiagramPropertiesDialog.
QgsDiagramLayerSettings diagramLayerSettings() const
Gets diagram layer settings built from the diagram properties widget.
void setAllowedToEditDiagramLayerSettings(bool allowed) const
Delegates to the main widget to set whether the widget should show diagram layer settings to be edite...
void syncToRenderer(const QgsDiagramRenderer *dr) const
Delegates to the diagram properties widget to sync with the given renderer.
void syncToSettings(const QgsDiagramLayerSettings *dls) const
Delegates to the diagram properties widget to sync with the given diagram layer settings.
bool isAllowedToEditDiagramLayerSettings() const
Returns whether the main widget is allowed to edit diagram layer settings.
void accept() override
Applies changes from the widget to the internal renderer and diagram layer settings.
QgsDiagramRenderer * renderer()
Gets a renderer object built from the diagram properties widget.
Model for sub diagrams in a stacked diagram view.
Qt::DropActions supportedDropActions() const override
~QgsStackedDiagramPropertiesModel() override
QMimeData * mimeData(const QModelIndexList &indexes) const override
void updateSubDiagram(const QModelIndex &index, QgsDiagramRenderer *dr)
Replaces the diagram located at index by dr. Takes ownership.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
void insertSubDiagram(const int index, QgsDiagramRenderer *newSubDiagram)
Inserts a new diagram at the specified position. Takes ownership.
QStringList mimeTypes() const override
QList< QgsDiagramRenderer * > mRenderers
QgsDiagramLayerSettings mDiagramLayerSettings
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QgsDiagramRenderer * subDiagramForIndex(const QModelIndex &index) const
Returns the diagram renderer at the specified index. Does not transfer ownership.
void updateDiagramLayerSettings(QgsDiagramLayerSettings dls)
Sets the diagram layer settings for the model.
Qt::ItemFlags flags(const QModelIndex &index) const override
QgsDiagramLayerSettings diagramLayerSettings() const
Returns the diagram layer settings from the model.
QList< QgsDiagramRenderer * > subRenderers() const
Returns the list of diagram renderers from the model. Does not transfer ownership.
int columnCount(const QModelIndex &=QModelIndex()) const override
void subDiagramsMoved()
Informs views that subdiagrams were moved in the model.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QgsStackedDiagramPropertiesModel(QObject *parent=nullptr)
constructor
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int rowCount(const QModelIndex &=QModelIndex()) const override
void clearCurrentIndex()
Clears current item from the view.
void syncToLayer()
Updates the widget to reflect the layer's current diagram settings.
void auxiliaryFieldCreated()
QgsStackedDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)
Renders diagrams using mixed diagram render types.
void setDiagramSettings(const QgsDiagramSettings &s)
static const QString DIAGRAM_RENDERER_NAME_STACKED
void addRenderer(QgsDiagramRenderer *renderer)
Adds a renderer to the stacked renderer object.
QList< QgsDiagramRenderer * > renderers(bool sortByDiagramMode=false) const
Returns an ordered list with the renderers of the stacked renderer object.
A diagram composed of several subdiagrams, located side by side.
static const QString DIAGRAM_NAME_STACKED
View style which shows a drop indicator line between items.
QgsStackedDiagramsViewStyle(QWidget *parent)
Constructor for QgsStackedDiagramsViewStyle.
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget=nullptr) const override
static const QString DIAGRAM_NAME_TEXT
Represents a vector layer which manages a vector based dataset.