Merge pull request #1974 from vmora/graduated_by_size

[feature] graduated with varying size
This commit is contained in:
Nyall Dawson 2015-04-11 11:15:50 +10:00
commit 28b5217bb8
8 changed files with 572 additions and 189 deletions

View File

@ -212,6 +212,29 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
/** Update all the symbols but leave breaks and colors. */
void updateSymbols( QgsSymbolV2* sym /Transfer/ );
//! set varying symbol size for classes
//! @note the classes must already be set so that symbols exist
//! @note added in 2.10
void setSymbolSizes( double minSize, double maxSize );
//! return the min symbol size when graduated by size
//! @note added in 2.10
double minSymbolSize() const;
//! return the max symbol size when graduated by size
//! @note added in 2.10
double maxSymbolSize() const;
enum GraduatedMethod {GraduatedColor = 0, GraduatedSize = 1 };
//! return the method used for graduation (either size or color)
//! @note added in 2.10
GraduatedMethod graduatedMethod() const;
//! set the method used for graduation (either size or color)
//! @note added in 2.10
void setGraduatedMethod( GraduatedMethod method );
void setRotationField( QString fieldOrExpression );
QString rotationField() const;

View File

@ -16,6 +16,7 @@ class QgsGraduatedSymbolRendererV2Widget : QgsRendererV2Widget
void graduatedColumnChanged( QString field );
void classifyGraduated();
void reapplyColorRamp();
void reapplySizes();
void rangesDoubleClicked( const QModelIndex & idx );
void rangesClicked( const QModelIndex & idx );
void changeCurrentValue( QStandardItem * item );

View File

@ -286,6 +286,7 @@ QgsGraduatedSymbolRendererV2::QgsGraduatedSymbolRendererV2( QString attrName, Qg
, mMode( Custom )
, mInvertedColorRamp( false )
, mScaleMethod( DEFAULT_SCALE_METHOD )
, mGraduatedMethod( GraduatedColor )
, mAttrNum( -1 )
, mCounting( false )
@ -519,6 +520,7 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::clone() const
r->setSizeScaleField( sizeScaleField() );
r->setScaleMethod( scaleMethod() );
r->setLabelFormat( labelFormat() );
r->setGraduatedMethod( graduatedMethod() );
copyPaintEffect( r );
return r;
}
@ -527,6 +529,7 @@ void QgsGraduatedSymbolRendererV2::toSld( QDomDocument& doc, QDomElement &elemen
{
QgsStringMap props;
props[ "attribute" ] = mAttrName;
props[ "method" ] = graduatedMethodStr( mGraduatedMethod );
if ( mRotation.data() )
props[ "angle" ] = mRotation->expression();
if ( mSizeScale.data() )
@ -962,6 +965,7 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
QList<double> QgsGraduatedSymbolRendererV2::getDataValues( QgsVectorLayer *vlayer )
{
QList<double> values;
QScopedPointer<QgsExpression> expression;
int attrNum = vlayer->fieldNameIndex( mAttrName );
@ -1022,7 +1026,7 @@ void QgsGraduatedSymbolRendererV2::updateClasses( QgsVectorLayer *vlayer, Mode m
if ( values.isEmpty() )
return;
qSort( values );
qSort( values ); // vmora: is wondering if O( n log(n) ) is really necessary here, min and max are O( n )
minimum = values.first();
maximum = values.last();
valuesLoaded = true;
@ -1146,6 +1150,16 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create( QDomElement& element
QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
QString attrMethod = element.attribute( "graduatedMethod" );
if ( attrMethod.length() )
{
if ( attrMethod == graduatedMethodStr( GraduatedColor ) )
r->setGraduatedMethod( GraduatedColor );
else if ( attrMethod == graduatedMethodStr( GraduatedSize ) )
r->setGraduatedMethod( GraduatedSize );
}
// delete symbols if there are any more
QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
@ -1214,6 +1228,7 @@ QDomElement QgsGraduatedSymbolRendererV2::save( QDomDocument& doc )
rendererElem.setAttribute( "type", "graduatedSymbol" );
rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
rendererElem.setAttribute( "attr", mAttrName );
rendererElem.setAttribute( "graduatedMethod", graduatedMethodStr( mGraduatedMethod ) );
// ranges
int i = 0;
@ -1348,6 +1363,52 @@ void QgsGraduatedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ram
mSourceColorRamp.reset( ramp );
}
double QgsGraduatedSymbolRendererV2::minSymbolSize() const
{
double min = DBL_MAX;
for ( int i = 0; i < mRanges.count(); i++ )
{
double sz = 0;
if ( mRanges[i].symbol()->type() == QgsSymbolV2::Marker )
sz = static_cast< QgsMarkerSymbolV2 * >( mRanges[i].symbol() )->size();
else if ( mRanges[i].symbol()->type() == QgsSymbolV2::Line )
sz = static_cast< QgsLineSymbolV2 * >( mRanges[i].symbol() )->width();
min = qMin( sz, min );
}
return min;
}
double QgsGraduatedSymbolRendererV2::maxSymbolSize() const
{
double max = DBL_MIN;
for ( int i = 0; i < mRanges.count(); i++ )
{
double sz = 0;
if ( mRanges[i].symbol()->type() == QgsSymbolV2::Marker )
sz = static_cast< QgsMarkerSymbolV2 * >( mRanges[i].symbol() )->size();
else if ( mRanges[i].symbol()->type() == QgsSymbolV2::Line )
sz = static_cast< QgsLineSymbolV2 * >( mRanges[i].symbol() )->width();
max = qMax( sz, max );
}
return max;
}
void QgsGraduatedSymbolRendererV2::setSymbolSizes( double minSize, double maxSize )
{
for ( int i = 0; i < mRanges.count(); i++ )
{
QScopedPointer<QgsSymbolV2> symbol( mRanges[i].symbol() ? mRanges[i].symbol()->clone() : 0 );
const double size = mRanges.count() > 1
? minSize + i * ( maxSize - minSize ) / ( mRanges.count() - 1 )
: .5 * ( maxSize + minSize );
if ( symbol->type() == QgsSymbolV2::Marker )
static_cast< QgsMarkerSymbolV2 * >( symbol.data() )->setSize( size );
if ( symbol->type() == QgsSymbolV2::Line )
static_cast< QgsLineSymbolV2 * >( symbol.data() )->setWidth( size );
updateRangeSymbol( i, symbol.take() );
}
}
void QgsGraduatedSymbolRendererV2::updateColorRamp( QgsVectorColorRampV2 *ramp, bool inverted )
{
int i = 0;
@ -1386,9 +1447,21 @@ void QgsGraduatedSymbolRendererV2::updateSymbols( QgsSymbolV2 *sym )
int i = 0;
foreach ( QgsRendererRangeV2 range, mRanges )
{
QgsSymbolV2 *symbol = sym->clone();
symbol->setColor( range.symbol()->color() );
updateRangeSymbol( i, symbol );
QScopedPointer<QgsSymbolV2> symbol( sym->clone() );
if ( mGraduatedMethod == GraduatedColor )
{
symbol->setColor( range.symbol()->color() );
}
else if ( mGraduatedMethod == GraduatedSize )
{
if ( symbol->type() == QgsSymbolV2::Marker )
static_cast<QgsMarkerSymbolV2 *>( symbol.data() )->setSize(
static_cast<QgsMarkerSymbolV2 *>( range.symbol() )->size() );
else if ( symbol->type() == QgsSymbolV2::Line )
static_cast<QgsLineSymbolV2 *>( symbol.data() )->setWidth(
static_cast<QgsLineSymbolV2 *>( range.symbol() )->width() );
}
updateRangeSymbol( i, symbol.take() );
++i;
}
setSourceSymbol( sym->clone() );
@ -1602,3 +1675,15 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::convertFromRenderer(
return r;
}
const char * QgsGraduatedSymbolRendererV2::graduatedMethodStr( GraduatedMethod method )
{
switch ( method )
{
case GraduatedColor: return "GraduatedColor";
case GraduatedSize: return "GraduatedSize";
}
return "";
}

View File

@ -113,6 +113,7 @@ class QgsVectorColorRampV2;
class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
{
public:
QgsGraduatedSymbolRendererV2( QString attrName = QString(), QgsRangeList ranges = QgsRangeList() );
QgsGraduatedSymbolRendererV2( const QgsGraduatedSymbolRendererV2 & other );
@ -243,6 +244,30 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
/** Update all the symbols but leave breaks and colors. */
void updateSymbols( QgsSymbolV2* sym );
//! set varying symbol size for classes
//! @note the classes must already be set so that symbols exist
//! @note added in 2.10
void setSymbolSizes( double minSize, double maxSize );
//! return the min symbol size when graduated by size
//! @note added in 2.10
double minSymbolSize() const;
//! return the max symbol size when graduated by size
//! @note added in 2.10
double maxSymbolSize() const;
enum GraduatedMethod {GraduatedColor = 0, GraduatedSize = 1 };
//! return the method used for graduation (either size or color)
//! @note added in 2.10
GraduatedMethod graduatedMethod() const { return mGraduatedMethod; }
//! set the method used for graduation (either size or color)
//! @note added in 2.10
void setGraduatedMethod( GraduatedMethod method ) { mGraduatedMethod = method; }
void setRotationField( QString fieldOrExpression ) override;
QString rotationField() const override;
@ -281,10 +306,12 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
QScopedPointer<QgsVectorColorRampV2> mSourceColorRamp;
bool mInvertedColorRamp;
QgsRendererRangeV2LabelFormat mLabelFormat;
QScopedPointer<QgsExpression> mRotation;
QScopedPointer<QgsExpression> mSizeScale;
QgsSymbolV2::ScaleMethod mScaleMethod;
QScopedPointer<QgsExpression> mExpression;
GraduatedMethod mGraduatedMethod;
//! attribute index (derived from attribute name in startRender)
int mAttrNum;
bool mCounting;
@ -294,6 +321,8 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
QgsSymbolV2* symbolForValue( double value );
static const char * graduatedMethodStr( GraduatedMethod method );
};
#endif // QGSGRADUATEDSYMBOLRENDERERV2_H

View File

@ -397,6 +397,9 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date );
mExpressionWidget->setLayer( mLayer );
mSizeUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::MapUnit );
cboGraduatedColorRamp->populate( mStyle );
spinPrecision->setMinimum( QgsRendererRangeV2LabelFormat::MinPrecision );
@ -416,6 +419,20 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
mGraduatedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
methodComboBox->addItem( "Color" );
if ( mGraduatedSymbol->type() == QgsSymbolV2::Marker )
{
methodComboBox->addItem( "Size" );
minSizeSpinBox->setValue( 1 );
maxSizeSpinBox->setValue( 8 );
}
else if ( mGraduatedSymbol->type() == QgsSymbolV2::Line )
{
methodComboBox->addItem( "Size" );
minSizeSpinBox->setValue( .1 );
maxSizeSpinBox->setValue( 2 );
}
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) );
connect( viewGraduated, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( rangesDoubleClicked( const QModelIndex & ) ) );
connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) );
@ -428,6 +445,10 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
connect( btnGraduatedAdd, SIGNAL( clicked() ), this, SLOT( addClass() ) );
connect( cbxLinkBoundaries, SIGNAL( toggled( bool ) ), this, SLOT( toggleBoundariesLink( bool ) ) );
connect( mSizeUnitWidget, SIGNAL( changed() ), this, SLOT( on_mSizeUnitWidget_changed() ) );
connect( methodComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( on_methodComboBox_currentChanged( int ) ) );
connectUpdateHandlers();
// initialize from previously set renderer
@ -446,6 +467,16 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
btnAdvanced->setMenu( advMenu );
}
void QgsGraduatedSymbolRendererV2Widget::on_mSizeUnitWidget_changed()
{
if ( !mGraduatedSymbol ) return;
mGraduatedSymbol->setOutputUnit( mSizeUnitWidget->unit() );
mGraduatedSymbol->setMapUnitScale( mSizeUnitWidget->getMapUnitScale() );
updateGraduatedSymbolIcon();
mRenderer->updateSymbols( mGraduatedSymbol );
refreshSymbolView();
}
QgsGraduatedSymbolRendererV2Widget::~QgsGraduatedSymbolRendererV2Widget()
{
delete mRenderer;
@ -467,7 +498,10 @@ void QgsGraduatedSymbolRendererV2Widget::connectUpdateHandlers()
connect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ), this, SLOT( reapplyColorRamp() ) );
connect( spinPrecision, SIGNAL( valueChanged( int ) ), this, SLOT( labelFormatChanged() ) );
connect( cbxTrimTrailingZeroes, SIGNAL( toggled( bool ) ), this, SLOT( labelFormatChanged() ) );
connect( txtFormat, SIGNAL( textChanged( QString ) ), this, SLOT( labelFormatChanged() ) );
connect( txtLegendFormat, SIGNAL( textChanged( QString ) ), this, SLOT( labelFormatChanged() ) );
connect( minSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( reapplySizes() ) );
connect( maxSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( reapplySizes() ) );
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
connect( mModel, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ), this, SLOT( modelDataChanged() ) );
@ -483,7 +517,9 @@ void QgsGraduatedSymbolRendererV2Widget::disconnectUpdateHandlers()
disconnect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ), this, SLOT( reapplyColorRamp() ) );
disconnect( spinPrecision, SIGNAL( valueChanged( int ) ), this, SLOT( labelFormatChanged() ) );
disconnect( cbxTrimTrailingZeroes, SIGNAL( toggled( bool ) ), this, SLOT( labelFormatChanged() ) );
disconnect( txtFormat, SIGNAL( textChanged( QString ) ), this, SLOT( labelFormatChanged() ) );
disconnect( txtLegendFormat, SIGNAL( textChanged( QString ) ), this, SLOT( labelFormatChanged() ) );
disconnect( minSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( reapplySizes() ) );
disconnect( maxSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( reapplySizes() ) );
disconnect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
disconnect( mModel, SIGNAL( dataChanged( QModelIndex, QModelIndex ) ), this, SLOT( modelDataChanged() ) );
@ -516,20 +552,40 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer( bool updateCount
updateGraduatedSymbolIcon();
}
// set source color ramp
if ( mRenderer->sourceColorRamp() )
mModel->setRenderer( mRenderer );
viewGraduated->setModel( mModel );
if ( mGraduatedSymbol )
{
cboGraduatedColorRamp->setSourceColorRamp( mRenderer->sourceColorRamp() );
mSizeUnitWidget->blockSignals( true );
mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
mSizeUnitWidget->blockSignals( false );
}
// set source color ramp
if ( mRenderer->graduatedMethod() == QgsGraduatedSymbolRendererV2::GraduatedColor )
{
methodComboBox->setCurrentIndex( 0 );
if ( mRenderer->sourceColorRamp() )
cboGraduatedColorRamp->setSourceColorRamp( mRenderer->sourceColorRamp() );
cbxInvertedColorRamp->setChecked( mRenderer->invertedColorRamp() );
}
else
{
methodComboBox->setCurrentIndex( 1 );
if ( mRenderer->ranges().count() ) // avoid overiding default size with zeros
{
minSizeSpinBox->setValue( mRenderer->minSymbolSize() );
maxSizeSpinBox->setValue( mRenderer->maxSymbolSize() );
}
}
QgsRendererRangeV2LabelFormat labelFormat = mRenderer->labelFormat();
txtFormat->setText( labelFormat.format() );
txtLegendFormat->setText( labelFormat.format() );
spinPrecision->setValue( labelFormat.precision() );
cbxTrimTrailingZeroes->setChecked( labelFormat.trimTrailingZeroes() );
mModel->setRenderer( mRenderer );
viewGraduated->setModel( mModel );
viewGraduated->resizeColumnToContents( 0 );
viewGraduated->resizeColumnToContents( 1 );
viewGraduated->resizeColumnToContents( 2 );
@ -542,6 +598,32 @@ void QgsGraduatedSymbolRendererV2Widget::graduatedColumnChanged( QString field )
mRenderer->setClassAttribute( field );
}
void QgsGraduatedSymbolRendererV2Widget::on_methodComboBox_currentChanged( int idx )
{
stackedWidget->setCurrentIndex( idx );
if ( idx == 0 )
{
mRenderer->setGraduatedMethod( QgsGraduatedSymbolRendererV2::GraduatedColor );
QgsVectorColorRampV2* ramp = cboGraduatedColorRamp->currentColorRamp();
if ( ramp == NULL )
{
if ( cboGraduatedColorRamp->count() == 0 )
QMessageBox::critical( this, tr( "Error" ), tr( "There are no available color ramps. You can add them in Style Manager." ) );
else
QMessageBox::critical( this, tr( "Error" ), tr( "The selected color ramp is not available." ) );
return;
}
mRenderer->setSourceColorRamp( ramp->clone() );
reapplyColorRamp();
}
else
{
mRenderer->setGraduatedMethod( QgsGraduatedSymbolRendererV2::GraduatedSize );
reapplySizes();
}
}
void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
{
QString attrName = mExpressionWidget->currentField();
@ -582,10 +664,32 @@ void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
mRenderer->setClassAttribute( attrName );
mRenderer->setMode( mode );
mRenderer->setSourceColorRamp( ramp->clone() );
if ( methodComboBox->currentIndex() == 0 )
{
QgsVectorColorRampV2* ramp = cboGraduatedColorRamp->currentColorRamp();
if ( ramp == NULL )
{
if ( cboGraduatedColorRamp->count() == 0 )
QMessageBox::critical( this, tr( "Error" ), tr( "There are no available color ramps. You can add them in Style Manager." ) );
else
QMessageBox::critical( this, tr( "Error" ), tr( "The selected color ramp is not available." ) );
return;
}
mRenderer->setSourceColorRamp( ramp->clone() );
}
else
{
mRenderer->setSourceColorRamp( NULL );
}
QApplication::setOverrideCursor( Qt::WaitCursor );
mRenderer->updateClasses( mLayer, mode, nclasses );
if ( methodComboBox->currentIndex() == 1 )
mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
mRenderer->calculateLabelPrecision();
QApplication::restoreOverrideCursor();
// PrettyBreaks and StdDev calculation don't generate exact
@ -600,6 +704,14 @@ void QgsGraduatedSymbolRendererV2Widget::reapplyColorRamp()
return;
mRenderer->updateColorRamp( ramp, cbxInvertedColorRamp->isChecked() );
mRenderer->updateSymbols( mGraduatedSymbol );
refreshSymbolView();
}
void QgsGraduatedSymbolRendererV2Widget::reapplySizes()
{
mRenderer->setSymbolSizes( minSizeSpinBox->value(), maxSizeSpinBox->value() );
mRenderer->updateSymbols( mGraduatedSymbol );
refreshSymbolView();
}
@ -626,6 +738,11 @@ void QgsGraduatedSymbolRendererV2Widget::changeGraduatedSymbol()
mGraduatedSymbol = newSymbol;
mSizeUnitWidget->blockSignals( true );
mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() );
mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() );
mSizeUnitWidget->blockSignals( false );
updateGraduatedSymbolIcon();
mRenderer->updateSymbols( mGraduatedSymbol );
refreshSymbolView();
@ -857,7 +974,7 @@ void QgsGraduatedSymbolRendererV2Widget::scaleMethodChanged( QgsSymbolV2::ScaleM
void QgsGraduatedSymbolRendererV2Widget::labelFormatChanged()
{
QgsRendererRangeV2LabelFormat labelFormat = QgsRendererRangeV2LabelFormat(
txtFormat->text(),
txtLegendFormat->text(),
spinPrecision->value(),
cbxTrimTrailingZeroes->isChecked() );
mRenderer->setLabelFormat( labelFormat, true );

View File

@ -86,6 +86,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
void graduatedColumnChanged( QString field );
void classifyGraduated();
void reapplyColorRamp();
void reapplySizes();
void rangesDoubleClicked( const QModelIndex & idx );
void rangesClicked( const QModelIndex & idx );
void changeCurrentValue( QStandardItem * item );
@ -108,6 +109,8 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
void rowsMoved();
void modelDataChanged();
void on_mSizeUnitWidget_changed();
void on_methodComboBox_currentChanged( int );
protected:
void updateUiFromRenderer( bool updateCount = true );

View File

@ -6,20 +6,130 @@
<rect>
<x>0</x>
<y>0</y>
<width>647</width>
<height>339</height>
<width>759</width>
<height>638</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0" 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>
<item row="0" column="0" colspan="4">
<layout class="QGridLayout">
<property name="rightMargin">
<number>6</number>
</property>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Column</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Precision</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>spinPrecision</cstring>
</property>
</widget>
</item>
<item row="6" column="3">
<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="4" column="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Mode</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>cboGraduatedMode</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QgsFieldExpressionWidget" name="mExpressionWidget" native="true">
<property name="minimumSize">
<size>
<width>10</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<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 row="5" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QSpinBox" name="spinPrecision">
@ -57,41 +167,17 @@ Negative rounds to powers of 10</string>
</item>
</layout>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="txtFormat">
<property name="toolTip">
<string>Template for the legend text associated with each classification.
Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot; for the upper bound.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Mode</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>cboGraduatedMode</cstring>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Color ramp</string>
<string>Symbol</string>
</property>
<property name="buddy">
<cstring>cboGraduatedColorRamp</cstring>
<cstring>btnChangeGraduatedSymbol</cstring>
</property>
</widget>
</item>
<item row="5" column="3">
<item row="4" column="3">
<widget class="QComboBox" name="cboGraduatedMode">
<item>
<property name="text">
@ -120,118 +206,21 @@ Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot;
</item>
</widget>
</item>
<item row="4" 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="4" column="1">
<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="4" column="3">
<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="4" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Classes</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>spinGraduatedClasses</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QgsColorRampComboBox" name="cboGraduatedColorRamp"/>
</item>
<item>
<widget class="QCheckBox" name="cbxInvertedColorRamp">
<property name="text">
<string>Invert</string>
<widget class="QLineEdit" name="txtLegendFormat">
<property name="toolTip">
<string>Template for the legend text associated with each classification.
Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot; for the upper bound.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Column</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QgsFieldExpressionWidget" name="mExpressionWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<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 row="6" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -241,51 +230,49 @@ Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot;
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>txtFormat</cstring>
<cstring>txtLegendFormat</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<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="6" column="2">
<widget class="QLabel" name="label_16">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Precision</string>
<string>Classes</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>spinPrecision</cstring>
<cstring>spinGraduatedClasses</cstring>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Method</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="methodComboBox"/>
</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>
<item row="3" column="0" colspan="4">
<layout class="QHBoxLayout" name="_2">
<item>
<widget class="QPushButton" name="btnGraduatedClassify">
@ -347,6 +334,123 @@ Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot;
</item>
</layout>
</item>
<item row="1" column="3">
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="3">
<widget class="QCheckBox" name="cbxInvertedColorRamp">
<property name="text">
<string>Invert</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Color ramp</string>
</property>
<property name="buddy">
<cstring>cboGraduatedColorRamp</cstring>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QgsColorRampComboBox" name="cboGraduatedColorRamp"/>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>208</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="minSizeSpinBox">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QDoubleSpinBox" name="maxSizeSpinBox">
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QgsUnitSelectionWidget" name="mSizeUnitWidget" native="true">
<property name="minimumSize">
<size>
<width>14</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>to</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Size from </string>
</property>
<property name="buddy">
<cstring>cboGraduatedColorRamp</cstring>
</property>
</widget>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>190</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -361,16 +465,22 @@ Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot;
<header location="global">qgsfieldexpressionwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsUnitSelectionWidget</class>
<extends>QWidget</extends>
<header>qgsunitselectionwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cboGraduatedMode</tabstop>
<tabstop>btnChangeGraduatedSymbol</tabstop>
<tabstop>spinPrecision</tabstop>
<tabstop>cbxTrimTrailingZeroes</tabstop>
<tabstop>txtLegendFormat</tabstop>
<tabstop>spinGraduatedClasses</tabstop>
<tabstop>cboGraduatedColorRamp</tabstop>
<tabstop>cbxInvertedColorRamp</tabstop>
<tabstop>cboGraduatedMode</tabstop>
<tabstop>txtFormat</tabstop>
<tabstop>spinPrecision</tabstop>
<tabstop>cbxTrimTrailingZeroes</tabstop>
<tabstop>viewGraduated</tabstop>
<tabstop>btnGraduatedClassify</tabstop>
<tabstop>btnGraduatedAdd</tabstop>
@ -378,6 +488,9 @@ Use &quot;%1&quot; for the lower bound of the classification, and &quot;%2&quot;
<tabstop>btnDeleteAllClasses</tabstop>
<tabstop>cbxLinkBoundaries</tabstop>
<tabstop>btnAdvanced</tabstop>
<tabstop>mSizeUnitWidget</tabstop>
<tabstop>minSizeSpinBox</tabstop>
<tabstop>maxSizeSpinBox</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@ -334,6 +334,18 @@ class TestQgsGraduatedSymbolRendererV2(TestCase):
renderer.setScaleMethod(sm)
self.assertEqual(str(sm),str(renderer.scaleMethod()),
"Get/set renderer scale method")
# test for classificatio with varying size
renderer.setGraduatedMethod(QgsGraduatedSymbolRendererV2.GraduatedSize)
renderer.setSourceColorRamp(None)
renderer.addClassLowerUpper(0, 2)
renderer.addClassLowerUpper(2, 4)
renderer.addClassLowerUpper(4, 6)
renderer.setSymbolSizes(2,13)
self.assertEqual(renderer.maxSymbolSize(), 13)
self.assertEqual(renderer.minSymbolSize(), 2)
refSizes = [2, (13+2)*.5, 13]
for idx, symbol in enumerate(renderer.symbols()):
self.assertEqual(symbol.size(), refSizes[idx])