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>
45 , mVectorLayer( layer )
46 , mSourceFieldExp( fieldOrExp )
47 , mXAxisTitle( QObject::tr(
"Value" ) )
48 , mYAxisTitle( QObject::tr(
"Count" ) )
55 QFrame *plotCanvasFrame =
dynamic_cast<QFrame *
>( mpPlot->canvas() );
56 if ( plotCanvasFrame )
57 plotCanvasFrame->setFrameStyle( QFrame::NoFrame );
60 mMeanCheckBox->setChecked( settings.
value( QStringLiteral(
"HistogramWidget/showMean" ),
false ).toBool() );
61 mStdevCheckBox->setChecked( settings.
value( QStringLiteral(
"HistogramWidget/showStdev" ),
false ).toBool() );
63 connect( mBinsSpinBox,
static_cast < void ( QSpinBox::* )(
int )
> ( &QSpinBox::valueChanged ),
this, &
QgsHistogramWidget::refresh );
68 mGridPen = QPen( QColor( 0, 0, 0, 40 ) );
69 mMeanPen = QPen( QColor( 10, 10, 10, 220 ) );
70 mMeanPen.setStyle( Qt::DashLine );
71 mStdevPen = QPen( QColor( 30, 30, 30, 200 ) );
72 mStdevPen.setStyle( Qt::DashLine );
74 if (
layer && !mSourceFieldExp.isEmpty() )
83 settings.
setValue( QStringLiteral(
"HistogramWidget/showMean" ), mMeanCheckBox->isChecked() );
84 settings.
setValue( QStringLiteral(
"HistogramWidget/showStdev" ), mStdevCheckBox->isChecked() );
102 if ( !mVectorLayer || mSourceFieldExp.isEmpty() )
105 QApplication::setOverrideCursor( Qt::WaitCursor );
112 QApplication::restoreOverrideCursor();
117 std::sort( mValues.begin(), mValues.end() );
119 mBinsSpinBox->blockSignals(
true );
121 mBinsSpinBox->blockSignals(
false );
126 mpPlot->setEnabled(
true );
127 mMeanCheckBox->setEnabled(
true );
128 mStdevCheckBox->setEnabled(
true );
129 mBinsSpinBox->setEnabled(
true );
131 QApplication::restoreOverrideCursor();
144 if (
layer == mVectorLayer )
147 mVectorLayer =
layer;
151void QgsHistogramWidget::clearHistogram()
157 mpPlot->setEnabled(
false );
158 mMeanCheckBox->setEnabled(
false );
159 mStdevCheckBox->setEnabled(
false );
160 mBinsSpinBox->setEnabled(
false );
165 if ( fieldOrExp == mSourceFieldExp )
168 mSourceFieldExp = fieldOrExp;
175 mpPlot->detachItems();
178 mpPlot->setAutoDelete(
true );
180 if ( !mXAxisTitle.isEmpty() )
181 mpPlot->setAxisTitle( QwtPlot::xBottom, mXAxisTitle );
182 if ( !mYAxisTitle.isEmpty() )
183 mpPlot->setAxisTitle( QwtPlot::yLeft, mYAxisTitle );
184 mpPlot->setAxisFont( QwtPlot::xBottom, this->font() );
185 mpPlot->setAxisFont( QwtPlot::yLeft, this->font() );
186 QFont titleFont = this->font();
187 titleFont.setBold(
true );
188 QwtText xAxisText = mpPlot->axisTitle( QwtPlot::xBottom );
189 xAxisText.setFont( titleFont );
190 mpPlot->setAxisTitle( QwtPlot::xBottom, xAxisText );
191 QwtText yAxisText = mpPlot->axisTitle( QwtPlot::yLeft );
192 yAxisText.setFont( titleFont );
193 mpPlot->setAxisTitle( QwtPlot::yLeft, yAxisText );
194 mpPlot->setAxisAutoScale( QwtPlot::yLeft );
195 mpPlot->setAxisAutoScale( QwtPlot::xBottom );
198 QwtPlotGrid *grid =
new QwtPlotGrid();
199 grid->enableX(
false );
200 grid->setPen( mGridPen );
201 grid->attach( mpPlot );
204 mHistoColors.clear();
207 mHistoColors << ( range.symbol() ? range.symbol()->color() : Qt::black );
211 QwtPlotHistogram *plotHistogram =
nullptr;
212 plotHistogram = createPlotHistogram( !
mRanges.isEmpty() ?
mRanges.at( 0 ).label() : QString(),
213 !
mRanges.isEmpty() ? QBrush( mHistoColors.at( 0 ) ) : mBrush,
214 !
mRanges.isEmpty() ? Qt::NoPen : mPen );
215 QVector<QwtIntervalSample> dataHisto;
217 int bins = mBinsSpinBox->value();
218 QList<double> edges = mHistogram.
binEdges( bins );
219 QList<int> counts = mHistogram.
counts( bins );
224 for (
int bin = 0; bin < bins; ++bin )
226 int binValue = counts.at( bin );
230 if ( rangeIndex <
mRanges.count() - 1 && edges.at( bin ) >
mRanges.at( rangeIndex ).upperValue() )
233 plotHistogram->setSamples( dataHisto );
234 plotHistogram->attach( mpPlot );
235 plotHistogram = createPlotHistogram(
mRanges.at( rangeIndex ).label(), mHistoColors.at( rangeIndex ) );
237 dataHisto << QwtIntervalSample( lastValue,
mRanges.at( rangeIndex - 1 ).upperValue(), edges.at( bin ) );
240 double upperEdge = !
mRanges.isEmpty() ? std::min( edges.at( bin + 1 ),
mRanges.at( rangeIndex ).upperValue() )
241 : edges.at( bin + 1 );
243 dataHisto << QwtIntervalSample( binValue, edges.at( bin ), upperEdge );
245 lastValue = binValue;
248 plotHistogram->setSamples( dataHisto );
249 plotHistogram->attach( mpPlot );
254 QwtPlotMarker *rangeMarker =
new QwtPlotMarker();
255 rangeMarker->attach( mpPlot );
256 rangeMarker->setLineStyle( QwtPlotMarker::VLine );
257 rangeMarker->setXValue( range.upperValue() );
258 rangeMarker->setLabel( QLocale().toString( range.upperValue() ) );
259 rangeMarker->setLabelOrientation( Qt::Vertical );
260 rangeMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
265 if ( mMeanCheckBox->isChecked() )
267 QwtPlotMarker *meanMarker =
new QwtPlotMarker();
268 meanMarker->attach( mpPlot );
269 meanMarker->setLineStyle( QwtPlotMarker::VLine );
270 meanMarker->setLinePen( mMeanPen );
271 meanMarker->setXValue( mStats.
mean() );
272 meanMarker->setLabel( QString( QChar( 956 ) ) );
273 meanMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
277 if ( mStdevCheckBox->isChecked() )
279 QwtPlotMarker *stdev1Marker =
new QwtPlotMarker();
280 stdev1Marker->attach( mpPlot );
281 stdev1Marker->setLineStyle( QwtPlotMarker::VLine );
282 stdev1Marker->setLinePen( mStdevPen );
283 stdev1Marker->setXValue( mStats.
mean() - mStats.
stDev() );
284 stdev1Marker->setLabel( QString( QChar( 963 ) ) );
285 stdev1Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
286 stdev1Marker->show();
288 QwtPlotMarker *stdev2Marker =
new QwtPlotMarker();
289 stdev2Marker->attach( mpPlot );
290 stdev2Marker->setLineStyle( QwtPlotMarker::VLine );
291 stdev2Marker->setLinePen( mStdevPen );
292 stdev2Marker->setXValue( mStats.
mean() + mStats.
stDev() );
293 stdev2Marker->setLabel( QString( QChar( 963 ) ) );
294 stdev2Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
295 stdev2Marker->show();
298 mpPlot->setEnabled(
true );
302QwtPlotHistogram *QgsHistogramWidget::createPlotHistogram(
const QString &title,
const QBrush &brush,
const QPen &pen )
const
304 QwtPlotHistogram *histogram =
new QwtPlotHistogram( title );
305 histogram->setBrush(
brush );
306 if (
pen != Qt::NoPen )
308 histogram->setPen(
pen );
310 else if (
brush.color().lightness() > 200 )
313 p.setColor(
brush.color().darker( 150 ) );
315 p.setCosmetic(
true );
316 histogram->setPen( p );
320 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
Returns the lower bound of the range.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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