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 );
68 mSubDiagramsView->setModel( mModel );
81void QgsStackedDiagramProperties::addSubDiagramRenderer()
84 std::unique_ptr<QgsDiagramRenderer> renderer;
85 auto dr = std::make_unique<QgsSingleCategoryDiagramRenderer>();
86 renderer = std::move( dr );
88 QItemSelectionModel *sel = mSubDiagramsView->selectionModel();
89 const QModelIndex index = sel->currentIndex();
91 if ( index.isValid() )
94 const QModelIndex currentIndex = mSubDiagramsView->selectionModel()->currentIndex();
96 const QModelIndex newIndex = mModel->index( currentIndex.row() + 1, 0 );
97 mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
102 appendSubDiagramRenderer( renderer.release() );
104 editSubDiagramRenderer();
109 const int rows = mModel->rowCount();
110 mModel->insertSubDiagram( rows, dr );
111 const QModelIndex newIndex = mModel->index( rows, 0 );
112 mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
115void QgsStackedDiagramProperties::editSubDiagramRenderer()
117 editSubDiagramRenderer( mSubDiagramsView->selectionModel()->currentIndex() );
120void QgsStackedDiagramProperties::editSubDiagramRenderer(
const QModelIndex &index )
122 if ( !index.isValid() )
125 QgsDiagramRenderer *renderer = mModel->subDiagramForIndex( index );
126 QgsDiagramLayerSettings dls = mModel->diagramLayerSettings();
131 QgsDiagramProperties *widget =
new QgsDiagramProperties( mLayer,
this, mMapCanvas );
133 widget->layout()->setContentsMargins( 0, 0, 0, 0 );
136 if ( !couldBeFirstSubDiagram( index ) )
148 QgsStackedDiagramPropertiesDialog dlg( mLayer,
this, mMapCanvas );
149 dlg.syncToRenderer( renderer );
150 dlg.syncToSettings( &dls );
151 if ( !couldBeFirstSubDiagram( index ) )
153 dlg.setAllowedToEditDiagramLayerSettings(
false );
158 const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
159 if ( dlg.isAllowedToEditDiagramLayerSettings() )
160 mModel->updateDiagramLayerSettings( dlg.diagramLayerSettings() );
163 mModel->updateSubDiagram( index, dlg.renderer() );
167void QgsStackedDiagramProperties::removeSubDiagramRenderer()
169 const QItemSelection sel = mSubDiagramsView->selectionModel()->selection();
170 const auto constSel = sel;
171 for (
const QItemSelectionRange &range : constSel )
173 if ( range.isValid() )
174 mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
177 mSubDiagramsView->selectionModel()->clear();
182 mSubDiagramsView->selectionModel()->clearCurrentIndex();
192 mStackedDiagramModeComboBox->setCurrentIndex( settingList.at( 0 ).stackedDiagramMode );
193 mStackedDiagramSpacingSpinBox->setValue( settingList.at( 0 ).stackedDiagramSpacing() );
194 mStackedDiagramSpacingUnitComboBox->setUnit( settingList.at( 0 ).stackedDiagramSpacingUnit() );
199 const QList<QgsDiagramRenderer *> renderers = stackedDiagramRenderer->
renderers();
202 appendSubDiagramRenderer( renderer->
clone() );
208 appendSubDiagramRenderer( dr->
clone() );
212 mModel->updateDiagramLayerSettings( *dls );
214 mSubDiagramsView->selectionModel()->clear();
220 auto ds = std::make_unique<QgsDiagramSettings>();
222 ds->setStackedDiagramSpacingUnit( mStackedDiagramSpacingUnitComboBox->unit() );
223 ds->setStackedDiagramSpacing( mStackedDiagramSpacingSpinBox->value() );
230 const QList<QgsDiagramRenderer *> renderers = mModel->subRenderers();
234 if ( !ds1.isEmpty() )
236 ds->categoryAttributes += ds1.at( 0 ).categoryAttributes;
237 ds->categoryLabels += ds1.at( 0 ).categoryLabels;
238 ds->categoryColors += ds1.at( 0 ).categoryColors;
244 mLayer->setDiagramRenderer( dr );
248 mLayer->setDiagramLayerSettings( dls );
252 mLayer->triggerRepaint();
255bool QgsStackedDiagramProperties::couldBeFirstSubDiagram(
const QModelIndex &index )
const
257 if ( !index.isValid() )
265 const QList<QgsDiagramRenderer *> renderers = mModel->
subRenderers();
267 for (
int i = 0; i < index.row(); i++ )
271 if ( !ds.isEmpty() && ds.at( 0 ).enabled )
285void QgsStackedDiagramProperties::subDiagramWidgetPanelAccepted(
QgsPanelWidget *panel )
287 QgsDiagramProperties *widget = qobject_cast<QgsDiagramProperties *>( panel );
289 std::unique_ptr<QgsDiagramRenderer> renderer = widget->createRenderer();
291 const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
293 mModel->updateDiagramLayerSettings( widget->createDiagramLayerSettings() );
295 mModel->updateSubDiagram( index, renderer.release() );
298void QgsStackedDiagramProperties::liveUpdateSubDiagramFromPanel()
300 subDiagramWidgetPanelAccepted( qobject_cast<QgsPanelWidget *>( sender() ) );
311 setWindowModality( Qt::WindowModal );
314 QVBoxLayout *layout =
new QVBoxLayout(
this );
316 scrollArea->setFrameShape( QFrame::NoFrame );
317 layout->addWidget( scrollArea );
319 buttonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
321 mPropsWidget->setDockMode(
false );
323 scrollArea->setWidget( mPropsWidget );
324 layout->addWidget( buttonBox );
325 this->setWindowTitle(
"Edit Sub Diagram" );
329 connect( buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
330 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsStackedDiagramPropertiesDialog::showHelp );
335 mPropsWidget->syncToRenderer( dr );
340 mPropsWidget->syncToSettings( dls );
346 mRenderer = mPropsWidget->createRenderer();
347 mDiagramLayerSettings = mPropsWidget->createDiagramLayerSettings();
353 return mRenderer.release();
358 return mDiagramLayerSettings;
363 mPropsWidget->setAllowedToEditDiagramLayerSettings( allowed );
368 return mPropsWidget->isAllowedToEditDiagramLayerSettings();
371void QgsStackedDiagramPropertiesDialog::showHelp()
373 QgsHelp::openHelp( u
"working_with_vector/vector_properties.html#diagrams-properties"_s );
379 : QAbstractTableModel( parent )
391 if ( !index.isValid() )
392 return Qt::ItemIsDropEnabled;
394 Qt::ItemFlags
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
396 if ( index.column() == 0 )
397 flags |= Qt::ItemIsUserCheckable;
404 return Qt::MoveAction;
410 types << u
"application/vnd.text.list"_s;
416 QMimeData *
mimeData =
new QMimeData();
417 QByteArray encodedData;
419 QDataStream stream( &encodedData, QIODevice::WriteOnly );
422 QModelIndexList sortedIndexes = indexes;
423 std::sort( sortedIndexes.begin(), sortedIndexes.end() );
425 for (
const QModelIndex &index : std::as_const( sortedIndexes ) )
428 if ( !index.isValid() || index.column() != 0 )
435 QDomElement rootElem = doc.createElement( u
"diagram_mime"_s );
437 doc.appendChild( rootElem );
438 stream << doc.toString( -1 );
442 mimeData->setData( u
"application/vnd.text.list"_s, encodedData );
451 if ( action == Qt::IgnoreAction )
454 if ( !
data->hasFormat( u
"application/vnd.text.list"_s ) )
457 QByteArray encodedData =
data->data( u
"application/vnd.text.list"_s );
458 QDataStream stream( &encodedData, QIODevice::ReadOnly );
467 while ( !stream.atEnd() )
473 if ( !doc.setContent( text ) )
475 const QDomElement rootElem = doc.documentElement();
476 if ( rootElem.tagName() !=
"diagram_mime"_L1 || !rootElem.hasChildNodes() )
478 const QDomElement childElem = rootElem.firstChild().toElement();
481 if ( childElem.nodeName() ==
"SingleCategoryDiagramRenderer"_L1 )
486 else if ( childElem.nodeName() ==
"LinearlyInterpolatedDiagramRenderer"_L1 )
491 else if ( childElem.nodeName() ==
"StackedDiagramRenderer"_L1 )
510 if ( !index.isValid() )
515 if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
517 switch ( index.column() )
524 return tr(
"Pie Chart" );
528 return tr(
"Text Diagram" );
532 return tr(
"Histogram" );
536 return tr(
"Stacked Bars" );
540 return tr(
"Stacked Diagram" );
549 return tr(
"(no diagram)" );
554 return tr(
"(no renderer)" );
559 return tr(
"Fixed" );
561 return tr(
"Scaled" );
563 return tr(
"Unknown" );
575 return tr(
"Right" );
588 else if ( role == Qt::CheckStateRole )
590 if ( index.column() != 0 )
603 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
606 lst << tr(
"Diagram type" ) << tr(
"Size" ) << tr(
"Orientation" );
625 if ( !index.isValid() )
630 if ( role == Qt::CheckStateRole )
635 ds.
enabled = ( value.toInt() == Qt::Checked );
648 emit dataChanged( index, index );
660 beginRemoveRows( parent, row, row + count - 1 );
670 if ( index.isValid() )
677 beginInsertRows( QModelIndex(), index, index );
684 if ( !index.isValid() )
689 emit dataChanged( index, index );
714 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
716 QStyleOption opt( *option );
717 opt.rect.setLeft( 0 );
719 opt.rect.setHeight( 0 );
721 opt.rect.setRight( widget->width() );
722 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
725 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.