23 #include "qgssettings.h"
26 #include <QMouseEvent>
29 #include <qwt_global.h>
30 #include <qwt_plot_canvas.h>
32 #include <qwt_plot_curve.h>
33 #include <qwt_plot_grid.h>
34 #include <qwt_plot_marker.h>
35 #include <qwt_plot_picker.h>
36 #include <qwt_picker_machine.h>
37 #include <qwt_plot_layout.h>
38 #include <qwt_plot_renderer.h>
39 #include <qwt_plot_histogram.h>
44 , mVectorLayer( layer )
45 , mSourceFieldExp( fieldOrExp )
46 , mXAxisTitle( QObject::tr(
"Value" ) )
47 , mYAxisTitle( QObject::tr(
"Count" ) )
54 QFrame *plotCanvasFrame =
dynamic_cast<QFrame *
>( mpPlot->canvas() );
55 if ( plotCanvasFrame )
56 plotCanvasFrame->setFrameStyle( QFrame::NoFrame );
59 mMeanCheckBox->setChecked( settings.value( QStringLiteral(
"HistogramWidget/showMean" ),
false ).toBool() );
60 mStdevCheckBox->setChecked( settings.value( QStringLiteral(
"HistogramWidget/showStdev" ),
false ).toBool() );
62 connect( mBinsSpinBox,
static_cast < void ( QSpinBox::* )(
int )
> ( &QSpinBox::valueChanged ),
this, &
QgsHistogramWidget::refresh );
67 mGridPen = QPen( QColor( 0, 0, 0, 40 ) );
68 mMeanPen = QPen( QColor( 10, 10, 10, 220 ) );
69 mMeanPen.setStyle( Qt::DashLine );
70 mStdevPen = QPen( QColor( 30, 30, 30, 200 ) );
71 mStdevPen.setStyle( Qt::DashLine );
73 if (
layer && !mSourceFieldExp.isEmpty() )
82 settings.setValue( QStringLiteral(
"HistogramWidget/showMean" ), mMeanCheckBox->isChecked() );
83 settings.setValue( QStringLiteral(
"HistogramWidget/showStdev" ), mStdevCheckBox->isChecked() );
101 if ( !mVectorLayer || mSourceFieldExp.isEmpty() )
104 QApplication::setOverrideCursor( Qt::WaitCursor );
111 QApplication::restoreOverrideCursor();
116 std::sort( mValues.begin(), mValues.end() );
118 mBinsSpinBox->blockSignals(
true );
120 mBinsSpinBox->blockSignals(
false );
125 mpPlot->setEnabled(
true );
126 mMeanCheckBox->setEnabled(
true );
127 mStdevCheckBox->setEnabled(
true );
128 mBinsSpinBox->setEnabled(
true );
130 QApplication::restoreOverrideCursor();
143 if (
layer == mVectorLayer )
146 mVectorLayer =
layer;
150 void QgsHistogramWidget::clearHistogram()
156 mpPlot->setEnabled(
false );
157 mMeanCheckBox->setEnabled(
false );
158 mStdevCheckBox->setEnabled(
false );
159 mBinsSpinBox->setEnabled(
false );
164 if ( fieldOrExp == mSourceFieldExp )
167 mSourceFieldExp = fieldOrExp;
174 mpPlot->detachItems();
177 mpPlot->setAutoDelete(
true );
179 if ( !mXAxisTitle.isEmpty() )
180 mpPlot->setAxisTitle( QwtPlot::xBottom, mXAxisTitle );
181 if ( !mYAxisTitle.isEmpty() )
182 mpPlot->setAxisTitle( QwtPlot::yLeft, mYAxisTitle );
183 mpPlot->setAxisFont( QwtPlot::xBottom, this->font() );
184 mpPlot->setAxisFont( QwtPlot::yLeft, this->font() );
185 QFont titleFont = this->font();
186 titleFont.setBold(
true );
187 QwtText xAxisText = mpPlot->axisTitle( QwtPlot::xBottom );
188 xAxisText.setFont( titleFont );
189 mpPlot->setAxisTitle( QwtPlot::xBottom, xAxisText );
190 QwtText yAxisText = mpPlot->axisTitle( QwtPlot::yLeft );
191 yAxisText.setFont( titleFont );
192 mpPlot->setAxisTitle( QwtPlot::yLeft, yAxisText );
193 mpPlot->setAxisAutoScale( QwtPlot::yLeft );
194 mpPlot->setAxisAutoScale( QwtPlot::xBottom );
197 QwtPlotGrid *grid =
new QwtPlotGrid();
198 grid->enableX(
false );
199 grid->setPen( mGridPen );
200 grid->attach( mpPlot );
203 mHistoColors.clear();
206 mHistoColors << ( range.symbol() ? range.symbol()->color() : Qt::black );
210 QwtPlotHistogram *plotHistogram =
nullptr;
211 plotHistogram = createPlotHistogram( !
mRanges.isEmpty() ?
mRanges.at( 0 ).label() : QString(),
212 !
mRanges.isEmpty() ? QBrush( mHistoColors.at( 0 ) ) : mBrush,
213 !
mRanges.isEmpty() ? Qt::NoPen : mPen );
214 QVector<QwtIntervalSample> dataHisto;
216 int bins = mBinsSpinBox->value();
217 QList<double> edges = mHistogram.
binEdges( bins );
218 QList<int> counts = mHistogram.
counts( bins );
223 for (
int bin = 0; bin < bins; ++bin )
225 int binValue = counts.at( bin );
229 if ( rangeIndex <
mRanges.count() - 1 && edges.at( bin ) >
mRanges.at( rangeIndex ).upperValue() )
232 plotHistogram->setSamples( dataHisto );
233 plotHistogram->attach( mpPlot );
234 plotHistogram = createPlotHistogram(
mRanges.at( rangeIndex ).label(), mHistoColors.at( rangeIndex ) );
236 dataHisto << QwtIntervalSample( lastValue,
mRanges.at( rangeIndex - 1 ).upperValue(), edges.at( bin ) );
239 double upperEdge = !
mRanges.isEmpty() ? std::min( edges.at( bin + 1 ),
mRanges.at( rangeIndex ).upperValue() )
240 : edges.at( bin + 1 );
242 dataHisto << QwtIntervalSample( binValue, edges.at( bin ), upperEdge );
244 lastValue = binValue;
247 plotHistogram->setSamples( dataHisto );
248 plotHistogram->attach( mpPlot );
253 QwtPlotMarker *rangeMarker =
new QwtPlotMarker();
254 rangeMarker->attach( mpPlot );
255 rangeMarker->setLineStyle( QwtPlotMarker::VLine );
256 rangeMarker->setXValue( range.upperValue() );
257 rangeMarker->setLabel( QString::number( range.upperValue() ) );
258 rangeMarker->setLabelOrientation( Qt::Vertical );
259 rangeMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
264 if ( mMeanCheckBox->isChecked() )
266 QwtPlotMarker *meanMarker =
new QwtPlotMarker();
267 meanMarker->attach( mpPlot );
268 meanMarker->setLineStyle( QwtPlotMarker::VLine );
269 meanMarker->setLinePen( mMeanPen );
270 meanMarker->setXValue( mStats.
mean() );
271 meanMarker->setLabel( QString( QChar( 956 ) ) );
272 meanMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
276 if ( mStdevCheckBox->isChecked() )
278 QwtPlotMarker *stdev1Marker =
new QwtPlotMarker();
279 stdev1Marker->attach( mpPlot );
280 stdev1Marker->setLineStyle( QwtPlotMarker::VLine );
281 stdev1Marker->setLinePen( mStdevPen );
282 stdev1Marker->setXValue( mStats.
mean() - mStats.
stDev() );
283 stdev1Marker->setLabel( QString( QChar( 963 ) ) );
284 stdev1Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
285 stdev1Marker->show();
287 QwtPlotMarker *stdev2Marker =
new QwtPlotMarker();
288 stdev2Marker->attach( mpPlot );
289 stdev2Marker->setLineStyle( QwtPlotMarker::VLine );
290 stdev2Marker->setLinePen( mStdevPen );
291 stdev2Marker->setXValue( mStats.
mean() + mStats.
stDev() );
292 stdev2Marker->setLabel( QString( QChar( 963 ) ) );
293 stdev2Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
294 stdev2Marker->show();
297 mpPlot->setEnabled(
true );
301 QwtPlotHistogram *QgsHistogramWidget::createPlotHistogram(
const QString &title,
const QBrush &brush,
const QPen &pen )
const
303 QwtPlotHistogram *histogram =
new QwtPlotHistogram( title );
304 histogram->setBrush(
brush );
305 if (
pen != Qt::NoPen )
307 histogram->setPen(
pen );
309 else if (
brush.color().lightness() > 200 )
312 p.setColor(
brush.color().darker( 150 ) );
314 p.setCosmetic(
true );
315 histogram->setPen( p );
319 histogram->setPen( QPen( Qt::NoPen ) );
QList< int > counts(int bins) const
Returns the calculated list of the counts for the histogram bins.
int optimalNumberBins() const
Returns the optimal number of bins for the source values, calculated using the Freedman-Diaconis rule...
QList< double > binEdges(int bins) const
Returns a list of edges for the histogram for a specified number of bins.
void setValues(const QList< double > &values)
Assigns numeric source values for the histogram.
double lowerValue() const
void calculate(const QList< double > &values)
Calculates summary statistics for a list of values.
@ StDev
Standard deviation of values.
double mean() const
Returns calculated mean of values.
double stDev() const
Returns population standard deviation.
void setStatistics(QgsStatisticalSummary::Statistics stats)
Sets flags which specify which statistics will be calculated.
static QList< double > getDoubleValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr)
Fetches all double values from a specified field name or expression.
Represents a vector layer which manages a vector based data sets.
QList< QgsRendererRange > QgsRangeList