Skip to content
Permalink
Browse files

[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)
  • Loading branch information
nyalldawson committed Apr 13, 2015
1 parent 17962ef commit 183286a006ec8e5184e47b890c8f0374ed7a4460
@@ -56,6 +56,7 @@
%Include qgsfilterlineedit.sip
%Include qgsformannotationitem.sip
%Include qgsgenericprojectionselector.sip
%Include qgshistogramwidget.sip
%Include qgshtmlannotationitem.sip
%Include qgsidentifymenu.sip
%Include qgslegendinterface.sip
@@ -173,6 +174,7 @@
%Include symbology-ng/qgsdatadefinedsymboldialog.sip
%Include symbology-ng/qgsstylev2exportimportdialog.sip
%Include symbology-ng/qgssvgselectorwidget.sip
%Include symbology-ng/qgsgraduatedhistogramwidget.sip

%Include effects/qgseffectdrawmodecombobox.sip
%Include effects/qgspainteffectpropertieswidget.sip
@@ -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 );
};
@@ -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 )
{
int count = 0;
while ( mValues.at( currentValueIndex ) < edges.at( i + 1 ) )
while ( currentValueIndex < mValues.count() && mValues.at( currentValueIndex ) < edges.at( i + 1 ) )
{
count++;
currentValueIndex++;
@@ -1357,6 +1357,37 @@ void QgsGraduatedSymbolRendererV2::addClass( double lower, double upper )
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 )
{
mRanges.append( range );
@@ -157,6 +157,16 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
void addClass( QgsRendererRangeV2 range );
//! @note available in python bindings as addClassLowerUpper
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 deleteAllClasses();

@@ -8,6 +8,7 @@ raster/qgspalettedrendererwidget.cpp
raster/qgssinglebandgrayrendererwidget.cpp
raster/qgssinglebandpseudocolorrendererwidget.cpp
raster/qgsrasterhistogramwidget.cpp
raster/qwt5_histogram_item.cpp

symbology-ng/qgsbrushstylecombobox.cpp
symbology-ng/qgscolorrampcombobox.cpp
@@ -19,6 +20,7 @@ symbology-ng/qgsrendererv2widget.cpp
symbology-ng/qgssinglesymbolrendererv2widget.cpp
symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
symbology-ng/qgsgraduatedhistogramwidget.cpp
symbology-ng/qgsrulebasedrendererv2widget.cpp
symbology-ng/qgsheatmaprendererwidget.cpp
symbology-ng/qgsinvertedpolygonrendererwidget.cpp
@@ -174,6 +176,7 @@ qgsfilterlineedit.cpp
qgsformannotationitem.cpp
qgsgenericprojectionselector.cpp
qgshighlight.cpp
qgshistogramwidget.cpp
qgsidentifymenu.cpp
qgshtmlannotationitem.cpp
qgslegendinterface.cpp
@@ -287,6 +290,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsfilterlineedit.h
qgsformannotationitem.h
qgsgenericprojectionselector.h
qgshistogramwidget.h
qgshtmlannotationitem.h
qgsidentifymenu.h
qgslegendinterface.h
@@ -352,6 +356,7 @@ SET(QGIS_GUI_MOC_HDRS
symbology-ng/qgsdatadefinedsymboldialog.h
symbology-ng/qgsellipsesymbollayerv2widget.h
symbology-ng/qgsgraduatedsymbolrendererv2widget.h
symbology-ng/qgsgraduatedhistogramwidget.h
symbology-ng/qgsheatmaprendererwidget.h
symbology-ng/qgsinvertedpolygonrendererwidget.h
symbology-ng/qgslayerpropertieswidget.h

0 comments on commit 183286a

Please sign in to comment.
You can’t perform that action at this time.