Skip to content

Commit

Permalink
[FEATURE] Add a graphical histogram for the graduated renderer
Browse files Browse the repository at this point in the history
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 May 18, 2015
1 parent 17962ef commit 183286a
Show file tree
Hide file tree
Showing 17 changed files with 1,893 additions and 550 deletions.
2 changes: 2 additions & 0 deletions python/gui/gui.sip
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
107 changes: 107 additions & 0 deletions python/gui/qgshistogramwidget.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 );
};
42 changes: 42 additions & 0 deletions python/gui/symbology-ng/qgsgraduatedhistogramwidget.sip
@@ -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();

};
2 changes: 1 addition & 1 deletion src/core/qgshistogram.cpp
Expand Up @@ -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++;
Expand Down
31 changes: 31 additions & 0 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Expand Up @@ -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 );
Expand Down
10 changes: 10 additions & 0 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h
Expand Up @@ -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();

Expand Down
5 changes: 5 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -174,6 +176,7 @@ qgsfilterlineedit.cpp
qgsformannotationitem.cpp
qgsgenericprojectionselector.cpp
qgshighlight.cpp
qgshistogramwidget.cpp
qgsidentifymenu.cpp
qgshtmlannotationitem.cpp
qgslegendinterface.cpp
Expand Down Expand Up @@ -287,6 +290,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsfilterlineedit.h
qgsformannotationitem.h
qgsgenericprojectionselector.h
qgshistogramwidget.h
qgshtmlannotationitem.h
qgsidentifymenu.h
qgslegendinterface.h
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 183286a

Please sign in to comment.