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();
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 );
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< double > binEdges(int bins) const
Returns a list of edges for the histogram for a specified number of bins.
QList< QgsRendererRange > QgsRangeList
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.
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.
double stDev() const
Returns population standard deviation.
double lowerValue() const
QgsSymbol * symbol() const
double mean() const
Returns calculated mean of values.
void setValues(const QList< double > &values)
Assigns numeric source values for the histogram.
QList< int > counts(int bins) const
Returns the calculated list of the counts for the histogram bins.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void setStatistics(QgsStatisticalSummary::Statistics stats)
Sets flags which specify which statistics will be calculated.
double upperValue() const
void calculate(const QList< double > &values)
Calculates summary statistics for a list of values.
Standard deviation of values.
Represents a vector layer which manages a vector based data sets.
int optimalNumberBins() const
Returns the optimal number of bins for the source values, calculated using the Freedman-Diaconis rule...