mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
Merge pull request #1587 from ccrook/CategorizedRendererUpdate
Categorized and graduated renderer enhancements
This commit is contained in:
commit
0c6576c423
@ -122,6 +122,10 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
bool invertedColorRamp();
|
||||
void setInvertedColorRamp( bool inverted );
|
||||
|
||||
// Update the color ramp used and all symbols colors.
|
||||
//! @note added in 2.5
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
|
||||
|
||||
//! @note added in 1.6
|
||||
void setRotationField( QString fieldOrExpression );
|
||||
//! @note added in 1.6
|
||||
@ -149,6 +153,10 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
// @note added in 2.5
|
||||
virtual void checkLegendSymbolItem( QString key, bool state = true );
|
||||
|
||||
//! If supported by the renderer, return classification attribute for the use in legend
|
||||
//! @note added in 2.6
|
||||
virtual QString legendClassificationAttribute() const;
|
||||
|
||||
//! creates a QgsCategorizedSymbolRendererV2 from an existing renderer.
|
||||
//! @note added in 2.5
|
||||
//! @returns a new renderer if the conversion was possible, otherwise 0.
|
||||
|
||||
@ -5,7 +5,8 @@ class QgsRendererRangeV2
|
||||
%End
|
||||
|
||||
public:
|
||||
QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol /Transfer/, QString label, bool render = true );
|
||||
QgsRendererRangeV2();
|
||||
QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol, QString label, bool render = true );
|
||||
QgsRendererRangeV2( const QgsRendererRangeV2& range );
|
||||
|
||||
// default dtor is ok
|
||||
@ -38,6 +39,42 @@ class QgsRendererRangeV2
|
||||
|
||||
typedef QList<QgsRendererRangeV2> QgsRangeList;
|
||||
|
||||
class QgsRendererRangeV2LabelFormat
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsgraduatedsymbolrendererv2.h>
|
||||
%End
|
||||
public:
|
||||
QgsRendererRangeV2LabelFormat();
|
||||
QgsRendererRangeV2LabelFormat( QString prefix, QString separator, QString suffix, int decimalPlaces=4, bool trimTrailingZeroes=false );
|
||||
|
||||
bool operator==( const QgsRendererRangeV2LabelFormat & other ) const;
|
||||
bool operator!=( const QgsRendererRangeV2LabelFormat & other ) const;
|
||||
|
||||
QString prefix() const;
|
||||
void setPrefix( QString prefix );
|
||||
|
||||
QString separator() const;
|
||||
void setSeparator( QString separator );
|
||||
|
||||
QString suffix() const;
|
||||
void setSuffix( QString suffix );
|
||||
|
||||
int decimalPlaces() const;
|
||||
void setDecimalPlaces( int decimalPlaces );
|
||||
|
||||
bool trimTrailingZeroes() const;
|
||||
void setTrimTrailingZeroes( bool trimTrailingZeroes );
|
||||
|
||||
//! @note labelForLowerUpper in python bindings
|
||||
QString labelForRange( double lower, double upper ) /PyName=labelForLowerUpper/;
|
||||
QString labelForRange( const QgsRendererRangeV2 &range );
|
||||
|
||||
void setFromDomElement( QDomElement &element );
|
||||
void saveToDomElement( QDomElement &element );
|
||||
};
|
||||
|
||||
|
||||
class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
{
|
||||
%TypeHeaderCode
|
||||
@ -86,6 +123,8 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
void addClass( QgsSymbolV2* symbol );
|
||||
//! @note available in python bindings as addClassRange
|
||||
void addClass( QgsRendererRangeV2 range ) /PyName=addClassRange/;
|
||||
//! @note available in python bindings as addClassLowerUpper
|
||||
void addClass( double lower, double upper ) /PyName=addClassLowerUpper/;
|
||||
void deleteClass( int idx );
|
||||
void deleteAllClasses();
|
||||
|
||||
@ -107,6 +146,30 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
|
||||
Mode mode() const;
|
||||
void setMode( Mode mode );
|
||||
//! Recalculate classes for a layer
|
||||
//! @param vlayer The layer being rendered (from which data values are calculated)
|
||||
//! @param mode The calculation mode
|
||||
//! @param nclasses The number of classes to calculate (approximate for some modes)
|
||||
//! @note Added in 2.6
|
||||
void updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses );
|
||||
//! Evaluates the data expression and returns the list of values from the layer
|
||||
//! @param vlayer The layer for which to evaluate the expression
|
||||
//! @note Added in 2.6
|
||||
QList<double> getDataValues( QgsVectorLayer *vlayer );
|
||||
|
||||
//! Return the label format used to generate default classification labels
|
||||
//! @note Added in 2.6
|
||||
const QgsRendererRangeV2LabelFormat &labelFormat();
|
||||
//! Set the label format used to generate default classification labels
|
||||
//! @param labelFormat The string appended to classification labels
|
||||
//! @param updateRanges If true then ranges ending with the old unit string are updated to the new.
|
||||
//! @note Added in 2.6
|
||||
void setLabelFormat( const QgsRendererRangeV2LabelFormat &labelFormat, bool updateRanges=true );
|
||||
|
||||
//! Reset the label decimal places to a numberbased on the minimum class interval
|
||||
//! @param updateRanges if true then ranges currently using the default label will be updated
|
||||
//! @note Added in 2.6
|
||||
void calculateLabelDecimalPlaces( bool updateRanges=true );
|
||||
|
||||
static QgsGraduatedSymbolRendererV2* createRenderer(
|
||||
QgsVectorLayer* vlayer,
|
||||
@ -115,7 +178,9 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
Mode mode,
|
||||
QgsSymbolV2* symbol /Transfer/,
|
||||
QgsVectorColorRampV2* ramp /Transfer/,
|
||||
bool inverted = false ) /Factory/;
|
||||
bool inverted = false,
|
||||
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat()
|
||||
);
|
||||
|
||||
//! create renderer from XML element
|
||||
static QgsFeatureRendererV2* create( QDomElement& element ) /Factory/;
|
||||
@ -143,9 +208,9 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
/** Update the color ramp used. Also updates all symbols colors.
|
||||
* Doesn't alter current breaks.
|
||||
*/
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp /Transfer/ );
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp /Transfer/ = 0, bool inverted = false );
|
||||
|
||||
/** Update the all symbols but leave breaks and colors. */
|
||||
/** Update all the symbols but leave breaks and colors. */
|
||||
void updateSymbols( QgsSymbolV2* sym /Transfer/ );
|
||||
|
||||
//! @note added in 1.6
|
||||
@ -175,6 +240,10 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
// @note added in 2.5
|
||||
virtual void checkLegendSymbolItem( QString key, bool state = true );
|
||||
|
||||
//! If supported by the renderer, return classification attribute for the use in legend
|
||||
//! @note added in 2.6
|
||||
virtual QString legendClassificationAttribute();
|
||||
|
||||
//! creates a QgsGraduatedSymbolRendererV2 from an existing renderer.
|
||||
//! @note added in 2.5
|
||||
//! @returns a new renderer if the conversion was possible, otherwise 0.
|
||||
|
||||
@ -18,6 +18,7 @@ class QgsCategorizedSymbolRendererV2Widget : QgsRendererV2Widget
|
||||
void categoriesDoubleClicked( const QModelIndex & idx );
|
||||
void addCategory();
|
||||
void addCategories();
|
||||
void applyColorRamp();
|
||||
void deleteCategories();
|
||||
void deleteAllCategories();
|
||||
|
||||
@ -49,6 +50,8 @@ class QgsCategorizedSymbolRendererV2Widget : QgsRendererV2Widget
|
||||
|
||||
void changeCategorySymbol();
|
||||
|
||||
QgsVectorColorRampV2* getColorRamp();
|
||||
|
||||
QList<QgsSymbolV2*> selectedSymbols();
|
||||
QgsCategoryList selectedCategoryList();
|
||||
void refreshSymbolView();
|
||||
|
||||
@ -26,17 +26,24 @@ class QgsGraduatedSymbolRendererV2Widget : QgsRendererV2Widget
|
||||
void deleteClasses();
|
||||
/**Removes all classes from the classification*/
|
||||
void deleteAllClasses();
|
||||
/**Toggle the link between classes boundaries */
|
||||
void toggleBoundariesLink( bool linked );
|
||||
|
||||
void rotationFieldChanged( QString fldName );
|
||||
void sizeScaleFieldChanged( QString fldName );
|
||||
void scaleMethodChanged( QgsSymbolV2::ScaleMethod scaleMethod );
|
||||
void labelFormatChanged();
|
||||
|
||||
void showSymbolLevels();
|
||||
|
||||
void rowsMoved();
|
||||
void modelDataChanged();
|
||||
|
||||
protected:
|
||||
void updateUiFromRenderer();
|
||||
void updateUiFromRenderer( bool updateCount=true );
|
||||
void connectUpdateHandlers();
|
||||
void disconnectUpdateHandlers();
|
||||
bool rowsOrdered();
|
||||
|
||||
void updateGraduatedSymbolIcon();
|
||||
|
||||
|
||||
@ -168,7 +168,7 @@ void QgsCategorizedSymbolRendererV2::rebuildHash()
|
||||
{
|
||||
mSymbolHash.clear();
|
||||
|
||||
for ( int i = 0; i < mCategories.count(); ++i )
|
||||
for ( int i = 0; i < mCategories.size(); ++i )
|
||||
{
|
||||
QgsRendererCategoryV2& cat = mCategories[i];
|
||||
mSymbolHash.insert( cat.value().toString(), ( cat.renderState() || mCounting ) ? cat.symbol() : &sSkipRender );
|
||||
@ -181,7 +181,7 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
|
||||
QHash<QString, QgsSymbolV2*>::iterator it = mSymbolHash.find( value.toString() );
|
||||
if ( it == mSymbolHash.end() )
|
||||
{
|
||||
if ( mSymbolHash.count() == 0 )
|
||||
if ( mSymbolHash.size() == 0 )
|
||||
{
|
||||
QgsDebugMsg( "there are no hashed symbols!!!" );
|
||||
}
|
||||
@ -700,11 +700,27 @@ QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2::sourceColorRamp()
|
||||
{
|
||||
return mSourceColorRamp.data();
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ramp )
|
||||
{
|
||||
mSourceColorRamp.reset( ramp );
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererV2::updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted )
|
||||
{
|
||||
setSourceColorRamp(ramp);
|
||||
setInvertedColorRamp(inverted);
|
||||
double num=mCategories.count()-1;
|
||||
double count = 0;
|
||||
foreach ( const QgsRendererCategoryV2 &cat, mCategories )
|
||||
{
|
||||
double value=count/num;
|
||||
if( mInvertedColorRamp ) value=1.0-value;
|
||||
cat.symbol()->setColor(mSourceColorRamp->color(value));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererV2::setRotationField( QString fieldOrExpression )
|
||||
{
|
||||
mRotation.reset( QgsSymbolLayerV2Utils::fieldOrExpressionToExpression( fieldOrExpression ) );
|
||||
@ -788,5 +804,16 @@ QgsCategorizedSymbolRendererV2* QgsCategorizedSymbolRendererV2::convertFromRende
|
||||
const QgsInvertedPolygonRenderer* invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer*>( renderer );
|
||||
return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
|
||||
}
|
||||
return 0;
|
||||
|
||||
// If not one of the specifically handled renderers, then just grab the symbol from the renderer
|
||||
// Could have applied this to specific renderer types (singleSymbol, graduatedSymbo)
|
||||
|
||||
QgsCategorizedSymbolRendererV2* r =new QgsCategorizedSymbolRendererV2( "", QgsCategoryList() );
|
||||
QgsSymbolV2List symbols=const_cast<QgsFeatureRendererV2 *>(renderer)->symbols();
|
||||
if( symbols.size() > 0 )
|
||||
{
|
||||
r->setSourceSymbol(symbols.at(0)->clone());
|
||||
}
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
@ -152,6 +152,10 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
bool invertedColorRamp() { return mInvertedColorRamp; }
|
||||
void setInvertedColorRamp( bool inverted ) { mInvertedColorRamp = inverted; }
|
||||
|
||||
// Update the color ramp used and all symbols colors.
|
||||
//! @note added in 2.5
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
|
||||
|
||||
//! @note added in 1.6
|
||||
void setRotationField( QString fieldOrExpression );
|
||||
//! @note added in 1.6
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
/***************************************************************************
|
||||
qgsgraduatedsymbolrendererv2.cpp
|
||||
---------------------
|
||||
@ -62,6 +63,14 @@ QgsRendererRangeV2& QgsRendererRangeV2::operator=( QgsRendererRangeV2 range )
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool QgsRendererRangeV2::operator<( const QgsRendererRangeV2 &other ) const
|
||||
{
|
||||
return
|
||||
lowerValue() < other.lowerValue() ||
|
||||
(lowerValue() == other.lowerValue() && upperValue() < other.upperValue());
|
||||
}
|
||||
|
||||
|
||||
void QgsRendererRangeV2::swap( QgsRendererRangeV2 & other )
|
||||
{
|
||||
qSwap( mLowerValue, other.mLowerValue );
|
||||
@ -157,6 +166,89 @@ void QgsRendererRangeV2::toSld( QDomDocument &doc, QDomElement &element, QgsStri
|
||||
|
||||
///////////
|
||||
|
||||
QgsRendererRangeV2LabelFormat::QgsRendererRangeV2LabelFormat():
|
||||
mPrefix(""),
|
||||
mSeparator(" - "),
|
||||
mSuffix(""),
|
||||
mDecimalPlaces(4),
|
||||
mTrimTrailingZeroes(false),
|
||||
mReTrailingZeroes("\\.?0*$")
|
||||
{
|
||||
}
|
||||
|
||||
QgsRendererRangeV2LabelFormat::QgsRendererRangeV2LabelFormat( QString prefix, QString separator, QString suffix, int decimalPlaces, bool trimTrailingZeroes ):
|
||||
mReTrailingZeroes("\\.?0*$")
|
||||
{
|
||||
setPrefix(prefix);
|
||||
setSeparator(separator);
|
||||
setSuffix(suffix);
|
||||
setDecimalPlaces(decimalPlaces);
|
||||
setTrimTrailingZeroes(trimTrailingZeroes);
|
||||
}
|
||||
|
||||
|
||||
bool QgsRendererRangeV2LabelFormat::operator==( const QgsRendererRangeV2LabelFormat &other ) const
|
||||
{
|
||||
return
|
||||
prefix()==other.prefix() &&
|
||||
separator()==other.separator() &&
|
||||
suffix()==other.suffix() &&
|
||||
decimalPlaces()==other.decimalPlaces() &&
|
||||
trimTrailingZeroes()==other.trimTrailingZeroes();
|
||||
}
|
||||
|
||||
bool QgsRendererRangeV2LabelFormat::operator!=( const QgsRendererRangeV2LabelFormat &other ) const
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
void QgsRendererRangeV2LabelFormat::setDecimalPlaces( int decimalPlaces )
|
||||
{
|
||||
// Limit the range of decimal places to a reasonable range
|
||||
if( decimalPlaces < 0 ) decimalPlaces=0;
|
||||
if( decimalPlaces > 15 ) decimalPlaces=15;
|
||||
mDecimalPlaces=decimalPlaces;
|
||||
}
|
||||
|
||||
QString QgsRendererRangeV2LabelFormat::labelForRange( const QgsRendererRangeV2 &range ) const
|
||||
{
|
||||
return labelForRange(range.lowerValue(),range.upperValue());
|
||||
}
|
||||
|
||||
QString QgsRendererRangeV2LabelFormat::labelForRange( double lower, double upper) const
|
||||
{
|
||||
QString lowerStr=QString::number(lower,'f',mDecimalPlaces);
|
||||
QString upperStr=QString::number(upper,'f',mDecimalPlaces);
|
||||
|
||||
if(mTrimTrailingZeroes)
|
||||
{
|
||||
if( lowerStr.contains('.')) lowerStr=lowerStr.replace(mReTrailingZeroes,"");
|
||||
if( upperStr.contains('.')) upperStr=upperStr.replace(mReTrailingZeroes,"");
|
||||
}
|
||||
|
||||
return mPrefix+lowerStr+ mSeparator+upperStr+mSuffix;
|
||||
}
|
||||
|
||||
void QgsRendererRangeV2LabelFormat::setFromDomElement( QDomElement &element )
|
||||
{
|
||||
mPrefix=element.attribute("prefix","");
|
||||
mSeparator=element.attribute("separator"," - ");
|
||||
mSuffix=element.attribute("suffix","");
|
||||
mDecimalPlaces=element.attribute("decimalplaces","4").toInt();
|
||||
mTrimTrailingZeroes=element.attribute("trimtrailingzeroes","false") == "true";
|
||||
}
|
||||
|
||||
void QgsRendererRangeV2LabelFormat::saveToDomElement( QDomElement &element )
|
||||
{
|
||||
element.setAttribute("prefix",mPrefix);
|
||||
element.setAttribute("separator",mSeparator);
|
||||
element.setAttribute("suffix",mSuffix);
|
||||
element.setAttribute("decimalplaces",mDecimalPlaces);
|
||||
element.setAttribute("trimtrailingzeroes",mTrimTrailingZeroes ? "true" : "false" );
|
||||
}
|
||||
|
||||
///////////
|
||||
|
||||
QgsGraduatedSymbolRendererV2::QgsGraduatedSymbolRendererV2( QString attrName, QgsRangeList ranges )
|
||||
: QgsFeatureRendererV2( "graduatedSymbol" ),
|
||||
mAttrName( attrName ),
|
||||
@ -336,7 +428,10 @@ bool QgsGraduatedSymbolRendererV2::updateRangeUpperValue( int rangeIndex, double
|
||||
{
|
||||
if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
|
||||
return false;
|
||||
mRanges[rangeIndex].setUpperValue( value );
|
||||
QgsRendererRangeV2 &range=mRanges[rangeIndex];
|
||||
bool isDefaultLabel= range.label() == mLabelFormat.labelForRange(range);
|
||||
range.setUpperValue( value );
|
||||
if( isDefaultLabel ) range.setLabel(mLabelFormat.labelForRange(range));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -344,7 +439,10 @@ bool QgsGraduatedSymbolRendererV2::updateRangeLowerValue( int rangeIndex, double
|
||||
{
|
||||
if ( rangeIndex < 0 || rangeIndex >= mRanges.size() )
|
||||
return false;
|
||||
mRanges[rangeIndex].setLowerValue( value );
|
||||
QgsRendererRangeV2 &range=mRanges[rangeIndex];
|
||||
bool isDefaultLabel= range.label() == mLabelFormat.labelForRange(range);
|
||||
range.setLowerValue( value );
|
||||
if( isDefaultLabel ) range.setLabel(mLabelFormat.labelForRange(range));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -379,6 +477,7 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::clone() const
|
||||
r->setRotationField( rotationField() );
|
||||
r->setSizeScaleField( sizeScaleField() );
|
||||
r->setScaleMethod( scaleMethod() );
|
||||
r->setLabelFormat( labelFormat() );
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -619,7 +718,7 @@ static QList<double> _calcPrettyBreaks( double minimum, double maximum, int clas
|
||||
} // _calcPrettyBreaks
|
||||
|
||||
|
||||
static QList<double> _calcStdDevBreaks( QList<double> values, int classes, QList<int> &labels )
|
||||
static QList<double> _calcStdDevBreaks( QList<double> values, int classes, QList<double> &labels )
|
||||
{
|
||||
|
||||
// C++ implementation of the standard deviation class interval algorithm
|
||||
@ -658,7 +757,7 @@ static QList<double> _calcStdDevBreaks( QList<double> values, int classes, QList
|
||||
QList<double> breaks = _calcPrettyBreaks(( minimum - mean ) / stdDev, ( maximum - mean ) / stdDev, classes );
|
||||
for ( int i = 0; i < breaks.count(); i++ )
|
||||
{
|
||||
labels.append(( int ) breaks[i] );
|
||||
labels.append( breaks[i] );
|
||||
breaks[i] = ( breaks[i] * stdDev ) + mean;
|
||||
}
|
||||
|
||||
@ -805,34 +904,76 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
|
||||
Mode mode,
|
||||
QgsSymbolV2* symbol,
|
||||
QgsVectorColorRampV2* ramp,
|
||||
bool inverted )
|
||||
bool inverted,
|
||||
QgsRendererRangeV2LabelFormat labelFormat
|
||||
)
|
||||
{
|
||||
if ( classes < 1 )
|
||||
return NULL;
|
||||
|
||||
int attrNum = vlayer->fieldNameIndex( attrName );
|
||||
double minimum;
|
||||
double maximum;
|
||||
QgsRangeList ranges;
|
||||
QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
|
||||
r->setSourceSymbol( symbol->clone() );
|
||||
r->setSourceColorRamp( ramp->clone() );
|
||||
r->setInvertedColorRamp( inverted );
|
||||
r->setMode( mode );
|
||||
r->setLabelFormat(labelFormat,false);
|
||||
r->updateClasses(vlayer,mode,classes);
|
||||
return r;
|
||||
}
|
||||
|
||||
QList<double> QgsGraduatedSymbolRendererV2::getDataValues( QgsVectorLayer *vlayer )
|
||||
{
|
||||
QList<double> values;
|
||||
QScopedPointer<QgsExpression> expression;
|
||||
int attrNum = vlayer->fieldNameIndex( mAttrName );
|
||||
|
||||
if ( attrNum == -1 )
|
||||
{
|
||||
// try to use expression
|
||||
expression.reset( new QgsExpression( attrName ) );
|
||||
expression.reset( new QgsExpression( mAttrName ) );
|
||||
if ( expression->hasParserError() || !expression->prepare( vlayer->pendingFields() ) )
|
||||
return 0; // should have a means to report errors
|
||||
return values; // should have a means to report errors
|
||||
}
|
||||
|
||||
QList<double> values;
|
||||
QgsFeatureIterator fit = vlayer->getFeatures();
|
||||
QgsFeature feature;
|
||||
while ( fit.nextFeature( feature ) )
|
||||
{
|
||||
values << expression->evaluate( feature ).toDouble();
|
||||
}
|
||||
QgsFeature f;
|
||||
QStringList lst;
|
||||
if ( expression.isNull() )
|
||||
lst.append( mAttrName );
|
||||
else
|
||||
lst = expression->referencedColumns();
|
||||
|
||||
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( lst, vlayer->pendingFields() ) );
|
||||
|
||||
// create list of non-null attribute values
|
||||
while ( fit.nextFeature( f ) )
|
||||
{
|
||||
QVariant v = expression.isNull() ? f.attribute( attrNum ) : expression->evaluate( f );
|
||||
if ( !v.isNull() )
|
||||
values.append( v.toDouble() );
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses )
|
||||
{
|
||||
// Custom classes are not recalculated
|
||||
setMode(mode);
|
||||
if( mode == Custom ) return;
|
||||
|
||||
if ( nclasses < 1 ) nclasses=1;
|
||||
|
||||
QList<double> values;
|
||||
bool valuesLoaded=false;
|
||||
double minimum;
|
||||
double maximum;
|
||||
|
||||
int attrNum = vlayer->fieldNameIndex( mAttrName );
|
||||
|
||||
if ( attrNum == -1 )
|
||||
{
|
||||
values=getDataValues( vlayer );
|
||||
qSort( values );
|
||||
minimum = values.first();
|
||||
maximum = values.last();
|
||||
valuesLoaded=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -842,48 +983,37 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
|
||||
|
||||
QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );
|
||||
QList<double> breaks;
|
||||
QList<int> labels;
|
||||
QList<double> labels;
|
||||
if ( mode == EqualInterval )
|
||||
{
|
||||
breaks = _calcEqualIntervalBreaks( minimum, maximum, classes );
|
||||
breaks = _calcEqualIntervalBreaks( minimum, maximum, nclasses );
|
||||
}
|
||||
else if ( mode == Pretty )
|
||||
{
|
||||
breaks = _calcPrettyBreaks( minimum, maximum, classes );
|
||||
breaks = _calcPrettyBreaks( minimum, maximum, nclasses );
|
||||
}
|
||||
else if ( mode == Quantile || mode == Jenks || mode == StdDev )
|
||||
{
|
||||
// get values from layer
|
||||
QList<double> values;
|
||||
QgsFeature f;
|
||||
QStringList lst;
|
||||
if ( expression.isNull() )
|
||||
lst.append( attrName );
|
||||
else
|
||||
lst = expression->referencedColumns();
|
||||
|
||||
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( lst, vlayer->pendingFields() ) );
|
||||
|
||||
// create list of non-null attribute values
|
||||
while ( fit.nextFeature( f ) )
|
||||
if( ! valuesLoaded )
|
||||
{
|
||||
QVariant v = expression.isNull() ? f.attribute( attrNum ) : expression->evaluate( f );
|
||||
if ( !v.isNull() )
|
||||
values.append( v.toDouble() );
|
||||
values=getDataValues( vlayer );
|
||||
}
|
||||
|
||||
// calculate the breaks
|
||||
if ( mode == Quantile )
|
||||
{
|
||||
breaks = _calcQuantileBreaks( values, classes );
|
||||
breaks = _calcQuantileBreaks( values, nclasses );
|
||||
}
|
||||
else if ( mode == Jenks )
|
||||
{
|
||||
breaks = _calcJenksBreaks( values, classes, minimum, maximum );
|
||||
breaks = _calcJenksBreaks( values, nclasses, minimum, maximum );
|
||||
}
|
||||
else if ( mode == StdDev )
|
||||
{
|
||||
breaks = _calcStdDevBreaks( values, classes, labels );
|
||||
breaks = _calcStdDevBreaks( values, nclasses, labels );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -891,53 +1021,48 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
|
||||
QgsRangeList ranges;
|
||||
|
||||
double lower, upper = minimum;
|
||||
QString label;
|
||||
deleteAllClasses();
|
||||
|
||||
// "breaks" list contains all values at class breaks plus maximum as last break
|
||||
|
||||
int i = 0;
|
||||
for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
|
||||
{
|
||||
lower = upper; // upper border from last interval
|
||||
upper = *it;
|
||||
|
||||
// Label - either StdDev label or default label for a range
|
||||
if ( mode == StdDev )
|
||||
{
|
||||
if ( i == 0 )
|
||||
{
|
||||
label = "< " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
|
||||
label = "< " + QString::number( labels[i], 'f', 2 ) + " Std Dev";
|
||||
}
|
||||
else if ( i == labels.count() - 1 )
|
||||
{
|
||||
label = ">= " + QString::number( labels[i-1], 'i', 0 ) + " Std Dev";
|
||||
label = ">= " + QString::number( labels[i-1], 'f', 2 ) + " Std Dev";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = QString::number( labels[i-1], 'i', 0 ) + " Std Dev" + " - " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
|
||||
label = QString::number( labels[i-1], 'f', 2 ) + " Std Dev" + " - " + QString::number( labels[i], 'f', 2 ) + " Std Dev";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 );
|
||||
label=mLabelFormat.labelForRange(lower,upper);
|
||||
}
|
||||
|
||||
QgsSymbolV2* newSymbol = symbol->clone();
|
||||
double colorValue;
|
||||
if ( inverted ) colorValue = ( breaks.count() > 1 ? ( double )( breaks.count() - i - 1 ) / ( breaks.count() - 1 ) : 0 );
|
||||
else colorValue = ( breaks.count() > 1 ? ( double ) i / ( breaks.count() - 1 ) : 0 );
|
||||
newSymbol->setColor( ramp->color( colorValue ) ); // color from (0 / cl-1) to (cl-1 / cl-1)
|
||||
|
||||
ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
|
||||
QgsSymbolV2* newSymbol = mSourceSymbol->clone();
|
||||
addClass( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
|
||||
}
|
||||
updateColorRamp(0,mInvertedColorRamp);
|
||||
|
||||
QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
|
||||
r->setSourceSymbol( symbol->clone() );
|
||||
r->setSourceColorRamp( ramp->clone() );
|
||||
r->setInvertedColorRamp( inverted );
|
||||
r->setMode( mode );
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create( QDomElement& element )
|
||||
{
|
||||
QDomElement symbolsElem = element.firstChildElement( "symbols" );
|
||||
@ -1024,6 +1149,13 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create( QDomElement& element
|
||||
r->setSizeScaleField( sizeScaleElem.attribute( "field" ) );
|
||||
r->setScaleMethod( QgsSymbolLayerV2Utils::decodeScaleMethod( sizeScaleElem.attribute( "scalemethod" ) ) );
|
||||
|
||||
QDomElement labelFormatElem = element.firstChildElement( "labelformat" );
|
||||
if( ! labelFormatElem.isNull() )
|
||||
{
|
||||
QgsRendererRangeV2LabelFormat labelFormat;
|
||||
labelFormat.setFromDomElement( labelFormatElem );
|
||||
r->setLabelFormat( labelFormat );
|
||||
}
|
||||
// TODO: symbol levels
|
||||
return r;
|
||||
}
|
||||
@ -1111,6 +1243,10 @@ QDomElement QgsGraduatedSymbolRendererV2::save( QDomDocument& doc )
|
||||
sizeScaleElem.setAttribute( "scalemethod", QgsSymbolLayerV2Utils::encodeScaleMethod( mScaleMethod ) );
|
||||
rendererElem.appendChild( sizeScaleElem );
|
||||
|
||||
QDomElement labelFormatElem=doc.createElement("labelformat");
|
||||
mLabelFormat.saveToDomElement(labelFormatElem);
|
||||
rendererElem.appendChild( labelFormatElem );
|
||||
|
||||
return rendererElem;
|
||||
}
|
||||
|
||||
@ -1164,18 +1300,26 @@ void QgsGraduatedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ram
|
||||
void QgsGraduatedSymbolRendererV2::updateColorRamp( QgsVectorColorRampV2 *ramp, bool inverted )
|
||||
{
|
||||
int i = 0;
|
||||
foreach ( QgsRendererRangeV2 range, mRanges )
|
||||
if( ramp )
|
||||
{
|
||||
QgsSymbolV2* symbol = range.symbol()->clone();
|
||||
double colorValue;
|
||||
if ( inverted ) colorValue = ( mRanges.count() > 1 ? ( double )( mRanges.count() - i - 1 ) / ( mRanges.count() - 1 ) : 0 );
|
||||
else colorValue = ( mRanges.count() > 1 ? ( double ) i / ( mRanges.count() - 1 ) : 0 );
|
||||
symbol->setColor( ramp->color( colorValue ) );
|
||||
updateRangeSymbol( i, symbol );
|
||||
++i;
|
||||
this->setSourceColorRamp( ramp );
|
||||
this->setInvertedColorRamp( inverted );
|
||||
}
|
||||
this->setSourceColorRamp( ramp );
|
||||
this->setInvertedColorRamp( inverted );
|
||||
|
||||
if( mSourceColorRamp )
|
||||
{
|
||||
foreach ( QgsRendererRangeV2 range, mRanges )
|
||||
{
|
||||
QgsSymbolV2* symbol = range.symbol()->clone();
|
||||
double colorValue;
|
||||
if ( inverted ) colorValue = ( mRanges.count() > 1 ? ( double )( mRanges.count() - i - 1 ) / ( mRanges.count() - 1 ) : 0 );
|
||||
else colorValue = ( mRanges.count() > 1 ? ( double ) i / ( mRanges.count() - 1 ) : 0 );
|
||||
symbol->setColor( mSourceColorRamp->color( colorValue ) );
|
||||
updateRangeSymbol( i, symbol );
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::updateSymbols( QgsSymbolV2 *sym )
|
||||
@ -1249,7 +1393,13 @@ void QgsGraduatedSymbolRendererV2::addClass( QgsSymbolV2* symbol )
|
||||
QgsSymbolV2* newSymbol = symbol->clone();
|
||||
QString label = "0.0 - 0.0";
|
||||
mRanges.insert( 0, QgsRendererRangeV2( 0.0, 0.0, newSymbol, label ) );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::addClass( double lower, double upper )
|
||||
{
|
||||
QgsSymbolV2* newSymbol = mSourceSymbol->clone();
|
||||
QString label=mLabelFormat.labelForRange( lower, upper );
|
||||
mRanges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ));
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::addClass( QgsRendererRangeV2 range )
|
||||
@ -1267,6 +1417,45 @@ void QgsGraduatedSymbolRendererV2::deleteAllClasses()
|
||||
mRanges.clear();
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::setLabelFormat( const QgsRendererRangeV2LabelFormat &labelFormat, bool updateRanges )
|
||||
{
|
||||
if( updateRanges && labelFormat != mLabelFormat)
|
||||
{
|
||||
for ( QgsRangeList::iterator it = mRanges.begin(); it != mRanges.end(); ++it )
|
||||
{
|
||||
it->setLabel( labelFormat.labelForRange(*it));
|
||||
}
|
||||
}
|
||||
mLabelFormat=labelFormat;
|
||||
}
|
||||
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::calculateLabelDecimalPlaces( bool updateRanges )
|
||||
{
|
||||
// Find the minimum size of a class
|
||||
double minClassRange=0.0;
|
||||
for ( QgsRangeList::iterator it = mRanges.begin(); it != mRanges.end(); ++it )
|
||||
{
|
||||
double range = it->upperValue()-it->lowerValue();
|
||||
if( range <= 0.0 ) continue;
|
||||
if( minClassRange == 0.0 || range < minClassRange ) minClassRange=range;
|
||||
}
|
||||
if( minClassRange <= 0.0 ) return;
|
||||
|
||||
// Now set the number of decimal places to ensure no more than 20% error in
|
||||
// representing this range (up to 10% at upper and lower end)
|
||||
|
||||
int ndp=10;
|
||||
double nextDpMinRange=0.0000000099;
|
||||
while( ndp > 0 && nextDpMinRange < minClassRange )
|
||||
{
|
||||
ndp--;
|
||||
nextDpMinRange *= 10.0;
|
||||
}
|
||||
mLabelFormat.setDecimalPlaces(ndp);
|
||||
if( updateRanges ) setLabelFormat( mLabelFormat, true );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2::moveClass( int from, int to )
|
||||
{
|
||||
if ( from < 0 || from >= mRanges.size() || to < 0 || to >= mRanges.size() ) return;
|
||||
@ -1275,7 +1464,7 @@ void QgsGraduatedSymbolRendererV2::moveClass( int from, int to )
|
||||
|
||||
bool valueLessThan( const QgsRendererRangeV2 &r1, const QgsRendererRangeV2 &r2 )
|
||||
{
|
||||
return r1.lowerValue() < r2.lowerValue();
|
||||
return r1 < r2;
|
||||
}
|
||||
|
||||
bool valueGreaterThan( const QgsRendererRangeV2 &r1, const QgsRendererRangeV2 &r2 )
|
||||
@ -1334,5 +1523,16 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::convertFromRenderer(
|
||||
const QgsInvertedPolygonRenderer* invertedPolygonRenderer = dynamic_cast<const QgsInvertedPolygonRenderer*>( renderer );
|
||||
return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
|
||||
}
|
||||
return 0;
|
||||
|
||||
// If not one of the specifically handled renderers, then just grab the symbol from the renderer
|
||||
// Could have applied this to specific renderer types (singleSymbol, graduatedSymbo)
|
||||
|
||||
QgsGraduatedSymbolRendererV2* r =new QgsGraduatedSymbolRendererV2( "", QgsRangeList() );
|
||||
QgsSymbolV2List symbols=const_cast<QgsFeatureRendererV2 *>(renderer)->symbols();
|
||||
if( symbols.size() > 0 )
|
||||
{
|
||||
r->setSourceSymbol(symbols.at(0)->clone());
|
||||
}
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "qgsrendererv2.h"
|
||||
#include "qgsexpression.h"
|
||||
#include <QScopedPointer>
|
||||
#include <QRegExp>
|
||||
|
||||
class CORE_EXPORT QgsRendererRangeV2
|
||||
{
|
||||
@ -30,6 +31,8 @@ class CORE_EXPORT QgsRendererRangeV2
|
||||
// default dtor is ok
|
||||
QgsRendererRangeV2& operator=( QgsRendererRangeV2 range );
|
||||
|
||||
bool operator<( const QgsRendererRangeV2 &other ) const;
|
||||
|
||||
double lowerValue() const;
|
||||
double upperValue() const;
|
||||
|
||||
@ -62,6 +65,48 @@ class CORE_EXPORT QgsRendererRangeV2
|
||||
|
||||
typedef QList<QgsRendererRangeV2> QgsRangeList;
|
||||
|
||||
|
||||
// @note added in 2.6
|
||||
class CORE_EXPORT QgsRendererRangeV2LabelFormat
|
||||
{
|
||||
public:
|
||||
QgsRendererRangeV2LabelFormat();
|
||||
QgsRendererRangeV2LabelFormat( QString prefix, QString separator, QString suffix, int decimalPlaces=4, bool trimTrailingZeroes=false );
|
||||
|
||||
bool operator==( const QgsRendererRangeV2LabelFormat & other ) const;
|
||||
bool operator!=( const QgsRendererRangeV2LabelFormat & other ) const;
|
||||
|
||||
QString prefix() const { return mPrefix; }
|
||||
void setPrefix( QString prefix ) { mPrefix=prefix; }
|
||||
|
||||
QString separator() const { return mSeparator; }
|
||||
void setSeparator( QString separator ) { mSeparator=separator; }
|
||||
|
||||
QString suffix() const { return mSuffix; }
|
||||
void setSuffix( QString suffix ){ mSuffix=suffix; }
|
||||
|
||||
int decimalPlaces() const { return mDecimalPlaces; }
|
||||
void setDecimalPlaces( int decimalPlaces );
|
||||
|
||||
bool trimTrailingZeroes() const { return mTrimTrailingZeroes; }
|
||||
void setTrimTrailingZeroes( bool trimTrailingZeroes ){ mTrimTrailingZeroes=trimTrailingZeroes; }
|
||||
|
||||
//! @note labelForLowerUpper in python bindings
|
||||
QString labelForRange( double lower, double upper ) const;
|
||||
QString labelForRange( const QgsRendererRangeV2 &range ) const;
|
||||
|
||||
void setFromDomElement( QDomElement &element );
|
||||
void saveToDomElement( QDomElement &element );
|
||||
|
||||
protected:
|
||||
QString mPrefix;
|
||||
QString mSeparator;
|
||||
QString mSuffix;
|
||||
int mDecimalPlaces;
|
||||
bool mTrimTrailingZeroes;
|
||||
QRegExp mReTrailingZeroes;
|
||||
};
|
||||
|
||||
class QgsVectorLayer;
|
||||
class QgsVectorColorRampV2;
|
||||
|
||||
@ -107,10 +152,11 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
//! @note added in 2.5
|
||||
bool updateRangeRenderState( int rangeIndex, bool render );
|
||||
|
||||
|
||||
void addClass( QgsSymbolV2* symbol );
|
||||
//! @note available in python bindings as addClassRange
|
||||
void addClass( QgsRendererRangeV2 range );
|
||||
//! @note available in python bindings as addClassLowerUpper
|
||||
void addClass( double lower, double upper );
|
||||
void deleteClass( int idx );
|
||||
void deleteAllClasses();
|
||||
|
||||
@ -132,6 +178,30 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
|
||||
Mode mode() const { return mMode; }
|
||||
void setMode( Mode mode ) { mMode = mode; }
|
||||
//! Recalculate classes for a layer
|
||||
//! @param vlayer The layer being rendered (from which data values are calculated)
|
||||
//! @param mode The calculation mode
|
||||
//! @param nclasses The number of classes to calculate (approximate for some modes)
|
||||
//! @note Added in 2.6
|
||||
void updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses );
|
||||
//! Evaluates the data expression and returns the list of values from the layer
|
||||
//! @param vlayer The layer for which to evaluate the expression
|
||||
//! @note Added in 2.6
|
||||
QList<double> getDataValues( QgsVectorLayer *vlayer );
|
||||
|
||||
//! Return the label format used to generate default classification labels
|
||||
//! @note Added in 2.6
|
||||
const QgsRendererRangeV2LabelFormat &labelFormat() const { return mLabelFormat; }
|
||||
//! Set the label format used to generate default classification labels
|
||||
//! @param labelFormat The string appended to classification labels
|
||||
//! @param updateRanges If true then ranges ending with the old unit string are updated to the new.
|
||||
//! @note Added in 2.6
|
||||
void setLabelFormat( const QgsRendererRangeV2LabelFormat &labelFormat, bool updateRanges=true );
|
||||
|
||||
//! Reset the label decimal places to a numberbased on the minimum class interval
|
||||
//! @param updateRanges if true then ranges currently using the default label will be updated
|
||||
//! @note Added in 2.6
|
||||
void calculateLabelDecimalPlaces( bool updateRanges=true );
|
||||
|
||||
static QgsGraduatedSymbolRendererV2* createRenderer(
|
||||
QgsVectorLayer* vlayer,
|
||||
@ -140,7 +210,9 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
Mode mode,
|
||||
QgsSymbolV2* symbol,
|
||||
QgsVectorColorRampV2* ramp,
|
||||
bool inverted = false );
|
||||
bool inverted = false,
|
||||
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat()
|
||||
);
|
||||
|
||||
//! create renderer from XML element
|
||||
static QgsFeatureRendererV2* create( QDomElement& element );
|
||||
@ -168,7 +240,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
/** Update the color ramp used. Also updates all symbols colors.
|
||||
* Doesn't alter current breaks.
|
||||
*/
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp, bool inverted = false );
|
||||
void updateColorRamp( QgsVectorColorRampV2* ramp=0, bool inverted = false );
|
||||
|
||||
/** Update all the symbols but leave breaks and colors. */
|
||||
void updateSymbols( QgsSymbolV2* sym );
|
||||
@ -193,11 +265,11 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
virtual bool legendSymbolItemsCheckable() const;
|
||||
|
||||
//! item in symbology was checked
|
||||
// @note added in 2.5
|
||||
//! @note added in 2.6
|
||||
virtual bool legendSymbolItemChecked( QString key );
|
||||
|
||||
//! item in symbology was checked
|
||||
// @note added in 2.5
|
||||
//! @note added in 2.6
|
||||
virtual void checkLegendSymbolItem( QString key, bool state = true );
|
||||
|
||||
//! If supported by the renderer, return classification attribute for the use in legend
|
||||
@ -205,7 +277,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
virtual QString legendClassificationAttribute() const { return classAttribute(); }
|
||||
|
||||
//! creates a QgsGraduatedSymbolRendererV2 from an existing renderer.
|
||||
//! @note added in 2.5
|
||||
//! @note added in 2.6
|
||||
//! @returns a new renderer if the conversion was possible, otherwise 0.
|
||||
static QgsGraduatedSymbolRendererV2* convertFromRenderer( const QgsFeatureRendererV2 *renderer );
|
||||
|
||||
@ -216,6 +288,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
QScopedPointer<QgsSymbolV2> mSourceSymbol;
|
||||
QScopedPointer<QgsVectorColorRampV2> mSourceColorRamp;
|
||||
bool mInvertedColorRamp;
|
||||
QgsRendererRangeV2LabelFormat mLabelFormat;
|
||||
QScopedPointer<QgsExpression> mRotation;
|
||||
QScopedPointer<QgsExpression> mSizeScale;
|
||||
QgsSymbolV2::ScaleMethod mScaleMethod;
|
||||
|
||||
@ -399,5 +399,11 @@ QgsSingleSymbolRendererV2* QgsSingleSymbolRendererV2::convertFromRenderer( const
|
||||
return convertFromRenderer( invertedPolygonRenderer->embeddedRenderer() );
|
||||
|
||||
}
|
||||
|
||||
QgsSymbolV2List symbols=const_cast<QgsFeatureRendererV2 *>(renderer)->symbols();
|
||||
if( symbols.size() > 0 )
|
||||
{
|
||||
return new QgsSingleSymbolRendererV2(symbols.at(0)->clone());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -202,4 +202,4 @@ void QgsAttributeTypeLoadDialog::accept()
|
||||
//store data to output variable
|
||||
loadDataToValueMap();
|
||||
QDialog::accept();
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,6 +338,11 @@ void QgsCategorizedSymbolRendererV2Model::sort( int column, Qt::SortOrder order
|
||||
QgsDebugMsg( "Done" );
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererV2Model::updateSymbology()
|
||||
{
|
||||
emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
|
||||
}
|
||||
|
||||
// ------------------------------ View style --------------------------------
|
||||
QgsCategorizedSymbolRendererV2ViewStyle::QgsCategorizedSymbolRendererV2ViewStyle( QStyle* style )
|
||||
: QProxyStyle( style )
|
||||
@ -405,8 +410,14 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
|
||||
cboCategorizedColorRamp->setCurrentIndex( index );
|
||||
}
|
||||
|
||||
mCategorizedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
|
||||
|
||||
mModel = new QgsCategorizedSymbolRendererV2Model( this );
|
||||
mModel->setRenderer( mRenderer );
|
||||
|
||||
// update GUI from renderer
|
||||
updateUiFromRenderer();
|
||||
|
||||
viewCategories->setModel( mModel );
|
||||
viewCategories->resizeColumnToContents( 0 );
|
||||
viewCategories->resizeColumnToContents( 1 );
|
||||
@ -414,8 +425,6 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
|
||||
|
||||
viewCategories->setStyle( new QgsCategorizedSymbolRendererV2ViewStyle( viewCategories->style() ) );
|
||||
|
||||
mCategorizedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() );
|
||||
|
||||
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
|
||||
|
||||
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
|
||||
@ -428,9 +437,8 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
|
||||
connect( btnDeleteCategories, SIGNAL( clicked() ), this, SLOT( deleteCategories() ) );
|
||||
connect( btnDeleteAllCategories, SIGNAL( clicked() ), this, SLOT( deleteAllCategories() ) );
|
||||
connect( btnAddCategory, SIGNAL( clicked() ), this, SLOT( addCategory() ) );
|
||||
|
||||
// update GUI from renderer
|
||||
updateUiFromRenderer();
|
||||
connect( cbxInvertedColorRamp, SIGNAL( toggled(bool)), this, SLOT( applyColorRamp()));
|
||||
connect( cboCategorizedColorRamp, SIGNAL(currentIndexChanged(int)), this, SLOT( applyColorRamp()));
|
||||
|
||||
// menus for data-defined rotation/size
|
||||
QMenu* advMenu = new QMenu;
|
||||
@ -453,16 +461,17 @@ QgsCategorizedSymbolRendererV2Widget::~QgsCategorizedSymbolRendererV2Widget()
|
||||
|
||||
void QgsCategorizedSymbolRendererV2Widget::updateUiFromRenderer()
|
||||
{
|
||||
// Note: This assumes that the signals for UI element changes have not
|
||||
// yet been connected, so that the updates to color ramp, symbol, etc
|
||||
// don't override existing customisations.
|
||||
|
||||
updateCategorizedSymbolIcon();
|
||||
|
||||
//mModel->setRenderer ( mRenderer ); // necessary?
|
||||
|
||||
// set column
|
||||
disconnect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
|
||||
QString attrName = mRenderer->classAttribute();
|
||||
mExpressionWidget->setField( attrName );
|
||||
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( categoryColumnChanged( QString ) ) );
|
||||
|
||||
|
||||
// set source symbol
|
||||
if ( mRenderer->sourceSymbol() )
|
||||
@ -585,7 +594,7 @@ void QgsCategorizedSymbolRendererV2Widget::changeCategorySymbol()
|
||||
mRenderer->updateCategorySymbol( catIdx, symbol );
|
||||
}
|
||||
|
||||
static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, QgsSymbolV2* symbol, QgsVectorColorRampV2* ramp, bool invert )
|
||||
static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, QgsSymbolV2* symbol )
|
||||
{
|
||||
// sort the categories first
|
||||
QgsSymbolLayerV2Utils::sortVariantList( values, Qt::AscendingOrder );
|
||||
@ -612,9 +621,7 @@ static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, Q
|
||||
{
|
||||
hasNull = true;
|
||||
}
|
||||
double x = ( invert ? num - i : i ) / ( double ) num;
|
||||
QgsSymbolV2* newSymbol = symbol->clone();
|
||||
newSymbol->setColor( ramp->color( x ) );
|
||||
|
||||
cats.append( QgsRendererCategoryV2( value, newSymbol, value.toString(), true ) );
|
||||
}
|
||||
@ -623,11 +630,24 @@ static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, Q
|
||||
if ( !hasNull )
|
||||
{
|
||||
QgsSymbolV2* newSymbol = symbol->clone();
|
||||
newSymbol->setColor( ramp->color( invert ? 0 : 1 ) );
|
||||
cats.append( QgsRendererCategoryV2( QVariant( "" ), newSymbol, QString(), true ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2Widget::getColorRamp()
|
||||
{
|
||||
QgsVectorColorRampV2* ramp = cboCategorizedColorRamp->currentColorRamp();
|
||||
if ( ramp == NULL )
|
||||
{
|
||||
if ( cboCategorizedColorRamp->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 ramp;
|
||||
}
|
||||
|
||||
|
||||
void QgsCategorizedSymbolRendererV2Widget::addCategories()
|
||||
{
|
||||
QString attrName = mExpressionWidget->currentField();
|
||||
@ -672,20 +692,8 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
|
||||
return;
|
||||
#endif
|
||||
|
||||
QgsVectorColorRampV2* ramp = cboCategorizedColorRamp->currentColorRamp();
|
||||
|
||||
if ( ramp == NULL )
|
||||
{
|
||||
if ( cboCategorizedColorRamp->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;
|
||||
}
|
||||
|
||||
QgsCategoryList cats;
|
||||
_createCategories( cats, unique_vals, mCategorizedSymbol, ramp, cbxInvertedColorRamp->isChecked() );
|
||||
|
||||
_createCategories( cats, unique_vals, mCategorizedSymbol );
|
||||
bool deleteExisting = false;
|
||||
|
||||
if ( !mOldClassificationAttribute.isEmpty() &&
|
||||
@ -706,9 +714,12 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
|
||||
deleteExisting = ( res == QMessageBox::Yes );
|
||||
}
|
||||
|
||||
// First element to apply coloring to
|
||||
bool keepExistingColors=false;
|
||||
if ( !deleteExisting )
|
||||
{
|
||||
QgsCategoryList prevCats = mRenderer->categories();
|
||||
keepExistingColors=prevCats.size() > 0;
|
||||
for ( int i = 0; i < cats.size(); ++i )
|
||||
{
|
||||
bool contains = false;
|
||||
@ -747,11 +758,12 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
|
||||
// recreate renderer
|
||||
QgsCategorizedSymbolRendererV2 *r = new QgsCategorizedSymbolRendererV2( attrName, cats );
|
||||
r->setSourceSymbol( mCategorizedSymbol->clone() );
|
||||
r->setSourceColorRamp( ramp->clone() );
|
||||
r->setScaleMethod( mRenderer->scaleMethod() );
|
||||
r->setSizeScaleField( mRenderer->sizeScaleField() );
|
||||
r->setRotationField( mRenderer->rotationField() );
|
||||
r->setInvertedColorRamp( cbxInvertedColorRamp->isChecked() );
|
||||
QgsVectorColorRampV2* ramp = getColorRamp();
|
||||
if( ramp ) r->setSourceColorRamp(ramp->clone());
|
||||
|
||||
if ( mModel )
|
||||
{
|
||||
@ -759,6 +771,17 @@ void QgsCategorizedSymbolRendererV2Widget::addCategories()
|
||||
}
|
||||
delete mRenderer;
|
||||
mRenderer = r;
|
||||
if( ! keepExistingColors && ramp ) applyColorRamp();
|
||||
}
|
||||
|
||||
void QgsCategorizedSymbolRendererV2Widget::applyColorRamp()
|
||||
{
|
||||
QgsVectorColorRampV2* ramp = getColorRamp();
|
||||
if( ramp )
|
||||
{
|
||||
mRenderer->updateColorRamp(ramp->clone(),cbxInvertedColorRamp->isChecked());
|
||||
}
|
||||
mModel->updateSymbology();
|
||||
}
|
||||
|
||||
int QgsCategorizedSymbolRendererV2Widget::currentCategoryRow()
|
||||
|
||||
@ -50,6 +50,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Model : public QAbstractItemModel
|
||||
void deleteRows( QList<int> rows );
|
||||
void removeAllRows( );
|
||||
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
|
||||
void updateSymbology();
|
||||
|
||||
signals:
|
||||
void rowsMoved();
|
||||
@ -85,6 +86,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg
|
||||
void categoriesDoubleClicked( const QModelIndex & idx );
|
||||
void addCategory();
|
||||
void addCategories();
|
||||
void applyColorRamp();
|
||||
void deleteCategories();
|
||||
void deleteAllCategories();
|
||||
|
||||
@ -116,6 +118,8 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg
|
||||
|
||||
void changeCategorySymbol();
|
||||
|
||||
QgsVectorColorRampV2* getColorRamp();
|
||||
|
||||
QList<QgsSymbolV2*> selectedSymbols();
|
||||
QgsCategoryList selectedCategoryList();
|
||||
void refreshSymbolView() { populateCategories(); }
|
||||
|
||||
@ -330,6 +330,16 @@ void QgsGraduatedSymbolRendererV2Model::sort( int column, Qt::SortOrder order )
|
||||
QgsDebugMsg( "Done" );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Model::updateSymbology()
|
||||
{
|
||||
emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->ranges().size(), 0 ) );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Model::updateLabels()
|
||||
{
|
||||
emit dataChanged( createIndex( 0, 2 ), createIndex( mRenderer->ranges().size(), 2 ) );
|
||||
}
|
||||
|
||||
// ------------------------------ View style --------------------------------
|
||||
QgsGraduatedSymbolRendererV2ViewStyle::QgsGraduatedSymbolRendererV2ViewStyle( QStyle* style )
|
||||
: QProxyStyle( style )
|
||||
@ -391,12 +401,6 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
|
||||
cboGraduatedColorRamp->setCurrentIndex( index );
|
||||
}
|
||||
|
||||
mModel = new QgsGraduatedSymbolRendererV2Model( this );
|
||||
mModel->setRenderer( mRenderer );
|
||||
viewGraduated->setModel( mModel );
|
||||
viewGraduated->resizeColumnToContents( 0 );
|
||||
viewGraduated->resizeColumnToContents( 1 );
|
||||
viewGraduated->resizeColumnToContents( 2 );
|
||||
|
||||
viewGraduated->setStyle( new QgsGraduatedSymbolRendererV2ViewStyle( viewGraduated->style() ) );
|
||||
|
||||
@ -407,8 +411,6 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
|
||||
connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) );
|
||||
connect( viewGraduated, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) );
|
||||
|
||||
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
|
||||
|
||||
connect( btnGraduatedClassify, SIGNAL( clicked() ), this, SLOT( classifyGraduated() ) );
|
||||
connect( btnChangeGraduatedSymbol, SIGNAL( clicked() ), this, SLOT( changeGraduatedSymbol() ) );
|
||||
connect( btnGraduatedDelete, SIGNAL( clicked() ), this, SLOT( deleteClasses() ) );
|
||||
@ -416,13 +418,11 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
|
||||
connect( btnGraduatedAdd, SIGNAL( clicked() ), this, SLOT( addClass() ) );
|
||||
connect( cbxLinkBoundaries, SIGNAL( toggled( bool ) ), this, SLOT( toggleBoundariesLink( bool ) ) );
|
||||
|
||||
connectUpdateHandlers();
|
||||
|
||||
// initialize from previously set renderer
|
||||
updateUiFromRenderer();
|
||||
|
||||
connect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
connect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
connect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
|
||||
|
||||
// menus for data-defined rotation/size
|
||||
QMenu* advMenu = new QMenu;
|
||||
|
||||
@ -447,22 +447,60 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2Widget::renderer()
|
||||
return mRenderer;
|
||||
}
|
||||
|
||||
// Connect/disconnect event handlers which trigger updating renderer
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer()
|
||||
void QgsGraduatedSymbolRendererV2Widget::connectUpdateHandlers()
|
||||
{
|
||||
connect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
connect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
connect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
|
||||
connect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ) , this, SLOT( reapplyColorRamp() ) );
|
||||
connect( spinDecimalPlaces, SIGNAL(valueChanged(int)), this, SLOT(labelFormatChanged()));
|
||||
connect( cbxTrimTrailingZeroes, SIGNAL(toggled(bool)),this,SLOT(labelFormatChanged()));
|
||||
connect( txtPrefix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
connect( txtSeparator, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
connect( txtSuffix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
|
||||
connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
|
||||
connect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex)), this, SLOT( modelDataChanged( )) );
|
||||
}
|
||||
|
||||
// Connect/disconnect event handlers which trigger updating renderer
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::disconnectUpdateHandlers()
|
||||
{
|
||||
disconnect( spinGraduatedClasses, SIGNAL( valueChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
disconnect( cboGraduatedMode, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( classifyGraduated() ) );
|
||||
disconnect( cboGraduatedColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( reapplyColorRamp() ) );
|
||||
disconnect( cbxInvertedColorRamp, SIGNAL( toggled( bool ) ) , this, SLOT( reapplyColorRamp() ) );
|
||||
disconnect( spinDecimalPlaces, SIGNAL(valueChanged(int)), this, SLOT(labelFormatChanged()));
|
||||
disconnect( cbxTrimTrailingZeroes, SIGNAL(toggled(bool)),this,SLOT(labelFormatChanged()));
|
||||
disconnect( txtPrefix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
disconnect( txtSeparator, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
disconnect( txtSuffix, SIGNAL( textChanged(QString)), this, SLOT(labelFormatChanged()));
|
||||
|
||||
disconnect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) );
|
||||
disconnect( mModel, SIGNAL( dataChanged(QModelIndex,QModelIndex)), this, SLOT( modelDataChanged( )) );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer( bool updateCount )
|
||||
{
|
||||
disconnectUpdateHandlers();
|
||||
|
||||
updateGraduatedSymbolIcon();
|
||||
|
||||
// update UI from the graduated renderer (update combo boxes, view)
|
||||
if ( mRenderer->mode() < cboGraduatedMode->count() )
|
||||
cboGraduatedMode->setCurrentIndex( mRenderer->mode() );
|
||||
if ( mRenderer->ranges().count() )
|
||||
|
||||
// Only update class count if different - otherwise typing value gets very messy
|
||||
int nclasses=mRenderer->ranges().count();
|
||||
if ( nclasses && updateCount )
|
||||
spinGraduatedClasses->setValue( mRenderer->ranges().count() );
|
||||
|
||||
// set column
|
||||
disconnect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) );
|
||||
QString attrName = mRenderer->classAttribute();
|
||||
mExpressionWidget->setField( attrName );
|
||||
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) );
|
||||
|
||||
// set source symbol
|
||||
if ( mRenderer->sourceSymbol() )
|
||||
@ -478,6 +516,22 @@ void QgsGraduatedSymbolRendererV2Widget::updateUiFromRenderer()
|
||||
cboGraduatedColorRamp->setSourceColorRamp( mRenderer->sourceColorRamp() );
|
||||
cbxInvertedColorRamp->setChecked( mRenderer->invertedColorRamp() );
|
||||
}
|
||||
|
||||
QgsRendererRangeV2LabelFormat labelFormat=mRenderer->labelFormat();
|
||||
txtPrefix->setText( labelFormat.prefix());
|
||||
txtSeparator->setText( labelFormat.separator() );
|
||||
txtSuffix->setText( labelFormat.suffix() );
|
||||
spinDecimalPlaces->setValue( labelFormat.decimalPlaces());
|
||||
cbxTrimTrailingZeroes->setChecked( labelFormat.trimTrailingZeroes());
|
||||
|
||||
mModel = new QgsGraduatedSymbolRendererV2Model( this );
|
||||
mModel->setRenderer( mRenderer );
|
||||
viewGraduated->setModel( mModel );
|
||||
viewGraduated->resizeColumnToContents( 0 );
|
||||
viewGraduated->resizeColumnToContents( 1 );
|
||||
viewGraduated->resizeColumnToContents( 2 );
|
||||
|
||||
connectUpdateHandlers();
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::graduatedColumnChanged( QString field )
|
||||
@ -489,7 +543,7 @@ void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
|
||||
{
|
||||
QString attrName = mExpressionWidget->currentField();
|
||||
|
||||
int classes = spinGraduatedClasses->value();
|
||||
int nclasses = spinGraduatedClasses->value();
|
||||
|
||||
QgsVectorColorRampV2* ramp = cboGraduatedColorRamp->currentColorRamp();
|
||||
|
||||
@ -524,26 +578,19 @@ void QgsGraduatedSymbolRendererV2Widget::classifyGraduated()
|
||||
}
|
||||
|
||||
// create and set new renderer
|
||||
|
||||
mRenderer->setClassAttribute(attrName);
|
||||
mRenderer->setMode(mode);
|
||||
mRenderer->setSourceColorRamp(ramp->clone());
|
||||
bool updateUiCount=true;
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
QgsGraduatedSymbolRendererV2* r = QgsGraduatedSymbolRendererV2::createRenderer(
|
||||
mLayer, attrName, classes, mode, mGraduatedSymbol, ramp, cbxInvertedColorRamp->isChecked() );
|
||||
mRenderer->updateClasses(mLayer,mode,nclasses);
|
||||
mRenderer->calculateLabelDecimalPlaces();
|
||||
QApplication::restoreOverrideCursor();
|
||||
if ( !r )
|
||||
{
|
||||
QMessageBox::critical( this, tr( "Error" ), tr( "Renderer creation has failed." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
r->setSizeScaleField( mRenderer->sizeScaleField() );
|
||||
r->setRotationField( mRenderer->rotationField() );
|
||||
r->setScaleMethod( mRenderer->scaleMethod() );
|
||||
|
||||
if ( mModel )
|
||||
{
|
||||
mModel->setRenderer( r );
|
||||
}
|
||||
delete mRenderer;
|
||||
mRenderer = r;
|
||||
// PrettyBreaks and StdDev calculation don't generate exact
|
||||
// number of classes - leave user interface unchanged for these
|
||||
updateUiCount=false;
|
||||
updateUiFromRenderer( updateUiCount );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::reapplyColorRamp()
|
||||
@ -644,8 +691,6 @@ void QgsGraduatedSymbolRendererV2Widget::rangesClicked( const QModelIndex & idx
|
||||
mRowSelected = idx.row();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::changeSelectedSymbols()
|
||||
{
|
||||
QItemSelectionModel* m = viewGraduated->selectionModel();
|
||||
@ -693,64 +738,35 @@ void QgsGraduatedSymbolRendererV2Widget::changeRange( int rangeIdx )
|
||||
QgsLUDialog dialog( this );
|
||||
|
||||
const QgsRendererRangeV2& range = mRenderer->ranges()[rangeIdx];
|
||||
dialog.setLowerValue( QString::number( range.lowerValue(), 'f', 4 ) );
|
||||
dialog.setUpperValue( QString::number( range.upperValue(), 'f', 4 ) );
|
||||
// Add arbitrary 3 to number of decimal places to retain a bit extra accuracy in
|
||||
// case we want to??
|
||||
int decimalPlaces=mRenderer->labelFormat().decimalPlaces();
|
||||
dialog.setLowerValue( QString::number( range.lowerValue(), 'f', decimalPlaces+3 ) );
|
||||
dialog.setUpperValue( QString::number( range.upperValue(), 'f', decimalPlaces+3 ) );
|
||||
|
||||
if ( dialog.exec() == QDialog::Accepted )
|
||||
{
|
||||
double lowerValue = dialog.lowerValue().toDouble();
|
||||
double upperValue = dialog.upperValue().toDouble();
|
||||
|
||||
QString label = createLabel( range.lowerValue(), range.upperValue() );
|
||||
QString newLabel;
|
||||
|
||||
mRenderer->updateRangeUpperValue( rangeIdx, upperValue );
|
||||
mRenderer->updateRangeLowerValue( rangeIdx, lowerValue );
|
||||
|
||||
//If the label was the label automatically generated, we generate a new one for the new range
|
||||
if ( range.label() == label )
|
||||
{
|
||||
newLabel = createLabel( lowerValue, upperValue );
|
||||
mRenderer->updateRangeLabel( rangeIdx, newLabel );
|
||||
}
|
||||
|
||||
//If the boundaries have to stay linked, we update the ranges above and below, as well as their label if needed
|
||||
if ( cbxLinkBoundaries->isChecked() )
|
||||
{
|
||||
if ( rangeIdx > 0 )
|
||||
{
|
||||
const QgsRendererRangeV2& rangeLower = mRenderer->ranges()[rangeIdx - 1];
|
||||
label = createLabel( rangeLower.lowerValue(), rangeLower.upperValue() );
|
||||
mRenderer->updateRangeUpperValue( rangeIdx - 1, lowerValue );
|
||||
|
||||
if ( label == rangeLower.label() )
|
||||
{
|
||||
newLabel = createLabel( rangeLower.lowerValue(), lowerValue );
|
||||
mRenderer->updateRangeLabel( rangeIdx - 1, newLabel );
|
||||
}
|
||||
}
|
||||
|
||||
if ( rangeIdx < mRenderer->ranges().size() - 1 )
|
||||
{
|
||||
const QgsRendererRangeV2& rangeUpper = mRenderer->ranges()[rangeIdx + 1];
|
||||
label = createLabel( rangeUpper.lowerValue(), rangeUpper.upperValue() );
|
||||
mRenderer->updateRangeLowerValue( rangeIdx + 1, upperValue );
|
||||
|
||||
if ( label == rangeUpper.label() )
|
||||
{
|
||||
newLabel = createLabel( upperValue, rangeUpper.upperValue() );
|
||||
mRenderer->updateRangeLabel( rangeIdx + 1, newLabel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsGraduatedSymbolRendererV2Widget::createLabel( double lowerValue, double upperValue )
|
||||
{
|
||||
return QString::number( lowerValue , 'f', 4 ) + " - " + QString::number( upperValue, 'f', 4 );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::addClass()
|
||||
{
|
||||
mModel->addClass( mGraduatedSymbol );
|
||||
@ -767,12 +783,46 @@ void QgsGraduatedSymbolRendererV2Widget::deleteAllClasses()
|
||||
mModel->removeAllRows();
|
||||
}
|
||||
|
||||
bool QgsGraduatedSymbolRendererV2Widget::rowsOrdered()
|
||||
{
|
||||
const QgsRangeList &ranges = mRenderer->ranges();
|
||||
bool ordered=true;
|
||||
for ( int i = 1;i < ranges.size();++i )
|
||||
{
|
||||
if( ranges[i] < ranges[i-1] )
|
||||
{
|
||||
ordered=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ordered;
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::toggleBoundariesLink( bool linked )
|
||||
{
|
||||
//If the checkbox controlling the link between boundaries was unchecked and we check it, we have to link the boundaries
|
||||
//This is done by updating all lower ranges to the upper value of the range above
|
||||
if ( linked )
|
||||
{
|
||||
// Cannot link ranges if they are not sorted - results will be crazy
|
||||
// qSort( mRenderer->ranges() );
|
||||
// Could not get qSort to work with copy/swap idiom on QgsVectorRange
|
||||
|
||||
if( ! rowsOrdered() )
|
||||
{
|
||||
int result=QMessageBox::warning(
|
||||
this,
|
||||
tr("Linked range warning"),
|
||||
tr("Linking ranges that are not ordered may produced unexpected results. Proceed?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel );
|
||||
if( result != QMessageBox::Ok )
|
||||
{
|
||||
cbxLinkBoundaries->setChecked( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok to proceed
|
||||
for ( int i = 1;i < mRenderer->ranges().size();++i )
|
||||
{
|
||||
mRenderer->updateRangeLowerValue( i, mRenderer->ranges()[i-1].upperValue() );
|
||||
@ -806,6 +856,19 @@ void QgsGraduatedSymbolRendererV2Widget::scaleMethodChanged( QgsSymbolV2::ScaleM
|
||||
mRenderer->setScaleMethod( scaleMethod );
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::labelFormatChanged()
|
||||
{
|
||||
QgsRendererRangeV2LabelFormat labelFormat=QgsRendererRangeV2LabelFormat(
|
||||
txtPrefix->text(),
|
||||
txtSeparator->text(),
|
||||
txtSuffix->text(),
|
||||
spinDecimalPlaces->value(),
|
||||
cbxTrimTrailingZeroes->isChecked());
|
||||
mRenderer->setLabelFormat(labelFormat,true);
|
||||
mModel->updateLabels();
|
||||
}
|
||||
|
||||
|
||||
QList<QgsSymbolV2*> QgsGraduatedSymbolRendererV2Widget::selectedSymbols()
|
||||
{
|
||||
QList<QgsSymbolV2*> selectedSymbols;
|
||||
@ -851,6 +914,10 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2Widget::findSymbolForRange( double lowe
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::refreshSymbolView()
|
||||
{
|
||||
if( mModel )
|
||||
{
|
||||
mModel->updateSymbology();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::showSymbolLevels()
|
||||
@ -863,6 +930,14 @@ void QgsGraduatedSymbolRendererV2Widget::rowsMoved()
|
||||
viewGraduated->selectionModel()->clear();
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::modelDataChanged()
|
||||
{
|
||||
if( ! rowsOrdered() )
|
||||
{
|
||||
cbxLinkBoundaries->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGraduatedSymbolRendererV2Widget::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
if ( !event )
|
||||
|
||||
@ -49,6 +49,8 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Model : public QAbstractItemModel
|
||||
void deleteRows( QList<int> rows );
|
||||
void removeAllRows( );
|
||||
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
|
||||
void updateSymbology();
|
||||
void updateLabels();
|
||||
|
||||
signals:
|
||||
void rowsMoved();
|
||||
@ -100,13 +102,18 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
|
||||
void rotationFieldChanged( QString fldName );
|
||||
void sizeScaleFieldChanged( QString fldName );
|
||||
void scaleMethodChanged( QgsSymbolV2::ScaleMethod scaleMethod );
|
||||
void labelFormatChanged();
|
||||
|
||||
void showSymbolLevels();
|
||||
|
||||
void rowsMoved();
|
||||
void modelDataChanged();
|
||||
|
||||
protected:
|
||||
void updateUiFromRenderer();
|
||||
void updateUiFromRenderer( bool updateCount=true );
|
||||
void connectUpdateHandlers();
|
||||
void disconnectUpdateHandlers();
|
||||
bool rowsOrdered();
|
||||
|
||||
void updateGraduatedSymbolIcon();
|
||||
|
||||
@ -117,8 +124,6 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget
|
||||
void changeRangeSymbol( int rangeIdx );
|
||||
void changeRange( int rangeIdx );
|
||||
|
||||
QString createLabel( double lowerValue, double upperValue );
|
||||
|
||||
void changeSelectedSymbols();
|
||||
|
||||
QList<QgsSymbolV2*> selectedSymbols();
|
||||
|
||||
@ -6,36 +6,20 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>615</width>
|
||||
<width>637</width>
|
||||
<height>339</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout">
|
||||
<item row="5" column="0">
|
||||
<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="5" column="2">
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Mode</string>
|
||||
@ -48,7 +32,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<item row="6" column="0">
|
||||
<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="6" column="3">
|
||||
<widget class="QComboBox" name="cboGraduatedMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
@ -77,7 +71,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Symbol</string>
|
||||
@ -87,7 +81,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="btnChangeGraduatedSymbol">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
@ -100,7 +94,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="spinGraduatedClasses">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
@ -119,7 +113,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Classes</string>
|
||||
@ -132,14 +126,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QgsColorRampComboBox" name="cboGraduatedColorRamp"/>
|
||||
@ -153,13 +140,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<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>
|
||||
@ -183,6 +183,104 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Label </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtPrefix</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtPrefix">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>#.##</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtSeparator">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>#.##</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtSuffix">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Decimal places</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>spinDecimalPlaces</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinDecimalPlaces">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbxTrimTrailingZeroes">
|
||||
<property name="text">
|
||||
<string>Trim</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -243,7 +341,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbxLinkBoundaries">
|
||||
<property name="text">
|
||||
<string>Link classes boundaries</string>
|
||||
<string>Link class boundaries</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
@ -288,14 +386,32 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>txtPrefix</tabstop>
|
||||
<tabstop>txtSeparator</tabstop>
|
||||
<tabstop>txtSuffix</tabstop>
|
||||
<tabstop>spinDecimalPlaces</tabstop>
|
||||
<tabstop>cbxTrimTrailingZeroes</tabstop>
|
||||
<tabstop>btnChangeGraduatedSymbol</tabstop>
|
||||
<tabstop>spinGraduatedClasses</tabstop>
|
||||
<tabstop>cboGraduatedColorRamp</tabstop>
|
||||
<tabstop>cbxInvertedColorRamp</tabstop>
|
||||
<tabstop>spinGraduatedClasses</tabstop>
|
||||
<tabstop>cboGraduatedMode</tabstop>
|
||||
<tabstop>viewGraduated</tabstop>
|
||||
<tabstop>btnGraduatedClassify</tabstop>
|
||||
<tabstop>btnGraduatedAdd</tabstop>
|
||||
<tabstop>btnGraduatedDelete</tabstop>
|
||||
<tabstop>btnDeleteAllClasses</tabstop>
|
||||
<tabstop>cbxLinkBoundaries</tabstop>
|
||||
<tabstop>btnAdvanced</tabstop>
|
||||
<tabstop>cboGraduatedMode_2</tabstop>
|
||||
<tabstop>btnChangeGraduatedSymbol_2</tabstop>
|
||||
<tabstop>spinGraduatedClasses_2</tabstop>
|
||||
<tabstop>cboGraduatedColorRamp_2</tabstop>
|
||||
<tabstop>cbxInvertedColorRamp_2</tabstop>
|
||||
<tabstop>spinDecimalPlaces_2</tabstop>
|
||||
<tabstop>txtPrefix_4</tabstop>
|
||||
<tabstop>txtPrefix_5</tabstop>
|
||||
<tabstop>txtPrefix_6</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user