mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
[gui] Move Diagrams properties to a panel widget, showing tabs instead of a list when docked; harmonize stacked diagram configuration with rule-based labeling; allow QgsDiagramProperties to sync to renderers and diagram layer settings, in addition to syncing to layers; when editing a subdiagram of a stacked diagram, only show widgets for diagram layer settings if the subdiagram is the first one, for the rest, hide those widgets and show a note informing users; make sure stacked diagrams handle enabled and disabled subdiagrams (i.e., don't take into account disabled subdiagrams) and add a test for it; switching from single to stacked diagram: take the single diagram definition as the first stacked diagram; fix #58782 (calling twice the apply method for label rendering)
This commit is contained in:
parent
e855941a34
commit
f81df2876c
@ -1017,30 +1017,24 @@ Writes stacked renderers state to a DOM element.
|
||||
virtual QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const /Factory/;
|
||||
|
||||
|
||||
QList< QgsDiagramRenderer * > renderers() const;
|
||||
QList< QgsDiagramRenderer * > renderers( bool sortByDiagramMode = false ) const;
|
||||
%Docstring
|
||||
Returns an ordered list with the renderers of the stacked renderer object.
|
||||
If the stacked diagram orientation is vertical, the list is returned backwards.
|
||||
@param sortByDiagramMode If true, the list is returned backwards for vertical orientation.
|
||||
%End
|
||||
|
||||
void addRenderer( QgsDiagramRenderer *renderer );
|
||||
%Docstring
|
||||
Adds a renderer to the stacked renderer object.
|
||||
|
||||
:param renderer: diagram renderer to be added to the stacked renderer
|
||||
Renderers added first will render their diagrams first, i.e., more to
|
||||
the left (horizontal mode) or more to the top (vertical mode).
|
||||
@param renderer diagram renderer to be added to the stacked renderer
|
||||
Renderers added first will render their diagrams first, i.e., more to
|
||||
the left (horizontal mode) or more to the top (vertical mode).
|
||||
%End
|
||||
|
||||
const QgsDiagramRenderer *renderer( const int index ) const;
|
||||
%Docstring
|
||||
Returns the renderer at the given ``index``.
|
||||
@param index index of the disired renderer in the stacked renderer
|
||||
%End
|
||||
|
||||
int rendererCount() const;
|
||||
%Docstring
|
||||
Returns the number of renderers that this stacked renderer is composed of.
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
@ -1017,30 +1017,24 @@ Writes stacked renderers state to a DOM element.
|
||||
virtual QList< QgsLayerTreeModelLegendNode * > legendItems( QgsLayerTreeLayer *nodeLayer ) const /Factory/;
|
||||
|
||||
|
||||
QList< QgsDiagramRenderer * > renderers() const;
|
||||
QList< QgsDiagramRenderer * > renderers( bool sortByDiagramMode = false ) const;
|
||||
%Docstring
|
||||
Returns an ordered list with the renderers of the stacked renderer object.
|
||||
If the stacked diagram orientation is vertical, the list is returned backwards.
|
||||
@param sortByDiagramMode If true, the list is returned backwards for vertical orientation.
|
||||
%End
|
||||
|
||||
void addRenderer( QgsDiagramRenderer *renderer );
|
||||
%Docstring
|
||||
Adds a renderer to the stacked renderer object.
|
||||
|
||||
:param renderer: diagram renderer to be added to the stacked renderer
|
||||
Renderers added first will render their diagrams first, i.e., more to
|
||||
the left (horizontal mode) or more to the top (vertical mode).
|
||||
@param renderer diagram renderer to be added to the stacked renderer
|
||||
Renderers added first will render their diagrams first, i.e., more to
|
||||
the left (horizontal mode) or more to the top (vertical mode).
|
||||
%End
|
||||
|
||||
const QgsDiagramRenderer *renderer( const int index ) const;
|
||||
%Docstring
|
||||
Returns the renderer at the given ``index``.
|
||||
@param index index of the disired renderer in the stacked renderer
|
||||
%End
|
||||
|
||||
int rendererCount() const;
|
||||
%Docstring
|
||||
Returns the number of renderers that this stacked renderer is composed of.
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
@ -8049,35 +8049,8 @@ void QgisApp::diagramProperties()
|
||||
return;
|
||||
}
|
||||
|
||||
QDialog dlg;
|
||||
dlg.setWindowTitle( tr( "Layer Diagram Properties" ) );
|
||||
QgsStackedDiagramProperties *gui = new QgsStackedDiagramProperties( vlayer, &dlg, mMapCanvas );
|
||||
gui->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
QVBoxLayout *layout = new QVBoxLayout( &dlg );
|
||||
layout->addWidget( gui );
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply,
|
||||
Qt::Horizontal, &dlg );
|
||||
layout->addWidget( buttonBox );
|
||||
|
||||
dlg.setLayout( layout );
|
||||
|
||||
connect( buttonBox->button( QDialogButtonBox::Ok ), &QAbstractButton::clicked,
|
||||
&dlg, &QDialog::accept );
|
||||
connect( buttonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked,
|
||||
&dlg, &QDialog::reject );
|
||||
connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked,
|
||||
gui, &QgsStackedDiagramProperties::apply );
|
||||
connect( buttonBox->button( QDialogButtonBox::Help ), &QAbstractButton::clicked, gui, [ = ]
|
||||
{
|
||||
QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#diagrams-properties" ) );
|
||||
} );
|
||||
|
||||
if ( dlg.exec() )
|
||||
gui->apply();
|
||||
|
||||
activateDeactivateLayerRelatedActions( vlayer );
|
||||
mapStyleDock( true );
|
||||
mMapStyleWidget->setCurrentPage( QgsLayerStylingWidget::VectorDiagram );
|
||||
}
|
||||
|
||||
void QgisApp::createAnnotationLayer()
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslabelingwidget.h"
|
||||
#include "qgsmaskingwidget.h"
|
||||
#include "qgsdiagramwidget.h"
|
||||
#include "qgslayerstylingwidget.h"
|
||||
#include "qgsrastertransparencywidget.h"
|
||||
#include "qgsrendererpropertiesdialog.h"
|
||||
@ -217,6 +218,11 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
|
||||
symbol3DItem->setToolTip( tr( "3D View" ) );
|
||||
mOptionsListWidget->addItem( symbol3DItem );
|
||||
#endif
|
||||
|
||||
QListWidgetItem *diagramItem = new QListWidgetItem( QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/diagram.svg" ) ), QString() );
|
||||
diagramItem->setData( Qt::UserRole, VectorDiagram );
|
||||
diagramItem->setToolTip( tr( "Diagrams" ) );
|
||||
mOptionsListWidget->addItem( diagramItem );
|
||||
break;
|
||||
}
|
||||
case Qgis::LayerType::Raster:
|
||||
@ -334,12 +340,6 @@ void QgsLayerStylingWidget::apply()
|
||||
|
||||
bool styleWasChanged = false;
|
||||
bool triggerRepaint = false; // whether the change needs the layer to be repainted
|
||||
if ( QgsLabelingWidget *widget = qobject_cast<QgsLabelingWidget *>( current ) )
|
||||
{
|
||||
widget->apply();
|
||||
styleWasChanged = true;
|
||||
undoName = QStringLiteral( "Label Change" );
|
||||
}
|
||||
if ( QgsMaskingWidget *widget = qobject_cast<QgsMaskingWidget *>( current ) )
|
||||
{
|
||||
widget->apply();
|
||||
@ -373,8 +373,23 @@ void QgsLayerStylingWidget::apply()
|
||||
styleWasChanged = true;
|
||||
triggerRepaint = true;
|
||||
}
|
||||
else if ( QgsLabelingWidget *widget = qobject_cast<QgsLabelingWidget *>( current ) )
|
||||
{
|
||||
widget->apply();
|
||||
styleWasChanged = true;
|
||||
undoName = QStringLiteral( "Label Change" );
|
||||
}
|
||||
else if ( QgsDiagramWidget *widget = qobject_cast<QgsDiagramWidget *>( current ) )
|
||||
{
|
||||
widget->apply();
|
||||
styleWasChanged = true;
|
||||
undoName = QStringLiteral( "Diagram Change" );
|
||||
}
|
||||
else if ( QgsMapLayerConfigWidget *widget = qobject_cast<QgsMapLayerConfigWidget *>( current ) )
|
||||
{
|
||||
// Warning: All classes inheriting from QgsMapLayerConfigWidget
|
||||
// should come in the current if block, before this else-if
|
||||
// clause, to avoid duplicate calls to apply()!
|
||||
widget->apply();
|
||||
styleWasChanged = true;
|
||||
triggerRepaint = widget->shouldTriggerLayerRepaint();
|
||||
@ -463,6 +478,10 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
|
||||
mMesh3DWidget = widget;
|
||||
}
|
||||
#endif
|
||||
else if ( QgsDiagramWidget *widget = qobject_cast<QgsDiagramWidget *>( current ) )
|
||||
{
|
||||
mDiagramWidget = widget;
|
||||
}
|
||||
}
|
||||
|
||||
mWidgetStack->clear();
|
||||
@ -495,6 +514,11 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
|
||||
{
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCurrentLayer );
|
||||
|
||||
#ifdef HAVE_3D
|
||||
const int tabShift = 1; // To move subsequent tabs
|
||||
#else
|
||||
const int tabShift = 0;
|
||||
#endif
|
||||
switch ( row )
|
||||
{
|
||||
case 0: // Style
|
||||
@ -550,6 +574,15 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case 3 + tabShift: // Diagrams
|
||||
{
|
||||
mDiagramWidget = new QgsDiagramWidget( vlayer, mMapCanvas, mWidgetStack );
|
||||
mDiagramWidget->setDockMode( true );
|
||||
connect( mDiagramWidget, &QgsDiagramWidget::widgetChanged, this, &QgsLayerStylingWidget::autoApply );
|
||||
mDiagramWidget->syncToOwnLayer();
|
||||
mWidgetStack->setMainPanel( mDiagramWidget );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
class QgsLabelingWidget;
|
||||
class QgsMaskingWidget;
|
||||
class QgsDiagramWidget;
|
||||
class QgsMapLayer;
|
||||
class QgsMapCanvas;
|
||||
class QgsRendererPropertiesDialog;
|
||||
@ -101,6 +102,7 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
|
||||
History,
|
||||
Symbology3D,
|
||||
RasterAttributeTables, //!< Raster attribute tables, since QGIS 3.30
|
||||
VectorDiagram, //!< Vector diagram, since QGIS 3.40
|
||||
};
|
||||
|
||||
QgsLayerStylingWidget( QgsMapCanvas *canvas, QgsMessageBar *messageBar, const QList<const QgsMapLayerConfigWidgetFactory *> &pages, QWidget *parent = nullptr );
|
||||
@ -175,6 +177,7 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
|
||||
QgsVectorLayer3DRendererWidget *mVector3DWidget = nullptr;
|
||||
QgsMeshLayer3DRendererWidget *mMesh3DWidget = nullptr;
|
||||
#endif
|
||||
QgsDiagramWidget *mDiagramWidget = nullptr;
|
||||
QgsRendererRasterPropertiesWidget *mRasterStyleWidget = nullptr;
|
||||
QgsRasterAttributeTableWidget *mRasterAttributeTableWidget = nullptr;
|
||||
QgsPanelWidget *mRasterAttributeTableDisabledWidget = nullptr;
|
||||
|
@ -528,7 +528,7 @@ void QgsDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRenderCont
|
||||
QSizeF QgsDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const QgsRenderContext &c ) const
|
||||
{
|
||||
QgsDiagramSettings s;
|
||||
if ( !diagramSettings( feature, c, s ) )
|
||||
if ( !diagramSettings( feature, c, s ) || !s.enabled )
|
||||
{
|
||||
return QSizeF();
|
||||
}
|
||||
@ -845,16 +845,18 @@ QgsStackedDiagramRenderer *QgsStackedDiagramRenderer::clone() const
|
||||
QSizeF QgsStackedDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const QgsRenderContext &c ) const
|
||||
{
|
||||
QSizeF stackedSize( 0, 0 );
|
||||
int enabledDiagramCount = 0; // We'll add spacing only for enabled subDiagrams
|
||||
|
||||
// Iterate renderers. For each renderer, get the diagram
|
||||
// size for the feature and add it to the total size
|
||||
// accounting for stacked diagram defined spacing
|
||||
for ( int i = 0; i < mDiagramRenderers.count(); i++ )
|
||||
for ( const auto &subRenderer : std::as_const( mDiagramRenderers ) )
|
||||
{
|
||||
QSizeF size = mDiagramRenderers.at( i )->sizeMapUnits( feature, c );
|
||||
QSizeF size = subRenderer->sizeMapUnits( feature, c );
|
||||
|
||||
if ( size.isValid() )
|
||||
{
|
||||
enabledDiagramCount++;
|
||||
switch ( mSettings.stackedDiagramMode )
|
||||
{
|
||||
case QgsDiagramSettings::Horizontal:
|
||||
@ -875,11 +877,11 @@ QSizeF QgsStackedDiagramRenderer::sizeMapUnits( const QgsFeature &feature, const
|
||||
switch ( mSettings.stackedDiagramMode )
|
||||
{
|
||||
case QgsDiagramSettings::Horizontal:
|
||||
stackedSize.scale( stackedSize.width() + spacing * ( mDiagramRenderers.count() - 1 ), stackedSize.height(), Qt::IgnoreAspectRatio );
|
||||
stackedSize.scale( stackedSize.width() + spacing * ( enabledDiagramCount - 1 ), stackedSize.height(), Qt::IgnoreAspectRatio );
|
||||
break;
|
||||
|
||||
case QgsDiagramSettings::Vertical:
|
||||
stackedSize.scale( stackedSize.width(), stackedSize.height() + spacing * ( mDiagramRenderers.count() - 1 ), Qt::IgnoreAspectRatio );
|
||||
stackedSize.scale( stackedSize.width(), stackedSize.height() + spacing * ( enabledDiagramCount - 1 ), Qt::IgnoreAspectRatio );
|
||||
break;
|
||||
}
|
||||
return stackedSize;
|
||||
@ -893,11 +895,15 @@ void QgsStackedDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRen
|
||||
}
|
||||
|
||||
QPointF newPos = pos; // Each subdiagram will have its own newPos
|
||||
QList< QgsDiagramRenderer * > stackedRenderers = renderers();
|
||||
for ( const auto &stackedRenderer : std::as_const( stackedRenderers ) )
|
||||
|
||||
// Get subrenderers sorted by mode (vertical diagrams are returned backwards)
|
||||
const QList< QgsDiagramRenderer * > stackedRenderers = renderers( true );
|
||||
|
||||
for ( const auto &stackedRenderer : stackedRenderers )
|
||||
{
|
||||
if ( stackedRenderer->rendererName() == QStringLiteral( "Stacked" ) )
|
||||
{
|
||||
// Nested stacked diagrams will use this recursion
|
||||
stackedRenderer->renderDiagram( feature, c, newPos, properties );
|
||||
continue;
|
||||
}
|
||||
@ -905,7 +911,12 @@ void QgsStackedDiagramRenderer::renderDiagram( const QgsFeature &feature, QgsRen
|
||||
QgsDiagramSettings s;
|
||||
if ( !stackedRenderer->diagramSettings( feature, c, s ) )
|
||||
{
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !s.enabled )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( properties.hasActiveProperties() )
|
||||
@ -963,26 +974,19 @@ QList<QString> QgsStackedDiagramRenderer::diagramAttributes() const
|
||||
QList< QgsLayerTreeModelLegendNode * > QgsStackedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
|
||||
{
|
||||
QList< QgsLayerTreeModelLegendNode * > nodes;
|
||||
for ( int i = 0; i < rendererCount(); i++ )
|
||||
for ( const auto &renderer : std::as_const( mDiagramRenderers ) )
|
||||
{
|
||||
nodes << mDiagramRenderers.at( i )->legendItems( nodeLayer );
|
||||
nodes << renderer->legendItems( nodeLayer );
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
QList< QgsDiagramRenderer * > QgsStackedDiagramRenderer::renderers() const
|
||||
QList< QgsDiagramRenderer * > QgsStackedDiagramRenderer::renderers( bool sortByDiagramMode ) const
|
||||
{
|
||||
QList< QgsDiagramRenderer * > renderers;
|
||||
|
||||
if ( mSettings.stackedDiagramMode == QgsDiagramSettings::Horizontal )
|
||||
{
|
||||
for ( const auto &item : std::as_const( mDiagramRenderers ) )
|
||||
{
|
||||
renderers.append( item );
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( sortByDiagramMode && mSettings.stackedDiagramMode == QgsDiagramSettings::Vertical )
|
||||
{
|
||||
// We draw vertical diagrams backwards, so
|
||||
// we return the subrenderers in reverse order
|
||||
@ -992,6 +996,10 @@ QList< QgsDiagramRenderer * > QgsStackedDiagramRenderer::renderers() const
|
||||
renderers.append( *iter );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderers = mDiagramRenderers;
|
||||
}
|
||||
return renderers;
|
||||
}
|
||||
|
||||
@ -1013,11 +1021,6 @@ const QgsDiagramRenderer *QgsStackedDiagramRenderer::renderer( const int index )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int QgsStackedDiagramRenderer::rendererCount() const
|
||||
{
|
||||
return mDiagramRenderers.count();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
|
||||
{
|
||||
const QDomElement categoryElem = elem.firstChildElement( QStringLiteral( "DiagramCategory" ) );
|
||||
@ -1234,7 +1237,7 @@ QList< QgsLayerTreeModelLegendNode * > QgsDiagramRenderer::legendItems( QgsLayer
|
||||
QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
|
||||
{
|
||||
QList< QgsLayerTreeModelLegendNode * > nodes;
|
||||
if ( mShowAttributeLegend )
|
||||
if ( mShowAttributeLegend && mSettings.enabled )
|
||||
nodes = mSettings.legendItems( nodeLayer );
|
||||
|
||||
return nodes;
|
||||
@ -1243,6 +1246,11 @@ QList< QgsLayerTreeModelLegendNode * > QgsSingleCategoryDiagramRenderer::legendI
|
||||
QList< QgsLayerTreeModelLegendNode * > QgsLinearlyInterpolatedDiagramRenderer::legendItems( QgsLayerTreeLayer *nodeLayer ) const
|
||||
{
|
||||
QList< QgsLayerTreeModelLegendNode * > nodes;
|
||||
if ( !mSettings.enabled )
|
||||
{
|
||||
return nodes;
|
||||
}
|
||||
|
||||
if ( mShowAttributeLegend )
|
||||
nodes = mSettings.legendItems( nodeLayer );
|
||||
|
||||
|
@ -1039,13 +1039,13 @@ class CORE_EXPORT QgsStackedDiagramRenderer : public QgsDiagramRenderer
|
||||
|
||||
/**
|
||||
* Returns an ordered list with the renderers of the stacked renderer object.
|
||||
* If the stacked diagram orientation is vertical, the list is returned backwards.
|
||||
* @param sortByDiagramMode If true, the list is returned backwards for vertical orientation.
|
||||
*/
|
||||
QList< QgsDiagramRenderer * > renderers() const;
|
||||
QList< QgsDiagramRenderer * > renderers( bool sortByDiagramMode = false ) const;
|
||||
|
||||
/**
|
||||
* Adds a renderer to the stacked renderer object.
|
||||
* \param renderer diagram renderer to be added to the stacked renderer
|
||||
* @param renderer diagram renderer to be added to the stacked renderer
|
||||
* Renderers added first will render their diagrams first, i.e., more to
|
||||
* the left (horizontal mode) or more to the top (vertical mode).
|
||||
*/
|
||||
@ -1057,11 +1057,6 @@ class CORE_EXPORT QgsStackedDiagramRenderer : public QgsDiagramRenderer
|
||||
*/
|
||||
const QgsDiagramRenderer *renderer( const int index ) const;
|
||||
|
||||
/**
|
||||
* Returns the number of renderers that this stacked renderer is composed of.
|
||||
*/
|
||||
int rendererCount() const;
|
||||
|
||||
protected:
|
||||
bool diagramSettings( const QgsFeature &feature, const QgsRenderContext &c, QgsDiagramSettings &s ) const override;
|
||||
QSizeF diagramSize( const QgsFeature &, const QgsRenderContext &c ) const override;
|
||||
|
@ -35,6 +35,7 @@ set(QGIS_GUI_SRCS
|
||||
vector/qgsattributesforminitcode.cpp
|
||||
vector/qgsattributesformproperties.cpp
|
||||
vector/qgsdiagramproperties.cpp
|
||||
vector/qgsdiagramwidget.cpp
|
||||
vector/qgsfieldcalculator.cpp
|
||||
vector/qgsjoindialog.cpp
|
||||
vector/qgssourcefieldsproperties.cpp
|
||||
@ -1497,6 +1498,7 @@ set(QGIS_GUI_HDRS
|
||||
vector/qgsattributesforminitcode.h
|
||||
vector/qgsattributesformproperties.h
|
||||
vector/qgsdiagramproperties.h
|
||||
vector/qgsdiagramwidget.h
|
||||
vector/qgsfieldcalculator.h
|
||||
vector/qgsjoindialog.h
|
||||
vector/qgssourcefieldsproperties.h
|
||||
|
@ -59,10 +59,10 @@ QgsExpressionContext QgsDiagramProperties::createExpressionContext() const
|
||||
}
|
||||
|
||||
QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas )
|
||||
: QWidget( parent )
|
||||
: QgsPanelWidget( parent )
|
||||
, mLayer( layer )
|
||||
, mMapCanvas( canvas )
|
||||
{
|
||||
mLayer = layer;
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
@ -80,6 +80,10 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
|
||||
// get rid of annoying outer focus rect on Mac
|
||||
mDiagramOptionsListWidget->setAttribute( Qt::WA_MacShowFocusRect, false );
|
||||
|
||||
const int iconSize = QgsGuiUtils::scaleIconSize( 20 );
|
||||
mOptionsTab->setIconSize( QSize( iconSize, iconSize ) );
|
||||
mDiagramOptionsListWidget->setIconSize( QSize( iconSize, iconSize ) ) ;
|
||||
|
||||
mBarSpacingSpinBox->setClearValue( 0 );
|
||||
mBarSpacingUnitComboBox->setUnits( { Qgis::RenderUnit::Millimeters,
|
||||
Qgis::RenderUnit::MetersInMapUnits,
|
||||
@ -144,6 +148,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
|
||||
if ( layerType == Qgis::GeometryType::Unknown || layerType == Qgis::GeometryType::Null )
|
||||
{
|
||||
mDiagramTypeComboBox->setEnabled( false );
|
||||
mOptionsTab->setEnabled( false );
|
||||
mDiagramFrame->setEnabled( false );
|
||||
}
|
||||
|
||||
@ -224,6 +229,10 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
|
||||
mDiagramOptionsSplitter->restoreState( settings.value( QStringLiteral( "Windows/Diagrams/OptionsSplitState" ) ).toByteArray() );
|
||||
mDiagramOptionsListWidget->setCurrentRow( settings.value( QStringLiteral( "Windows/Diagrams/Tab" ), 0 ).toInt() );
|
||||
|
||||
// set correct initial tab to match displayed setting page
|
||||
whileBlocking( mOptionsTab )->setCurrentIndex( mDiagramStackedWidget->currentIndex() );
|
||||
mOptionsTab->tabBar()->setUsesScrollButtons( true );
|
||||
|
||||
// field combo and expression button
|
||||
mSizeFieldExpressionWidget->setLayer( mLayer );
|
||||
QgsDistanceArea myDa;
|
||||
@ -250,6 +259,11 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
|
||||
mOrientationUpButton->setProperty( "direction", QgsDiagramSettings::Up );
|
||||
mOrientationDownButton->setProperty( "direction", QgsDiagramSettings::Down );
|
||||
|
||||
// Labels to let users know some widgets are not present
|
||||
// when editing sub diagrams in a stacked diagram.
|
||||
mDlsLabel_1->hide();
|
||||
mDlsLabel_2->hide();
|
||||
|
||||
//force a refresh of widget status to match diagram type
|
||||
mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
|
||||
|
||||
@ -268,15 +282,99 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
|
||||
registerDataDefinedButton( mStartAngleDDBtn, QgsDiagramLayerSettings::Property::StartAngle );
|
||||
|
||||
connect( mButtonSizeLegendSettings, &QPushButton::clicked, this, &QgsDiagramProperties::showSizeLegendDialog );
|
||||
|
||||
QList<QWidget *> widgets;
|
||||
widgets << chkLineAbove;
|
||||
widgets << chkLineBelow;
|
||||
widgets << chkLineOn;
|
||||
widgets << chkLineOrientationDependent;
|
||||
widgets << mAngleDirectionComboBox;
|
||||
widgets << mAngleOffsetComboBox;
|
||||
widgets << mAttributeBasedScalingRadio;
|
||||
widgets << mAxisLineStyleButton;
|
||||
widgets << mBackgroundColorButton;
|
||||
widgets << mBarSpacingSpinBox;
|
||||
widgets << mBarSpacingUnitComboBox;
|
||||
widgets << mBarWidthSpinBox;
|
||||
widgets << mCheckBoxAttributeLegend;
|
||||
widgets << mDiagramAttributesTreeWidget;
|
||||
widgets << mDiagramDistanceSpinBox;
|
||||
//widgets << mDiagramFontButton;
|
||||
widgets << mDiagramPenColorButton;
|
||||
widgets << mDiagramSizeSpinBox;
|
||||
widgets << mDiagramLineUnitComboBox;
|
||||
widgets << mDiagramTypeComboBox;
|
||||
widgets << mDiagramUnitComboBox;
|
||||
widgets << mFixedSizeRadio;
|
||||
widgets << mIncreaseMinimumSizeSpinBox;
|
||||
widgets << mIncreaseSmallDiagramsCheck;
|
||||
widgets << mLabelPlacementComboBox;
|
||||
widgets << mMaxValueSpinBox;
|
||||
widgets << mPenWidthSpinBox;
|
||||
widgets << mPrioritySlider;
|
||||
widgets << mOpacityWidget;
|
||||
widgets << mOrientationDownButton;
|
||||
widgets << mOrientationLeftButton;
|
||||
widgets << mOrientationRightButton;
|
||||
widgets << mOrientationUpButton;
|
||||
widgets << mScaleDependencyComboBox;
|
||||
widgets << mScaleRangeWidget;
|
||||
widgets << mScaleVisibilityGroupBox;
|
||||
widgets << mShowAllCheckBox;
|
||||
widgets << mShowAxisGroupBox;
|
||||
widgets << mSizeFieldExpressionWidget;
|
||||
widgets << mSizeSpinBox;
|
||||
widgets << mZIndexSpinBox;
|
||||
widgets << radAroundCentroid;
|
||||
widgets << radAroundLine;
|
||||
widgets << radAroundPoint;
|
||||
widgets << radInsidePolygon;
|
||||
widgets << radOverCentroid;
|
||||
widgets << radOverLine;
|
||||
widgets << radOverPoint;
|
||||
widgets << radPolygonPerimeter;
|
||||
|
||||
connectValueChanged( widgets, SIGNAL( widgetChanged() ) );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::syncToLayer( const QgsDiagramRenderer *dr )
|
||||
void QgsDiagramProperties::setDockMode( bool dockMode )
|
||||
{
|
||||
QgsPanelWidget::setDockMode( dockMode );
|
||||
mOptionsTab->setVisible( dockMode );
|
||||
mOptionsTab->setTabToolTip( 0, tr( "Attributes" ) );
|
||||
mOptionsTab->setTabToolTip( 1, tr( "Rendering" ) );
|
||||
mOptionsTab->setTabToolTip( 2, tr( "Size" ) );
|
||||
mOptionsTab->setTabToolTip( 3, tr( "Placement" ) );
|
||||
mOptionsTab->setTabToolTip( 4, tr( "Options" ) );
|
||||
mOptionsTab->setTabToolTip( 5, tr( "Legend" ) );
|
||||
mDiagramOptionsListFrame->setVisible( !dockMode );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::setDiagramType( const QString diagramType )
|
||||
{
|
||||
mDiagramType = diagramType;
|
||||
|
||||
mDiagramTypeComboBox->setVisible( false );
|
||||
mDiagramTypeComboBox->blockSignals( true );
|
||||
mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( mDiagramType ) );
|
||||
mDiagramTypeComboBox->blockSignals( false );
|
||||
|
||||
//force a refresh of widget status to match diagram type
|
||||
mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::syncToLayer()
|
||||
{
|
||||
const QgsDiagramRenderer *renderer = mLayer->diagramRenderer();
|
||||
syncToRenderer( renderer );
|
||||
|
||||
const QgsDiagramLayerSettings *layerDls = mLayer->diagramLayerSettings();
|
||||
syncToSettings( layerDls );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::syncToRenderer( const QgsDiagramRenderer *dr )
|
||||
{
|
||||
mDiagramAttributesTreeWidget->clear();
|
||||
if ( !dr )
|
||||
{
|
||||
dr = mLayer->diagramRenderer();
|
||||
}
|
||||
|
||||
if ( !dr ) //no diagram renderer yet, insert reasonable default
|
||||
{
|
||||
@ -344,6 +442,7 @@ void QgsDiagramProperties::syncToLayer( const QgsDiagramRenderer *dr )
|
||||
const QList<QgsDiagramSettings> settingList = dr->diagramSettings();
|
||||
if ( !settingList.isEmpty() )
|
||||
{
|
||||
mOptionsTab->setEnabled( settingList.at( 0 ).enabled );
|
||||
mDiagramFrame->setEnabled( settingList.at( 0 ).enabled );
|
||||
mDiagramFontButton->setCurrentFont( settingList.at( 0 ).font );
|
||||
const QSizeF size = settingList.at( 0 ).size;
|
||||
@ -458,51 +557,6 @@ void QgsDiagramProperties::syncToLayer( const QgsDiagramRenderer *dr )
|
||||
}
|
||||
}
|
||||
|
||||
const QgsDiagramLayerSettings *dls = mLayer->diagramLayerSettings();
|
||||
if ( dls )
|
||||
{
|
||||
mDiagramDistanceSpinBox->setValue( dls->distance() );
|
||||
mPrioritySlider->setValue( dls->priority() );
|
||||
mZIndexSpinBox->setValue( dls->zIndex() );
|
||||
|
||||
switch ( dls->placement() )
|
||||
{
|
||||
case QgsDiagramLayerSettings::AroundPoint:
|
||||
radAroundPoint->setChecked( true );
|
||||
radAroundCentroid->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::OverPoint:
|
||||
radOverPoint->setChecked( true );
|
||||
radOverCentroid->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::Line:
|
||||
radAroundLine->setChecked( true );
|
||||
radPolygonPerimeter->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::Horizontal:
|
||||
radOverLine->setChecked( true );
|
||||
radInsidePolygon->setChecked( true );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
chkLineAbove->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::AboveLine );
|
||||
chkLineBelow->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::BelowLine );
|
||||
chkLineOn->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::OnLine );
|
||||
if ( !( dls->linePlacementFlags() & QgsDiagramLayerSettings::MapOrientation ) )
|
||||
chkLineOrientationDependent->setChecked( true );
|
||||
updatePlacementWidgets();
|
||||
|
||||
mShowAllCheckBox->setChecked( dls->showAllDiagrams() );
|
||||
|
||||
mDataDefinedProperties = dls->dataDefinedProperties();
|
||||
}
|
||||
|
||||
if ( dr->diagram() )
|
||||
{
|
||||
mDiagramType = dr->diagram()->diagramName();
|
||||
@ -523,6 +577,53 @@ void QgsDiagramProperties::syncToLayer( const QgsDiagramRenderer *dr )
|
||||
mPaintEffectWidget->setPaintEffect( mPaintEffect.get() );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::syncToSettings( const QgsDiagramLayerSettings *dls )
|
||||
{
|
||||
if ( dls )
|
||||
{
|
||||
mDiagramDistanceSpinBox->setValue( dls->distance() );
|
||||
mPrioritySlider->setValue( dls->priority() );
|
||||
mZIndexSpinBox->setValue( dls->zIndex() );
|
||||
|
||||
switch ( dls->placement() )
|
||||
{
|
||||
case QgsDiagramLayerSettings::AroundPoint:
|
||||
radAroundPoint->setChecked( true );
|
||||
radAroundCentroid->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::OverPoint:
|
||||
radOverPoint->setChecked( true );
|
||||
radOverCentroid->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::Line:
|
||||
radAroundLine->setChecked( true );
|
||||
radPolygonPerimeter->setChecked( true );
|
||||
break;
|
||||
|
||||
case QgsDiagramLayerSettings::Horizontal:
|
||||
radOverLine->setChecked( true );
|
||||
radInsidePolygon->setChecked( true );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
chkLineAbove->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::AboveLine );
|
||||
chkLineBelow->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::BelowLine );
|
||||
chkLineOn->setChecked( dls->linePlacementFlags() & QgsDiagramLayerSettings::OnLine );
|
||||
if ( !( dls->linePlacementFlags() & QgsDiagramLayerSettings::MapOrientation ) )
|
||||
chkLineOrientationDependent->setChecked( true );
|
||||
updatePlacementWidgets();
|
||||
|
||||
mShowAllCheckBox->setChecked( dls->showAllDiagrams() );
|
||||
|
||||
mDataDefinedProperties = dls->dataDefinedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
QgsDiagramProperties::~QgsDiagramProperties()
|
||||
{
|
||||
QgsSettings settings;
|
||||
@ -543,6 +644,7 @@ void QgsDiagramProperties::updateProperty()
|
||||
QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
|
||||
const QgsDiagramLayerSettings::Property key = static_cast< QgsDiagramLayerSettings::Property >( button->propertyKey() );
|
||||
mDataDefinedProperties.setProperty( key, button->toProperty() );
|
||||
emit widgetChanged();
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::mDiagramTypeComboBox_currentIndexChanged( int index )
|
||||
@ -750,6 +852,29 @@ void QgsDiagramProperties::mDiagramAttributesTreeWidget_itemDoubleClicked( QTree
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr< QgsDiagram > QgsDiagramProperties::createDiagramObject()
|
||||
{
|
||||
std::unique_ptr< QgsDiagram > diagram;
|
||||
|
||||
if ( mDiagramType == DIAGRAM_NAME_TEXT )
|
||||
{
|
||||
diagram = std::make_unique< QgsTextDiagram >();
|
||||
}
|
||||
else if ( mDiagramType == DIAGRAM_NAME_PIE )
|
||||
{
|
||||
diagram = std::make_unique< QgsPieDiagram >();
|
||||
}
|
||||
else if ( mDiagramType == DIAGRAM_NAME_STACKED_BAR )
|
||||
{
|
||||
diagram = std::make_unique< QgsStackedBarDiagram >();
|
||||
}
|
||||
else // if ( diagramType == DIAGRAM_NAME_HISTOGRAM )
|
||||
{
|
||||
diagram = std::make_unique< QgsHistogramDiagram >();
|
||||
}
|
||||
return diagram;
|
||||
}
|
||||
|
||||
std::unique_ptr<QgsDiagramSettings> QgsDiagramProperties::createDiagramSettings()
|
||||
{
|
||||
std::unique_ptr< QgsDiagramSettings > ds = std::make_unique< QgsDiagramSettings>();
|
||||
@ -821,13 +946,15 @@ std::unique_ptr<QgsDiagramSettings> QgsDiagramProperties::createDiagramSettings(
|
||||
return ds;
|
||||
}
|
||||
|
||||
std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRendererBaseInfo( const QgsDiagramSettings &ds )
|
||||
std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRenderer()
|
||||
{
|
||||
std::unique_ptr< QgsDiagramSettings > ds = createDiagramSettings();
|
||||
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer;
|
||||
if ( mFixedSizeRadio->isChecked() )
|
||||
{
|
||||
std::unique_ptr< QgsSingleCategoryDiagramRenderer > dr = std::make_unique< QgsSingleCategoryDiagramRenderer >();
|
||||
dr->setDiagramSettings( ds );
|
||||
dr->setDiagramSettings( *ds );
|
||||
renderer = std::move( dr );
|
||||
}
|
||||
else
|
||||
@ -849,7 +976,7 @@ std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRendererBaseInfo
|
||||
{
|
||||
dr->setClassificationField( sizeFieldNameOrExp );
|
||||
}
|
||||
dr->setDiagramSettings( ds );
|
||||
dr->setDiagramSettings( *ds );
|
||||
|
||||
dr->setDataDefinedSizeLegend( mSizeLegend ? new QgsDataDefinedSizeLegend( *mSizeLegend ) : nullptr );
|
||||
|
||||
@ -857,6 +984,10 @@ std::unique_ptr<QgsDiagramRenderer> QgsDiagramProperties::createRendererBaseInfo
|
||||
}
|
||||
|
||||
renderer->setAttributeLegend( mCheckBoxAttributeLegend->isChecked() );
|
||||
|
||||
std::unique_ptr< QgsDiagram > diagram = createDiagramObject();
|
||||
renderer->setDiagram( diagram.release() );
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
@ -914,34 +1045,18 @@ void QgsDiagramProperties::apply()
|
||||
const int index = mDiagramTypeComboBox->currentIndex();
|
||||
const bool diagramsEnabled = ( index != -1 );
|
||||
|
||||
std::unique_ptr< QgsDiagram > diagram;
|
||||
|
||||
if ( diagramsEnabled && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
|
||||
// Avoid this messageBox when in both dock and liveUpdate mode
|
||||
QgsSettings settings;
|
||||
if ( !dockMode() || !settings.value( QStringLiteral( "UI/autoApplyStyling" ), true ).toBool() )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Diagrams: No attributes added." ),
|
||||
tr( "You did not add any attributes to this diagram layer. Please specify the attributes to visualize on the diagrams or disable diagrams." ) );
|
||||
if ( diagramsEnabled && 0 == mDiagramAttributesTreeWidget->topLevelItemCount() )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Diagrams: No attributes added." ),
|
||||
tr( "You did not add any attributes to this diagram layer. Please specify the attributes to visualize on the diagrams or disable diagrams." ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( mDiagramType == DIAGRAM_NAME_TEXT )
|
||||
{
|
||||
diagram = std::make_unique< QgsTextDiagram >();
|
||||
}
|
||||
else if ( mDiagramType == DIAGRAM_NAME_PIE )
|
||||
{
|
||||
diagram = std::make_unique< QgsPieDiagram >();
|
||||
}
|
||||
else if ( mDiagramType == DIAGRAM_NAME_STACKED_BAR )
|
||||
{
|
||||
diagram = std::make_unique< QgsStackedBarDiagram >();
|
||||
}
|
||||
else // if ( diagramType == DIAGRAM_NAME_HISTOGRAM )
|
||||
{
|
||||
diagram = std::make_unique< QgsHistogramDiagram >();
|
||||
}
|
||||
|
||||
std::unique_ptr< QgsDiagramSettings > ds = createDiagramSettings();
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer = createRendererBaseInfo( *ds );
|
||||
renderer->setDiagram( diagram.release() );
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer = createRenderer();
|
||||
mLayer->setDiagramRenderer( renderer.release() );
|
||||
|
||||
QgsDiagramLayerSettings dls = createDiagramLayerSettings();
|
||||
@ -1051,6 +1166,30 @@ void QgsDiagramProperties::scalingTypeChanged()
|
||||
mButtonSizeLegendSettings->setEnabled( mAttributeBasedScalingRadio->isChecked() );
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::setAllowedToEditDiagramLayerSettings( bool allowed )
|
||||
{
|
||||
mAllowedToEditDls = allowed;
|
||||
|
||||
label_16->setVisible( allowed );
|
||||
mZIndexSpinBox->setVisible( allowed );
|
||||
mZOrderDDBtn->setVisible( allowed );
|
||||
mShowAllCheckBox->setVisible( allowed );
|
||||
mDlsLabel_1->setVisible( !allowed );
|
||||
|
||||
mCoordinatesGrpBox->setVisible( allowed );
|
||||
mLinePlacementFrame->setVisible( allowed );
|
||||
mObstaclesGrpBox->setVisible( allowed );
|
||||
mPlacementFrame->setVisible( allowed );
|
||||
mPriorityGrpBox->setVisible( allowed );
|
||||
stackedPlacement->setVisible( allowed );
|
||||
mDlsLabel_2->setVisible( !allowed );
|
||||
}
|
||||
|
||||
bool QgsDiagramProperties::isAllowedToEditDiagramLayerSettings() const
|
||||
{
|
||||
return mAllowedToEditDls;
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::showSizeLegendDialog()
|
||||
{
|
||||
// prepare size transformer
|
||||
@ -1112,3 +1251,71 @@ void QgsDiagramProperties::createAuxiliaryField()
|
||||
|
||||
emit auxiliaryFieldCreated();
|
||||
}
|
||||
|
||||
void QgsDiagramProperties::connectValueChanged( const QList<QWidget *> &widgets, const char *signal )
|
||||
{
|
||||
const auto constWidgets = widgets;
|
||||
for ( QWidget *widget : constWidgets )
|
||||
{
|
||||
if ( QgsSymbolButton *w = qobject_cast<QgsSymbolButton *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( changed() ), this, signal );
|
||||
}
|
||||
else if ( QgsFieldExpressionWidget *w = qobject_cast< QgsFieldExpressionWidget *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( fieldChanged( QString ) ), this, signal );
|
||||
}
|
||||
else if ( QgsOpacityWidget *w = qobject_cast< QgsOpacityWidget *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( opacityChanged( double ) ), this, signal );
|
||||
}
|
||||
else if ( QgsUnitSelectionWidget *w = qobject_cast<QgsUnitSelectionWidget *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( changed() ), this, signal );
|
||||
}
|
||||
else if ( QComboBox *w = qobject_cast<QComboBox *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( currentIndexChanged( int ) ), this, signal );
|
||||
}
|
||||
else if ( QSpinBox *w = qobject_cast<QSpinBox *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( valueChanged( int ) ), this, signal );
|
||||
}
|
||||
else if ( QDoubleSpinBox *w = qobject_cast<QDoubleSpinBox *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( valueChanged( double ) ), this, signal );
|
||||
}
|
||||
else if ( QgsColorButton *w = qobject_cast<QgsColorButton *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( colorChanged( QColor ) ), this, signal );
|
||||
}
|
||||
else if ( QCheckBox *w = qobject_cast<QCheckBox *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( toggled( bool ) ), this, signal );
|
||||
}
|
||||
else if ( QRadioButton *w = qobject_cast<QRadioButton *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( toggled( bool ) ), this, signal );
|
||||
}
|
||||
else if ( QSlider *w = qobject_cast<QSlider *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( valueChanged( int ) ), this, signal );
|
||||
}
|
||||
else if ( QGroupBox *w = qobject_cast<QGroupBox *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( toggled( bool ) ), this, signal );
|
||||
}
|
||||
else if ( QTreeWidget *w = qobject_cast<QTreeWidget *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( itemChanged( QTreeWidgetItem *, int ) ), this, signal );
|
||||
}
|
||||
else if ( QgsScaleRangeWidget *w = qobject_cast<QgsScaleRangeWidget *>( widget ) )
|
||||
{
|
||||
connect( w, SIGNAL( rangeChanged( double, double ) ), this, signal );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsLogger::warning( QStringLiteral( "Could not create connection for widget %1" ).arg( widget->objectName() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,26 +36,68 @@ class QgsMapCanvas;
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \class QgsDiagramProperties
|
||||
*
|
||||
* \note This class is not a part of public API
|
||||
*/
|
||||
class GUI_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPropertiesBase, private QgsExpressionContextGenerator
|
||||
class GUI_EXPORT QgsDiagramProperties : public QgsPanelWidget, private Ui::QgsDiagramPropertiesBase, private QgsExpressionContextGenerator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsDiagramProperties( QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas );
|
||||
~QgsDiagramProperties() override;
|
||||
|
||||
/**
|
||||
* Updates the widget to reflect the layer's current diagram settings.
|
||||
*
|
||||
* \since QGIS 3.16
|
||||
*/
|
||||
void syncToLayer( const QgsDiagramRenderer *dr = nullptr );
|
||||
void syncToLayer();
|
||||
|
||||
~QgsDiagramProperties() override;
|
||||
/**
|
||||
* Updates the widget to reflect the diagram renderer.
|
||||
* \param dr Diagram renderer where settings are taken from.
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
void syncToRenderer( const QgsDiagramRenderer *dr );
|
||||
|
||||
/**
|
||||
* Updates the widget to reflect the diagram layer settings.
|
||||
* \param dls Diagram Layer Settings to update the widget.
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
void syncToSettings( const QgsDiagramLayerSettings *dls );
|
||||
|
||||
//! Adds an attribute from the list of available attributes to the assigned attributes with a random color.
|
||||
void addAttribute( QTreeWidgetItem *item );
|
||||
|
||||
/**
|
||||
* Sets the widget in dock mode.
|
||||
* \param dockMode TRUE for dock mode.
|
||||
*/
|
||||
void setDockMode( bool dockMode ) override;
|
||||
|
||||
/**
|
||||
* Defines the widget's diagram type and lets it know it should hide the type comboBox.
|
||||
* @param diagramType Type of diagram to be set
|
||||
*/
|
||||
void setDiagramType( const QString diagramType );
|
||||
|
||||
/**
|
||||
* Sets whether the widget should show diagram layer settings.
|
||||
* Used by stacked diagrams, which disable editing of DLS for sub diagrams
|
||||
* other than the first one.
|
||||
* @param allowed Whether this widget should be allowed to edit diagram layer settings.
|
||||
*/
|
||||
void setAllowedToEditDiagramLayerSettings( bool allowed );
|
||||
|
||||
/**
|
||||
* Returns whether this widget is allowed to edit diagram layer settings.
|
||||
*/
|
||||
bool isAllowedToEditDiagramLayerSettings() const;
|
||||
|
||||
signals:
|
||||
|
||||
void auxiliaryFieldCreated();
|
||||
@ -118,8 +160,24 @@ class GUI_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
|
||||
bool mAllowedToEditDls = true;
|
||||
|
||||
void registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsDiagramLayerSettings::Property key );
|
||||
|
||||
/**
|
||||
* Convenience function to chain widgets' change value signal to another signal.
|
||||
* @param widgets List of widgets.
|
||||
* @param signal Signal to be triggered by each widget's change value signal.
|
||||
*/
|
||||
void connectValueChanged( const QList<QWidget *> &widgets, const char *signal );
|
||||
|
||||
/**
|
||||
* Creates a QgsDiagram object from the GUI settings.
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
std::unique_ptr< QgsDiagram > createDiagramObject();
|
||||
|
||||
/**
|
||||
* Creates a QgsDiagramSettings object from the GUI settings.
|
||||
*
|
||||
@ -132,7 +190,7 @@ class GUI_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
std::unique_ptr<QgsDiagramRenderer> createRendererBaseInfo( const QgsDiagramSettings &ds );
|
||||
std::unique_ptr<QgsDiagramRenderer> createRenderer();
|
||||
|
||||
/**
|
||||
* Creates a QgsDiagramLayerSettings object from the GUI settings.
|
||||
@ -142,6 +200,7 @@ class GUI_EXPORT QgsDiagramProperties : public QWidget, private Ui::QgsDiagramPr
|
||||
QgsDiagramLayerSettings createDiagramLayerSettings();
|
||||
|
||||
friend class QgsStackedDiagramProperties;
|
||||
friend class QgsStackedDiagramPropertiesDialog;
|
||||
};
|
||||
|
||||
|
||||
|
220
src/gui/vector/qgsdiagramwidget.cpp
Normal file
220
src/gui/vector/qgsdiagramwidget.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
/***************************************************************************
|
||||
qgsdiagramwidget.h
|
||||
Container widget for diagram layers
|
||||
-------------------
|
||||
begin : September 2024
|
||||
copyright : (C) Germán Carrillo
|
||||
email : german at opengis dot ch
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "diagram/qgshistogramdiagram.h"
|
||||
#include "diagram/qgspiediagram.h"
|
||||
#include "diagram/qgstextdiagram.h"
|
||||
#include "diagram/qgsstackedbardiagram.h"
|
||||
|
||||
#include "qgsdiagramwidget.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsguiutils.h"
|
||||
#include "qgslabelengineconfigdialog.h"
|
||||
#include "qgsdiagramproperties.h"
|
||||
#include "qgsstackeddiagramproperties.h"
|
||||
|
||||
|
||||
QgsDiagramWidget::QgsDiagramWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent )
|
||||
: QgsMapLayerConfigWidget( layer, canvas, parent )
|
||||
, mLayer( layer )
|
||||
, mCanvas( canvas )
|
||||
{
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setupUi( this );
|
||||
|
||||
// Initialize stacked diagram controls
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "diagramNone.svg" ) ), tr( "No Diagrams" ), ModeNone );
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "pie-chart.svg" ) ), tr( "Pie Chart" ), ModePie );
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "text.svg" ) ), tr( "Text Diagram" ), ModeText );
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "histogram.svg" ) ), tr( "Histogram" ), ModeHistogram );
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "stacked-bar.svg" ) ), tr( "Stacked Bars" ), ModeStackedBar );
|
||||
mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "diagramNone.svg" ) ), tr( "Stacked Diagram" ), ModeStacked );
|
||||
|
||||
connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsDiagramWidget::showEngineConfigDialog );
|
||||
|
||||
connect( mDiagramTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsDiagramWidget::mDiagramTypeComboBox_currentIndexChanged );
|
||||
|
||||
const int iconSize16 = QgsGuiUtils::scaleIconSize( 16 );
|
||||
mEngineSettingsButton->setIconSize( QSize( iconSize16, iconSize16 ) );
|
||||
}
|
||||
|
||||
void QgsDiagramWidget::apply()
|
||||
{
|
||||
const Mode mode = static_cast< Mode >( mDiagramTypeComboBox->currentData().toInt() );
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case ModeStacked:
|
||||
{
|
||||
// Delegate to stacked diagram's apply
|
||||
static_cast<QgsStackedDiagramProperties *>( mWidget )->apply();
|
||||
break;
|
||||
}
|
||||
case ModePie:
|
||||
case ModeText:
|
||||
case ModeHistogram:
|
||||
case ModeStackedBar:
|
||||
{
|
||||
// Delegate to single diagram's apply
|
||||
static_cast<QgsDiagramProperties *>( mWidget )->apply();
|
||||
break;
|
||||
}
|
||||
case ModeNone:
|
||||
{
|
||||
mLayer->setDiagramRenderer( nullptr );
|
||||
|
||||
QgsDiagramLayerSettings dls;
|
||||
mLayer->setDiagramLayerSettings( dls );
|
||||
|
||||
// refresh
|
||||
QgsProject::instance()->setDirty( true );
|
||||
mLayer->triggerRepaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDiagramWidget::syncToOwnLayer()
|
||||
{
|
||||
if ( !mLayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
whileBlocking( mDiagramTypeComboBox )->setCurrentIndex( -1 );
|
||||
|
||||
const QgsDiagramRenderer *dr = mLayer->diagramRenderer();
|
||||
|
||||
// pick the right mode from the layer
|
||||
if ( dr && dr->diagram() )
|
||||
{
|
||||
if ( dr->rendererName() == QStringLiteral( "Stacked" ) )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModeStacked );
|
||||
}
|
||||
else // Single diagram
|
||||
{
|
||||
const QString diagramName = dr->diagram()->diagramName();
|
||||
if ( diagramName == DIAGRAM_NAME_PIE )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModePie ) ;
|
||||
}
|
||||
else if ( diagramName == DIAGRAM_NAME_TEXT )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModeText ) ;
|
||||
}
|
||||
else if ( diagramName == DIAGRAM_NAME_STACKED_BAR )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModeStackedBar ) ;
|
||||
}
|
||||
else // diagramName == DIAGRAM_NAME_HISTOGRAM
|
||||
{
|
||||
// Play safe and set to histogram by default if the diagram name is unknown
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModeHistogram );
|
||||
}
|
||||
// TODO: if we get a stacked diagram, take the first subdiagram,
|
||||
// Set its diagram type and sync to its settings
|
||||
|
||||
// Delegate to single diagram's syncToLayer
|
||||
static_cast<QgsDiagramProperties *>( mWidget )->syncToLayer();
|
||||
}
|
||||
}
|
||||
else // No Diagram
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( ModeNone );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDiagramWidget::mDiagramTypeComboBox_currentIndexChanged( int index )
|
||||
{
|
||||
if ( mWidget )
|
||||
mStackedWidget->removeWidget( mWidget );
|
||||
|
||||
delete mWidget;
|
||||
mWidget = nullptr;
|
||||
|
||||
if ( index < 0 )
|
||||
return;
|
||||
|
||||
const Mode mode = static_cast< Mode >( mDiagramTypeComboBox->currentData().toInt() );
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case ModePie:
|
||||
case ModeText:
|
||||
case ModeHistogram:
|
||||
case ModeStackedBar:
|
||||
{
|
||||
QgsDiagramProperties *singleWidget = new QgsDiagramProperties( mLayer, this, mMapCanvas );
|
||||
singleWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
singleWidget->setDockMode( dockMode() );
|
||||
|
||||
if ( mode == ModePie )
|
||||
singleWidget->setDiagramType( DIAGRAM_NAME_PIE );
|
||||
else if ( mode == ModeText )
|
||||
singleWidget->setDiagramType( DIAGRAM_NAME_TEXT );
|
||||
else if ( mode == ModeHistogram )
|
||||
singleWidget->setDiagramType( DIAGRAM_NAME_HISTOGRAM );
|
||||
else if ( mode == ModeStackedBar )
|
||||
singleWidget->setDiagramType( DIAGRAM_NAME_STACKED_BAR );
|
||||
|
||||
connect( singleWidget, &QgsDiagramProperties::widgetChanged, this, &QgsDiagramWidget::widgetChanged );
|
||||
connect( singleWidget, &QgsDiagramProperties::auxiliaryFieldCreated, this, &QgsDiagramWidget::auxiliaryFieldCreated );
|
||||
|
||||
mWidget = singleWidget;
|
||||
mStackedWidget->addWidget( mWidget );
|
||||
mStackedWidget->setCurrentWidget( mWidget );
|
||||
break;
|
||||
}
|
||||
case ModeStacked:
|
||||
{
|
||||
QgsStackedDiagramProperties *stackedWidget = new QgsStackedDiagramProperties( mLayer, this, mCanvas );
|
||||
stackedWidget->setDockMode( dockMode() );
|
||||
connect( stackedWidget, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
|
||||
connect( stackedWidget, &QgsStackedDiagramProperties::widgetChanged, this, &QgsDiagramWidget::widgetChanged );
|
||||
mWidget = stackedWidget;
|
||||
mStackedWidget->addWidget( mWidget );
|
||||
mStackedWidget->setCurrentWidget( mWidget );
|
||||
break;
|
||||
}
|
||||
case ModeNone:
|
||||
break;
|
||||
}
|
||||
emit widgetChanged();
|
||||
}
|
||||
|
||||
void QgsDiagramWidget::showEngineConfigDialog()
|
||||
{
|
||||
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
|
||||
if ( panel && panel->dockMode() )
|
||||
{
|
||||
QgsLabelEngineConfigWidget *widget = new QgsLabelEngineConfigWidget( mCanvas );
|
||||
connect( widget, &QgsLabelEngineConfigWidget::widgetChanged, widget, &QgsLabelEngineConfigWidget::apply );
|
||||
panel->openPanel( widget );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsLabelEngineConfigDialog dialog( mCanvas, this );
|
||||
dialog.exec();
|
||||
// reactivate button's window
|
||||
activateWindow();
|
||||
}
|
||||
}
|
78
src/gui/vector/qgsdiagramwidget.h
Normal file
78
src/gui/vector/qgsdiagramwidget.h
Normal file
@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
qgsdiagramwidget.h
|
||||
Container widget for diagram layers
|
||||
-------------------
|
||||
begin : September 2024
|
||||
copyright : (C) Germán Carrillo
|
||||
email : german at opengis dot ch
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSDIAGRAMWIDGET_H
|
||||
#define QGSDIAGRAMWIDGET_H
|
||||
|
||||
// We don't want to expose this in the public API
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include <qgsmaplayerconfigwidget.h>
|
||||
#include "ui_qgsdiagramwidget.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \class QgsDiagramWidget
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class GUI_EXPORT QgsDiagramWidget : public QgsMapLayerConfigWidget, private Ui::QgsDiagramWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
QgsDiagramWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, QWidget *parent = nullptr );
|
||||
|
||||
/**
|
||||
* Updates the widget to reflect the layer's current diagram settings.
|
||||
*/
|
||||
void syncToOwnLayer();
|
||||
|
||||
public slots:
|
||||
//! Saves the labeling configuration and immediately updates the map canvas to reflect the changes
|
||||
void apply() override;
|
||||
|
||||
signals:
|
||||
//! Emitted when an auxiliary field is created
|
||||
void auxiliaryFieldCreated();
|
||||
|
||||
private slots:
|
||||
void mDiagramTypeComboBox_currentIndexChanged( int index );
|
||||
void showEngineConfigDialog();
|
||||
|
||||
private:
|
||||
|
||||
enum Mode
|
||||
{
|
||||
ModeNone,
|
||||
ModePie,
|
||||
ModeText,
|
||||
ModeHistogram,
|
||||
ModeStackedBar,
|
||||
ModeStacked
|
||||
};
|
||||
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
QgsMapCanvas *mCanvas = nullptr;
|
||||
|
||||
QWidget *mWidget = nullptr;
|
||||
};
|
||||
|
||||
#endif // QGSDIAGRAMWIDGET_H
|
@ -19,40 +19,37 @@
|
||||
#include "diagram/qgspiediagram.h"
|
||||
#include "diagram/qgstextdiagram.h"
|
||||
#include "diagram/qgsstackedbardiagram.h"
|
||||
#include "diagram/qgsstackeddiagram.h"
|
||||
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgsdiagramproperties.h"
|
||||
#include "qgslabelengineconfigdialog.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsstackeddiagram.h"
|
||||
#include "qgsstackeddiagramproperties.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgshelp.h"
|
||||
|
||||
QgsStackedDiagramProperties::QgsStackedDiagramProperties( QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas )
|
||||
: QWidget{parent}
|
||||
: QgsPanelWidget( parent )
|
||||
, mLayer( layer )
|
||||
, mMapCanvas( canvas )
|
||||
{
|
||||
mLayer = layer;
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setupUi( this );
|
||||
connect( mDiagramTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsStackedDiagramProperties::mDiagramTypeComboBox_currentIndexChanged );
|
||||
connect( mEngineSettingsButton, &QPushButton::clicked, this, &QgsStackedDiagramProperties::mEngineSettingsButton_clicked );
|
||||
|
||||
connect( mSubDiagramsView, &QAbstractItemView::doubleClicked, this, static_cast<void ( QgsStackedDiagramProperties::* )( const QModelIndex & )>( &QgsStackedDiagramProperties::editSubDiagram ) );
|
||||
|
||||
connect( mAddSubDiagramButton, &QPushButton::clicked, this, &QgsStackedDiagramProperties::addSubDiagram );
|
||||
connect( mEditSubDiagramButton, &QAbstractButton::clicked, this, static_cast<void ( QgsStackedDiagramProperties::* )()>( &QgsStackedDiagramProperties::editSubDiagram ) );
|
||||
connect( mRemoveSubDiagramButton, &QPushButton::clicked, this, &QgsStackedDiagramProperties::removeSubDiagram );
|
||||
connect( mSubDiagramsTabWidget->tabBar(), &QTabBar::tabMoved, this, &QgsStackedDiagramProperties::mSubDiagramsTabWidget_tabMoved );
|
||||
|
||||
// Initialize stacked diagram controls
|
||||
QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "diagramNone.svg" ) );
|
||||
mDiagramTypeComboBox->addItem( icon, tr( "No Diagrams" ), "None" );
|
||||
mDiagramTypeComboBox->addItem( tr( "Single diagram" ), QgsDiagramLayerSettings::Single );
|
||||
mDiagramTypeComboBox->addItem( tr( "Stacked diagrams" ), QgsDiagramLayerSettings::Stacked );
|
||||
mStackedDiagramModeComboBox->addItem( tr( "Horizontal" ), QgsDiagramSettings::Horizontal );
|
||||
mStackedDiagramModeComboBox->addItem( tr( "Vertical" ), QgsDiagramSettings::Vertical );
|
||||
mRemoveSubDiagramButton->setEnabled( false );
|
||||
|
||||
mStackedDiagramSpacingSpinBox->setClearValue( 0 );
|
||||
mStackedDiagramSpacingUnitComboBox->setUnits( { Qgis::RenderUnit::Millimeters,
|
||||
@ -62,37 +59,117 @@ QgsStackedDiagramProperties::QgsStackedDiagramProperties( QgsVectorLayer *layer,
|
||||
Qgis::RenderUnit::Points,
|
||||
Qgis::RenderUnit::Inches } );
|
||||
|
||||
// Add default subdiagram tab
|
||||
addSubDiagram();
|
||||
connect( mStackedDiagramModeComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
connect( mStackedDiagramSpacingSpinBox, qOverload< double >( &QgsDoubleSpinBox::valueChanged ), this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
connect( mStackedDiagramSpacingUnitComboBox, &QgsUnitSelectionWidget::changed, this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
|
||||
mModel = new QgsStackedDiagramPropertiesModel();
|
||||
mSubDiagramsView->setModel( mModel );
|
||||
|
||||
connect( mModel, &QAbstractItemModel::dataChanged, this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
connect( mModel, &QAbstractItemModel::rowsInserted, this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
connect( mModel, &QAbstractItemModel::rowsRemoved, this, &QgsStackedDiagramProperties::widgetChanged );
|
||||
|
||||
syncToLayer();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::addSubDiagram()
|
||||
{
|
||||
QgsDiagramProperties *gui = new QgsDiagramProperties( mLayer, this, mMapCanvas );
|
||||
gui->layout()->setContentsMargins( 6, 6, 6, 6 );
|
||||
connect( gui, &QgsDiagramProperties::auxiliaryFieldCreated, this, &QgsStackedDiagramProperties::auxiliaryFieldCreated );
|
||||
// Create a single category renderer by default
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer;
|
||||
std::unique_ptr< QgsSingleCategoryDiagramRenderer > dr = std::make_unique< QgsSingleCategoryDiagramRenderer >();
|
||||
renderer = std::move( dr );
|
||||
|
||||
mSubDiagramsTabWidget->addTab( gui, tr( "Diagram %1" ).arg( mSubDiagramsTabWidget->count() + 1 ) );
|
||||
QItemSelectionModel *sel = mSubDiagramsView->selectionModel();
|
||||
const QModelIndex index = sel->currentIndex();
|
||||
|
||||
mRemoveSubDiagramButton->setEnabled( mSubDiagramsTabWidget->count() > 2 );
|
||||
if ( index.isValid() )
|
||||
{
|
||||
// add after this subDiagram
|
||||
const QModelIndex currentIndex = mSubDiagramsView->selectionModel()->currentIndex();
|
||||
mModel->insertSubDiagram( currentIndex.row() + 1, renderer.release() );
|
||||
const QModelIndex newIndex = mModel->index( currentIndex.row() + 1, 0 );
|
||||
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect );
|
||||
}
|
||||
else
|
||||
{
|
||||
// append to root
|
||||
appendSubDiagram( renderer.release() );
|
||||
}
|
||||
editSubDiagram();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::appendSubDiagram( QgsDiagramRenderer *dr )
|
||||
{
|
||||
const int rows = mModel->rowCount();
|
||||
mModel->insertSubDiagram( rows, dr );
|
||||
const QModelIndex newIndex = mModel->index( rows, 0 );
|
||||
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::editSubDiagram()
|
||||
{
|
||||
editSubDiagram( mSubDiagramsView->selectionModel()->currentIndex() );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::editSubDiagram( const QModelIndex &index )
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return;
|
||||
|
||||
QgsDiagramRenderer *renderer = mModel->subDiagramForIndex( index );
|
||||
QgsDiagramLayerSettings dls = mModel->diagramLayerSettings();
|
||||
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
|
||||
|
||||
if ( panel && panel->dockMode() )
|
||||
{
|
||||
QgsDiagramProperties *widget = new QgsDiagramProperties( mLayer, this, mMapCanvas );
|
||||
widget->setPanelTitle( tr( "Edit Sub Diagram" ) );
|
||||
widget->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
widget->syncToRenderer( renderer );
|
||||
widget->syncToSettings( &dls );
|
||||
if ( !couldBeFirstSubDiagram( index ) )
|
||||
{
|
||||
widget->setAllowedToEditDiagramLayerSettings( false );
|
||||
}
|
||||
|
||||
connect( widget, &QgsDiagramProperties::auxiliaryFieldCreated, this, &QgsStackedDiagramProperties::auxiliaryFieldCreated );
|
||||
connect( widget, &QgsPanelWidget::panelAccepted, this, &QgsStackedDiagramProperties::subDiagramWidgetPanelAccepted );
|
||||
connect( widget, &QgsDiagramProperties::widgetChanged, this, &QgsStackedDiagramProperties::liveUpdateSubDiagramFromPanel );
|
||||
openPanel( widget );
|
||||
return;
|
||||
}
|
||||
|
||||
QgsStackedDiagramPropertiesDialog dlg( mLayer, this, mMapCanvas );
|
||||
dlg.syncToRenderer( renderer );
|
||||
dlg.syncToSettings( &dls );
|
||||
if ( !couldBeFirstSubDiagram( index ) )
|
||||
{
|
||||
dlg.setAllowedToEditDiagramLayerSettings( false );
|
||||
}
|
||||
|
||||
if ( dlg.exec() )
|
||||
{
|
||||
const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
|
||||
if ( dlg.isAllowedToEditDiagramLayerSettings() )
|
||||
mModel->updateDiagramLayerSettings( dlg.diagramLayerSettings() );
|
||||
|
||||
// This call will emit dataChanged, which in turns triggers widgetChanged()
|
||||
mModel->updateSubDiagram( index, dlg.renderer() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::removeSubDiagram()
|
||||
{
|
||||
if ( mSubDiagramsTabWidget->count() > 2 )
|
||||
const QItemSelection sel = mSubDiagramsView->selectionModel()->selection();
|
||||
const auto constSel = sel;
|
||||
for ( const QItemSelectionRange &range : constSel )
|
||||
{
|
||||
const int index = mSubDiagramsTabWidget->currentIndex();
|
||||
delete mSubDiagramsTabWidget->widget( index );
|
||||
|
||||
mRemoveSubDiagramButton->setEnabled( mSubDiagramsTabWidget->count() > 2 );
|
||||
|
||||
for ( int i = index; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
{
|
||||
mSubDiagramsTabWidget->setTabText( i, tr( "Diagram %1" ).arg( i + 1 ) );
|
||||
}
|
||||
if ( range.isValid() )
|
||||
mModel->removeRows( range.top(), range.bottom() - range.top() + 1, range.parent() );
|
||||
}
|
||||
// make sure that the selection is gone
|
||||
mSubDiagramsView->selectionModel()->clear();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::syncToLayer()
|
||||
@ -101,222 +178,372 @@ void QgsStackedDiagramProperties::syncToLayer()
|
||||
|
||||
if ( dr && dr->diagram() )
|
||||
{
|
||||
if ( dr->rendererName() == QStringLiteral( "Stacked" ) )
|
||||
const QList<QgsDiagramSettings> settingList = dr->diagramSettings();
|
||||
mStackedDiagramModeComboBox->setCurrentIndex( settingList.at( 0 ).stackedDiagramMode );
|
||||
mStackedDiagramSpacingSpinBox->setValue( settingList.at( 0 ).stackedDiagramSpacing() );
|
||||
mStackedDiagramSpacingUnitComboBox->setUnit( settingList.at( 0 ).stackedDiagramSpacingUnit() );
|
||||
|
||||
if ( dr->rendererName() == QLatin1String( "Stacked" ) )
|
||||
{
|
||||
mDiagramTypeComboBox->blockSignals( true );
|
||||
mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( QgsDiagramLayerSettings::Stacked ) );
|
||||
mDiagramTypeComboBox->blockSignals( false );
|
||||
//force a refresh of widget status to match diagram type
|
||||
mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
|
||||
|
||||
const QList<QgsDiagramSettings> settingList = dr->diagramSettings();
|
||||
mStackedDiagramModeComboBox->setCurrentIndex( settingList.at( 0 ).stackedDiagramMode );
|
||||
mStackedDiagramSpacingSpinBox->setValue( settingList.at( 0 ).stackedDiagramSpacing() );
|
||||
mStackedDiagramSpacingUnitComboBox->setUnit( settingList.at( 0 ).stackedDiagramSpacingUnit() );
|
||||
|
||||
// Create/remove as many tabs as necessary
|
||||
const QgsStackedDiagramRenderer *stackedDiagramRenderer = static_cast< const QgsStackedDiagramRenderer * >( dr );
|
||||
const int rendererCount = stackedDiagramRenderer->rendererCount();
|
||||
while ( mSubDiagramsTabWidget->count() < rendererCount )
|
||||
const auto renderers = stackedDiagramRenderer->renderers();
|
||||
for ( const auto &renderer : renderers )
|
||||
{
|
||||
addSubDiagram();
|
||||
}
|
||||
while ( mSubDiagramsTabWidget->count() > rendererCount )
|
||||
{
|
||||
mSubDiagramsTabWidget->setCurrentIndex( mSubDiagramsTabWidget->count() - 1 );
|
||||
removeSubDiagram();
|
||||
}
|
||||
|
||||
// Call subdiagrams' syncToLayer with the corresponding rendering object
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
{
|
||||
QgsDiagramProperties *diagramProperties = static_cast<QgsDiagramProperties *>( mSubDiagramsTabWidget->widget( i ) );
|
||||
diagramProperties->syncToLayer( stackedDiagramRenderer->renderer( i ) );
|
||||
appendSubDiagram( renderer );
|
||||
}
|
||||
}
|
||||
else // Single diagram
|
||||
else
|
||||
{
|
||||
mDiagramTypeComboBox->blockSignals( true );
|
||||
mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findData( QgsDiagramLayerSettings::Single ) );
|
||||
mDiagramTypeComboBox->blockSignals( false );
|
||||
//force a refresh of widget status to match diagram type
|
||||
mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
|
||||
|
||||
// Delegate to single diagram's syncToLayer
|
||||
// If the diagram name is unknown, the single diagram will choose a default one (pie)
|
||||
static_cast<QgsDiagramProperties *>( mSubDiagramsTabWidget->widget( 0 ) )->syncToLayer();
|
||||
// Take this single renderer as the first stacked renderer
|
||||
appendSubDiagram( dr->clone() );
|
||||
}
|
||||
}
|
||||
else // No Diagram
|
||||
{
|
||||
mDiagramTypeComboBox->blockSignals( true );
|
||||
mDiagramTypeComboBox->setCurrentIndex( 0 );
|
||||
mDiagramTypeComboBox->blockSignals( false );
|
||||
//force a refresh of widget status to match diagram type
|
||||
mDiagramTypeComboBox_currentIndexChanged( mDiagramTypeComboBox->currentIndex() );
|
||||
|
||||
// Delegate to first diagram's syncToLayer
|
||||
// It will add required reasonable defaults
|
||||
static_cast<QgsDiagramProperties *>( mSubDiagramsTabWidget->widget( 0 ) )->syncToLayer();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::mSubDiagramsTabWidget_tabMoved( int from, int to )
|
||||
{
|
||||
Q_UNUSED( from )
|
||||
Q_UNUSED( to )
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
{
|
||||
mSubDiagramsTabWidget->setTabText( i, tr( "Diagram %1" ).arg( i + 1 ) );
|
||||
const QgsDiagramLayerSettings *dls = mLayer->diagramLayerSettings();
|
||||
mModel->updateDiagramLayerSettings( *dls );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::apply()
|
||||
{
|
||||
if ( mDiagramTypeComboBox->currentData( Qt::UserRole ) == "None" )
|
||||
std::unique_ptr< QgsDiagramSettings> ds = std::make_unique< QgsDiagramSettings >();
|
||||
ds->stackedDiagramMode = static_cast<QgsDiagramSettings::StackedDiagramMode>( mStackedDiagramModeComboBox->currentData().toInt() );
|
||||
ds->setStackedDiagramSpacingUnit( mStackedDiagramSpacingUnitComboBox->unit() );
|
||||
ds->setStackedDiagramSpacing( mStackedDiagramSpacingSpinBox->value() );
|
||||
|
||||
// Create diagram renderer for the StackedDiagram
|
||||
QgsStackedDiagramRenderer *dr = new QgsStackedDiagramRenderer();
|
||||
dr->setDiagram( new QgsStackedDiagram() );
|
||||
|
||||
// Get DiagramSettings from each subdiagram
|
||||
const QList< QgsDiagramRenderer *> renderers = mModel->subRenderers();
|
||||
for ( const auto &renderer : renderers )
|
||||
{
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer;
|
||||
mLayer->setDiagramRenderer( renderer.release() );
|
||||
|
||||
QgsDiagramLayerSettings dls;
|
||||
mLayer->setDiagramLayerSettings( dls );
|
||||
|
||||
// refresh
|
||||
QgsProject::instance()->setDirty( true );
|
||||
mLayer->triggerRepaint();
|
||||
}
|
||||
else if ( mDiagramTypeComboBox->currentData( Qt::UserRole ) == QgsDiagramLayerSettings::Single )
|
||||
{
|
||||
static_cast<QgsDiagramProperties *>( mSubDiagramsTabWidget->widget( 0 ) )->apply();
|
||||
}
|
||||
else // Stacked diagram
|
||||
{
|
||||
// Create diagram settings for the StackedDiagram
|
||||
std::unique_ptr< QgsDiagramSettings> ds = std::make_unique< QgsDiagramSettings >();
|
||||
ds->stackedDiagramMode = static_cast<QgsDiagramSettings::StackedDiagramMode>( mStackedDiagramModeComboBox->currentData().toInt() );
|
||||
ds->setStackedDiagramSpacingUnit( mStackedDiagramSpacingUnitComboBox->unit() );
|
||||
ds->setStackedDiagramSpacing( mStackedDiagramSpacingSpinBox->value() );
|
||||
|
||||
// Create diagram renderer for the StackedDiagram
|
||||
QgsStackedDiagramRenderer *dr = new QgsStackedDiagramRenderer();
|
||||
dr->setDiagram( new QgsStackedDiagram() );
|
||||
|
||||
// Get DiagramSettings from each subdiagram
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
const QList< QgsDiagramSettings > ds1 = renderer->diagramSettings();
|
||||
if ( !ds1.isEmpty() )
|
||||
{
|
||||
QgsDiagramProperties *diagramProperties = static_cast<QgsDiagramProperties *>( mSubDiagramsTabWidget->widget( i ) );
|
||||
std::unique_ptr< QgsDiagramSettings > ds1 = diagramProperties->createDiagramSettings();
|
||||
ds->categoryAttributes += ds1->categoryAttributes;
|
||||
ds->categoryLabels += ds1->categoryLabels;
|
||||
ds->categoryColors += ds1->categoryColors;
|
||||
|
||||
std::unique_ptr< QgsDiagramRenderer > dr1 = diagramProperties->createRendererBaseInfo( *ds1 );
|
||||
|
||||
std::unique_ptr< QgsDiagram > diagram;
|
||||
|
||||
if ( diagramProperties->mDiagramType == DIAGRAM_NAME_TEXT )
|
||||
{
|
||||
diagram = std::make_unique< QgsTextDiagram >();
|
||||
}
|
||||
else if ( diagramProperties->mDiagramType == DIAGRAM_NAME_PIE )
|
||||
{
|
||||
diagram = std::make_unique< QgsPieDiagram >();
|
||||
}
|
||||
else if ( diagramProperties->mDiagramType == DIAGRAM_NAME_STACKED_BAR )
|
||||
{
|
||||
diagram = std::make_unique< QgsStackedBarDiagram >();
|
||||
}
|
||||
else // DIAGRAM_NAME_HISTOGRAM
|
||||
{
|
||||
diagram = std::make_unique< QgsHistogramDiagram >();
|
||||
}
|
||||
|
||||
dr1->setDiagram( diagram.release() );
|
||||
dr->addRenderer( dr1.release() );
|
||||
ds->categoryAttributes += ds1.at( 0 ).categoryAttributes;
|
||||
ds->categoryLabels += ds1.at( 0 ).categoryLabels;
|
||||
ds->categoryColors += ds1.at( 0 ).categoryColors;
|
||||
}
|
||||
|
||||
dr->setDiagramSettings( *ds );
|
||||
mLayer->setDiagramRenderer( dr );
|
||||
|
||||
// Create DiagramLayerSettings from first diagram
|
||||
QgsDiagramProperties *firstDiagramProperties = static_cast< QgsDiagramProperties * >( mSubDiagramsTabWidget->widget( 0 ) );
|
||||
QgsDiagramLayerSettings dls = firstDiagramProperties->createDiagramLayerSettings();
|
||||
mLayer->setDiagramLayerSettings( dls );
|
||||
|
||||
// refresh
|
||||
QgsProject::instance()->setDirty( true );
|
||||
mLayer->triggerRepaint();
|
||||
dr->addRenderer( renderer );
|
||||
}
|
||||
|
||||
dr->setDiagramSettings( *ds );
|
||||
mLayer->setDiagramRenderer( dr );
|
||||
|
||||
// Get DiagramLayerSettings from the model
|
||||
QgsDiagramLayerSettings dls = mModel->diagramLayerSettings();
|
||||
mLayer->setDiagramLayerSettings( dls );
|
||||
|
||||
// refresh
|
||||
QgsProject::instance()->setDirty( true );
|
||||
mLayer->triggerRepaint();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::mDiagramTypeComboBox_currentIndexChanged( int index )
|
||||
bool QgsStackedDiagramProperties::couldBeFirstSubDiagram( const QModelIndex &index ) const
|
||||
{
|
||||
if ( index == 0 ) // No diagram
|
||||
if ( !index.isValid() )
|
||||
return false;
|
||||
|
||||
if ( mModel->rowCount() == 1 )
|
||||
return true;
|
||||
|
||||
// Is there any enabled subdiagram before our index.row()?
|
||||
// If so, ours cannot be the first diagram.
|
||||
const QList< QgsDiagramRenderer * > renderers = mModel->subRenderers();
|
||||
|
||||
for ( int i = 0; i < index.row(); i++ )
|
||||
{
|
||||
mDiagramsFrame->setEnabled( false );
|
||||
mStackedDiagramSettingsFrame->hide();
|
||||
|
||||
// Hide tabs other than the first one
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
const auto &renderer = renderers.at( i );
|
||||
const QList< QgsDiagramSettings > ds = renderer->diagramSettings();
|
||||
if ( !ds.isEmpty() && ds.at( 0 ).enabled )
|
||||
{
|
||||
if ( i < 1 )
|
||||
continue;
|
||||
|
||||
mSubDiagramsTabWidget->setTabVisible( i, false );
|
||||
}
|
||||
}
|
||||
else if ( index == 1 ) // Single
|
||||
{
|
||||
mDiagramsFrame->setEnabled( true );
|
||||
mStackedDiagramSettingsFrame->hide();
|
||||
|
||||
// Hide tabs other than the first one
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
{
|
||||
if ( i < 1 )
|
||||
continue;
|
||||
|
||||
mSubDiagramsTabWidget->setTabVisible( i, false );
|
||||
}
|
||||
}
|
||||
else // Stacked
|
||||
{
|
||||
mDiagramsFrame->setEnabled( true );
|
||||
mStackedDiagramSettingsFrame->show();
|
||||
|
||||
// Create the second tab or show all hidden tabs
|
||||
if ( mSubDiagramsTabWidget->count() == 1 )
|
||||
{
|
||||
// Add second subdiagram tab
|
||||
addSubDiagram();
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < mSubDiagramsTabWidget->count(); i++ )
|
||||
{
|
||||
if ( i < 1 )
|
||||
continue;
|
||||
|
||||
mSubDiagramsTabWidget->setTabVisible( i, true );
|
||||
}
|
||||
// First enabled subdiagram found, and we know our row is after.
|
||||
// Therefore, return false to disallow showing DLS settings for it.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Either our row is the first subdiagram enabled or it's disabled,
|
||||
// but there are no enabled ones before. So, ours could be the first
|
||||
// enabled one after being edited.
|
||||
// Therefore, we should allow DLS settings on its corresponding widget.
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::mEngineSettingsButton_clicked()
|
||||
void QgsStackedDiagramProperties::subDiagramWidgetPanelAccepted( QgsPanelWidget *panel )
|
||||
{
|
||||
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
|
||||
if ( panel && panel->dockMode() )
|
||||
QgsDiagramProperties *widget = qobject_cast<QgsDiagramProperties *>( panel );
|
||||
|
||||
std::unique_ptr< QgsDiagramRenderer > renderer = widget->createRenderer();
|
||||
|
||||
const QModelIndex index = mSubDiagramsView->selectionModel()->currentIndex();
|
||||
if ( widget->isAllowedToEditDiagramLayerSettings() )
|
||||
mModel->updateDiagramLayerSettings( widget->createDiagramLayerSettings() );
|
||||
|
||||
mModel->updateSubDiagram( index, renderer.release() );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramProperties::liveUpdateSubDiagramFromPanel()
|
||||
{
|
||||
subDiagramWidgetPanelAccepted( qobject_cast<QgsPanelWidget *>( sender() ) );
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
#include "qgsvscrollarea.h"
|
||||
|
||||
QgsStackedDiagramPropertiesDialog::QgsStackedDiagramPropertiesDialog( QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *mapCanvas )
|
||||
: QDialog( parent )
|
||||
{
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
setWindowModality( Qt::WindowModal );
|
||||
#endif
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout( this );
|
||||
QgsVScrollArea *scrollArea = new QgsVScrollArea( this );
|
||||
scrollArea->setFrameShape( QFrame::NoFrame );
|
||||
layout->addWidget( scrollArea );
|
||||
|
||||
buttonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
|
||||
mPropsWidget = new QgsDiagramProperties( layer, this, mapCanvas );
|
||||
mPropsWidget->setDockMode( false );
|
||||
|
||||
scrollArea->setWidget( mPropsWidget );
|
||||
layout->addWidget( buttonBox );
|
||||
this->setWindowTitle( "Edit Sub Diagram" );
|
||||
QgsGui::enableAutoGeometryRestore( this );
|
||||
|
||||
connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsStackedDiagramPropertiesDialog::accept );
|
||||
connect( buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
|
||||
connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsStackedDiagramPropertiesDialog::showHelp );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesDialog::syncToRenderer( const QgsDiagramRenderer *dr ) const
|
||||
{
|
||||
mPropsWidget->syncToRenderer( dr );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesDialog::syncToSettings( const QgsDiagramLayerSettings *dls ) const
|
||||
{
|
||||
mPropsWidget->syncToSettings( dls );
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesDialog::accept()
|
||||
{
|
||||
// Get renderer and diagram layer settings from widget
|
||||
mRenderer = mPropsWidget->createRenderer();
|
||||
mDiagramLayerSettings = mPropsWidget->createDiagramLayerSettings();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
QgsDiagramRenderer *QgsStackedDiagramPropertiesDialog::renderer()
|
||||
{
|
||||
return mRenderer.release();
|
||||
}
|
||||
|
||||
QgsDiagramLayerSettings QgsStackedDiagramPropertiesDialog::diagramLayerSettings() const
|
||||
{
|
||||
return mDiagramLayerSettings;
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesDialog::setAllowedToEditDiagramLayerSettings( bool allowed ) const
|
||||
{
|
||||
mPropsWidget->setAllowedToEditDiagramLayerSettings( allowed );
|
||||
}
|
||||
|
||||
bool QgsStackedDiagramPropertiesDialog::isAllowedToEditDiagramLayerSettings() const
|
||||
{
|
||||
return mPropsWidget->isAllowedToEditDiagramLayerSettings();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesDialog::showHelp()
|
||||
{
|
||||
QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#diagrams-properties" ) );
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
QgsStackedDiagramPropertiesModel::QgsStackedDiagramPropertiesModel( QObject *parent )
|
||||
: QAbstractTableModel( parent )
|
||||
{
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsStackedDiagramPropertiesModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
const Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | checkable;
|
||||
}
|
||||
|
||||
QVariant QgsStackedDiagramPropertiesModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return QVariant();
|
||||
|
||||
QgsDiagramRenderer *dr = subDiagramForIndex( index );
|
||||
|
||||
if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
|
||||
{
|
||||
QgsLabelEngineConfigWidget *widget = new QgsLabelEngineConfigWidget( mMapCanvas );
|
||||
connect( widget, &QgsLabelEngineConfigWidget::widgetChanged, widget, &QgsLabelEngineConfigWidget::apply );
|
||||
panel->openPanel( widget );
|
||||
switch ( index.column() )
|
||||
{
|
||||
case 1:
|
||||
return ( !dr || !dr->diagram() ) ? tr( "(no diagram)" ) : dr->diagram()->diagramName();
|
||||
case 2:
|
||||
if ( !dr )
|
||||
{
|
||||
return tr( "(no renderer)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( dr->rendererName() == QLatin1String( "SingleCategory" ) )
|
||||
return tr( "Fixed" );
|
||||
else if ( dr->rendererName() == QLatin1String( "LinearlyInterpolated" ) )
|
||||
return tr( "Scaled" );
|
||||
else
|
||||
return tr( "Unknown" );
|
||||
}
|
||||
case 3:
|
||||
if ( dr && dr->diagram() && !dr->diagramSettings().isEmpty() )
|
||||
{
|
||||
if ( DIAGRAM_NAME_HISTOGRAM == dr->diagram()->diagramName() || DIAGRAM_NAME_STACKED_BAR == dr->diagram()->diagramName() )
|
||||
{
|
||||
switch ( dr->diagramSettings().at( 0 ).diagramOrientation )
|
||||
{
|
||||
case QgsDiagramSettings::Left:
|
||||
return tr( "Left" );
|
||||
case QgsDiagramSettings::Right:
|
||||
return tr( "Right" );
|
||||
case QgsDiagramSettings::Up:
|
||||
return tr( "Up" );
|
||||
case QgsDiagramSettings::Down:
|
||||
return tr( "Down" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
case 0:
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else if ( role == Qt::TextAlignmentRole )
|
||||
{
|
||||
return index.column() == 0 ? static_cast<Qt::Alignment::Int>( Qt::AlignCenter ) : static_cast<Qt::Alignment::Int>( Qt::AlignLeft );
|
||||
}
|
||||
else if ( role == Qt::CheckStateRole )
|
||||
{
|
||||
if ( index.column() != 0 )
|
||||
return QVariant();
|
||||
|
||||
return ( dr && !dr->diagramSettings().isEmpty() && dr->diagramSettings().at( 0 ).enabled ) ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsLabelEngineConfigDialog dialog( mMapCanvas, this );
|
||||
dialog.exec();
|
||||
// reactivate button's window
|
||||
activateWindow();
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant QgsStackedDiagramPropertiesModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 4 )
|
||||
{
|
||||
QStringList lst;
|
||||
lst << tr( "Enabled" ) << tr( "Diagram type" ) << tr( "Size" ) << tr( "Orientation" );
|
||||
return lst[section];
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int QgsStackedDiagramPropertiesModel::rowCount( const QModelIndex & ) const
|
||||
{
|
||||
return mRenderers.size();
|
||||
}
|
||||
|
||||
int QgsStackedDiagramPropertiesModel::columnCount( const QModelIndex & ) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool QgsStackedDiagramPropertiesModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return false;
|
||||
|
||||
QgsDiagramRenderer *dr = subDiagramForIndex( index );
|
||||
|
||||
if ( role == Qt::CheckStateRole )
|
||||
{
|
||||
if ( dr && !dr->diagramSettings().isEmpty() )
|
||||
{
|
||||
QgsDiagramSettings ds = dr->diagramSettings().at( 0 );
|
||||
ds.enabled = ( value.toInt() == Qt::Checked );
|
||||
|
||||
if ( dr->rendererName() == QLatin1String( "SingleCategory" ) )
|
||||
{
|
||||
QgsSingleCategoryDiagramRenderer *dsr = static_cast< QgsSingleCategoryDiagramRenderer * >( dr );
|
||||
dsr->setDiagramSettings( ds );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsLinearlyInterpolatedDiagramRenderer *dlir = static_cast< QgsLinearlyInterpolatedDiagramRenderer * >( dr );
|
||||
dlir->setDiagramSettings( ds );
|
||||
}
|
||||
|
||||
emit dataChanged( index, index );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsStackedDiagramPropertiesModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
if ( row < 0 || row >= mRenderers.size() )
|
||||
return false;
|
||||
|
||||
beginRemoveRows( parent, row, row + count - 1 );
|
||||
while ( count-- )
|
||||
mRenderers.removeAt( row );
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsDiagramRenderer *QgsStackedDiagramPropertiesModel::subDiagramForIndex( const QModelIndex &index ) const
|
||||
{
|
||||
if ( index.isValid() )
|
||||
return mRenderers.at( index.row() );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesModel::insertSubDiagram( const int index, QgsDiagramRenderer *newSubDiagram )
|
||||
{
|
||||
beginInsertRows( QModelIndex(), index, index );
|
||||
mRenderers.insert( index, newSubDiagram );
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesModel::updateSubDiagram( const QModelIndex &index, QgsDiagramRenderer *dr )
|
||||
{
|
||||
mRenderers.replace( index.row(), dr );
|
||||
emit dataChanged( index, index );
|
||||
}
|
||||
|
||||
QList< QgsDiagramRenderer *> QgsStackedDiagramPropertiesModel::subRenderers() const
|
||||
{
|
||||
QList<QgsDiagramRenderer *> subRenderers;
|
||||
subRenderers = mRenderers;
|
||||
return subRenderers;
|
||||
}
|
||||
|
||||
void QgsStackedDiagramPropertiesModel::updateDiagramLayerSettings( QgsDiagramLayerSettings dls )
|
||||
{
|
||||
mDiagramLayerSettings = dls;
|
||||
}
|
||||
|
||||
QgsDiagramLayerSettings QgsStackedDiagramPropertiesModel::diagramLayerSettings() const
|
||||
{
|
||||
return mDiagramLayerSettings;
|
||||
}
|
||||
|
@ -22,14 +22,71 @@
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis_gui.h"
|
||||
#include "qgsdiagramrenderer.h"
|
||||
#include "ui_qgsstackeddiagrampropertiesbase.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
class QgsVectorLayer;
|
||||
class QgsMapCanvas;
|
||||
class QgsDiagramProperties;
|
||||
class QgsDiagramRenderer;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \brief Model for sub diagrams in a stacked diagram view.
|
||||
*
|
||||
* \note This class is not a part of public API
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class GUI_EXPORT QgsStackedDiagramPropertiesModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
QgsStackedDiagramPropertiesModel( QObject *parent = nullptr );
|
||||
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
||||
QVariant headerData( int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole ) const override;
|
||||
int rowCount( const QModelIndex & = QModelIndex() ) const override;
|
||||
int columnCount( const QModelIndex & = QModelIndex() ) const override;
|
||||
|
||||
// editing support
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
|
||||
// new methods
|
||||
|
||||
//! Returns the diagram renderer at the specified index
|
||||
QgsDiagramRenderer *subDiagramForIndex( const QModelIndex &index ) const;
|
||||
|
||||
//! Inserts a new diagram at the specified position
|
||||
void insertSubDiagram( const int index, QgsDiagramRenderer *newSubDiagram );
|
||||
//! Replaces the diagram located at \a index by \a dr
|
||||
void updateSubDiagram( const QModelIndex &index, QgsDiagramRenderer *dr );
|
||||
|
||||
//! Returns the list of diagram renderers from the model
|
||||
QList< QgsDiagramRenderer *> subRenderers() const;
|
||||
|
||||
//! Returns the diagram layer settings from the model
|
||||
QgsDiagramLayerSettings diagramLayerSettings() const;
|
||||
|
||||
/**
|
||||
* Sets the diagram layer settings for the model.
|
||||
* @param dls DiagramLayerSettings to be set.
|
||||
*/
|
||||
void updateDiagramLayerSettings( QgsDiagramLayerSettings dls );
|
||||
|
||||
protected:
|
||||
QList< QgsDiagramRenderer *> mRenderers;
|
||||
QgsDiagramLayerSettings mDiagramLayerSettings;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -38,7 +95,7 @@ class QgsDiagramProperties;
|
||||
*
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class GUI_EXPORT QgsStackedDiagramProperties : public QWidget, private Ui::QgsStackedDiagramPropertiesBase
|
||||
class GUI_EXPORT QgsStackedDiagramProperties : public QgsPanelWidget, private Ui::QgsStackedDiagramPropertiesBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -55,27 +112,127 @@ class GUI_EXPORT QgsStackedDiagramProperties : public QWidget, private Ui::QgsSt
|
||||
|
||||
public slots:
|
||||
void apply();
|
||||
void mDiagramTypeComboBox_currentIndexChanged( int index );
|
||||
void mSubDiagramsTabWidget_tabMoved( int from, int to );
|
||||
void mEngineSettingsButton_clicked();
|
||||
|
||||
private slots:
|
||||
|
||||
/**
|
||||
* Adds a diagram tab to the current QgsStackedDiagramProperties.
|
||||
* Adds a diagram to the current QgsStackedDiagramProperties.
|
||||
*/
|
||||
void addSubDiagram();
|
||||
|
||||
/**
|
||||
* Removes a diagram tab from the current QgsStackedDiagramProperties.
|
||||
* Diagram tabs are removed only if the tab count is greater than 2.
|
||||
* Tab texts are adjusted after tab removal, to keep sequential order.
|
||||
* Appends a diagram to the current QgsStackedDiagramProperties.
|
||||
* @param dr Diagram renderer to be appended.
|
||||
*/
|
||||
void appendSubDiagram( QgsDiagramRenderer *dr );
|
||||
|
||||
/**
|
||||
* Edits the properties of the current diagram.
|
||||
*/
|
||||
void editSubDiagram();
|
||||
|
||||
/**
|
||||
* Edits the properties of a diagram located at a given \a index.
|
||||
* @param index Model index where the diagram is located.
|
||||
*/
|
||||
void editSubDiagram( const QModelIndex &index );
|
||||
|
||||
/**
|
||||
* Removes a diagram from the current QgsStackedDiagramProperties.
|
||||
*/
|
||||
void removeSubDiagram();
|
||||
|
||||
private:
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
QgsMapCanvas *mMapCanvas = nullptr;
|
||||
|
||||
QgsStackedDiagramPropertiesModel *mModel = nullptr;
|
||||
|
||||
/**
|
||||
* Determines whether the subdiagram in the given \a index may be
|
||||
* the first sub diagram in the stacked diagram. This includes the
|
||||
* first enabled sub diagram, as well as disabled sub diagrams that,
|
||||
* after being edited, can become the first enabled one.
|
||||
* @param index Model index where the sub diagram is located.
|
||||
*/
|
||||
bool couldBeFirstSubDiagram( const QModelIndex &index ) const;
|
||||
|
||||
private slots:
|
||||
void subDiagramWidgetPanelAccepted( QgsPanelWidget *panel );
|
||||
void liveUpdateSubDiagramFromPanel();
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \class QgsStackedDiagramPropertiesDialog
|
||||
* \brief Dialog for editing sub diagrams
|
||||
*
|
||||
* \note This class is not a part of public API
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
class GUI_EXPORT QgsStackedDiagramPropertiesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsStackedDiagramPropertiesDialog
|
||||
* \param layer source vector layer
|
||||
* \param parent parent widget
|
||||
* \param mapCanvas map canvas
|
||||
*/
|
||||
QgsStackedDiagramPropertiesDialog( QgsVectorLayer *layer, QWidget *parent = nullptr, QgsMapCanvas *mapCanvas = nullptr );
|
||||
|
||||
/**
|
||||
* Delegates to the diagram properties widget to sync with the given renderer.
|
||||
* @param dr Diagram Renderer to be used for the sync.
|
||||
*/
|
||||
void syncToRenderer( const QgsDiagramRenderer *dr ) const;
|
||||
|
||||
/**
|
||||
* Delegates to the diagram properties widget to sync with the given diagram layer settings.
|
||||
* @param dls Diagram Layer Settings to be used for the sync.
|
||||
*/
|
||||
void syncToSettings( const QgsDiagramLayerSettings *dls ) const;
|
||||
|
||||
/**
|
||||
* Gets a renderer object built from the diagram properties widget.
|
||||
*/
|
||||
QgsDiagramRenderer *renderer();
|
||||
|
||||
/**
|
||||
* Gets diagram layer settings built from the diagram properties widget.
|
||||
*/
|
||||
QgsDiagramLayerSettings diagramLayerSettings() const;
|
||||
|
||||
/**
|
||||
* Delegates to the main widget to set whether the widget should show
|
||||
* diagram layer settings to be edited.
|
||||
* @param allowed Whether the main widget should be allowed to edit diagram layer settings.
|
||||
*/
|
||||
void setAllowedToEditDiagramLayerSettings( bool allowed ) const;
|
||||
|
||||
/**
|
||||
* Returns whether the main widget is allowed to edit diagram layer settings.
|
||||
*/
|
||||
bool isAllowedToEditDiagramLayerSettings() const;
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Applies changes from the widget to the internal renderer and diagram layer settings.
|
||||
*/
|
||||
void accept() override;
|
||||
|
||||
private slots:
|
||||
void showHelp();
|
||||
|
||||
private:
|
||||
QgsDiagramProperties *mPropsWidget = nullptr;
|
||||
std::unique_ptr< QgsDiagramRenderer > mRenderer;
|
||||
QgsDiagramLayerSettings mDiagramLayerSettings;
|
||||
QDialogButtonBox *buttonBox = nullptr;
|
||||
};
|
||||
|
||||
#endif // QGSSTACKEDDIAGRAMPROPERTIES_H
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsattributeactiondialog.h"
|
||||
#include "qgsdatumtransformdialog.h"
|
||||
#include "qgsstackeddiagramproperties.h"
|
||||
#include "qgsdiagramwidget.h"
|
||||
#include "qgssourcefieldsproperties.h"
|
||||
#include "qgsattributesformproperties.h"
|
||||
#include "qgslabelingwidget.h"
|
||||
@ -280,6 +280,15 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
mSelectionSymbolButton->setEnabled( false );
|
||||
mRadioDefaultSelectionColor->setChecked( true );
|
||||
|
||||
// Diagram tab, before the syncToLayer
|
||||
QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
|
||||
diagLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
diagramPropertiesDialog = new QgsDiagramWidget( mLayer, mCanvas, mDiagramFrame );
|
||||
diagramPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
connect( diagramPropertiesDialog, &QgsDiagramWidget::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
|
||||
diagLayout->addWidget( diagramPropertiesDialog );
|
||||
mDiagramFrame->setLayout( diagLayout );
|
||||
|
||||
syncToLayer();
|
||||
|
||||
if ( mLayer->dataProvider() )
|
||||
@ -333,14 +342,6 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
|
||||
mOldJoins = mLayer->vectorJoins();
|
||||
|
||||
QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
|
||||
diagLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
diagramPropertiesDialog = new QgsStackedDiagramProperties( mLayer, mDiagramFrame, mCanvas );
|
||||
diagramPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
connect( diagramPropertiesDialog, &QgsStackedDiagramProperties::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
|
||||
diagLayout->addWidget( diagramPropertiesDialog );
|
||||
mDiagramFrame->setLayout( diagLayout );
|
||||
|
||||
// Legend tab
|
||||
mLegendWidget->setMapCanvas( mCanvas );
|
||||
mLegendWidget->setLayer( mLayer );
|
||||
@ -728,7 +729,7 @@ void QgsVectorLayerProperties::syncToLayer()
|
||||
updateVariableEditor();
|
||||
|
||||
if ( diagramPropertiesDialog )
|
||||
diagramPropertiesDialog->syncToLayer();
|
||||
diagramPropertiesDialog->syncToOwnLayer();
|
||||
|
||||
// sync all plugin dialogs
|
||||
for ( QgsMapLayerConfigWidget *page : std::as_const( mConfigWidgets ) )
|
||||
|
@ -33,7 +33,7 @@ class QgsMapLayer;
|
||||
class QgsAttributeActionDialog;
|
||||
class QgsVectorLayer;
|
||||
class QgsLabelingWidget;
|
||||
class QgsStackedDiagramProperties;
|
||||
class QgsDiagramWidget;
|
||||
class QgsSourceFieldsProperties;
|
||||
class QgsAttributesFormProperties;
|
||||
class QgsRendererPropertiesDialog;
|
||||
@ -172,7 +172,7 @@ class GUI_EXPORT QgsVectorLayerProperties : public QgsLayerPropertiesDialog, pri
|
||||
//! Actions dialog. If apply is pressed, the actions are stored for later use
|
||||
QgsAttributeActionDialog *mActionDialog = nullptr;
|
||||
//! Diagram dialog. If apply is pressed, options are applied to vector's diagrams
|
||||
QgsStackedDiagramProperties *diagramPropertiesDialog = nullptr;
|
||||
QgsDiagramWidget *diagramPropertiesDialog = nullptr;
|
||||
//! SourceFields dialog. If apply is pressed, options are applied to vector's diagrams
|
||||
QgsSourceFieldsProperties *mSourceFieldsPropertiesDialog = nullptr;
|
||||
//! AttributesForm dialog. If apply is pressed, options are applied to vector's diagrams
|
||||
|
File diff suppressed because it is too large
Load Diff
59
src/ui/qgsdiagramwidget.ui
Normal file
59
src/ui/qgsdiagramwidget.ui
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsDiagramWidget</class>
|
||||
<widget class="QWidget" name="QgsDiagramWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>842</width>
|
||||
<height>472</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDiagramTypeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mEngineSettingsButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Automated placement settings (applies to all layers)</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mIconAutoPlacementSettings.svg</normaloff>:/images/themes/default/mIconAutoPlacementSettings.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QStackedWidget" name="mStackedWidget">
|
||||
<widget class="QWidget" name="page"/>
|
||||
<widget class="QWidget" name="page_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -11,25 +11,106 @@
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<widget class="QTreeView" name="mSubDiagramsView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SelectionMode::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>57</number>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDiagramTypeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mEngineSettingsButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="mAddSubDiagramButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Automated placement settings (apply to all layers)</string>
|
||||
<string>Add subdiagram to the stacked diagram</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mIconAutoPlacementSettings.svg</normaloff>:/images/themes/default/mIconAutoPlacementSettings.svg</iconset>
|
||||
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mEditSubDiagramButton">
|
||||
<property name="toolTip">
|
||||
<string>Edit subdiagram from the stacked diagram</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyEdit.svg</normaloff>:/images/themes/default/symbologyEdit.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mRemoveSubDiagramButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove subdiagram from the stacked diagram</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -41,93 +122,6 @@
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="mAddSubDiagramButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add subdiagram to the stacked diagram</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add subdiagram</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mRemoveSubDiagramButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove subdiagram from the stacked diagram</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove subdiagram</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="stackedDiagramModeLabel">
|
||||
<property name="text">
|
||||
<string>Stacked Diagram Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mStackedDiagramModeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
@ -175,42 +169,32 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="mDiagramsFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="mSubDiagramsTabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="stackedDiagramModeLabel">
|
||||
<property name="text">
|
||||
<string>Stacked diagram mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mStackedDiagramModeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -286,7 +286,8 @@ ACCEPTABLE_MISSING_DOCS = {
|
||||
"QgsEffectStack": ["QgsEffectStack(const QgsEffectStack &other)"],
|
||||
"QgsRelationReferenceWidget": ["setRelation(const QgsRelation &relation, bool allowNullValue)", "CanvasExtent", "setOpenFormButtonVisible(bool openFormButtonVisible)", "QgsRelationReferenceWidget(QWidget *parent)", "setReadOnlySelector(bool readOnly)", "setRelationEditable(bool editable)", "init()", "setAllowMapIdentification(bool allowMapIdentification)", "setEmbedForm(bool display)"],
|
||||
"QgsDiagramProperties": ["mAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)", "scalingTypeChanged()", "mAddCategoryPushButton_clicked()", "mEngineSettingsButton_clicked()", "apply()", "mRemoveCategoryPushButton_clicked()", "showSizeLegendDialog()", "QgsDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)", "mDiagramAttributesTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)", "mDiagramStackedWidget_currentChanged(int index)", "mDiagramTypeComboBox_currentIndexChanged(int index)", "mFindMaximumValueButton_clicked()", "showAddAttributeExpressionDialog()", "auxiliaryFieldCreated()", "updatePlacementWidgets()"],
|
||||
"QgsStackedDiagramProperties": ["mDiagramTypeComboBox_currentIndexChanged(int index)", "apply()", "mEngineSettingsButton_clicked()", "mSubDiagramsTabWidget_tabMoved(int from, int to)", "auxiliaryFieldCreated()", "QgsStackedDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)"],
|
||||
"QgsStackedDiagramProperties": ["apply()", "auxiliaryFieldCreated()", "QgsStackedDiagramProperties(QgsVectorLayer *layer, QWidget *parent, QgsMapCanvas *canvas)"],
|
||||
"QgsDiagramWidget": ["mDiagramTypeComboBox_currentIndexChanged(int index)", "showEngineConfigDialog()"],
|
||||
"QgsFeatureListView": ["repaintRequested()", "repaintRequested(const QModelIndexList &indexes)"],
|
||||
"QgsGradientFillSymbolLayerWidget": ["setGradientSpread(int index)", "setColor(const QColor &color)", "setCoordinateMode(int index)", "setColor2(const QColor &color)", "setGradientType(int index)"],
|
||||
"QgsFillSymbol": ["setAngle(double angle) const"],
|
||||
|
@ -191,6 +191,96 @@ class TestQgsStackedDiagram : public QgsTest
|
||||
QGSVERIFYRENDERMAPSETTINGSCHECK( "stackedhistograms", "stackedhistograms", *mMapSettings, 200, 15 );
|
||||
}
|
||||
|
||||
void testDisabledSubDiagram()
|
||||
{
|
||||
// Histogram 1 (disabled)
|
||||
QgsDiagramSettings ds1;
|
||||
QColor col1 = Qt::blue;
|
||||
QColor col2 = Qt::red;
|
||||
QColor col3 = Qt::yellow;
|
||||
QColor col4 = Qt::green;
|
||||
col1.setAlphaF( 0.5 );
|
||||
col2.setAlphaF( 0.5 );
|
||||
col3.setAlphaF( 0.5 );
|
||||
col4.setAlphaF( 0.5 );
|
||||
ds1.categoryColors = QList<QColor>() << col1 << col2 << col3 << col4;
|
||||
ds1.categoryAttributes = QList<QString>() << QStringLiteral( "\"maennlich_ab_65\"" ) << QStringLiteral( "\"maennlich_18_64\"" ) << QStringLiteral( "\"maennlich_6_17\"" ) << QStringLiteral( "\"maennlich_unter_6\"" ); //#spellok
|
||||
ds1.minimumScale = -1;
|
||||
ds1.maximumScale = -1;
|
||||
ds1.minimumSize = 0;
|
||||
ds1.penColor = Qt::black;
|
||||
ds1.penWidth = .5;
|
||||
ds1.scaleByArea = true;
|
||||
ds1.sizeType = Qgis::RenderUnit::Millimeters;
|
||||
ds1.rotationOffset = 0;
|
||||
ds1.diagramOrientation = QgsDiagramSettings::Left;
|
||||
ds1.enabled = false;
|
||||
|
||||
QgsLinearlyInterpolatedDiagramRenderer *dr1 = new QgsLinearlyInterpolatedDiagramRenderer();
|
||||
dr1->setDiagram( new QgsHistogramDiagram() );
|
||||
dr1->setDiagramSettings( ds1 );
|
||||
dr1->setLowerValue( 0.0 );
|
||||
dr1->setLowerSize( QSizeF( 0.0, 0.0 ) );
|
||||
dr1->setUpperValue( 15000 );
|
||||
dr1->setUpperSize( QSizeF( 20, 20 ) );
|
||||
//dr1->setClassificationField( QStringLiteral( "max(\"maennlich_18_64\", \"maennlich_ab_65\", \"maennlich_6_17\", \"maennlich_unter_6\")" ) ); //#spellok
|
||||
|
||||
// Histogram 2
|
||||
QgsDiagramSettings ds2;
|
||||
col1 = Qt::blue;
|
||||
col2 = Qt::red;
|
||||
col3 = Qt::yellow;
|
||||
col4 = Qt::green;
|
||||
col1.setAlphaF( 0.5 );
|
||||
col2.setAlphaF( 0.5 );
|
||||
col3.setAlphaF( 0.5 );
|
||||
col4.setAlphaF( 0.5 );
|
||||
ds2.categoryColors = QList<QColor>() << col1 << col2 << col3 << col4;
|
||||
ds2.categoryAttributes = QList<QString>() << QStringLiteral( "\"weiblich_ab_65\"" ) << QStringLiteral( "\"weiblich_18_64\"" ) << QStringLiteral( "\"weiblich_6_17\"" ) << QStringLiteral( "\"weiblich_unter_6\"" ); //#spellok
|
||||
ds2.minimumScale = -1;
|
||||
ds2.maximumScale = -1;
|
||||
ds2.minimumSize = 0;
|
||||
ds2.penColor = Qt::black;
|
||||
ds2.penWidth = .5;
|
||||
ds2.scaleByArea = true;
|
||||
ds2.sizeType = Qgis::RenderUnit::Millimeters;
|
||||
ds2.rotationOffset = 0;
|
||||
ds2.diagramOrientation = QgsDiagramSettings::Right;
|
||||
|
||||
QgsLinearlyInterpolatedDiagramRenderer *dr2 = new QgsLinearlyInterpolatedDiagramRenderer();
|
||||
dr2->setDiagram( new QgsHistogramDiagram() );
|
||||
dr2->setDiagramSettings( ds2 );
|
||||
dr2->setLowerValue( 0.0 );
|
||||
dr2->setLowerSize( QSizeF( 0.0, 0.0 ) );
|
||||
dr2->setUpperValue( 15000 );
|
||||
dr2->setUpperSize( QSizeF( 20, 20 ) );
|
||||
//dr2->setClassificationField( QStringLiteral( "max(\"weiblich_unter_6\", \"weiblich_6_17\", \"weiblich_18_64\", \"weiblich_ab_65\")" ) ); //#spellok
|
||||
|
||||
QgsDiagramSettings ds;
|
||||
ds.stackedDiagramMode = QgsDiagramSettings::Horizontal;
|
||||
ds.categoryAttributes = ds1.categoryAttributes + ds2.categoryAttributes;
|
||||
ds.setStackedDiagramSpacingUnit( Qgis::RenderUnit::Pixels );
|
||||
ds.setStackedDiagramSpacing( 0 );
|
||||
|
||||
QgsStackedDiagramRenderer *dr = new QgsStackedDiagramRenderer();
|
||||
dr->setDiagram( new QgsStackedDiagram() );
|
||||
dr->setDiagramSettings( ds );
|
||||
dr->addRenderer( dr1 );
|
||||
dr->addRenderer( dr2 );
|
||||
mPointsLayer->setDiagramRenderer( dr );
|
||||
|
||||
QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
|
||||
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
|
||||
dls.setShowAllDiagrams( true );
|
||||
mPointsLayer->setDiagramLayerSettings( dls );
|
||||
|
||||
const QgsRectangle extent( 9.7, 53.5, 9.95, 53.6 );
|
||||
mMapSettings->setExtent( extent );
|
||||
mMapSettings->setFlag( Qgis::MapSettingsFlag::ForceVectorOutput );
|
||||
mMapSettings->setOutputDpi( 96 );
|
||||
QGSVERIFYRENDERMAPSETTINGSCHECK( "disabledsubdiagram", "disabledsubdiagram", *mMapSettings, 200, 15 );
|
||||
}
|
||||
|
||||
void testVerticallyStackedHistograms()
|
||||
{
|
||||
// Histogram 1
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 998 KiB |
Loading…
x
Reference in New Issue
Block a user