Skip to content

Commit 0c6576c

Browse files
committedSep 26, 2014
Merge pull request #1587 from ccrook/CategorizedRendererUpdate
Categorized and graduated renderer enhancements
2 parents b734e87 + b558c08 commit 0c6576c

15 files changed

+843
-223
lines changed
 

‎python/core/symbology-ng/qgscategorizedsymbolrendererv2.sip

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
122122
bool invertedColorRamp();
123123
void setInvertedColorRamp( bool inverted );
124124

125+
// Update the color ramp used and all symbols colors.
126+
//! @note added in 2.5
127+
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
128+
125129
//! @note added in 1.6
126130
void setRotationField( QString fieldOrExpression );
127131
//! @note added in 1.6
@@ -149,6 +153,10 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
149153
// @note added in 2.5
150154
virtual void checkLegendSymbolItem( QString key, bool state = true );
151155

156+
//! If supported by the renderer, return classification attribute for the use in legend
157+
//! @note added in 2.6
158+
virtual QString legendClassificationAttribute() const;
159+
152160
//! creates a QgsCategorizedSymbolRendererV2 from an existing renderer.
153161
//! @note added in 2.5
154162
//! @returns a new renderer if the conversion was possible, otherwise 0.

‎python/core/symbology-ng/qgsgraduatedsymbolrendererv2.sip

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ class QgsRendererRangeV2
55
%End
66

77
public:
8-
QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol /Transfer/, QString label, bool render = true );
8+
QgsRendererRangeV2();
9+
QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol, QString label, bool render = true );
910
QgsRendererRangeV2( const QgsRendererRangeV2& range );
1011

1112
// default dtor is ok
@@ -38,6 +39,42 @@ class QgsRendererRangeV2
3839

3940
typedef QList<QgsRendererRangeV2> QgsRangeList;
4041

42+
class QgsRendererRangeV2LabelFormat
43+
{
44+
%TypeHeaderCode
45+
#include <qgsgraduatedsymbolrendererv2.h>
46+
%End
47+
public:
48+
QgsRendererRangeV2LabelFormat();
49+
QgsRendererRangeV2LabelFormat( QString prefix, QString separator, QString suffix, int decimalPlaces=4, bool trimTrailingZeroes=false );
50+
51+
bool operator==( const QgsRendererRangeV2LabelFormat & other ) const;
52+
bool operator!=( const QgsRendererRangeV2LabelFormat & other ) const;
53+
54+
QString prefix() const;
55+
void setPrefix( QString prefix );
56+
57+
QString separator() const;
58+
void setSeparator( QString separator );
59+
60+
QString suffix() const;
61+
void setSuffix( QString suffix );
62+
63+
int decimalPlaces() const;
64+
void setDecimalPlaces( int decimalPlaces );
65+
66+
bool trimTrailingZeroes() const;
67+
void setTrimTrailingZeroes( bool trimTrailingZeroes );
68+
69+
//! @note labelForLowerUpper in python bindings
70+
QString labelForRange( double lower, double upper ) /PyName=labelForLowerUpper/;
71+
QString labelForRange( const QgsRendererRangeV2 &range );
72+
73+
void setFromDomElement( QDomElement &element );
74+
void saveToDomElement( QDomElement &element );
75+
};
76+
77+
4178
class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
4279
{
4380
%TypeHeaderCode
@@ -86,6 +123,8 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
86123
void addClass( QgsSymbolV2* symbol );
87124
//! @note available in python bindings as addClassRange
88125
void addClass( QgsRendererRangeV2 range ) /PyName=addClassRange/;
126+
//! @note available in python bindings as addClassLowerUpper
127+
void addClass( double lower, double upper ) /PyName=addClassLowerUpper/;
89128
void deleteClass( int idx );
90129
void deleteAllClasses();
91130

@@ -107,6 +146,30 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
107146

108147
Mode mode() const;
109148
void setMode( Mode mode );
149+
//! Recalculate classes for a layer
150+
//! @param vlayer The layer being rendered (from which data values are calculated)
151+
//! @param mode The calculation mode
152+
//! @param nclasses The number of classes to calculate (approximate for some modes)
153+
//! @note Added in 2.6
154+
void updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses );
155+
//! Evaluates the data expression and returns the list of values from the layer
156+
//! @param vlayer The layer for which to evaluate the expression
157+
//! @note Added in 2.6
158+
QList<double> getDataValues( QgsVectorLayer *vlayer );
159+
160+
//! Return the label format used to generate default classification labels
161+
//! @note Added in 2.6
162+
const QgsRendererRangeV2LabelFormat &labelFormat();
163+
//! Set the label format used to generate default classification labels
164+
//! @param labelFormat The string appended to classification labels
165+
//! @param updateRanges If true then ranges ending with the old unit string are updated to the new.
166+
//! @note Added in 2.6
167+
void setLabelFormat( const QgsRendererRangeV2LabelFormat &labelFormat, bool updateRanges=true );
168+
169+
//! Reset the label decimal places to a numberbased on the minimum class interval
170+
//! @param updateRanges if true then ranges currently using the default label will be updated
171+
//! @note Added in 2.6
172+
void calculateLabelDecimalPlaces( bool updateRanges=true );
110173

111174
static QgsGraduatedSymbolRendererV2* createRenderer(
112175
QgsVectorLayer* vlayer,
@@ -115,7 +178,9 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
115178
Mode mode,
116179
QgsSymbolV2* symbol /Transfer/,
117180
QgsVectorColorRampV2* ramp /Transfer/,
118-
bool inverted = false ) /Factory/;
181+
bool inverted = false,
182+
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat()
183+
);
119184

120185
//! create renderer from XML element
121186
static QgsFeatureRendererV2* create( QDomElement& element ) /Factory/;
@@ -143,9 +208,9 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
143208
/** Update the color ramp used. Also updates all symbols colors.
144209
* Doesn't alter current breaks.
145210
*/
146-
void updateColorRamp( QgsVectorColorRampV2* ramp /Transfer/ );
211+
void updateColorRamp( QgsVectorColorRampV2* ramp /Transfer/ = 0, bool inverted = false );
147212

148-
/** Update the all symbols but leave breaks and colors. */
213+
/** Update all the symbols but leave breaks and colors. */
149214
void updateSymbols( QgsSymbolV2* sym /Transfer/ );
150215

151216
//! @note added in 1.6
@@ -175,6 +240,10 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
175240
// @note added in 2.5
176241
virtual void checkLegendSymbolItem( QString key, bool state = true );
177242

243+
//! If supported by the renderer, return classification attribute for the use in legend
244+
//! @note added in 2.6
245+
virtual QString legendClassificationAttribute();
246+
178247
//! creates a QgsGraduatedSymbolRendererV2 from an existing renderer.
179248
//! @note added in 2.5
180249
//! @returns a new renderer if the conversion was possible, otherwise 0.

‎python/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.sip

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class QgsCategorizedSymbolRendererV2Widget : QgsRendererV2Widget
1818
void categoriesDoubleClicked( const QModelIndex & idx );
1919
void addCategory();
2020
void addCategories();
21+
void applyColorRamp();
2122
void deleteCategories();
2223
void deleteAllCategories();
2324

@@ -49,6 +50,8 @@ class QgsCategorizedSymbolRendererV2Widget : QgsRendererV2Widget
4950

5051
void changeCategorySymbol();
5152

53+
QgsVectorColorRampV2* getColorRamp();
54+
5255
QList<QgsSymbolV2*> selectedSymbols();
5356
QgsCategoryList selectedCategoryList();
5457
void refreshSymbolView();

‎python/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.sip

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,24 @@ class QgsGraduatedSymbolRendererV2Widget : QgsRendererV2Widget
2626
void deleteClasses();
2727
/**Removes all classes from the classification*/
2828
void deleteAllClasses();
29+
/**Toggle the link between classes boundaries */
30+
void toggleBoundariesLink( bool linked );
2931

3032
void rotationFieldChanged( QString fldName );
3133
void sizeScaleFieldChanged( QString fldName );
3234
void scaleMethodChanged( QgsSymbolV2::ScaleMethod scaleMethod );
35+
void labelFormatChanged();
3336

3437
void showSymbolLevels();
3538

3639
void rowsMoved();
40+
void modelDataChanged();
3741

3842
protected:
39-
void updateUiFromRenderer();
43+
void updateUiFromRenderer( bool updateCount=true );
44+
void connectUpdateHandlers();
45+
void disconnectUpdateHandlers();
46+
bool rowsOrdered();
4047

4148
void updateGraduatedSymbolIcon();
4249

‎src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ void QgsCategorizedSymbolRendererV2::rebuildHash()
168168
{
169169
mSymbolHash.clear();
170170

171-
for ( int i = 0; i < mCategories.count(); ++i )
171+
for ( int i = 0; i < mCategories.size(); ++i )
172172
{
173173
QgsRendererCategoryV2& cat = mCategories[i];
174174
mSymbolHash.insert( cat.value().toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : &sSkipRender );
@@ -181,7 +181,7 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
181181
QHash<QString, QgsSymbolV2*>::iterator it = mSymbolHash.find( value.toString() );
182182
if ( it == mSymbolHash.end() )
183183
{
184-
if ( mSymbolHash.count() == 0 )
184+
if ( mSymbolHash.size() == 0 )
185185
{
186186
QgsDebugMsg( "there are no hashed symbols!!!" );
187187
}
@@ -700,11 +700,27 @@ QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2::sourceColorRamp()
700700
{
701701
return mSourceColorRamp.data();
702702
}
703+
703704
void QgsCategorizedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ramp )
704705
{
705706
mSourceColorRamp.reset( ramp );
706707
}
707708

709+
void QgsCategorizedSymbolRendererV2::updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted )
710+
{
711+
setSourceColorRamp(ramp);
712+
setInvertedColorRamp(inverted);
713+
double num=mCategories.count()-1;
714+
double count = 0;
715+
foreach ( const QgsRendererCategoryV2 &cat, mCategories )
716+
{
717+
double value=count/num;
718+
if( mInvertedColorRamp ) value=1.0-value;
719+
cat.symbol()->setColor(mSourceColorRamp->color(value));
720+
count += 1;
721+
}
722+
}
723+
708724
void QgsCategorizedSymbolRendererV2::setRotationField( QString fieldOrExpression )
709725
{
710726
mRotation.reset( QgsSymbolLayerV2Utils::fieldOrExpressionToExpression( fieldOrExpression ) );
@@ -788,5 +804,16 @@ QgsCategorizedSymbolRendererV2* QgsCategorizedSymbolRendererV2::convertFromRende
788804
const QgsInvertedPolygonRenderer* invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer*>( renderer );
789805
return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
790806
}
791-
return 0;
807+
808+
// If not one of the specifically handled renderers, then just grab the symbol from the renderer
809+
// Could have applied this to specific renderer types (singleSymbol, graduatedSymbo)
810+
811+
QgsCategorizedSymbolRendererV2* r =new QgsCategorizedSymbolRendererV2( "", QgsCategoryList() );
812+
QgsSymbolV2List symbols=const_cast<QgsFeatureRendererV2 *>(renderer)->symbols();
813+
if( symbols.size() > 0 )
814+
{
815+
r->setSourceSymbol(symbols.at(0)->clone());
816+
}
817+
return r;
818+
792819
}

‎src/core/symbology-ng/qgscategorizedsymbolrendererv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
152152
bool invertedColorRamp() { return mInvertedColorRamp; }
153153
void setInvertedColorRamp( bool inverted ) { mInvertedColorRamp = inverted; }
154154

155+
// Update the color ramp used and all symbols colors.
156+
//! @note added in 2.5
157+
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
158+
155159
//! @note added in 1.6
156160
void setRotationField( QString fieldOrExpression );
157161
//! @note added in 1.6

‎src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp

Lines changed: 270 additions & 70 deletions
Large diffs are not rendered by default.

‎src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgsrendererv2.h"
2020
#include "qgsexpression.h"
2121
#include <QScopedPointer>
22+
#include <QRegExp>
2223

2324
class CORE_EXPORT QgsRendererRangeV2
2425
{
@@ -30,6 +31,8 @@ class CORE_EXPORT QgsRendererRangeV2
3031
// default dtor is ok
3132
QgsRendererRangeV2& operator=( QgsRendererRangeV2 range );
3233

34+
bool operator<( const QgsRendererRangeV2 &other ) const;
35+
3336
double lowerValue() const;
3437
double upperValue() const;
3538

@@ -62,6 +65,48 @@ class CORE_EXPORT QgsRendererRangeV2
6265

6366
typedef QList<QgsRendererRangeV2> QgsRangeList;
6467

68+
69+
// @note added in 2.6
70+
class CORE_EXPORT QgsRendererRangeV2LabelFormat
71+
{
72+
public:
73+
QgsRendererRangeV2LabelFormat();
74+
QgsRendererRangeV2LabelFormat( QString prefix, QString separator, QString suffix, int decimalPlaces=4, bool trimTrailingZeroes=false );
75+
76+
bool operator==( const QgsRendererRangeV2LabelFormat & other ) const;
77+
bool operator!=( const QgsRendererRangeV2LabelFormat & other ) const;
78+
79+
QString prefix() const { return mPrefix; }
80+
void setPrefix( QString prefix ) { mPrefix=prefix; }
81+
82+
QString separator() const { return mSeparator; }
83+
void setSeparator( QString separator ) { mSeparator=separator; }
84+
85+
QString suffix() const { return mSuffix; }
86+
void setSuffix( QString suffix ){ mSuffix=suffix; }
87+
88+
int decimalPlaces() const { return mDecimalPlaces; }
89+
void setDecimalPlaces( int decimalPlaces );
90+
91+
bool trimTrailingZeroes() const { return mTrimTrailingZeroes; }
92+
void setTrimTrailingZeroes( bool trimTrailingZeroes ){ mTrimTrailingZeroes=trimTrailingZeroes; }
93+
94+
//! @note labelForLowerUpper in python bindings
95+
QString labelForRange( double lower, double upper ) const;
96+
QString labelForRange( const QgsRendererRangeV2 &range ) const;
97+
98+
void setFromDomElement( QDomElement &element );
99+
void saveToDomElement( QDomElement &element );
100+
101+
protected:
102+
QString mPrefix;
103+
QString mSeparator;
104+
QString mSuffix;
105+
int mDecimalPlaces;
106+
bool mTrimTrailingZeroes;
107+
QRegExp mReTrailingZeroes;
108+
};
109+
65110
class QgsVectorLayer;
66111
class QgsVectorColorRampV2;
67112

@@ -107,10 +152,11 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
107152
//! @note added in 2.5
108153
bool updateRangeRenderState( int rangeIndex, bool render );
109154

110-
111155
void addClass( QgsSymbolV2* symbol );
112156
//! @note available in python bindings as addClassRange
113157
void addClass( QgsRendererRangeV2 range );
158+
//! @note available in python bindings as addClassLowerUpper
159+
void addClass( double lower, double upper );
114160
void deleteClass( int idx );
115161
void deleteAllClasses();
116162

@@ -132,6 +178,30 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
132178

133179
Mode mode() const { return mMode; }
134180
void setMode( Mode mode ) { mMode = mode; }
181+
//! Recalculate classes for a layer
182+
//! @param vlayer The layer being rendered (from which data values are calculated)
183+
//! @param mode The calculation mode
184+
//! @param nclasses The number of classes to calculate (approximate for some modes)
185+
//! @note Added in 2.6
186+
void updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses );
187+
//! Evaluates the data expression and returns the list of values from the layer
188+
//! @param vlayer The layer for which to evaluate the expression
189+
//! @note Added in 2.6
190+
QList<double> getDataValues( QgsVectorLayer *vlayer );
191+
192+
//! Return the label format used to generate default classification labels
193+
//! @note Added in 2.6
194+
const QgsRendererRangeV2LabelFormat &labelFormat() const { return mLabelFormat; }
195+
//! Set the label format used to generate default classification labels
196+
//! @param labelFormat The string appended to classification labels
197+
//! @param updateRanges If true then ranges ending with the old unit string are updated to the new.
198+
//! @note Added in 2.6
199+
void setLabelFormat( const QgsRendererRangeV2LabelFormat &labelFormat, bool updateRanges=true );
200+
201+
//! Reset the label decimal places to a numberbased on the minimum class interval
202+
//! @param updateRanges if true then ranges currently using the default label will be updated
203+
//! @note Added in 2.6
204+
void calculateLabelDecimalPlaces( bool updateRanges=true );
135205

136206
static QgsGraduatedSymbolRendererV2* createRenderer(
137207
QgsVectorLayer* vlayer,
@@ -140,7 +210,9 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
140210
Mode mode,
141211
QgsSymbolV2* symbol,
142212
QgsVectorColorRampV2* ramp,
143-
bool inverted = false );
213+
bool inverted = false,
214+
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat()
215+
);
144216

145217
//! create renderer from XML element
146218
static QgsFeatureRendererV2* create( QDomElement& element );
@@ -168,7 +240,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
168240
/** Update the color ramp used. Also updates all symbols colors.
169241
* Doesn't alter current breaks.
170242
*/
171-
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
243+
void updateColorRamp( QgsVectorColorRampV2* ramp=0, bool inverted = false );
172244

173245
/** Update all the symbols but leave breaks and colors. */
174246
void updateSymbols( QgsSymbolV2* sym );
@@ -193,19 +265,19 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
193265
virtual bool legendSymbolItemsCheckable() const;
194266

195267
//! item in symbology was checked
196-
// @note added in 2.5
268+
//! @note added in 2.6
197269
virtual bool legendSymbolItemChecked( QString key );
198270

199271
//! item in symbology was checked
200-
// @note added in 2.5
272+
//! @note added in 2.6
201273
virtual void checkLegendSymbolItem( QString key, bool state = true );
202274

203275
//! If supported by the renderer, return classification attribute for the use in legend
204276
//! @note added in 2.6
205277
virtual QString legendClassificationAttribute() const { return classAttribute(); }
206278

207279
//! creates a QgsGraduatedSymbolRendererV2 from an existing renderer.
208-
//! @note added in 2.5
280+
//! @note added in 2.6
209281
//! @returns a new renderer if the conversion was possible, otherwise 0.
210282
static QgsGraduatedSymbolRendererV2* convertFromRenderer( const QgsFeatureRendererV2 *renderer );
211283

@@ -216,6 +288,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
216288
QScopedPointer<QgsSymbolV2> mSourceSymbol;
217289
QScopedPointer<QgsVectorColorRampV2> mSourceColorRamp;
218290
bool mInvertedColorRamp;
291+
QgsRendererRangeV2LabelFormat mLabelFormat;
219292
QScopedPointer<QgsExpression> mRotation;
220293
QScopedPointer<QgsExpression> mSizeScale;
221294
QgsSymbolV2::ScaleMethod mScaleMethod;

‎src/core/symbology-ng/qgssinglesymbolrendererv2.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,5 +399,11 @@ QgsSingleSymbolRendererV2* QgsSingleSymbolRendererV2::convertFromRenderer( const
399399
return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
400400

401401
}
402+
403+
QgsSymbolV2List symbols=const_cast<QgsFeatureRendererV2 *>(renderer)->symbols();
404+
if( symbols.size() > 0 )
405+
{
406+
return new QgsSingleSymbolRendererV2(symbols.at(0)->clone());
407+
}
402408
return 0;
403409
}

‎src/gui/qgsattributetypeloaddialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,4 @@ void QgsAttributeTypeLoadDialog::accept()
202202
//store data to output variable
203203
loadDataToValueMap();
204204
QDialog::accept();
205-
}
205+
}

‎src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ void QgsCategorizedSymbolRendererV2Model::sort( int column, Qt::SortOrder order
338338
QgsDebugMsg( "Done" );
339339
}
340340

341+
void QgsCategorizedSymbolRendererV2Model::updateSymbology()
342+
{
343+
emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
344+
}
345+
341346
// ------------------------------ View style --------------------------------
342347
QgsCategorizedSymbolRendererV2ViewStyle::QgsCategorizedSymbolRendererV2ViewStyle( QStyle* style )
343348
: QProxyStyle( style )
@@ -405,17 +410,21 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
405410
cboCategorizedColorRamp->setCurrentIndex( index );
406411
}
407412

413+
mCategorizedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
414+
408415
mModel = new QgsCategorizedSymbolRendererV2Model( this );
409416
mModel->setRenderer( mRenderer );
417+
418+
// update GUI from renderer
419+
updateUiFromRenderer();
420+
410421
viewCategories->setModel( mModel );
411422
viewCategories->resizeColumnToContents( 0 );
412423
viewCategories->resizeColumnToContents( 1 );
413424
viewCategories->resizeColumnToContents( 2 );
414425

415426
viewCategories->setStyle( new QgsCategorizedSymbolRendererV2ViewStyle( viewCategories->style() ) );
416427

417-
mCategorizedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
418-
419428
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
420429

421430
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
@@ -428,9 +437,8 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
428437
connect( btnDeleteCategories, SIGNAL( clicked() ), this, SLOT( deleteCategories() ) );
429438
connect( btnDeleteAllCategories, SIGNAL( clicked() ), this, SLOT( deleteAllCategories() ) );
430439
connect( btnAddCategory, SIGNAL( clicked() ), this, SLOT( addCategory() ) );
431-
432-
// update GUI from renderer
433-
updateUiFromRenderer();
440+
connect( cbxInvertedColorRamp, SIGNAL( toggled(bool)), this, SLOT( applyColorRamp()));
441+
connect( cboCategorizedColorRamp, SIGNAL(currentIndexChanged(int)), this, SLOT( applyColorRamp()));
434442

435443
// menus for data-defined rotation/size
436444
QMenu* advMenu = new QMenu;
@@ -453,16 +461,17 @@ QgsCategorizedSymbolRendererV2Widget::~QgsCategorizedSymbolRendererV2Widget()
453461

454462
void QgsCategorizedSymbolRendererV2Widget::updateUiFromRenderer()
455463
{
464+
// Note: This assumes that the signals for UI element changes have not
465+
// yet been connected, so that the updates to color ramp, symbol, etc
466+
// don't override existing customisations.
467+
456468
updateCategorizedSymbolIcon();
457469

458470
//mModel->setRenderer ( mRenderer ); // necessary?
459471

460472
// set column
461-
disconnect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
462473
QString attrName = mRenderer->classAttribute();
463474
mExpressionWidget->setField( attrName );
464-
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
465-
466475

467476
// set source symbol
468477
if ( mRenderer->sourceSymbol() )
@@ -585,7 +594,7 @@ void QgsCategorizedSymbolRendererV2Widget::changeCategorySymbol()
585594
mRenderer->updateCategorySymbol( catIdx, symbol );
586595
}
587596

588-
static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, QgsSymbolV2* symbol, QgsVectorColorRampV2* ramp, bool invert )
597+
static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, QgsSymbolV2* symbol )
589598
{
590599
// sort the categories first
591600
QgsSymbolLayerV2Utils::sortVariantList( values, Qt::AscendingOrder );
@@ -612,9 +621,7 @@ static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, Q
612621
{
613622
hasNull = true;
614623
}
615-
double x = ( invert ? num - i : i ) / ( double ) num;
616624
QgsSymbolV2* newSymbol = symbol->clone();
617-
newSymbol->setColor( ramp->color( x ) );
618625

619626
cats.append( QgsRendererCategoryV2( value, newSymbol, value.toString(), true ) );
620627
}
@@ -623,11 +630,24 @@ static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, Q
623630
if ( !hasNull )
624631
{
625632
QgsSymbolV2* newSymbol = symbol->clone();
626-
newSymbol->setColor( ramp->color( invert ? 0 : 1 ) );
627633
cats.append( QgsRendererCategoryV2( QVariant( "" ), newSymbol, QString(), true ) );
628634
}
629635
}
630636

637+
QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2Widget::getColorRamp()
638+
{
639+
QgsVectorColorRampV2* ramp = cboCategorizedColorRamp->currentColorRamp();
640+
if ( ramp == NULL )
641+
{
642+
if ( cboCategorizedColorRamp->count() == 0 )
643+
QMessageBox::critical( this, tr( "Error" ), tr( "There are no available color ramps. You can add them in Style Manager." ) );
644+
else
645+
QMessageBox::critical( this, tr( "Error" ), tr( "The selected color ramp is not available." ) );
646+
}
647+
return ramp;
648+
}
649+
650+
631651
void QgsCategorizedSymbolRendererV2Widget::addCategories()
632652
{
633653
QString attrName = mExpressionWidget->currentField();
@@ -672,20 +692,8 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
672692
return;
673693
#endif
674694

675-
QgsVectorColorRampV2* ramp = cboCategorizedColorRamp->currentColorRamp();
676-
677-
if ( ramp == NULL )
678-
{
679-
if ( cboCategorizedColorRamp->count() == 0 )
680-
QMessageBox::critical( this, tr( "Error" ), tr( "There are no available color ramps. You can add them in Style Manager." ) );
681-
else
682-
QMessageBox::critical( this, tr( "Error" ), tr( "The selected color ramp is not available." ) );
683-
return;
684-
}
685-
686695
QgsCategoryList cats;
687-
_createCategories( cats, unique_vals, mCategorizedSymbol, ramp, cbxInvertedColorRamp->isChecked() );
688-
696+
_createCategories( cats, unique_vals, mCategorizedSymbol );
689697
bool deleteExisting = false;
690698

691699
if ( !mOldClassificationAttribute.isEmpty() &&
@@ -706,9 +714,12 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
706714
deleteExisting = ( res == QMessageBox::Yes );
707715
}
708716

717+
// First element to apply coloring to
718+
bool keepExistingColors=false;
709719
if ( !deleteExisting )
710720
{
711721
QgsCategoryList prevCats = mRenderer->categories();
722+
keepExistingColors=prevCats.size() > 0;
712723
for ( int i = 0; i < cats.size(); ++i )
713724
{
714725
bool contains = false;
@@ -747,18 +758,30 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
747758
// recreate renderer
748759
QgsCategorizedSymbolRendererV2 *r = new QgsCategorizedSymbolRendererV2( attrName, cats );
749760
r->setSourceSymbol( mCategorizedSymbol->clone() );
750-
r->setSourceColorRamp( ramp->clone() );
751761
r->setScaleMethod( mRenderer->scaleMethod() );
752762
r->setSizeScaleField( mRenderer->sizeScaleField() );
753763
r->setRotationField( mRenderer->rotationField() );
754764
r->setInvertedColorRamp( cbxInvertedColorRamp->isChecked() );
765+
QgsVectorColorRampV2* ramp = getColorRamp();
766+
if( ramp ) r->setSourceColorRamp(ramp->clone());
755767

756768
if ( mModel )
757769
{
758770
mModel->setRenderer( r );
759771
}
760772
delete mRenderer;
761773
mRenderer = r;
774+
if( ! keepExistingColors && ramp ) applyColorRamp();
775+
}
776+
777+
void QgsCategorizedSymbolRendererV2Widget::applyColorRamp()
778+
{
779+
QgsVectorColorRampV2* ramp = getColorRamp();
780+
if( ramp )
781+
{
782+
mRenderer->updateColorRamp(ramp->clone(),cbxInvertedColorRamp->isChecked());
783+
}
784+
mModel->updateSymbology();
762785
}
763786

764787
int QgsCategorizedSymbolRendererV2Widget::currentCategoryRow()

‎src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Model : public QAbstractItemModel
5050
void deleteRows( QList<int> rows );
5151
void removeAllRows( );
5252
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
53+
void updateSymbology();
5354

5455
signals:
5556
void rowsMoved();
@@ -85,6 +86,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg
8586
void categoriesDoubleClicked( const QModelIndex & idx );
8687
void addCategory();
8788
void addCategories();
89+
void applyColorRamp();
8890
void deleteCategories();
8991
void deleteAllCategories();
9092

@@ -116,6 +118,8 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg
116118

117119
void changeCategorySymbol();
118120

121+
QgsVectorColorRampV2* getColorRamp();
122+
119123
QList<QgsSymbolV2*> selectedSymbols();
120124
QgsCategoryList selectedCategoryList();
121125
void refreshSymbolView() { populateCategories(); }

‎src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp

Lines changed: 146 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,16 @@ void QgsGraduatedSymbolRendererV2Model::sort( int column, Qt::SortOrder order )
330330
QgsDebugMsg( "Done" );
331331
}
332332

333+
void QgsGraduatedSymbolRendererV2Model::updateSymbology()
334+
{
335+
emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
336+
}
337+
338+
void QgsGraduatedSymbolRendererV2Model::updateLabels()
339+
{
340+
emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
341+
}
342+
333343
// ------------------------------ View style --------------------------------
334344
QgsGraduatedSymbolRendererV2ViewStyle::QgsGraduatedSymbolRendererV2ViewStyle( QStyle* style )
335345
: QProxyStyle( style )
@@ -391,12 +401,6 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
391401
cboGraduatedColorRamp->setCurrentIndex( index );
392402
}
393403

394-
mModel = new QgsGraduatedSymbolRendererV2Model( this );
395-
mModel->setRenderer( mRenderer );
396-
viewGraduated->setModel( mModel );
397-
viewGraduated->resizeColumnToContents( 0 );
398-
viewGraduated->resizeColumnToContents( 1 );
399-
viewGraduated->resizeColumnToContents( 2 );
400404

401405
viewGraduated->setStyle( new QgsGraduatedSymbolRendererV2ViewStyle( viewGraduated->style() ) );
402406

@@ -407,22 +411,18 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
407411
connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) );
408412
connect( viewGraduated, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) );
409413

410-
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
411-
412414
connect( btnGraduatedClassify, SIGNAL( clicked() ), this, SLOT( classifyGraduated() ) );
413415
connect( btnChangeGraduatedSymbol, SIGNAL( clicked() ), this, SLOT( changeGraduatedSymbol() ) );
414416
connect( btnGraduatedDelete, SIGNAL( clicked() ), this, SLOT( deleteClasses() ) );
415417
connect( btnDeleteAllClasses, SIGNAL( clicked() ), this, SLOT( deleteAllClasses() ) );
416418
connect( btnGraduatedAdd, SIGNAL( clicked() ), this, SLOT( addClass() ) );
417419
connect( cbxLinkBoundaries, SIGNAL( toggled( bool ) ), this, SLOT( toggleBoundariesLink( bool ) ) );
418420

421+
connectUpdateHandlers();
422+
419423
// initialize from previously set renderer
420424
updateUiFromRenderer();
421425

422-
connect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
423-
connect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
424-
connect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
425-
426426
// menus for data-defined rotation/size
427427
QMenu* advMenu = new QMenu;
428428

@@ -447,22 +447,60 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2Widget::renderer()
447447
return mRenderer;
448448
}
449449

450+
// Connect/disconnect event handlers which trigger updating renderer
451+
452+
void QgsGraduatedSymbolRendererV2Widget::connectUpdateHandlers()
453+
{
454+
connect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
455+
connect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
456+
connect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
457+
connect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ) , this, SLOT( reapplyColorRamp() ) );
458+
connect( spinDecimalPlaces, SIGNAL(valueChanged(int)), this, SLOT(labelFormatChanged()));
459+
connect( cbxTrimTrailingZeroes, SIGNAL(toggled(bool)),this,SLOT(labelFormatChanged()));
460+
connect( txtPrefix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
461+
connect( txtSeparator, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
462+
connect( txtSuffix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
463+
464+
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
465+
connect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex)), this, SLOT( modelDataChanged( )) );
466+
}
467+
468+
// Connect/disconnect event handlers which trigger updating renderer
450469

451-
void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer()
470+
void QgsGraduatedSymbolRendererV2Widget::disconnectUpdateHandlers()
452471
{
472+
disconnect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
473+
disconnect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
474+
disconnect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
475+
disconnect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ) , this, SLOT( reapplyColorRamp() ) );
476+
disconnect( spinDecimalPlaces, SIGNAL(valueChanged(int)), this, SLOT(labelFormatChanged()));
477+
disconnect( cbxTrimTrailingZeroes, SIGNAL(toggled(bool)),this,SLOT(labelFormatChanged()));
478+
disconnect( txtPrefix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
479+
disconnect( txtSeparator, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
480+
disconnect( txtSuffix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
481+
482+
disconnect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
483+
disconnect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex)), this, SLOT( modelDataChanged( )) );
484+
}
485+
486+
void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer( bool updateCount )
487+
{
488+
disconnectUpdateHandlers();
489+
453490
updateGraduatedSymbolIcon();
454491

455492
// update UI from the graduated renderer (update combo boxes, view)
456493
if ( mRenderer->mode() < cboGraduatedMode->count() )
457494
cboGraduatedMode->setCurrentIndex( mRenderer->mode() );
458-
if ( mRenderer->ranges().count() )
495+
496+
// Only update class count if different - otherwise typing value gets very messy
497+
int nclasses=mRenderer->ranges().count();
498+
if ( nclasses && updateCount )
459499
spinGraduatedClasses->setValue( mRenderer->ranges().count() );
460500

461501
// set column
462-
disconnect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) );
463502
QString attrName = mRenderer->classAttribute();
464503
mExpressionWidget->setField( attrName );
465-
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) );
466504

467505
// set source symbol
468506
if ( mRenderer->sourceSymbol() )
@@ -478,6 +516,22 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer()
478516
cboGraduatedColorRamp->setSourceColorRamp( mRenderer->sourceColorRamp() );
479517
cbxInvertedColorRamp->setChecked( mRenderer->invertedColorRamp() );
480518
}
519+
520+
QgsRendererRangeV2LabelFormat labelFormat=mRenderer->labelFormat();
521+
txtPrefix->setText( labelFormat.prefix());
522+
txtSeparator->setText( labelFormat.separator() );
523+
txtSuffix->setText( labelFormat.suffix() );
524+
spinDecimalPlaces->setValue( labelFormat.decimalPlaces());
525+
cbxTrimTrailingZeroes->setChecked( labelFormat.trimTrailingZeroes());
526+
527+
mModel = new QgsGraduatedSymbolRendererV2Model( this );
528+
mModel->setRenderer( mRenderer );
529+
viewGraduated->setModel( mModel );
530+
viewGraduated->resizeColumnToContents( 0 );
531+
viewGraduated->resizeColumnToContents( 1 );
532+
viewGraduated->resizeColumnToContents( 2 );
533+
534+
connectUpdateHandlers();
481535
}
482536

483537
void QgsGraduatedSymbolRendererV2Widget::graduatedColumnChanged( QString field )
@@ -489,7 +543,7 @@ void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
489543
{
490544
QString attrName = mExpressionWidget->currentField();
491545

492-
int classes = spinGraduatedClasses->value();
546+
int nclasses = spinGraduatedClasses->value();
493547

494548
QgsVectorColorRampV2* ramp = cboGraduatedColorRamp->currentColorRamp();
495549

@@ -524,26 +578,19 @@ void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
524578
}
525579

526580
// create and set new renderer
581+
582+
mRenderer->setClassAttribute(attrName);
583+
mRenderer->setMode(mode);
584+
mRenderer->setSourceColorRamp(ramp->clone());
585+
bool updateUiCount=true;
527586
QApplication::setOverrideCursor( Qt::WaitCursor );
528-
QgsGraduatedSymbolRendererV2* r = QgsGraduatedSymbolRendererV2::createRenderer(
529-
mLayer, attrName, classes, mode, mGraduatedSymbol, ramp, cbxInvertedColorRamp->isChecked() );
587+
mRenderer->updateClasses(mLayer,mode,nclasses);
588+
mRenderer->calculateLabelDecimalPlaces();
530589
QApplication::restoreOverrideCursor();
531-
if ( !r )
532-
{
533-
QMessageBox::critical( this, tr( "Error" ), tr( "Renderer creation has failed." ) );
534-
return;
535-
}
536-
537-
r->setSizeScaleField( mRenderer->sizeScaleField() );
538-
r->setRotationField( mRenderer->rotationField() );
539-
r->setScaleMethod( mRenderer->scaleMethod() );
540-
541-
if ( mModel )
542-
{
543-
mModel->setRenderer( r );
544-
}
545-
delete mRenderer;
546-
mRenderer = r;
590+
// PrettyBreaks and StdDev calculation don't generate exact
591+
// number of classes - leave user interface unchanged for these
592+
updateUiCount=false;
593+
updateUiFromRenderer( updateUiCount );
547594
}
548595

549596
void QgsGraduatedSymbolRendererV2Widget::reapplyColorRamp()
@@ -644,8 +691,6 @@ void QgsGraduatedSymbolRendererV2Widget::rangesClicked( const QModelIndex & idx
644691
mRowSelected = idx.row();
645692
}
646693

647-
648-
649694
void QgsGraduatedSymbolRendererV2Widget::changeSelectedSymbols()
650695
{
651696
QItemSelectionModel* m = viewGraduated->selectionModel();
@@ -693,64 +738,35 @@ void QgsGraduatedSymbolRendererV2Widget::changeRange( int rangeIdx )
693738
QgsLUDialog dialog( this );
694739

695740
const QgsRendererRangeV2& range = mRenderer->ranges()[rangeIdx];
696-
dialog.setLowerValue( QString::number( range.lowerValue(), 'f', 4 ) );
697-
dialog.setUpperValue( QString::number( range.upperValue(), 'f', 4 ) );
741+
// Add arbitrary 3 to number of decimal places to retain a bit extra accuracy in
742+
// case we want to??
743+
int decimalPlaces=mRenderer->labelFormat().decimalPlaces();
744+
dialog.setLowerValue( QString::number( range.lowerValue(), 'f', decimalPlaces+3 ) );
745+
dialog.setUpperValue( QString::number( range.upperValue(), 'f', decimalPlaces+3 ) );
698746

699747
if ( dialog.exec() == QDialog::Accepted )
700748
{
701749
double lowerValue = dialog.lowerValue().toDouble();
702750
double upperValue = dialog.upperValue().toDouble();
703-
704-
QString label = createLabel( range.lowerValue(), range.upperValue() );
705-
QString newLabel;
706-
707751
mRenderer->updateRangeUpperValue( rangeIdx, upperValue );
708752
mRenderer->updateRangeLowerValue( rangeIdx, lowerValue );
709753

710-
//If the label was the label automatically generated, we generate a new one for the new range
711-
if ( range.label() == label )
712-
{
713-
newLabel = createLabel( lowerValue, upperValue );
714-
mRenderer->updateRangeLabel( rangeIdx, newLabel );
715-
}
716-
717754
//If the boundaries have to stay linked, we update the ranges above and below, as well as their label if needed
718755
if ( cbxLinkBoundaries->isChecked() )
719756
{
720757
if ( rangeIdx > 0 )
721758
{
722-
const QgsRendererRangeV2& rangeLower = mRenderer->ranges()[rangeIdx - 1];
723-
label = createLabel( rangeLower.lowerValue(), rangeLower.upperValue() );
724759
mRenderer->updateRangeUpperValue( rangeIdx - 1, lowerValue );
725-
726-
if ( label == rangeLower.label() )
727-
{
728-
newLabel = createLabel( rangeLower.lowerValue(), lowerValue );
729-
mRenderer->updateRangeLabel( rangeIdx - 1, newLabel );
730-
}
731760
}
732761

733762
if ( rangeIdx < mRenderer->ranges().size() - 1 )
734763
{
735-
const QgsRendererRangeV2& rangeUpper = mRenderer->ranges()[rangeIdx + 1];
736-
label = createLabel( rangeUpper.lowerValue(), rangeUpper.upperValue() );
737764
mRenderer->updateRangeLowerValue( rangeIdx + 1, upperValue );
738-
739-
if ( label == rangeUpper.label() )
740-
{
741-
newLabel = createLabel( upperValue, rangeUpper.upperValue() );
742-
mRenderer->updateRangeLabel( rangeIdx + 1, newLabel );
743-
}
744765
}
745766
}
746767
}
747768
}
748769

749-
QString QgsGraduatedSymbolRendererV2Widget::createLabel( double lowerValue, double upperValue )
750-
{
751-
return QString::number( lowerValue , 'f', 4 ) + " - " + QString::number( upperValue, 'f', 4 );
752-
}
753-
754770
void QgsGraduatedSymbolRendererV2Widget::addClass()
755771
{
756772
mModel->addClass( mGraduatedSymbol );
@@ -767,12 +783,46 @@ void QgsGraduatedSymbolRendererV2Widget::deleteAllClasses()
767783
mModel->removeAllRows();
768784
}
769785

786+
bool QgsGraduatedSymbolRendererV2Widget::rowsOrdered()
787+
{
788+
const QgsRangeList &ranges = mRenderer->ranges();
789+
bool ordered=true;
790+
for ( int i = 1;i < ranges.size();++i )
791+
{
792+
if( ranges[i] < ranges[i-1] )
793+
{
794+
ordered=false;
795+
break;
796+
}
797+
}
798+
return ordered;
799+
}
800+
770801
void QgsGraduatedSymbolRendererV2Widget::toggleBoundariesLink( bool linked )
771802
{
772803
//If the checkbox controlling the link between boundaries was unchecked and we check it, we have to link the boundaries
773804
//This is done by updating all lower ranges to the upper value of the range above
774805
if ( linked )
775806
{
807+
// Cannot link ranges if they are not sorted - results will be crazy
808+
// qSort( mRenderer->ranges() );
809+
// Could not get qSort to work with copy/swap idiom on QgsVectorRange
810+
811+
if( ! rowsOrdered() )
812+
{
813+
int result=QMessageBox::warning(
814+
this,
815+
tr("Linked range warning"),
816+
tr("Linking ranges that are not ordered may produced unexpected results. Proceed?"),
817+
QMessageBox::Ok | QMessageBox::Cancel );
818+
if( result != QMessageBox::Ok )
819+
{
820+
cbxLinkBoundaries->setChecked( false );
821+
return;
822+
}
823+
}
824+
825+
// Ok to proceed
776826
for ( int i = 1;i < mRenderer->ranges().size();++i )
777827
{
778828
mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i-1].upperValue() );
@@ -806,6 +856,19 @@ void QgsGraduatedSymbolRendererV2Widget::scaleMethodChanged( QgsSymbolV2::ScaleM
806856
mRenderer->setScaleMethod( scaleMethod );
807857
}
808858

859+
void QgsGraduatedSymbolRendererV2Widget::labelFormatChanged()
860+
{
861+
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat(
862+
txtPrefix->text(),
863+
txtSeparator->text(),
864+
txtSuffix->text(),
865+
spinDecimalPlaces->value(),
866+
cbxTrimTrailingZeroes->isChecked());
867+
mRenderer->setLabelFormat(labelFormat,true);
868+
mModel->updateLabels();
869+
}
870+
871+
809872
QList<QgsSymbolV2*> QgsGraduatedSymbolRendererV2Widget::selectedSymbols()
810873
{
811874
QList<QgsSymbolV2*> selectedSymbols;
@@ -851,6 +914,10 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2Widget::findSymbolForRange( double lowe
851914

852915
void QgsGraduatedSymbolRendererV2Widget::refreshSymbolView()
853916
{
917+
if( mModel )
918+
{
919+
mModel->updateSymbology();
920+
}
854921
}
855922

856923
void QgsGraduatedSymbolRendererV2Widget::showSymbolLevels()
@@ -863,6 +930,14 @@ void QgsGraduatedSymbolRendererV2Widget::rowsMoved()
863930
viewGraduated->selectionModel()->clear();
864931
}
865932

933+
void QgsGraduatedSymbolRendererV2Widget::modelDataChanged()
934+
{
935+
if( ! rowsOrdered() )
936+
{
937+
cbxLinkBoundaries->setChecked(false);
938+
}
939+
}
940+
866941
void QgsGraduatedSymbolRendererV2Widget::keyPressEvent( QKeyEvent* event )
867942
{
868943
if ( !event )

‎src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Model : public QAbstractItemModel
4949
void deleteRows( QList<int> rows );
5050
void removeAllRows( );
5151
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
52+
void updateSymbology();
53+
void updateLabels();
5254

5355
signals:
5456
void rowsMoved();
@@ -100,13 +102,18 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
100102
void rotationFieldChanged( QString fldName );
101103
void sizeScaleFieldChanged( QString fldName );
102104
void scaleMethodChanged( QgsSymbolV2::ScaleMethod scaleMethod );
105+
void labelFormatChanged();
103106

104107
void showSymbolLevels();
105108

106109
void rowsMoved();
110+
void modelDataChanged();
107111

108112
protected:
109-
void updateUiFromRenderer();
113+
void updateUiFromRenderer( bool updateCount=true );
114+
void connectUpdateHandlers();
115+
void disconnectUpdateHandlers();
116+
bool rowsOrdered();
110117

111118
void updateGraduatedSymbolIcon();
112119

@@ -117,8 +124,6 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
117124
void changeRangeSymbol( int rangeIdx );
118125
void changeRange( int rangeIdx );
119126

120-
QString createLabel( double lowerValue, double upperValue );
121-
122127
void changeSelectedSymbols();
123128

124129
QList<QgsSymbolV2*> selectedSymbols();

‎src/ui/qgsgraduatedsymbolrendererv2widget.ui

Lines changed: 154 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,20 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>615</width>
9+
<width>637</width>
1010
<height>339</height>
1111
</rect>
1212
</property>
1313
<layout class="QVBoxLayout" name="verticalLayout">
14-
<property name="leftMargin">
15-
<number>0</number>
16-
</property>
17-
<property name="topMargin">
18-
<number>0</number>
19-
</property>
20-
<property name="rightMargin">
21-
<number>0</number>
22-
</property>
23-
<property name="bottomMargin">
14+
<property name="margin">
2415
<number>0</number>
2516
</property>
2617
<item>
2718
<layout class="QGridLayout">
28-
<item row="5" column="0">
29-
<widget class="QLabel" name="label_7">
30-
<property name="text">
31-
<string>Color ramp</string>
32-
</property>
33-
<property name="buddy">
34-
<cstring>cboGraduatedColorRamp</cstring>
35-
</property>
36-
</widget>
37-
</item>
38-
<item row="5" column="2">
19+
<property name="rightMargin">
20+
<number>6</number>
21+
</property>
22+
<item row="6" column="2">
3923
<widget class="QLabel" name="label_8">
4024
<property name="text">
4125
<string>Mode</string>
@@ -48,7 +32,17 @@
4832
</property>
4933
</widget>
5034
</item>
51-
<item row="5" column="3">
35+
<item row="6" column="0">
36+
<widget class="QLabel" name="label_7">
37+
<property name="text">
38+
<string>Color ramp</string>
39+
</property>
40+
<property name="buddy">
41+
<cstring>cboGraduatedColorRamp</cstring>
42+
</property>
43+
</widget>
44+
</item>
45+
<item row="6" column="3">
5246
<widget class="QComboBox" name="cboGraduatedMode">
5347
<item>
5448
<property name="text">
@@ -77,7 +71,7 @@
7771
</item>
7872
</widget>
7973
</item>
80-
<item row="4" column="0">
74+
<item row="5" column="0">
8175
<widget class="QLabel" name="label_6">
8276
<property name="text">
8377
<string>Symbol</string>
@@ -87,7 +81,7 @@
8781
</property>
8882
</widget>
8983
</item>
90-
<item row="4" column="1">
84+
<item row="5" column="1">
9185
<widget class="QPushButton" name="btnChangeGraduatedSymbol">
9286
<property name="sizePolicy">
9387
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -100,7 +94,7 @@
10094
</property>
10195
</widget>
10296
</item>
103-
<item row="4" column="3">
97+
<item row="5" column="3">
10498
<widget class="QSpinBox" name="spinGraduatedClasses">
10599
<property name="sizePolicy">
106100
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -119,7 +113,7 @@
119113
</property>
120114
</widget>
121115
</item>
122-
<item row="4" column="2">
116+
<item row="5" column="2">
123117
<widget class="QLabel" name="label_5">
124118
<property name="text">
125119
<string>Classes</string>
@@ -132,14 +126,7 @@
132126
</property>
133127
</widget>
134128
</item>
135-
<item row="0" column="0">
136-
<widget class="QLabel" name="label_4">
137-
<property name="text">
138-
<string>Column</string>
139-
</property>
140-
</widget>
141-
</item>
142-
<item row="5" column="1">
129+
<item row="6" column="1">
143130
<layout class="QHBoxLayout" name="horizontalLayout_2">
144131
<item>
145132
<widget class="QgsColorRampComboBox" name="cboGraduatedColorRamp"/>
@@ -153,13 +140,26 @@
153140
</item>
154141
</layout>
155142
</item>
156-
<item row="0" column="1" colspan="3">
143+
<item row="2" column="0">
144+
<widget class="QLabel" name="label_4">
145+
<property name="text">
146+
<string>Column</string>
147+
</property>
148+
</widget>
149+
</item>
150+
<item row="2" column="1" colspan="2">
157151
<layout class="QHBoxLayout" name="horizontalLayout">
158152
<property name="topMargin">
159153
<number>0</number>
160154
</property>
161155
<item>
162156
<widget class="QgsFieldExpressionWidget" name="mExpressionWidget" native="true">
157+
<property name="minimumSize">
158+
<size>
159+
<width>0</width>
160+
<height>0</height>
161+
</size>
162+
</property>
163163
<property name="maximumSize">
164164
<size>
165165
<width>500</width>
@@ -183,6 +183,104 @@
183183
</item>
184184
</layout>
185185
</item>
186+
<item row="3" column="0">
187+
<widget class="QLabel" name="label">
188+
<property name="text">
189+
<string>Label </string>
190+
</property>
191+
<property name="alignment">
192+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
193+
</property>
194+
<property name="buddy">
195+
<cstring>txtPrefix</cstring>
196+
</property>
197+
</widget>
198+
</item>
199+
<item row="3" column="1">
200+
<layout class="QHBoxLayout" name="horizontalLayout_3">
201+
<property name="topMargin">
202+
<number>0</number>
203+
</property>
204+
<item>
205+
<widget class="QLineEdit" name="txtPrefix">
206+
<property name="alignment">
207+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
208+
</property>
209+
</widget>
210+
</item>
211+
<item>
212+
<widget class="QLabel" name="label_3">
213+
<property name="text">
214+
<string>#.##</string>
215+
</property>
216+
</widget>
217+
</item>
218+
<item>
219+
<widget class="QLineEdit" name="txtSeparator">
220+
<property name="alignment">
221+
<set>Qt::AlignCenter</set>
222+
</property>
223+
</widget>
224+
</item>
225+
<item>
226+
<widget class="QLabel" name="label_17">
227+
<property name="text">
228+
<string>#.##</string>
229+
</property>
230+
</widget>
231+
</item>
232+
<item>
233+
<widget class="QLineEdit" name="txtSuffix">
234+
<property name="alignment">
235+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
236+
</property>
237+
</widget>
238+
</item>
239+
</layout>
240+
</item>
241+
<item row="3" column="2">
242+
<widget class="QLabel" name="label_16">
243+
<property name="text">
244+
<string>Decimal places</string>
245+
</property>
246+
<property name="alignment">
247+
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
248+
</property>
249+
<property name="buddy">
250+
<cstring>spinDecimalPlaces</cstring>
251+
</property>
252+
</widget>
253+
</item>
254+
<item row="3" column="3">
255+
<layout class="QHBoxLayout" name="horizontalLayout_7">
256+
<item>
257+
<widget class="QSpinBox" name="spinDecimalPlaces">
258+
<property name="sizePolicy">
259+
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
260+
<horstretch>0</horstretch>
261+
<verstretch>0</verstretch>
262+
</sizepolicy>
263+
</property>
264+
<property name="minimum">
265+
<number>0</number>
266+
</property>
267+
<property name="maximum">
268+
<number>10</number>
269+
</property>
270+
<property name="value">
271+
<number>4</number>
272+
</property>
273+
</widget>
274+
</item>
275+
<item>
276+
<widget class="QCheckBox" name="cbxTrimTrailingZeroes">
277+
<property name="text">
278+
<string>Trim</string>
279+
</property>
280+
</widget>
281+
</item>
282+
</layout>
283+
</item>
186284
</layout>
187285
</item>
188286
<item>
@@ -243,7 +341,7 @@
243341
<item>
244342
<widget class="QCheckBox" name="cbxLinkBoundaries">
245343
<property name="text">
246-
<string>Link classes boundaries</string>
344+
<string>Link class boundaries</string>
247345
</property>
248346
<property name="checked">
249347
<bool>true</bool>
@@ -288,14 +386,32 @@
288386
</customwidget>
289387
</customwidgets>
290388
<tabstops>
389+
<tabstop>txtPrefix</tabstop>
390+
<tabstop>txtSeparator</tabstop>
391+
<tabstop>txtSuffix</tabstop>
392+
<tabstop>spinDecimalPlaces</tabstop>
393+
<tabstop>cbxTrimTrailingZeroes</tabstop>
291394
<tabstop>btnChangeGraduatedSymbol</tabstop>
395+
<tabstop>spinGraduatedClasses</tabstop>
292396
<tabstop>cboGraduatedColorRamp</tabstop>
293397
<tabstop>cbxInvertedColorRamp</tabstop>
294-
<tabstop>spinGraduatedClasses</tabstop>
295398
<tabstop>cboGraduatedMode</tabstop>
296399
<tabstop>viewGraduated</tabstop>
297400
<tabstop>btnGraduatedClassify</tabstop>
401+
<tabstop>btnGraduatedAdd</tabstop>
298402
<tabstop>btnGraduatedDelete</tabstop>
403+
<tabstop>btnDeleteAllClasses</tabstop>
404+
<tabstop>cbxLinkBoundaries</tabstop>
405+
<tabstop>btnAdvanced</tabstop>
406+
<tabstop>cboGraduatedMode_2</tabstop>
407+
<tabstop>btnChangeGraduatedSymbol_2</tabstop>
408+
<tabstop>spinGraduatedClasses_2</tabstop>
409+
<tabstop>cboGraduatedColorRamp_2</tabstop>
410+
<tabstop>cbxInvertedColorRamp_2</tabstop>
411+
<tabstop>spinDecimalPlaces_2</tabstop>
412+
<tabstop>txtPrefix_4</tabstop>
413+
<tabstop>txtPrefix_5</tabstop>
414+
<tabstop>txtPrefix_6</tabstop>
299415
</tabstops>
300416
<resources/>
301417
<connections/>

0 commit comments

Comments
 (0)
Please sign in to comment.