mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
[FEATURE] Add a graphical histogram for the graduated renderer
This adds a new histogram tab to the graduated renderer, which shows an interactive histogram of the values from the assigned field or expression. Class breaks can be moved or added using the histogram widget. A base class, QgsHistogramWidget, has been created to display histograms for a field or expression. In future this could be used to show a histogram within a "selection statistics" panel. Sponsored by ADUGA (http://www.aduga.org)
This commit is contained in:
parent
17962ef47b
commit
183286a006
@ -56,6 +56,7 @@
|
|||||||
%Include qgsfilterlineedit.sip
|
%Include qgsfilterlineedit.sip
|
||||||
%Include qgsformannotationitem.sip
|
%Include qgsformannotationitem.sip
|
||||||
%Include qgsgenericprojectionselector.sip
|
%Include qgsgenericprojectionselector.sip
|
||||||
|
%Include qgshistogramwidget.sip
|
||||||
%Include qgshtmlannotationitem.sip
|
%Include qgshtmlannotationitem.sip
|
||||||
%Include qgsidentifymenu.sip
|
%Include qgsidentifymenu.sip
|
||||||
%Include qgslegendinterface.sip
|
%Include qgslegendinterface.sip
|
||||||
@ -173,6 +174,7 @@
|
|||||||
%Include symbology-ng/qgsdatadefinedsymboldialog.sip
|
%Include symbology-ng/qgsdatadefinedsymboldialog.sip
|
||||||
%Include symbology-ng/qgsstylev2exportimportdialog.sip
|
%Include symbology-ng/qgsstylev2exportimportdialog.sip
|
||||||
%Include symbology-ng/qgssvgselectorwidget.sip
|
%Include symbology-ng/qgssvgselectorwidget.sip
|
||||||
|
%Include symbology-ng/qgsgraduatedhistogramwidget.sip
|
||||||
|
|
||||||
%Include effects/qgseffectdrawmodecombobox.sip
|
%Include effects/qgseffectdrawmodecombobox.sip
|
||||||
%Include effects/qgspainteffectpropertieswidget.sip
|
%Include effects/qgspainteffectpropertieswidget.sip
|
||||||
|
107
python/gui/qgshistogramwidget.sip
Normal file
107
python/gui/qgshistogramwidget.sip
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
/** \ingroup gui
|
||||||
|
* \class QgsHistogramWidget
|
||||||
|
* \brief Graphical histogram for displaying distributions of field values.
|
||||||
|
*
|
||||||
|
* \note Added in version 2.9
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QgsHistogramWidget : QWidget
|
||||||
|
{
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include <qgshistogramwidget.h>
|
||||||
|
%End
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** QgsHistogramWidget constructor. If layer and fieldOrExp are specified then the histogram
|
||||||
|
* will be initially populated with the corresponding values.
|
||||||
|
* @param parent parent widget
|
||||||
|
* @param layer source vector layer
|
||||||
|
* @param fieldOrExp field name or expression string
|
||||||
|
*/
|
||||||
|
QgsHistogramWidget( QWidget *parent /TransferThis/ = 0, QgsVectorLayer* layer = 0, const QString& fieldOrExp = QString() );
|
||||||
|
|
||||||
|
~QgsHistogramWidget();
|
||||||
|
|
||||||
|
/** Returns the layer currently associated with the widget.
|
||||||
|
* @see setLayer
|
||||||
|
* @see sourceFieldExp
|
||||||
|
*/
|
||||||
|
QgsVectorLayer* layer();
|
||||||
|
|
||||||
|
/** Returns the source field name or expression used to calculate values displayed
|
||||||
|
* in the histogram.
|
||||||
|
* @see setSourceFieldExp
|
||||||
|
* @see layer
|
||||||
|
*/
|
||||||
|
QString sourceFieldExp() const;
|
||||||
|
|
||||||
|
/** Sets the pen to use when drawing histogram bars. If set to Qt::NoPen then the
|
||||||
|
* pen will be automatically calculated. If ranges have been set using @link setGraduatedRanges @endlink
|
||||||
|
* then the pen and brush will have no effect.
|
||||||
|
* @param pen histogram pen
|
||||||
|
* @see pen
|
||||||
|
* @see setBrush
|
||||||
|
*/
|
||||||
|
void setPen( const QPen& pen );
|
||||||
|
|
||||||
|
/** Returns the pen used when drawing histogram bars.
|
||||||
|
* @see setPen
|
||||||
|
* @see brush
|
||||||
|
*/
|
||||||
|
QPen pen() const;
|
||||||
|
|
||||||
|
/** Sets the brush used for drawing histogram bars. If ranges have been set using @link setGraduatedRanges @endlink
|
||||||
|
* then the pen and brush will have no effect.
|
||||||
|
* @param brush histogram brush
|
||||||
|
* @see brush
|
||||||
|
* @see setPen
|
||||||
|
*/
|
||||||
|
void setBrush( const QBrush& brush );
|
||||||
|
|
||||||
|
/** Returns the brush used when drawing histogram bars.
|
||||||
|
* @see setBrush
|
||||||
|
* @see pen
|
||||||
|
*/
|
||||||
|
QBrush brush() const;
|
||||||
|
|
||||||
|
/** Sets the graduated ranges associated with the histogram. If set, the ranges will be used to colour the histogram
|
||||||
|
* bars and for showing vertical dividers at the histogram breaks.
|
||||||
|
* @param ranges graduated range list
|
||||||
|
*/
|
||||||
|
void setGraduatedRanges( const QgsRangeList& ranges );
|
||||||
|
|
||||||
|
/** Returns the graduated ranges associated with the histogram. If set, the ranges will be used to colour the histogram
|
||||||
|
* bars and for showing vertical dividers at the histogram breaks.
|
||||||
|
* @returns graduated range list
|
||||||
|
* @see setGraduatedRanges
|
||||||
|
*/
|
||||||
|
QgsRangeList graduatedRanges() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
/** Triggers a refresh of the histogram when the widget is next repainted.
|
||||||
|
*/
|
||||||
|
void refreshHistogram();
|
||||||
|
|
||||||
|
/** Sets the vector layer associated with the histogram.
|
||||||
|
* @param layer source vector layer
|
||||||
|
* @see setSourceFieldExp
|
||||||
|
*/
|
||||||
|
void setLayer( QgsVectorLayer* layer );
|
||||||
|
|
||||||
|
/** Sets the source field or expression to use for values in the histogram.
|
||||||
|
* @param fieldOrExp field name or expression string
|
||||||
|
* @see setLayer
|
||||||
|
*/
|
||||||
|
void setSourceFieldExp( const QString& fieldOrExp );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Updates and redraws the histogram.
|
||||||
|
*/
|
||||||
|
virtual void drawHistogram();
|
||||||
|
|
||||||
|
virtual void paintEvent( QPaintEvent * event );
|
||||||
|
};
|
42
python/gui/symbology-ng/qgsgraduatedhistogramwidget.sip
Normal file
42
python/gui/symbology-ng/qgsgraduatedhistogramwidget.sip
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
/** \ingroup gui
|
||||||
|
* \class QgsGraduatedHistogramWidget
|
||||||
|
* \brief Graphical histogram for displaying distribution of field values and
|
||||||
|
* editing range breaks for a QgsGraduatedSymbolRendererV2 renderer.
|
||||||
|
*
|
||||||
|
* \note Added in version 2.9
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QgsGraduatedHistogramWidget : QWidget
|
||||||
|
{
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include <qgsgraduatedhistogramwidget.h>
|
||||||
|
%End
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** QgsGraduatedHistogramWidget constructor
|
||||||
|
* @param parent parent widget
|
||||||
|
*/
|
||||||
|
QgsGraduatedHistogramWidget( QWidget *parent /TransferThis/ = 0 );
|
||||||
|
~QgsGraduatedHistogramWidget();
|
||||||
|
|
||||||
|
/** Sets the QgsGraduatedSymbolRendererV2 renderer associated with the histogram.
|
||||||
|
* The histogram will fetch the ranges from the renderer before every refresh.
|
||||||
|
* @param renderer associated QgsGraduatedSymbolRendererV2
|
||||||
|
*/
|
||||||
|
void setRenderer( QgsGraduatedSymbolRendererV2* renderer );
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
/** Emitted when the user modifies the graduated ranges using the histogram widget.
|
||||||
|
* @param rangesAdded true if the user has added ranges, false if the user has just
|
||||||
|
* modified existing range breaks
|
||||||
|
*/
|
||||||
|
void rangesModified( bool rangesAdded );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void drawHistogram();
|
||||||
|
|
||||||
|
};
|
@ -103,7 +103,7 @@ QList<int> QgsHistogram::counts( int bins ) const
|
|||||||
for ( int i = 0; i < bins; ++i )
|
for ( int i = 0; i < bins; ++i )
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while ( mValues.at( currentValueIndex ) < edges.at( i + 1 ) )
|
while ( currentValueIndex < mValues.count() && mValues.at( currentValueIndex ) < edges.at( i + 1 ) )
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
currentValueIndex++;
|
currentValueIndex++;
|
||||||
|
@ -1357,6 +1357,37 @@ void QgsGraduatedSymbolRendererV2::addClass( double lower, double upper )
|
|||||||
mRanges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
|
mRanges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedSymbolRendererV2::addBreak( double breakValue, bool updateSymbols )
|
||||||
|
{
|
||||||
|
QMutableListIterator< QgsRendererRangeV2 > it( mRanges );
|
||||||
|
while ( it.hasNext() )
|
||||||
|
{
|
||||||
|
QgsRendererRangeV2 range = it.next();
|
||||||
|
if ( range.lowerValue() < breakValue && range.upperValue() > breakValue )
|
||||||
|
{
|
||||||
|
QgsRendererRangeV2 newRange = QgsRendererRangeV2();
|
||||||
|
newRange.setLowerValue( breakValue );
|
||||||
|
newRange.setUpperValue( range.upperValue() );
|
||||||
|
newRange.setLabel( mLabelFormat.labelForRange( newRange ) );
|
||||||
|
newRange.setSymbol( mSourceSymbol->clone() );
|
||||||
|
|
||||||
|
//update old range
|
||||||
|
bool isDefaultLabel = range.label() == mLabelFormat.labelForRange( range );
|
||||||
|
range.setUpperValue( breakValue );
|
||||||
|
if ( isDefaultLabel ) range.setLabel( mLabelFormat.labelForRange( range.lowerValue(), breakValue ) );
|
||||||
|
it.setValue( range );
|
||||||
|
|
||||||
|
it.insert( newRange );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( updateSymbols && mGraduatedMethod == GraduatedColor )
|
||||||
|
{
|
||||||
|
updateColorRamp( mSourceColorRamp.data(), mInvertedColorRamp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2::addClass( QgsRendererRangeV2 range )
|
void QgsGraduatedSymbolRendererV2::addClass( QgsRendererRangeV2 range )
|
||||||
{
|
{
|
||||||
mRanges.append( range );
|
mRanges.append( range );
|
||||||
|
@ -157,6 +157,16 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
|||||||
void addClass( QgsRendererRangeV2 range );
|
void addClass( QgsRendererRangeV2 range );
|
||||||
//! @note available in python bindings as addClassLowerUpper
|
//! @note available in python bindings as addClassLowerUpper
|
||||||
void addClass( double lower, double upper );
|
void addClass( double lower, double upper );
|
||||||
|
|
||||||
|
/** Add a breakpoint by splitting existing classes so that the specified
|
||||||
|
* value becomes a break between two classes.
|
||||||
|
* @param breakValue position to insert break
|
||||||
|
* @param updateSymbols set to true to reapply ramp colors to the new
|
||||||
|
* symbol ranges
|
||||||
|
* @note added in QGIS 2.9
|
||||||
|
*/
|
||||||
|
void addBreak( double breakValue, bool updateSymbols = true );
|
||||||
|
|
||||||
void deleteClass( int idx );
|
void deleteClass( int idx );
|
||||||
void deleteAllClasses();
|
void deleteAllClasses();
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ raster/qgspalettedrendererwidget.cpp
|
|||||||
raster/qgssinglebandgrayrendererwidget.cpp
|
raster/qgssinglebandgrayrendererwidget.cpp
|
||||||
raster/qgssinglebandpseudocolorrendererwidget.cpp
|
raster/qgssinglebandpseudocolorrendererwidget.cpp
|
||||||
raster/qgsrasterhistogramwidget.cpp
|
raster/qgsrasterhistogramwidget.cpp
|
||||||
|
raster/qwt5_histogram_item.cpp
|
||||||
|
|
||||||
symbology-ng/qgsbrushstylecombobox.cpp
|
symbology-ng/qgsbrushstylecombobox.cpp
|
||||||
symbology-ng/qgscolorrampcombobox.cpp
|
symbology-ng/qgscolorrampcombobox.cpp
|
||||||
@ -19,6 +20,7 @@ symbology-ng/qgsrendererv2widget.cpp
|
|||||||
symbology-ng/qgssinglesymbolrendererv2widget.cpp
|
symbology-ng/qgssinglesymbolrendererv2widget.cpp
|
||||||
symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
|
symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
|
||||||
symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
|
symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
|
||||||
|
symbology-ng/qgsgraduatedhistogramwidget.cpp
|
||||||
symbology-ng/qgsrulebasedrendererv2widget.cpp
|
symbology-ng/qgsrulebasedrendererv2widget.cpp
|
||||||
symbology-ng/qgsheatmaprendererwidget.cpp
|
symbology-ng/qgsheatmaprendererwidget.cpp
|
||||||
symbology-ng/qgsinvertedpolygonrendererwidget.cpp
|
symbology-ng/qgsinvertedpolygonrendererwidget.cpp
|
||||||
@ -174,6 +176,7 @@ qgsfilterlineedit.cpp
|
|||||||
qgsformannotationitem.cpp
|
qgsformannotationitem.cpp
|
||||||
qgsgenericprojectionselector.cpp
|
qgsgenericprojectionselector.cpp
|
||||||
qgshighlight.cpp
|
qgshighlight.cpp
|
||||||
|
qgshistogramwidget.cpp
|
||||||
qgsidentifymenu.cpp
|
qgsidentifymenu.cpp
|
||||||
qgshtmlannotationitem.cpp
|
qgshtmlannotationitem.cpp
|
||||||
qgslegendinterface.cpp
|
qgslegendinterface.cpp
|
||||||
@ -287,6 +290,7 @@ SET(QGIS_GUI_MOC_HDRS
|
|||||||
qgsfilterlineedit.h
|
qgsfilterlineedit.h
|
||||||
qgsformannotationitem.h
|
qgsformannotationitem.h
|
||||||
qgsgenericprojectionselector.h
|
qgsgenericprojectionselector.h
|
||||||
|
qgshistogramwidget.h
|
||||||
qgshtmlannotationitem.h
|
qgshtmlannotationitem.h
|
||||||
qgsidentifymenu.h
|
qgsidentifymenu.h
|
||||||
qgslegendinterface.h
|
qgslegendinterface.h
|
||||||
@ -352,6 +356,7 @@ SET(QGIS_GUI_MOC_HDRS
|
|||||||
symbology-ng/qgsdatadefinedsymboldialog.h
|
symbology-ng/qgsdatadefinedsymboldialog.h
|
||||||
symbology-ng/qgsellipsesymbollayerv2widget.h
|
symbology-ng/qgsellipsesymbollayerv2widget.h
|
||||||
symbology-ng/qgsgraduatedsymbolrendererv2widget.h
|
symbology-ng/qgsgraduatedsymbolrendererv2widget.h
|
||||||
|
symbology-ng/qgsgraduatedhistogramwidget.h
|
||||||
symbology-ng/qgsheatmaprendererwidget.h
|
symbology-ng/qgsheatmaprendererwidget.h
|
||||||
symbology-ng/qgsinvertedpolygonrendererwidget.h
|
symbology-ng/qgsinvertedpolygonrendererwidget.h
|
||||||
symbology-ng/qgslayerpropertieswidget.h
|
symbology-ng/qgslayerpropertieswidget.h
|
||||||
|
353
src/gui/qgshistogramwidget.cpp
Normal file
353
src/gui/qgshistogramwidget.cpp
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgshistogramwidget.cpp
|
||||||
|
----------------------
|
||||||
|
begin : May 2015
|
||||||
|
copyright : (C) 2015 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 "qgshistogramwidget.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsstatisticalsummary.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
// QWT Charting widget
|
||||||
|
#include <qwt_global.h>
|
||||||
|
#include <qwt_plot_canvas.h>
|
||||||
|
#include <qwt_plot.h>
|
||||||
|
#include <qwt_plot_curve.h>
|
||||||
|
#include <qwt_plot_grid.h>
|
||||||
|
#include <qwt_plot_marker.h>
|
||||||
|
#include <qwt_plot_picker.h>
|
||||||
|
#include <qwt_picker_machine.h>
|
||||||
|
#include <qwt_plot_layout.h>
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
#include <qwt_plot_renderer.h>
|
||||||
|
#include <qwt_plot_histogram.h>
|
||||||
|
#else
|
||||||
|
#include "../raster/qwt5_histogram_item.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
QgsHistogramWidget::QgsHistogramWidget( QWidget *parent, QgsVectorLayer* layer, const QString& fieldOrExp )
|
||||||
|
: QWidget( parent )
|
||||||
|
, mRedrawRequired( true )
|
||||||
|
, mVectorLayer( layer )
|
||||||
|
, mSourceFieldExp( fieldOrExp )
|
||||||
|
{
|
||||||
|
setupUi( this );
|
||||||
|
|
||||||
|
mPlot = mpPlot;
|
||||||
|
|
||||||
|
// hide the ugly canvas frame
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QFrame* plotCanvasFrame = dynamic_cast<QFrame*>( mpPlot->canvas() );
|
||||||
|
if ( plotCanvasFrame )
|
||||||
|
plotCanvasFrame->setFrameStyle( QFrame::NoFrame );
|
||||||
|
#else
|
||||||
|
mpPlot->canvas()->setFrameStyle( QFrame::NoFrame );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
mMeanCheckBox->setChecked( settings.value( "/HistogramWidget/showMean", false ).toBool() );
|
||||||
|
mStdevCheckBox->setChecked( settings.value( "/HistogramWidget/showStdev", false ).toBool() );
|
||||||
|
|
||||||
|
connect( mBinsSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( refreshHistogram() ) );
|
||||||
|
connect( mMeanCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( refreshHistogram() ) );
|
||||||
|
connect( mStdevCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( refreshHistogram() ) );
|
||||||
|
|
||||||
|
mGridPen = QPen( QColor( 0, 0, 0, 40 ) );
|
||||||
|
mMeanPen = QPen( QColor( 10, 10, 10, 220 ) );
|
||||||
|
mMeanPen.setStyle( Qt::DashLine );
|
||||||
|
mStdevPen = QPen( QColor( 30, 30, 30, 200 ) );
|
||||||
|
mStdevPen.setStyle( Qt::DashLine );
|
||||||
|
|
||||||
|
if ( layer && !mSourceFieldExp.isEmpty() )
|
||||||
|
{
|
||||||
|
refreshHistogram();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsHistogramWidget::~QgsHistogramWidget()
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue( "/HistogramWidget/showMean", mMeanCheckBox->isChecked() );
|
||||||
|
settings.setValue( "/HistogramWidget/showStdev", mStdevCheckBox->isChecked() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsHistogramWidget::setLayer( QgsVectorLayer *layer )
|
||||||
|
{
|
||||||
|
if ( layer == mVectorLayer )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mVectorLayer = layer;
|
||||||
|
mValues.clear();
|
||||||
|
mRedrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsHistogramWidget::refreshHistogram()
|
||||||
|
{
|
||||||
|
mRedrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsHistogramWidget::setSourceFieldExp( const QString &fieldOrExp )
|
||||||
|
{
|
||||||
|
if ( fieldOrExp == mSourceFieldExp )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mSourceFieldExp = fieldOrExp;
|
||||||
|
mValues.clear();
|
||||||
|
mRedrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsHistogramWidget::drawHistogram()
|
||||||
|
{
|
||||||
|
if ( !mVectorLayer || mSourceFieldExp.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||||
|
|
||||||
|
if ( mValues.empty() )
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
mValues = mVectorLayer->getDoubleValues( mSourceFieldExp, ok );
|
||||||
|
|
||||||
|
if ( ! ok )
|
||||||
|
{
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qSort( mValues.begin(), mValues.end() );
|
||||||
|
mHistogram.setValues( mValues );
|
||||||
|
mBinsSpinBox->blockSignals( true );
|
||||||
|
mBinsSpinBox->setValue( qMax( mHistogram.optimalNumberBins(), 30 ) );
|
||||||
|
mBinsSpinBox->blockSignals( false );
|
||||||
|
|
||||||
|
mStats.setStatistics( QgsStatisticalSummary::StDev );
|
||||||
|
mStats.calculate( mValues );
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear plot
|
||||||
|
mpPlot->detachItems();
|
||||||
|
|
||||||
|
//ensure all children get removed
|
||||||
|
mpPlot->setAutoDelete( true );
|
||||||
|
// Set axis titles
|
||||||
|
mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr( "Value" ) );
|
||||||
|
mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr( "Count" ) );
|
||||||
|
mpPlot->setAxisAutoScale( QwtPlot::yLeft );
|
||||||
|
mpPlot->setAxisAutoScale( QwtPlot::xBottom );
|
||||||
|
|
||||||
|
// add a grid
|
||||||
|
QwtPlotGrid * grid = new QwtPlotGrid();
|
||||||
|
grid->enableX( false );
|
||||||
|
grid->setPen( mGridPen );
|
||||||
|
grid->attach( mpPlot );
|
||||||
|
|
||||||
|
// make colors list
|
||||||
|
mHistoColors.clear();
|
||||||
|
foreach ( QgsRendererRangeV2 range, mRanges )
|
||||||
|
{
|
||||||
|
mHistoColors << ( range.symbol() ? range.symbol()->color() : Qt::black );
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw histogram
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QwtPlotHistogram * plotHistogram = 0;
|
||||||
|
plotHistogram = createPlotHistogram( mRanges.count() > 0 ? mRanges.at( 0 ).label() : QString(),
|
||||||
|
mRanges.count() > 0 ? QBrush( mHistoColors.at( 0 ) ) : mBrush,
|
||||||
|
mRanges.count() > 0 ? Qt::NoPen : mPen );
|
||||||
|
#else
|
||||||
|
HistogramItem *plotHistogramItem = 0;
|
||||||
|
plotHistogramItem = createHistoItem( mRanges.count() > 0 ? mRanges.at( 0 ).label() : QString(),
|
||||||
|
mRanges.count() > 0 ? QBrush( mHistoColors.at( 0 ) ) : mBrush,
|
||||||
|
mRanges.count() > 0 ? Qt::NoPen : mPen );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QVector<QwtIntervalSample> dataHisto;
|
||||||
|
#else
|
||||||
|
|
||||||
|
// we safely assume that QT>=4.0 (min version is 4.7), therefore QwtArray is a QVector, so don't set size here
|
||||||
|
QwtArray<QwtDoubleInterval> intervalsHisto;
|
||||||
|
QwtArray<double> valuesHisto;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int bins = mBinsSpinBox->value();
|
||||||
|
QList<double> edges = mHistogram.binEdges( bins );
|
||||||
|
QList<int> counts = mHistogram.counts( bins );
|
||||||
|
|
||||||
|
int rangeIndex = 0;
|
||||||
|
int lastValue = 0;
|
||||||
|
|
||||||
|
for ( int bin = 0; bin < bins; ++bin )
|
||||||
|
{
|
||||||
|
int binValue = counts.at( bin );
|
||||||
|
|
||||||
|
//current bin crosses two graduated ranges, so we split between
|
||||||
|
//two histogram items
|
||||||
|
if ( rangeIndex < mRanges.count() - 1 && edges.at( bin ) > mRanges.at( rangeIndex ).upperValue() )
|
||||||
|
{
|
||||||
|
rangeIndex++;
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
plotHistogram->setSamples( dataHisto );
|
||||||
|
plotHistogram->attach( mpPlot );
|
||||||
|
plotHistogram = createPlotHistogram( mRanges.at( rangeIndex ).label(), mHistoColors.at( rangeIndex ) );
|
||||||
|
dataHisto.clear();
|
||||||
|
dataHisto << QwtIntervalSample( lastValue, mRanges.at( rangeIndex - 1 ).upperValue(), edges.at( bin ) );
|
||||||
|
#else
|
||||||
|
plotHistogramItem->setData( QwtIntervalData( intervalsHisto, valuesHisto ) );
|
||||||
|
plotHistogramItem->attach( mpPlot );
|
||||||
|
plotHistogramItem = createHistoItem( mRanges.at( rangeIndex ).label(), mHistoColors.at( rangeIndex ) );
|
||||||
|
intervalsHisto.clear();
|
||||||
|
valuesHisto.clear();
|
||||||
|
intervalsHisto.append( QwtDoubleInterval( mRanges.at( rangeIndex - 1 ).upperValue(), edges.at( bin ) ) );
|
||||||
|
valuesHisto.append( lastValue );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
double upperEdge = mRanges.count() > 0 ? qMin( edges.at( bin + 1 ), mRanges.at( rangeIndex ).upperValue() )
|
||||||
|
: edges.at( bin + 1 );
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
dataHisto << QwtIntervalSample( binValue, edges.at( bin ), upperEdge );
|
||||||
|
#else
|
||||||
|
intervalsHisto.append( QwtDoubleInterval( edges.at( bin ), upperEdge ) );
|
||||||
|
valuesHisto.append( double( binValue ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lastValue = binValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
plotHistogram->setSamples( dataHisto );
|
||||||
|
plotHistogram->attach( mpPlot );
|
||||||
|
#else
|
||||||
|
plotHistogramItem->setData( QwtIntervalData( intervalsHisto, valuesHisto ) );
|
||||||
|
plotHistogramItem->attach( mpPlot );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mRangeMarkers.clear();
|
||||||
|
foreach ( QgsRendererRangeV2 range, mRanges )
|
||||||
|
{
|
||||||
|
QwtPlotMarker* rangeMarker = new QwtPlotMarker();
|
||||||
|
rangeMarker->attach( mpPlot );
|
||||||
|
rangeMarker->setLineStyle( QwtPlotMarker::VLine );
|
||||||
|
rangeMarker->setXValue( range.upperValue() );
|
||||||
|
rangeMarker->setLabel( QString::number( range.upperValue() ) );
|
||||||
|
rangeMarker->setLabelOrientation( Qt::Vertical );
|
||||||
|
rangeMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||||
|
rangeMarker->show();
|
||||||
|
mRangeMarkers << rangeMarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mMeanCheckBox->isChecked() )
|
||||||
|
{
|
||||||
|
QwtPlotMarker* meanMarker = new QwtPlotMarker();
|
||||||
|
meanMarker->attach( mpPlot );
|
||||||
|
meanMarker->setLineStyle( QwtPlotMarker::VLine );
|
||||||
|
meanMarker->setLinePen( mMeanPen );
|
||||||
|
meanMarker->setXValue( mStats.mean() );
|
||||||
|
meanMarker->setLabel( QString( QChar( 956 ) ) );
|
||||||
|
meanMarker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||||
|
meanMarker->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mStdevCheckBox->isChecked() )
|
||||||
|
{
|
||||||
|
QwtPlotMarker* stdev1Marker = new QwtPlotMarker();
|
||||||
|
stdev1Marker->attach( mpPlot );
|
||||||
|
stdev1Marker->setLineStyle( QwtPlotMarker::VLine );
|
||||||
|
stdev1Marker->setLinePen( mStdevPen );
|
||||||
|
stdev1Marker->setXValue( mStats.mean() - mStats.stDev() );
|
||||||
|
stdev1Marker->setLabel( QString( QChar( 963 ) ) );
|
||||||
|
stdev1Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||||
|
stdev1Marker->show();
|
||||||
|
|
||||||
|
QwtPlotMarker* stdev2Marker = new QwtPlotMarker();
|
||||||
|
stdev2Marker->attach( mpPlot );
|
||||||
|
stdev2Marker->setLineStyle( QwtPlotMarker::VLine );
|
||||||
|
stdev2Marker->setLinePen( mStdevPen );
|
||||||
|
stdev2Marker->setXValue( mStats.mean() + mStats.stDev() );
|
||||||
|
stdev2Marker->setLabel( QString( QChar( 963 ) ) );
|
||||||
|
stdev2Marker->setLabelAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||||
|
stdev2Marker->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
mpPlot->setEnabled( true );
|
||||||
|
mpPlot->replot();
|
||||||
|
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
|
mRedrawRequired = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsHistogramWidget::paintEvent( QPaintEvent *event )
|
||||||
|
{
|
||||||
|
if ( mRedrawRequired )
|
||||||
|
{
|
||||||
|
drawHistogram();
|
||||||
|
}
|
||||||
|
QWidget::paintEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QwtPlotHistogram* QgsHistogramWidget::createPlotHistogram( const QString& title, const QBrush& brush, const QPen& pen ) const
|
||||||
|
{
|
||||||
|
QwtPlotHistogram* histogram = new QwtPlotHistogram( title );
|
||||||
|
histogram->setBrush( brush );
|
||||||
|
if ( pen != Qt::NoPen )
|
||||||
|
{
|
||||||
|
histogram->setPen( pen );
|
||||||
|
}
|
||||||
|
else if ( brush.color().lightness() > 200 )
|
||||||
|
{
|
||||||
|
QPen p;
|
||||||
|
p.setColor( brush.color().darker( 150 ) );
|
||||||
|
p.setWidth( 0 );
|
||||||
|
p.setCosmetic( true );
|
||||||
|
histogram->setPen( p );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
histogram->setPen( QPen( Qt::NoPen ) );
|
||||||
|
}
|
||||||
|
return histogram;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
HistogramItem * QgsHistogramWidget::createHistoItem( const QString& title, const QBrush& brush, const QPen& pen ) const
|
||||||
|
{
|
||||||
|
HistogramItem* item = new HistogramItem( title );
|
||||||
|
item->setColor( brush.color() );
|
||||||
|
item->setFlat( true );
|
||||||
|
item->setSpacing( 0 );
|
||||||
|
if ( pen != Qt::NoPen )
|
||||||
|
{
|
||||||
|
item->setPen( pen );
|
||||||
|
}
|
||||||
|
else if ( brush.color().lightness() > 200 )
|
||||||
|
{
|
||||||
|
QPen p;
|
||||||
|
p.setColor( brush.color().darker( 150 ) );
|
||||||
|
p.setWidth( 0 );
|
||||||
|
p.setCosmetic( true );
|
||||||
|
item->setPen( p );
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
174
src/gui/qgshistogramwidget.h
Normal file
174
src/gui/qgshistogramwidget.h
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgshistogramwidget.h
|
||||||
|
--------------------
|
||||||
|
begin : May 2015
|
||||||
|
copyright : (C) 2015 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 QGSHISTOGRAMWIDGET_H
|
||||||
|
#define QGSHISTOGRAMWIDGET_H
|
||||||
|
|
||||||
|
#include "ui_qgshistogramwidgetbase.h"
|
||||||
|
|
||||||
|
#include "qgshistogram.h"
|
||||||
|
#include "qgsstatisticalsummary.h"
|
||||||
|
#include "qgsgraduatedsymbolrendererv2.h"
|
||||||
|
#include <QPen>
|
||||||
|
#include <QBrush>
|
||||||
|
|
||||||
|
class QgsVectorLayer;
|
||||||
|
class QgsGraduatedSymbolRendererV2;
|
||||||
|
class QwtPlotPicker;
|
||||||
|
class QwtPlotMarker;
|
||||||
|
class QwtPlot;
|
||||||
|
class HistogramItem;
|
||||||
|
class QwtPlotHistogram;
|
||||||
|
|
||||||
|
// fix for qwt5/qwt6 QwtDoublePoint vs. QPointF
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
typedef QPointF QwtDoublePoint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** \ingroup gui
|
||||||
|
* \class QgsHistogramWidget
|
||||||
|
* \brief Graphical histogram for displaying distributions of field values.
|
||||||
|
*
|
||||||
|
* \note Added in version 2.9
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GUI_EXPORT QgsHistogramWidget : public QWidget, private Ui::QgsHistogramWidgetBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** QgsHistogramWidget constructor. If layer and fieldOrExp are specified then the histogram
|
||||||
|
* will be initially populated with the corresponding values.
|
||||||
|
* @param parent parent widget
|
||||||
|
* @param layer source vector layer
|
||||||
|
* @param fieldOrExp field name or expression string
|
||||||
|
*/
|
||||||
|
QgsHistogramWidget( QWidget *parent = 0, QgsVectorLayer* layer = 0, const QString& fieldOrExp = QString() );
|
||||||
|
|
||||||
|
~QgsHistogramWidget();
|
||||||
|
|
||||||
|
/** Returns the layer currently associated with the widget.
|
||||||
|
* @see setLayer
|
||||||
|
* @see sourceFieldExp
|
||||||
|
*/
|
||||||
|
QgsVectorLayer* layer() { return mVectorLayer; }
|
||||||
|
|
||||||
|
/** Returns the source field name or expression used to calculate values displayed
|
||||||
|
* in the histogram.
|
||||||
|
* @see setSourceFieldExp
|
||||||
|
* @see layer
|
||||||
|
*/
|
||||||
|
QString sourceFieldExp() const { return mSourceFieldExp; }
|
||||||
|
|
||||||
|
/** Sets the pen to use when drawing histogram bars. If set to Qt::NoPen then the
|
||||||
|
* pen will be automatically calculated. If ranges have been set using @link setGraduatedRanges @endlink
|
||||||
|
* then the pen and brush will have no effect.
|
||||||
|
* @param pen histogram pen
|
||||||
|
* @see pen
|
||||||
|
* @see setBrush
|
||||||
|
*/
|
||||||
|
void setPen( const QPen& pen ) { mPen = pen; }
|
||||||
|
|
||||||
|
/** Returns the pen used when drawing histogram bars.
|
||||||
|
* @see setPen
|
||||||
|
* @see brush
|
||||||
|
*/
|
||||||
|
QPen pen() const { return mPen; }
|
||||||
|
|
||||||
|
/** Sets the brush used for drawing histogram bars. If ranges have been set using @link setGraduatedRanges @endlink
|
||||||
|
* then the pen and brush will have no effect.
|
||||||
|
* @param brush histogram brush
|
||||||
|
* @see brush
|
||||||
|
* @see setPen
|
||||||
|
*/
|
||||||
|
void setBrush( const QBrush& brush ) { mBrush = brush; }
|
||||||
|
|
||||||
|
/** Returns the brush used when drawing histogram bars.
|
||||||
|
* @see setBrush
|
||||||
|
* @see pen
|
||||||
|
*/
|
||||||
|
QBrush brush() const { return mBrush; }
|
||||||
|
|
||||||
|
/** Sets the graduated ranges associated with the histogram. If set, the ranges will be used to colour the histogram
|
||||||
|
* bars and for showing vertical dividers at the histogram breaks.
|
||||||
|
* @param ranges graduated range list
|
||||||
|
* @see graduatedRanges
|
||||||
|
*/
|
||||||
|
void setGraduatedRanges( const QgsRangeList& ranges ) { mRanges = ranges; }
|
||||||
|
|
||||||
|
/** Returns the graduated ranges associated with the histogram. If set, the ranges will be used to colour the histogram
|
||||||
|
* bars and for showing vertical dividers at the histogram breaks.
|
||||||
|
* @returns graduated range list
|
||||||
|
* @see setGraduatedRanges
|
||||||
|
*/
|
||||||
|
QgsRangeList graduatedRanges() const { return mRanges; }
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
/** Triggers a refresh of the histogram when the widget is next repainted.
|
||||||
|
*/
|
||||||
|
void refreshHistogram();
|
||||||
|
|
||||||
|
/** Sets the vector layer associated with the histogram.
|
||||||
|
* @param layer source vector layer
|
||||||
|
* @see setSourceFieldExp
|
||||||
|
*/
|
||||||
|
void setLayer( QgsVectorLayer* layer );
|
||||||
|
|
||||||
|
/** Sets the source field or expression to use for values in the histogram.
|
||||||
|
* @param fieldOrExp field name or expression string
|
||||||
|
* @see setLayer
|
||||||
|
*/
|
||||||
|
void setSourceFieldExp( const QString& fieldOrExp );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Updates and redraws the histogram.
|
||||||
|
*/
|
||||||
|
virtual void drawHistogram();
|
||||||
|
|
||||||
|
virtual void paintEvent( QPaintEvent * event ) override;
|
||||||
|
|
||||||
|
QwtPlot* mPlot;
|
||||||
|
QgsRangeList mRanges;
|
||||||
|
QList< QwtPlotMarker* > mRangeMarkers;
|
||||||
|
bool mRedrawRequired;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsVectorLayer * mVectorLayer;
|
||||||
|
QString mSourceFieldExp;
|
||||||
|
QList<double> mValues;
|
||||||
|
QgsStatisticalSummary mStats;
|
||||||
|
QgsHistogram mHistogram;
|
||||||
|
QVector<QColor> mHistoColors;
|
||||||
|
QPen mPen;
|
||||||
|
QBrush mBrush;
|
||||||
|
QPen mMeanPen;
|
||||||
|
QPen mStdevPen;
|
||||||
|
QPen mGridPen;
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QwtPlotHistogram* createPlotHistogram( const QString& title, const QBrush &brush, const QPen &pen = Qt::NoPen ) const;
|
||||||
|
#else
|
||||||
|
HistogramItem* createHistoItem( const QString& title, const QBrush& brush, const QPen& pen = Qt::NoPen ) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QGSHISTOGRAMWIDGET_H
|
397
src/gui/raster/qwt5_histogram_item.cpp
Normal file
397
src/gui/raster/qwt5_histogram_item.cpp
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||||||
|
* Qwt Widget Library
|
||||||
|
* Copyright (C) 1997 Josef Wilgen
|
||||||
|
* Copyright (C) 2002 Uwe Rathmann
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the Qwt License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <qwt_global.h>
|
||||||
|
|
||||||
|
#if defined( QWT_VERSION ) && QWT_VERSION<0x060000
|
||||||
|
|
||||||
|
#include <qglobal.h>
|
||||||
|
#include <qcolor.h>
|
||||||
|
|
||||||
|
#include "qwt5_histogram_item.h"
|
||||||
|
|
||||||
|
HistogramItem::HistogramItem( const QwtText &title ):
|
||||||
|
QwtPlotItem( title )
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistogramItem::HistogramItem( const QString &title ):
|
||||||
|
QwtPlotItem( QwtText( title ) )
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistogramItem::~HistogramItem()
|
||||||
|
{
|
||||||
|
delete d_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::init()
|
||||||
|
{
|
||||||
|
d_data = new PrivateData();
|
||||||
|
d_data->reference = 0.0;
|
||||||
|
d_data->attributes = HistogramItem::Auto;
|
||||||
|
d_data->flat = false;
|
||||||
|
d_data->spacing = 1;
|
||||||
|
d_data->pen = Qt::NoPen;
|
||||||
|
|
||||||
|
setItemAttribute( QwtPlotItem::AutoScale, true );
|
||||||
|
setItemAttribute( QwtPlotItem::Legend, true );
|
||||||
|
|
||||||
|
setZ( 20.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setBaseline( double reference )
|
||||||
|
{
|
||||||
|
if ( d_data->reference != reference )
|
||||||
|
{
|
||||||
|
d_data->reference = reference;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double HistogramItem::baseline() const
|
||||||
|
{
|
||||||
|
return d_data->reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setData( const QwtIntervalData &data )
|
||||||
|
{
|
||||||
|
d_data->data = data;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QwtIntervalData &HistogramItem::data() const
|
||||||
|
{
|
||||||
|
return d_data->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setColor( const QColor &color )
|
||||||
|
{
|
||||||
|
if ( d_data->color != color )
|
||||||
|
{
|
||||||
|
d_data->color = color;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor HistogramItem::color() const
|
||||||
|
{
|
||||||
|
return d_data->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setFlat( bool flat )
|
||||||
|
{
|
||||||
|
if ( d_data->flat != flat )
|
||||||
|
{
|
||||||
|
d_data->flat = flat;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistogramItem::flat() const
|
||||||
|
{
|
||||||
|
return d_data->flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setSpacing( int spacing )
|
||||||
|
{
|
||||||
|
if ( d_data->spacing != spacing )
|
||||||
|
{
|
||||||
|
d_data->spacing = spacing;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HistogramItem::spacing() const
|
||||||
|
{
|
||||||
|
return d_data->spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setPen( const QPen &pen )
|
||||||
|
{
|
||||||
|
if ( d_data->pen != pen )
|
||||||
|
{
|
||||||
|
d_data->pen = pen;
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen HistogramItem::pen() const
|
||||||
|
{
|
||||||
|
return d_data->pen;
|
||||||
|
}
|
||||||
|
|
||||||
|
QwtDoubleRect HistogramItem::boundingRect() const
|
||||||
|
{
|
||||||
|
QwtDoubleRect rect = d_data->data.boundingRect();
|
||||||
|
if ( !rect.isValid() )
|
||||||
|
return rect;
|
||||||
|
|
||||||
|
if ( d_data->attributes & Xfy )
|
||||||
|
{
|
||||||
|
rect = QwtDoubleRect( rect.y(), rect.x(),
|
||||||
|
rect.height(), rect.width() );
|
||||||
|
|
||||||
|
if ( rect.left() > d_data->reference )
|
||||||
|
rect.setLeft( d_data->reference );
|
||||||
|
else if ( rect.right() < d_data->reference )
|
||||||
|
rect.setRight( d_data->reference );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( rect.bottom() < d_data->reference )
|
||||||
|
rect.setBottom( d_data->reference );
|
||||||
|
else if ( rect.top() > d_data->reference )
|
||||||
|
rect.setTop( d_data->reference );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int HistogramItem::rtti() const
|
||||||
|
{
|
||||||
|
return QwtPlotItem::Rtti_PlotHistogram;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::setHistogramAttribute( HistogramAttribute attribute, bool on )
|
||||||
|
{
|
||||||
|
if ( bool( d_data->attributes & attribute ) == on )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( on )
|
||||||
|
d_data->attributes |= attribute;
|
||||||
|
else
|
||||||
|
d_data->attributes &= ~attribute;
|
||||||
|
|
||||||
|
itemChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistogramItem::testHistogramAttribute( HistogramAttribute attribute ) const
|
||||||
|
{
|
||||||
|
return d_data->attributes & attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::draw( QPainter *painter, const QwtScaleMap &xMap,
|
||||||
|
const QwtScaleMap &yMap, const QRect & ) const
|
||||||
|
{
|
||||||
|
const QwtIntervalData &iData = d_data->data;
|
||||||
|
const int x0 = xMap.transform( baseline() );
|
||||||
|
const int y0 = yMap.transform( baseline() );
|
||||||
|
|
||||||
|
for ( int i = 0; i < ( int )iData.size(); i++ )
|
||||||
|
{
|
||||||
|
if ( d_data->attributes & HistogramItem::Xfy )
|
||||||
|
{
|
||||||
|
const int x2 = xMap.transform( iData.value( i ) );
|
||||||
|
if ( x2 == x0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int y1 = yMap.transform( iData.interval( i ).minValue() );
|
||||||
|
int y2 = yMap.transform( iData.interval( i ).maxValue() );
|
||||||
|
if ( y1 > y2 )
|
||||||
|
qSwap( y1, y2 );
|
||||||
|
|
||||||
|
if ( i < ( int )iData.size() - 2 )
|
||||||
|
{
|
||||||
|
const int yy1 = yMap.transform( iData.interval( i + 1 ).minValue() );
|
||||||
|
const int yy2 = yMap.transform( iData.interval( i + 1 ).maxValue() );
|
||||||
|
|
||||||
|
if ( y2 == qwtMin( yy1, yy2 ) )
|
||||||
|
{
|
||||||
|
const int xx2 = xMap.transform(
|
||||||
|
iData.interval( i + 1 ).minValue() );
|
||||||
|
if ( xx2 != x0 && (( xx2 < x0 && x2 < x0 ) ||
|
||||||
|
( xx2 > x0 && x2 > x0 ) ) )
|
||||||
|
{
|
||||||
|
// distance between neighboured bars
|
||||||
|
y2 += d_data->spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawBar( painter, Qt::Horizontal,
|
||||||
|
QRect( x0, y1, x2 - x0, y2 - y1 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int y2 = yMap.transform( iData.value( i ) );
|
||||||
|
if ( y2 == y0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int x1 = xMap.transform( iData.interval( i ).minValue() );
|
||||||
|
int x2 = xMap.transform( iData.interval( i ).maxValue() );
|
||||||
|
if ( x1 > x2 )
|
||||||
|
qSwap( x1, x2 );
|
||||||
|
|
||||||
|
if ( i < ( int )iData.size() - 2 )
|
||||||
|
{
|
||||||
|
const int xx1 = xMap.transform( iData.interval( i + 1 ).minValue() );
|
||||||
|
const int xx2 = xMap.transform( iData.interval( i + 1 ).maxValue() );
|
||||||
|
|
||||||
|
if ( x2 == qwtMin( xx1, xx2 ) )
|
||||||
|
{
|
||||||
|
const int yy2 = yMap.transform( iData.value( i + 1 ) );
|
||||||
|
if ( yy2 != y0 && (( yy2 < y0 && y2 < y0 ) ||
|
||||||
|
( yy2 > y0 && y2 > y0 ) ) )
|
||||||
|
{
|
||||||
|
//distance between neighboured bars
|
||||||
|
x2 -= d_data->spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawBar( painter, Qt::Vertical,
|
||||||
|
QRect( x1, y0, x2 - x1, y2 - y0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistogramItem::drawBar( QPainter *painter,
|
||||||
|
Qt::Orientation, const QRect& rect ) const
|
||||||
|
{
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x040000
|
||||||
|
const QRect r = rect.normalized();
|
||||||
|
#else
|
||||||
|
const QRect r = rect.normalize();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
painter->setBrush( d_data->color );
|
||||||
|
|
||||||
|
if ( d_data->flat )
|
||||||
|
{
|
||||||
|
painter->setPen( d_data->pen );
|
||||||
|
int penWidth = d_data->pen == Qt::NoPen ? 0 :
|
||||||
|
( d_data->pen.isCosmetic() ? 1 : d_data->pen.width() );
|
||||||
|
QwtPainter::drawRect( painter, r.x(), r.y(),
|
||||||
|
r.width(), r.height() - penWidth );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int factor = 125;
|
||||||
|
const QColor light( d_data->color.light( factor ) );
|
||||||
|
const QColor dark( d_data->color.dark( factor ) );
|
||||||
|
|
||||||
|
QwtPainter::drawRect( painter, r.x() + 1, r.y() + 1,
|
||||||
|
r.width() - 2, r.height() - 2 );
|
||||||
|
|
||||||
|
painter->setBrush( Qt::NoBrush );
|
||||||
|
|
||||||
|
painter->setPen( QPen( light, 2 ) );
|
||||||
|
#if QT_VERSION >= 0x040000
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2 );
|
||||||
|
#else
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left(), r.top() + 2, r.right() + 1, r.top() + 2 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
painter->setPen( QPen( dark, 2 ) );
|
||||||
|
#if QT_VERSION >= 0x040000
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left() + 1, r.bottom(), r.right() + 1, r.bottom() );
|
||||||
|
#else
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left(), r.bottom(), r.right() + 1, r.bottom() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
painter->setPen( QPen( light, 1 ) );
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x040000
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left(), r.top() + 1, r.left(), r.bottom() );
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1 );
|
||||||
|
#else
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left(), r.top() + 1, r.left(), r.bottom() + 1 );
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
painter->setPen( QPen( dark, 1 ) );
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x040000
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() );
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.right(), r.top() + 2, r.right(), r.bottom() - 1 );
|
||||||
|
#else
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1 );
|
||||||
|
QwtPainter::drawLine( painter,
|
||||||
|
r.right(), r.top() + 2, r.right(), r.bottom() );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Update the widget that represents the curve on the legend
|
||||||
|
// this was adapted from QwtPlotCurve::updateLegend()
|
||||||
|
void HistogramItem::updateLegend( QwtLegend *legend ) const
|
||||||
|
{
|
||||||
|
if ( !legend )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QwtPlotItem::updateLegend( legend );
|
||||||
|
|
||||||
|
QWidget *widget = legend->find( this );
|
||||||
|
if ( !widget || !widget->inherits( "QwtLegendItem" ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QwtLegendItem *legendItem = ( QwtLegendItem * )widget;
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x040000
|
||||||
|
const bool doUpdate = legendItem->isUpdatesEnabled();
|
||||||
|
#else
|
||||||
|
const bool doUpdate = legendItem->updatesEnabled();
|
||||||
|
#endif
|
||||||
|
legendItem->setUpdatesEnabled( false );
|
||||||
|
|
||||||
|
const int policy = legend->displayPolicy();
|
||||||
|
|
||||||
|
if ( policy == QwtLegend::FixedIdentifier )
|
||||||
|
{
|
||||||
|
int mode = legend->identifierMode();
|
||||||
|
|
||||||
|
legendItem->setCurvePen( QPen( color() ) );
|
||||||
|
|
||||||
|
if ( mode & QwtLegendItem::ShowText )
|
||||||
|
legendItem->setText( title() );
|
||||||
|
else
|
||||||
|
legendItem->setText( QwtText() );
|
||||||
|
|
||||||
|
legendItem->setIdentifierMode( mode );
|
||||||
|
}
|
||||||
|
else if ( policy == QwtLegend::AutoIdentifier )
|
||||||
|
{
|
||||||
|
int mode = 0;
|
||||||
|
|
||||||
|
legendItem->setCurvePen( QPen( color() ) );
|
||||||
|
mode |= QwtLegendItem::ShowLine;
|
||||||
|
if ( !title().isEmpty() )
|
||||||
|
{
|
||||||
|
legendItem->setText( title() );
|
||||||
|
mode |= QwtLegendItem::ShowText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
legendItem->setText( QwtText() );
|
||||||
|
}
|
||||||
|
legendItem->setIdentifierMode( mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
legendItem->setUpdatesEnabled( doUpdate );
|
||||||
|
legendItem->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -6,6 +6,9 @@
|
|||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the Qwt License, Version 1.0
|
* modify it under the terms of the Qwt License, Version 1.0
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
#include <qwt_global.h>
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION<0x060000
|
||||||
|
|
||||||
#ifndef HISTOGRAM_ITEM_H
|
#ifndef HISTOGRAM_ITEM_H
|
||||||
#define HISTOGRAM_ITEM_H
|
#define HISTOGRAM_ITEM_H
|
||||||
@ -31,6 +34,15 @@ class HistogramItem: public QwtPlotItem
|
|||||||
void setColor( const QColor & );
|
void setColor( const QColor & );
|
||||||
QColor color() const;
|
QColor color() const;
|
||||||
|
|
||||||
|
void setFlat( bool flat );
|
||||||
|
bool flat() const;
|
||||||
|
|
||||||
|
void setSpacing( int spacing );
|
||||||
|
int spacing() const;
|
||||||
|
|
||||||
|
void setPen( const QPen& pen );
|
||||||
|
QPen pen() const;
|
||||||
|
|
||||||
virtual QwtDoubleRect boundingRect() const;
|
virtual QwtDoubleRect boundingRect() const;
|
||||||
|
|
||||||
virtual int rtti() const;
|
virtual int rtti() const;
|
||||||
@ -77,333 +89,11 @@ class HistogramItem::PrivateData
|
|||||||
int attributes;
|
int attributes;
|
||||||
QwtIntervalData data;
|
QwtIntervalData data;
|
||||||
QColor color;
|
QColor color;
|
||||||
|
QPen pen;
|
||||||
double reference;
|
double reference;
|
||||||
|
bool flat;
|
||||||
|
int spacing;
|
||||||
};
|
};
|
||||||
|
|
||||||
HistogramItem::HistogramItem( const QwtText &title ):
|
|
||||||
QwtPlotItem( title )
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
HistogramItem::HistogramItem( const QString &title ):
|
|
||||||
QwtPlotItem( QwtText( title ) )
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
HistogramItem::~HistogramItem()
|
|
||||||
{
|
|
||||||
delete d_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::init()
|
|
||||||
{
|
|
||||||
d_data = new PrivateData();
|
|
||||||
d_data->reference = 0.0;
|
|
||||||
d_data->attributes = HistogramItem::Auto;
|
|
||||||
|
|
||||||
setItemAttribute( QwtPlotItem::AutoScale, true );
|
|
||||||
setItemAttribute( QwtPlotItem::Legend, true );
|
|
||||||
|
|
||||||
setZ( 20.0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::setBaseline( double reference )
|
|
||||||
{
|
|
||||||
if ( d_data->reference != reference )
|
|
||||||
{
|
|
||||||
d_data->reference = reference;
|
|
||||||
itemChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double HistogramItem::baseline() const
|
|
||||||
{
|
|
||||||
return d_data->reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::setData( const QwtIntervalData &data )
|
|
||||||
{
|
|
||||||
d_data->data = data;
|
|
||||||
itemChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QwtIntervalData &HistogramItem::data() const
|
|
||||||
{
|
|
||||||
return d_data->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::setColor( const QColor &color )
|
|
||||||
{
|
|
||||||
if ( d_data->color != color )
|
|
||||||
{
|
|
||||||
d_data->color = color;
|
|
||||||
itemChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor HistogramItem::color() const
|
|
||||||
{
|
|
||||||
return d_data->color;
|
|
||||||
}
|
|
||||||
|
|
||||||
QwtDoubleRect HistogramItem::boundingRect() const
|
|
||||||
{
|
|
||||||
QwtDoubleRect rect = d_data->data.boundingRect();
|
|
||||||
if ( !rect.isValid() )
|
|
||||||
return rect;
|
|
||||||
|
|
||||||
if ( d_data->attributes & Xfy )
|
|
||||||
{
|
|
||||||
rect = QwtDoubleRect( rect.y(), rect.x(),
|
|
||||||
rect.height(), rect.width() );
|
|
||||||
|
|
||||||
if ( rect.left() > d_data->reference )
|
|
||||||
rect.setLeft( d_data->reference );
|
|
||||||
else if ( rect.right() < d_data->reference )
|
|
||||||
rect.setRight( d_data->reference );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( rect.bottom() < d_data->reference )
|
|
||||||
rect.setBottom( d_data->reference );
|
|
||||||
else if ( rect.top() > d_data->reference )
|
|
||||||
rect.setTop( d_data->reference );
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int HistogramItem::rtti() const
|
|
||||||
{
|
|
||||||
return QwtPlotItem::Rtti_PlotHistogram;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::setHistogramAttribute( HistogramAttribute attribute, bool on )
|
|
||||||
{
|
|
||||||
if ( bool( d_data->attributes & attribute ) == on )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( on )
|
|
||||||
d_data->attributes |= attribute;
|
|
||||||
else
|
|
||||||
d_data->attributes &= ~attribute;
|
|
||||||
|
|
||||||
itemChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HistogramItem::testHistogramAttribute( HistogramAttribute attribute ) const
|
|
||||||
{
|
|
||||||
return d_data->attributes & attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::draw( QPainter *painter, const QwtScaleMap &xMap,
|
|
||||||
const QwtScaleMap &yMap, const QRect & ) const
|
|
||||||
{
|
|
||||||
const QwtIntervalData &iData = d_data->data;
|
|
||||||
|
|
||||||
painter->setPen( QPen( d_data->color ) );
|
|
||||||
|
|
||||||
const int x0 = xMap.transform( baseline() );
|
|
||||||
const int y0 = yMap.transform( baseline() );
|
|
||||||
|
|
||||||
for ( int i = 0; i < ( int )iData.size(); i++ )
|
|
||||||
{
|
|
||||||
if ( d_data->attributes & HistogramItem::Xfy )
|
|
||||||
{
|
|
||||||
const int x2 = xMap.transform( iData.value( i ) );
|
|
||||||
if ( x2 == x0 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int y1 = yMap.transform( iData.interval( i ).minValue() );
|
|
||||||
int y2 = yMap.transform( iData.interval( i ).maxValue() );
|
|
||||||
if ( y1 > y2 )
|
|
||||||
qSwap( y1, y2 );
|
|
||||||
|
|
||||||
if ( i < ( int )iData.size() - 2 )
|
|
||||||
{
|
|
||||||
const int yy1 = yMap.transform( iData.interval( i + 1 ).minValue() );
|
|
||||||
const int yy2 = yMap.transform( iData.interval( i + 1 ).maxValue() );
|
|
||||||
|
|
||||||
if ( y2 == qwtMin( yy1, yy2 ) )
|
|
||||||
{
|
|
||||||
const int xx2 = xMap.transform(
|
|
||||||
iData.interval( i + 1 ).minValue() );
|
|
||||||
if ( xx2 != x0 && (( xx2 < x0 && x2 < x0 ) ||
|
|
||||||
( xx2 > x0 && x2 > x0 ) ) )
|
|
||||||
{
|
|
||||||
// One pixel distance between neighboured bars
|
|
||||||
y2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drawBar( painter, Qt::Horizontal,
|
|
||||||
QRect( x0, y1, x2 - x0, y2 - y1 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int y2 = yMap.transform( iData.value( i ) );
|
|
||||||
if ( y2 == y0 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int x1 = xMap.transform( iData.interval( i ).minValue() );
|
|
||||||
int x2 = xMap.transform( iData.interval( i ).maxValue() );
|
|
||||||
if ( x1 > x2 )
|
|
||||||
qSwap( x1, x2 );
|
|
||||||
|
|
||||||
if ( i < ( int )iData.size() - 2 )
|
|
||||||
{
|
|
||||||
const int xx1 = xMap.transform( iData.interval( i + 1 ).minValue() );
|
|
||||||
const int xx2 = xMap.transform( iData.interval( i + 1 ).maxValue() );
|
|
||||||
|
|
||||||
if ( x2 == qwtMin( xx1, xx2 ) )
|
|
||||||
{
|
|
||||||
const int yy2 = yMap.transform( iData.value( i + 1 ) );
|
|
||||||
if ( yy2 != y0 && (( yy2 < y0 && y2 < y0 ) ||
|
|
||||||
( yy2 > y0 && y2 > y0 ) ) )
|
|
||||||
{
|
|
||||||
// One pixel distance between neighboured bars
|
|
||||||
x2--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawBar( painter, Qt::Vertical,
|
|
||||||
QRect( x1, y0, x2 - x1, y2 - y0 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistogramItem::drawBar( QPainter *painter,
|
|
||||||
Qt::Orientation, const QRect& rect ) const
|
|
||||||
{
|
|
||||||
painter->save();
|
|
||||||
|
|
||||||
const QColor color( painter->pen().color() );
|
|
||||||
#if QT_VERSION >= 0x040000
|
|
||||||
const QRect r = rect.normalized();
|
|
||||||
#else
|
|
||||||
const QRect r = rect.normalize();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const int factor = 125;
|
|
||||||
const QColor light( color.light( factor ) );
|
|
||||||
const QColor dark( color.dark( factor ) );
|
|
||||||
|
|
||||||
painter->setBrush( color );
|
|
||||||
painter->setPen( Qt::NoPen );
|
|
||||||
QwtPainter::drawRect( painter, r.x() + 1, r.y() + 1,
|
|
||||||
r.width() - 2, r.height() - 2 );
|
|
||||||
painter->setBrush( Qt::NoBrush );
|
|
||||||
|
|
||||||
painter->setPen( QPen( light, 2 ) );
|
|
||||||
#if QT_VERSION >= 0x040000
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2 );
|
|
||||||
#else
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left(), r.top() + 2, r.right() + 1, r.top() + 2 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
painter->setPen( QPen( dark, 2 ) );
|
|
||||||
#if QT_VERSION >= 0x040000
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left() + 1, r.bottom(), r.right() + 1, r.bottom() );
|
|
||||||
#else
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left(), r.bottom(), r.right() + 1, r.bottom() );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
painter->setPen( QPen( light, 1 ) );
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040000
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left(), r.top() + 1, r.left(), r.bottom() );
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1 );
|
|
||||||
#else
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left(), r.top() + 1, r.left(), r.bottom() + 1 );
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
painter->setPen( QPen( dark, 1 ) );
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040000
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() );
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.right(), r.top() + 2, r.right(), r.bottom() - 1 );
|
|
||||||
#else
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1 );
|
|
||||||
QwtPainter::drawLine( painter,
|
|
||||||
r.right(), r.top() + 2, r.right(), r.bottom() );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
painter->restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Update the widget that represents the curve on the legend
|
|
||||||
// this was adapted from QwtPlotCurve::updateLegend()
|
|
||||||
void HistogramItem::updateLegend( QwtLegend *legend ) const
|
|
||||||
{
|
|
||||||
if ( !legend )
|
|
||||||
return;
|
|
||||||
|
|
||||||
QwtPlotItem::updateLegend( legend );
|
|
||||||
|
|
||||||
QWidget *widget = legend->find( this );
|
|
||||||
if ( !widget || !widget->inherits( "QwtLegendItem" ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
QwtLegendItem *legendItem = ( QwtLegendItem * )widget;
|
|
||||||
|
|
||||||
#if QT_VERSION < 0x040000
|
|
||||||
const bool doUpdate = legendItem->isUpdatesEnabled();
|
|
||||||
#else
|
|
||||||
const bool doUpdate = legendItem->updatesEnabled();
|
|
||||||
#endif
|
|
||||||
legendItem->setUpdatesEnabled( false );
|
|
||||||
|
|
||||||
const int policy = legend->displayPolicy();
|
|
||||||
|
|
||||||
if ( policy == QwtLegend::FixedIdentifier )
|
|
||||||
{
|
|
||||||
int mode = legend->identifierMode();
|
|
||||||
|
|
||||||
legendItem->setCurvePen( QPen( color() ) );
|
|
||||||
|
|
||||||
if ( mode & QwtLegendItem::ShowText )
|
|
||||||
legendItem->setText( title() );
|
|
||||||
else
|
|
||||||
legendItem->setText( QwtText() );
|
|
||||||
|
|
||||||
legendItem->setIdentifierMode( mode );
|
|
||||||
}
|
|
||||||
else if ( policy == QwtLegend::AutoIdentifier )
|
|
||||||
{
|
|
||||||
int mode = 0;
|
|
||||||
|
|
||||||
legendItem->setCurvePen( QPen( color() ) );
|
|
||||||
mode |= QwtLegendItem::ShowLine;
|
|
||||||
if ( !title().isEmpty() )
|
|
||||||
{
|
|
||||||
legendItem->setText( title() );
|
|
||||||
mode |= QwtLegendItem::ShowText;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
legendItem->setText( QwtText() );
|
|
||||||
}
|
|
||||||
legendItem->setIdentifierMode( mode );
|
|
||||||
}
|
|
||||||
|
|
||||||
legendItem->setUpdatesEnabled( doUpdate );
|
|
||||||
legendItem->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
203
src/gui/symbology-ng/qgsgraduatedhistogramwidget.cpp
Normal file
203
src/gui/symbology-ng/qgsgraduatedhistogramwidget.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsgraduatedhistogramwidget.cpp
|
||||||
|
-------------------------------
|
||||||
|
begin : May 2015
|
||||||
|
copyright : (C) 2015 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 "qgsgraduatedhistogramwidget.h"
|
||||||
|
#include "qgsgraduatedsymbolrendererv2.h"
|
||||||
|
#include "qgsgraduatedsymbolrendererv2widget.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsstatisticalsummary.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
// QWT Charting widget
|
||||||
|
#include <qwt_global.h>
|
||||||
|
#include <qwt_plot_canvas.h>
|
||||||
|
#include <qwt_plot.h>
|
||||||
|
#include <qwt_plot_curve.h>
|
||||||
|
#include <qwt_plot_grid.h>
|
||||||
|
#include <qwt_plot_marker.h>
|
||||||
|
#include <qwt_plot_picker.h>
|
||||||
|
#include <qwt_picker_machine.h>
|
||||||
|
#include <qwt_plot_layout.h>
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
#include <qwt_plot_renderer.h>
|
||||||
|
#include <qwt_plot_histogram.h>
|
||||||
|
#else
|
||||||
|
#include "../raster/qwt5_histogram_item.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
QgsGraduatedHistogramWidget::QgsGraduatedHistogramWidget( QWidget *parent )
|
||||||
|
: QgsHistogramWidget( parent )
|
||||||
|
, mRenderer( 0 )
|
||||||
|
, mHistoPicker( 0 )
|
||||||
|
, mPressedValue( 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
mFilter = new QgsGraduatedHistogramEventFilter( mPlot );
|
||||||
|
|
||||||
|
connect( mFilter, SIGNAL( mousePress( double ) ), this, SLOT( mousePress( double ) ) );
|
||||||
|
connect( mFilter, SIGNAL( mouseRelease( double ) ), this, SLOT( mouseRelease( double ) ) );
|
||||||
|
|
||||||
|
mHistoPicker = new QwtPlotPicker( mPlot->canvas() );
|
||||||
|
mHistoPicker->setTrackerMode( QwtPicker::ActiveOnly );
|
||||||
|
mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
mHistoPicker->setStateMachine( new QwtPickerDragPointMachine );
|
||||||
|
#else
|
||||||
|
mHistoPicker->setSelectionFlags( QwtPicker::PointSelection | QwtPicker::DragSelection );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QgsGraduatedHistogramWidget::~QgsGraduatedHistogramWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedHistogramWidget::setRenderer( QgsGraduatedSymbolRendererV2 *renderer )
|
||||||
|
{
|
||||||
|
mRenderer = renderer;
|
||||||
|
mRedrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedHistogramWidget::drawHistogram()
|
||||||
|
{
|
||||||
|
if ( !mRenderer )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRanges = mRenderer->ranges();
|
||||||
|
QgsHistogramWidget::drawHistogram();
|
||||||
|
|
||||||
|
// histo picker
|
||||||
|
mHistoPicker->setEnabled( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedHistogramWidget::mousePress( double value )
|
||||||
|
{
|
||||||
|
mPressedValue = value;
|
||||||
|
|
||||||
|
int closestRangeIndex = 0;
|
||||||
|
int minPixelDistance = 9999;
|
||||||
|
findClosestRange( mPressedValue, closestRangeIndex, minPixelDistance );
|
||||||
|
|
||||||
|
if ( minPixelDistance <= 6 )
|
||||||
|
{
|
||||||
|
//moving a break, so hide the break line
|
||||||
|
mRangeMarkers.at( closestRangeIndex )->hide();
|
||||||
|
mRedrawRequired = true;
|
||||||
|
mPlot->replot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedHistogramWidget::mouseRelease( double value )
|
||||||
|
{
|
||||||
|
int closestRangeIndex = 0;
|
||||||
|
int minPixelDistance = 9999;
|
||||||
|
findClosestRange( mPressedValue, closestRangeIndex, minPixelDistance );
|
||||||
|
|
||||||
|
if ( minPixelDistance <= 6 )
|
||||||
|
{
|
||||||
|
//do a sanity check - don't allow users to drag a break line
|
||||||
|
//into the middle of a different range. Doing so causes overlap
|
||||||
|
//of the ranges
|
||||||
|
|
||||||
|
//new value needs to be within range covered by closestRangeIndex or
|
||||||
|
//closestRangeIndex + 1
|
||||||
|
if ( value <= mRenderer->ranges().at( closestRangeIndex ).lowerValue() ||
|
||||||
|
value >= mRenderer->ranges().at( closestRangeIndex + 1 ).upperValue() )
|
||||||
|
{
|
||||||
|
refreshHistogram();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRenderer->updateRangeUpperValue( closestRangeIndex, value );
|
||||||
|
mRenderer->updateRangeLowerValue( closestRangeIndex + 1, value );
|
||||||
|
emit rangesModified( false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if distance from markers is too big, add a break
|
||||||
|
mRenderer->addBreak( value );
|
||||||
|
emit rangesModified( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
drawHistogram();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedHistogramWidget::findClosestRange( double value, int &closestRangeIndex, int& pixelDistance ) const
|
||||||
|
{
|
||||||
|
const QgsRangeList& ranges = mRenderer->ranges();
|
||||||
|
|
||||||
|
double minDistance = DBL_MAX;
|
||||||
|
int pressedPixel = mPlot->canvasMap( QwtPlot::xBottom ).transform( value );
|
||||||
|
for ( int i = 0; i < ranges.count() - 1; ++i )
|
||||||
|
{
|
||||||
|
if ( qAbs( mPressedValue - ranges.at( i ).upperValue() ) < minDistance )
|
||||||
|
{
|
||||||
|
closestRangeIndex = i;
|
||||||
|
minDistance = qAbs( mPressedValue - ranges.at( i ).upperValue() );
|
||||||
|
pixelDistance = qAbs( pressedPixel - mPlot->canvasMap( QwtPlot::xBottom ).transform( ranges.at( i ).upperValue() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsGraduatedHistogramEventFilter::QgsGraduatedHistogramEventFilter( QwtPlot *plot )
|
||||||
|
: QObject( plot )
|
||||||
|
, mPlot( plot )
|
||||||
|
{
|
||||||
|
mPlot->canvas()->installEventFilter( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsGraduatedHistogramEventFilter::eventFilter( QObject *object, QEvent *event )
|
||||||
|
{
|
||||||
|
switch ( event->type() )
|
||||||
|
{
|
||||||
|
case QEvent::MouseButtonPress:
|
||||||
|
{
|
||||||
|
const QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent* >( event );
|
||||||
|
if ( mouseEvent->button() == Qt::LeftButton )
|
||||||
|
{
|
||||||
|
emit mousePress( posToValue( mouseEvent->pos() ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::MouseButtonRelease:
|
||||||
|
{
|
||||||
|
const QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent* >( event );
|
||||||
|
if ( mouseEvent->button() == Qt::LeftButton )
|
||||||
|
{
|
||||||
|
emit mouseRelease( posToValue( mouseEvent->pos() ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter( object, event );
|
||||||
|
}
|
||||||
|
|
||||||
|
double QgsGraduatedHistogramEventFilter::posToValue( const QPointF &point ) const
|
||||||
|
{
|
||||||
|
if ( !mPlot )
|
||||||
|
return -99999999;
|
||||||
|
|
||||||
|
return mPlot->canvasMap( QwtPlot::xBottom ).invTransform( point.x() );
|
||||||
|
}
|
114
src/gui/symbology-ng/qgsgraduatedhistogramwidget.h
Normal file
114
src/gui/symbology-ng/qgsgraduatedhistogramwidget.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsgraduatedhistogramwidget.h
|
||||||
|
-----------------------------
|
||||||
|
begin : May 2015
|
||||||
|
copyright : (C) 2015 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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 QGSGRADUATEDHISTOGRAMWIDGET_H
|
||||||
|
#define QGSGRADUATEDHISTOGRAMWIDGET_H
|
||||||
|
|
||||||
|
#include "qgshistogramwidget.h"
|
||||||
|
|
||||||
|
class QwtPlotPicker;
|
||||||
|
class QgsGraduatedHistogramEventFilter;
|
||||||
|
|
||||||
|
/** \ingroup gui
|
||||||
|
* \class QgsGraduatedHistogramWidget
|
||||||
|
* \brief Graphical histogram for displaying distribution of field values and
|
||||||
|
* editing range breaks for a QgsGraduatedSymbolRendererV2 renderer.
|
||||||
|
*
|
||||||
|
* \note Added in version 2.9
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GUI_EXPORT QgsGraduatedHistogramWidget : public QgsHistogramWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** QgsGraduatedHistogramWidget constructor
|
||||||
|
* @param parent parent widget
|
||||||
|
*/
|
||||||
|
QgsGraduatedHistogramWidget( QWidget *parent = 0 );
|
||||||
|
~QgsGraduatedHistogramWidget();
|
||||||
|
|
||||||
|
/** Sets the QgsGraduatedSymbolRendererV2 renderer associated with the histogram.
|
||||||
|
* The histogram will fetch the ranges from the renderer before every refresh.
|
||||||
|
* @param renderer associated QgsGraduatedSymbolRendererV2
|
||||||
|
*/
|
||||||
|
void setRenderer( QgsGraduatedSymbolRendererV2* renderer );
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
/** Emitted when the user modifies the graduated ranges using the histogram widget.
|
||||||
|
* @param rangesAdded true if the user has added ranges, false if the user has just
|
||||||
|
* modified existing range breaks
|
||||||
|
*/
|
||||||
|
void rangesModified( bool rangesAdded );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void drawHistogram() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void mousePress( double value );
|
||||||
|
void mouseRelease( double value );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsGraduatedSymbolRendererV2* mRenderer;
|
||||||
|
QwtPlotPicker* mHistoPicker;
|
||||||
|
QgsGraduatedHistogramEventFilter* mFilter;
|
||||||
|
double mPressedValue;
|
||||||
|
|
||||||
|
void findClosestRange( double value, int &closestRangeIndex, int &pixelDistance ) const;
|
||||||
|
|
||||||
|
#if defined(QWT_VERSION) && QWT_VERSION>=0x060000
|
||||||
|
QwtPlotHistogram* createPlotHistogram( const QString& title, const QColor& color ) const;
|
||||||
|
#else
|
||||||
|
HistogramItem* createHistoItem( const QString& title, const QColor& color ) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// NOTE:
|
||||||
|
// For private use by QgsGraduatedHistogramWidget only,
|
||||||
|
// not part of stable api or exposed to Python bindings
|
||||||
|
//
|
||||||
|
|
||||||
|
class GUI_EXPORT QgsGraduatedHistogramEventFilter: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
QgsGraduatedHistogramEventFilter( QwtPlot *plot );
|
||||||
|
|
||||||
|
virtual ~QgsGraduatedHistogramEventFilter() {}
|
||||||
|
|
||||||
|
virtual bool eventFilter( QObject* object, QEvent* event ) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void mousePress( double );
|
||||||
|
void mouseRelease( double );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QwtPlot* mPlot;
|
||||||
|
double posToValue( const QPointF& point ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QGSGRADUATEDHISTOGRAMWIDGET_H
|
@ -335,9 +335,16 @@ void QgsGraduatedSymbolRendererV2Model::sort( int column, Qt::SortOrder order )
|
|||||||
QgsDebugMsg( "Done" );
|
QgsDebugMsg( "Done" );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Model::updateSymbology()
|
void QgsGraduatedSymbolRendererV2Model::updateSymbology( bool resetModel )
|
||||||
{
|
{
|
||||||
emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
|
if ( resetModel )
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Model::updateLabels()
|
void QgsGraduatedSymbolRendererV2Model::updateLabels()
|
||||||
@ -465,6 +472,11 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
|
|||||||
connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) );
|
connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) );
|
||||||
connect( mDataDefinedMenus, SIGNAL( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ), this, SLOT( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ) );
|
connect( mDataDefinedMenus, SIGNAL( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ), this, SLOT( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ) );
|
||||||
btnAdvanced->setMenu( advMenu );
|
btnAdvanced->setMenu( advMenu );
|
||||||
|
|
||||||
|
mHistogramWidget->setLayer( mLayer );
|
||||||
|
mHistogramWidget->setRenderer( mRenderer );
|
||||||
|
connect( mHistogramWidget, SIGNAL( rangesModified( bool ) ), this, SLOT( refreshRanges( bool ) ) );
|
||||||
|
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), mHistogramWidget, SLOT( setSourceFieldExp( QString ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Widget::on_mSizeUnitWidget_changed()
|
void QgsGraduatedSymbolRendererV2Widget::on_mSizeUnitWidget_changed()
|
||||||
@ -543,6 +555,7 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer( bool updateCount
|
|||||||
// set column
|
// set column
|
||||||
QString attrName = mRenderer->classAttribute();
|
QString attrName = mRenderer->classAttribute();
|
||||||
mExpressionWidget->setField( attrName );
|
mExpressionWidget->setField( attrName );
|
||||||
|
mHistogramWidget->setSourceFieldExp( attrName );
|
||||||
|
|
||||||
// set source symbol
|
// set source symbol
|
||||||
if ( mRenderer->sourceSymbol() )
|
if ( mRenderer->sourceSymbol() )
|
||||||
@ -593,6 +606,8 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer( bool updateCount
|
|||||||
viewGraduated->resizeColumnToContents( 1 );
|
viewGraduated->resizeColumnToContents( 1 );
|
||||||
viewGraduated->resizeColumnToContents( 2 );
|
viewGraduated->resizeColumnToContents( 2 );
|
||||||
|
|
||||||
|
mHistogramWidget->refreshHistogram();
|
||||||
|
|
||||||
connectUpdateHandlers();
|
connectUpdateHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,6 +642,14 @@ void QgsGraduatedSymbolRendererV2Widget::on_methodComboBox_currentIndexChanged(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsGraduatedSymbolRendererV2Widget::refreshRanges( bool reset )
|
||||||
|
{
|
||||||
|
if ( !mModel )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mModel->updateSymbology( reset );
|
||||||
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
|
void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
|
||||||
{
|
{
|
||||||
QString attrName = mExpressionWidget->currentField();
|
QString attrName = mExpressionWidget->currentField();
|
||||||
@ -1052,6 +1075,7 @@ void QgsGraduatedSymbolRendererV2Widget::rowsMoved()
|
|||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Widget::modelDataChanged()
|
void QgsGraduatedSymbolRendererV2Widget::modelDataChanged()
|
||||||
{
|
{
|
||||||
|
mHistogramWidget->refreshHistogram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGraduatedSymbolRendererV2Widget::keyPressEvent( QKeyEvent* event )
|
void QgsGraduatedSymbolRendererV2Widget::keyPressEvent( QKeyEvent* event )
|
||||||
|
@ -49,7 +49,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Model : public QAbstractItemModel
|
|||||||
void deleteRows( QList<int> rows );
|
void deleteRows( QList<int> rows );
|
||||||
void removeAllRows();
|
void removeAllRows();
|
||||||
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override;
|
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override;
|
||||||
void updateSymbology();
|
void updateSymbology( bool resetModel = false );
|
||||||
void updateLabels();
|
void updateLabels();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -111,6 +111,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
|
|||||||
void modelDataChanged();
|
void modelDataChanged();
|
||||||
void on_mSizeUnitWidget_changed();
|
void on_mSizeUnitWidget_changed();
|
||||||
void on_methodComboBox_currentIndexChanged( int );
|
void on_methodComboBox_currentIndexChanged( int );
|
||||||
|
void refreshRanges( bool reset = false );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateUiFromRenderer( bool updateCount = true );
|
void updateUiFromRenderer( bool updateCount = true );
|
||||||
|
@ -7,53 +7,213 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>759</width>
|
<width>759</width>
|
||||||
<height>638</height>
|
<height>394</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,1,0,0">
|
<layout class="QGridLayout" name="gridLayout" rowstretch="0,1,0">
|
||||||
<property name="margin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="3" column="0" colspan="4">
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Classes</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>cboGraduatedMode</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="cboGraduatedMode">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Equal Interval</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Quantile (Equal Count)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Natural Breaks (Jenks)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Standard Deviation</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pretty Breaks</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Classes</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>spinGraduatedClasses</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinGraduatedClasses">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnGraduatedClassify">
|
||||||
|
<property name="text">
|
||||||
|
<string>Classify</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="viewGraduated">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="itemsExpandable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnGraduatedAdd">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add class</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnGraduatedDelete">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnDeleteAllClasses">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete all</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbxLinkBoundaries">
|
||||||
|
<property name="text">
|
||||||
|
<string>Link class boundaries</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Histogram</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0">
|
||||||
|
<item>
|
||||||
|
<widget class="QgsGraduatedHistogramWidget" name="mHistogramWidget" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="_2">
|
<layout class="QHBoxLayout" name="_2">
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnGraduatedClassify">
|
|
||||||
<property name="text">
|
|
||||||
<string>Classify</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnGraduatedAdd">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add class</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnGraduatedDelete">
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnDeleteAllClasses">
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete all</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbxLinkBoundaries">
|
|
||||||
<property name="text">
|
|
||||||
<string>Link class boundaries</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -76,11 +236,22 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="4">
|
<item row="0" column="0" colspan="2">
|
||||||
<layout class="QGridLayout">
|
<layout class="QGridLayout" columnstretch="0,3,0,0,1,0">
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item row="2" column="1" colspan="2">
|
||||||
|
<widget class="QLineEdit" name="txtLegendFormat">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Template for the legend text associated with each classification.
|
||||||
|
Use "%1" for the lower bound of the classification, and "%2" for the upper bound.</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="2" column="4">
|
<item row="2" column="4">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
<item>
|
<item>
|
||||||
@ -107,45 +278,65 @@ Negative rounds to powers of 10</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="cbxTrimTrailingZeroes">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Check to remove trailing zeroes after the decimal point from the upper and lower values in the legend.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Trim</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="0">
|
||||||
<widget class="QComboBox" name="cboGraduatedMode">
|
<widget class="QLabel" name="label_4">
|
||||||
<item>
|
<property name="text">
|
||||||
<property name="text">
|
<string>Column</string>
|
||||||
<string>Equal Interval</string>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="0" column="1" colspan="2">
|
||||||
<property name="text">
|
<widget class="QgsFieldExpressionWidget" name="mExpressionWidget" native="true">
|
||||||
<string>Quantile (Equal Count)</string>
|
<property name="minimumSize">
|
||||||
</property>
|
<size>
|
||||||
</item>
|
<width>10</width>
|
||||||
<item>
|
<height>0</height>
|
||||||
<property name="text">
|
</size>
|
||||||
<string>Natural Breaks (Jenks)</string>
|
</property>
|
||||||
</property>
|
<property name="maximumSize">
|
||||||
</item>
|
<size>
|
||||||
<item>
|
<width>500</width>
|
||||||
<property name="text">
|
<height>16777215</height>
|
||||||
<string>Standard Deviation</string>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
<property name="focusPolicy">
|
||||||
<item>
|
<enum>Qt::StrongFocus</enum>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Pretty Breaks</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</item>
|
<item row="1" column="1" colspan="2">
|
||||||
|
<widget class="QPushButton" name="btnChangeGraduatedSymbol">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Change...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="text">
|
||||||
|
<string>Precision</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>spinPrecision</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Symbol</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>btnChangeGraduatedSymbol</cstring>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
@ -155,35 +346,6 @@ Negative rounds to powers of 10</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Classes</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>spinGraduatedClasses</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QSpinBox" name="spinGraduatedClasses">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>999</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -197,17 +359,20 @@ Negative rounds to powers of 10</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="3" column="1" colspan="2">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QComboBox" name="methodComboBox"/>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Mode</string>
|
<item row="2" column="5">
|
||||||
|
<widget class="QCheckBox" name="cbxTrimTrailingZeroes">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Check to remove trailing zeroes after the decimal point from the upper and lower values in the legend.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="text">
|
||||||
<cstring>cboGraduatedMode</cstring>
|
<string>Trim</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" colspan="4">
|
<item row="4" column="1" colspan="5">
|
||||||
<widget class="QStackedWidget" name="mMethodStackedWidget">
|
<widget class="QStackedWidget" name="mMethodStackedWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
@ -226,7 +391,16 @@ Negative rounds to powers of 10</string>
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page">
|
<widget class="QWidget" name="page">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0,0">
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0,0">
|
||||||
<property name="margin">
|
<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>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@ -266,7 +440,16 @@ Negative rounds to powers of 10</string>
|
|||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_2">
|
<widget class="QWidget" name="page_2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,1,1">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,1,1">
|
||||||
<property name="margin">
|
<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>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@ -293,7 +476,7 @@ Negative rounds to powers of 10</string>
|
|||||||
<property name="value">
|
<property name="value">
|
||||||
<double>1.000000000000000</double>
|
<double>1.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="showClearButton">
|
<property name="showClearButton" stdset="0">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -319,7 +502,7 @@ Negative rounds to powers of 10</string>
|
|||||||
<property name="value">
|
<property name="value">
|
||||||
<double>10.000000000000000</double>
|
<double>10.000000000000000</double>
|
||||||
</property>
|
</property>
|
||||||
<property name="showClearButton">
|
<property name="showClearButton" stdset="0">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -341,106 +524,8 @@ Negative rounds to powers of 10</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Symbol</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>btnChangeGraduatedSymbol</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QLabel" name="label_16">
|
|
||||||
<property name="text">
|
|
||||||
<string>Precision</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>spinPrecision</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Column</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="2">
|
|
||||||
<widget class="QgsFieldExpressionWidget" name="mExpressionWidget">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>10</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>500</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::StrongFocus</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1" colspan="2">
|
|
||||||
<widget class="QLineEdit" name="txtLegendFormat">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Template for the legend text associated with each classification.
|
|
||||||
Use "%1" for the lower bound of the classification, and "%2" for the upper bound.</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" colspan="2">
|
|
||||||
<widget class="QPushButton" name="btnChangeGraduatedSymbol">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>1</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Change...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1" colspan="2">
|
|
||||||
<widget class="QComboBox" name="methodComboBox"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" rowspan="2" colspan="4">
|
|
||||||
<widget class="QTreeView" name="viewGraduated">
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="showDropIndicator" stdset="0">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="dragDropMode">
|
|
||||||
<enum>QAbstractItemView::InternalMove</enum>
|
|
||||||
</property>
|
|
||||||
<property name="selectionMode">
|
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
|
||||||
</property>
|
|
||||||
<property name="rootIsDecorated">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="itemsExpandable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sortingEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@ -449,6 +534,12 @@ Use "%1" for the lower bound of the classification, and "%2"
|
|||||||
<extends>QDoubleSpinBox</extends>
|
<extends>QDoubleSpinBox</extends>
|
||||||
<header>qgsdoublespinbox.h</header>
|
<header>qgsdoublespinbox.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QgsUnitSelectionWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>qgsunitselectionwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>QgsFieldExpressionWidget</class>
|
<class>QgsFieldExpressionWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
@ -461,32 +552,23 @@ Use "%1" for the lower bound of the classification, and "%2"
|
|||||||
<header>qgscolorrampcombobox.h</header>
|
<header>qgscolorrampcombobox.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>QgsUnitSelectionWidget</class>
|
<class>QgsGraduatedHistogramWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>qgsunitselectionwidget.h</header>
|
<header>qgsgraduatedhistogramwidget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>mExpressionWidget</tabstop>
|
<tabstop>mExpressionWidget</tabstop>
|
||||||
<tabstop>cboGraduatedMode</tabstop>
|
|
||||||
<tabstop>btnChangeGraduatedSymbol</tabstop>
|
<tabstop>btnChangeGraduatedSymbol</tabstop>
|
||||||
<tabstop>spinGraduatedClasses</tabstop>
|
|
||||||
<tabstop>txtLegendFormat</tabstop>
|
<tabstop>txtLegendFormat</tabstop>
|
||||||
<tabstop>spinPrecision</tabstop>
|
<tabstop>spinPrecision</tabstop>
|
||||||
<tabstop>cbxTrimTrailingZeroes</tabstop>
|
|
||||||
<tabstop>methodComboBox</tabstop>
|
<tabstop>methodComboBox</tabstop>
|
||||||
<tabstop>cboGraduatedColorRamp</tabstop>
|
<tabstop>cboGraduatedColorRamp</tabstop>
|
||||||
<tabstop>cbxInvertedColorRamp</tabstop>
|
<tabstop>cbxInvertedColorRamp</tabstop>
|
||||||
<tabstop>minSizeSpinBox</tabstop>
|
<tabstop>minSizeSpinBox</tabstop>
|
||||||
<tabstop>maxSizeSpinBox</tabstop>
|
<tabstop>maxSizeSpinBox</tabstop>
|
||||||
<tabstop>mSizeUnitWidget</tabstop>
|
<tabstop>mSizeUnitWidget</tabstop>
|
||||||
<tabstop>viewGraduated</tabstop>
|
|
||||||
<tabstop>btnGraduatedClassify</tabstop>
|
|
||||||
<tabstop>btnGraduatedAdd</tabstop>
|
|
||||||
<tabstop>btnGraduatedDelete</tabstop>
|
|
||||||
<tabstop>btnDeleteAllClasses</tabstop>
|
|
||||||
<tabstop>cbxLinkBoundaries</tabstop>
|
|
||||||
<tabstop>btnAdvanced</tabstop>
|
<tabstop>btnAdvanced</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
108
src/ui/qgshistogramwidgetbase.ui
Normal file
108
src/ui/qgshistogramwidgetbase.ui
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>QgsHistogramWidgetBase</class>
|
||||||
|
<widget class="QWidget" name="QgsHistogramWidgetBase">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>694</width>
|
||||||
|
<height>128</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QwtPlot" name="mpPlot">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Histogram bins</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="mBinsSpinBox">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="mMeanCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show mean value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="mStdevCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show standard deviation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QwtPlot</class>
|
||||||
|
<extends>QFrame</extends>
|
||||||
|
<header>qwt_plot.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
x
Reference in New Issue
Block a user