void QgsGraduatedSymbolRendererV2::updateClasses( QgsVectorLayer *vlayer, Mode mode, int nclasses ) { if ( mAttrName.isEmpty() ) return; setMode( mode ); // Custom classes are not recalculated if ( mode == Custom ) return; if ( nclasses < 1 ) nclasses = 1; QList<double> values; bool valuesLoaded = false; double minimum; double maximum; int attrNum = vlayer->fieldNameIndex( mAttrName ); bool ok; if ( attrNum == -1 ) { values = vlayer->getDoubleValues( mAttrName, ok ); if ( !ok || values.isEmpty() ) return; qSort( values ); // vmora: is wondering if O( n log(n) ) is really necessary here, min and max are O( n ) minimum = values.first(); maximum = values.last(); valuesLoaded = true; } else { minimum = vlayer->minimumValue( attrNum ).toDouble(); maximum = vlayer->maximumValue( attrNum ).toDouble(); } QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) ); QList<double> breaks; QList<double> labels; if ( mode == EqualInterval ) { breaks = _calcEqualIntervalBreaks( minimum, maximum, nclasses ); } else if ( mode == Pretty ) { breaks = QgsSymbolLayerV2Utils::prettyBreaks( minimum, maximum, nclasses ); } else if ( mode == Quantile || mode == Jenks || mode == StdDev ) { // get values from layer if ( !valuesLoaded ) { values = vlayer->getDoubleValues( mAttrName, ok ); } // calculate the breaks if ( mode == Quantile ) { breaks = _calcQuantileBreaks( values, nclasses ); } else if ( mode == Jenks ) { breaks = _calcJenksBreaks( values, nclasses, minimum, maximum ); } else if ( mode == StdDev ) { breaks = _calcStdDevBreaks( values, nclasses, labels ); } } else { Q_ASSERT( false ); } 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], 'f', 2 ) + " Std Dev"; } else if ( i == labels.count() - 1 ) { label = ">= " + QString::number( labels[i-1], 'f', 2 ) + " Std Dev"; } else { label = QString::number( labels[i-1], 'f', 2 ) + " Std Dev" + " - " + QString::number( labels[i], 'f', 2 ) + " Std Dev"; } } else { label = mLabelFormat.labelForRange( lower, upper ); } QgsSymbolV2* newSymbol = mSourceSymbol ? mSourceSymbol->clone() : QgsSymbolV2::defaultSymbol( vlayer->geometryType() ); addClass( QgsRendererRangeV2( lower, upper, newSymbol, label ) ); } updateColorRamp( 0, mInvertedColorRamp ); }
QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) : QgsRendererV2Widget( layer, style ) , mRenderer( nullptr ) , mModel( nullptr ) { // try to recognize the previous renderer // (null renderer means "no previous renderer") if ( renderer ) { mRenderer = QgsGraduatedSymbolRendererV2::convertFromRenderer( renderer ); } if ( !mRenderer ) { mRenderer = new QgsGraduatedSymbolRendererV2( "", QgsRangeList() ); } // setup user interface setupUi( this ); mModel = new QgsGraduatedSymbolRendererV2Model( this ); mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date ); mExpressionWidget->setLayer( mLayer ); mSizeUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels ); cboGraduatedColorRamp->populate( mStyle ); spinPrecision->setMinimum( QgsRendererRangeV2LabelFormat::MinPrecision ); spinPrecision->setMaximum( QgsRendererRangeV2LabelFormat::MaxPrecision ); // set project default color ramp QString defaultColorRamp = QgsProject::instance()->readEntry( "DefaultStyles", "/ColorRamp", "" ); if ( defaultColorRamp != "" ) { int index = cboGraduatedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive ); if ( index >= 0 ) cboGraduatedColorRamp->setCurrentIndex( index ); } viewGraduated->setStyle( new QgsGraduatedSymbolRendererV2ViewStyle( viewGraduated->style() ) ); mGraduatedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() ); methodComboBox->blockSignals( true ); methodComboBox->addItem( "Color" ); if ( mGraduatedSymbol->type() == QgsSymbolV2::Marker ) { methodComboBox->addItem( "Size" ); minSizeSpinBox->setValue( 1 ); maxSizeSpinBox->setValue( 8 ); } else if ( mGraduatedSymbol->type() == QgsSymbolV2::Line ) { methodComboBox->addItem( "Size" ); minSizeSpinBox->setValue( .1 ); maxSizeSpinBox->setValue( 2 ); } methodComboBox->blockSignals( false ); connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) ); connect( viewGraduated, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( rangesDoubleClicked( const QModelIndex & ) ) ); connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) ); connect( viewGraduated, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) ); connect( btnGraduatedClassify, SIGNAL( clicked() ), this, SLOT( classifyGraduated() ) ); connect( btnChangeGraduatedSymbol, SIGNAL( clicked() ), this, SLOT( changeGraduatedSymbol() ) ); connect( btnGraduatedDelete, SIGNAL( clicked() ), this, SLOT( deleteClasses() ) ); connect( btnDeleteAllClasses, SIGNAL( clicked() ), this, SLOT( deleteAllClasses() ) ); connect( btnGraduatedAdd, SIGNAL( clicked() ), this, SLOT( addClass() ) ); connect( cbxLinkBoundaries, SIGNAL( toggled( bool ) ), this, SLOT( toggleBoundariesLink( bool ) ) ); connect( mSizeUnitWidget, SIGNAL( changed() ), this, SLOT( on_mSizeUnitWidget_changed() ) ); connectUpdateHandlers(); // initialize from previously set renderer updateUiFromRenderer(); // menus for data-defined rotation/size QMenu* advMenu = new QMenu; advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) ); btnAdvanced->setMenu( advMenu ); mHistogramWidget->setLayer( mLayer ); mHistogramWidget->setRenderer( mRenderer ); connect( mHistogramWidget, SIGNAL( rangesModified( bool ) ), this, SLOT( refreshRanges( bool ) ) ); connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), mHistogramWidget, SLOT( setSourceFieldExp( QString ) ) ); mExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, this ); }
QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) : QgsRendererV2Widget( layer, style ) , mRenderer( 0 ) , mModel( 0 ) { // try to recognize the previous renderer // (null renderer means "no previous renderer") if ( !renderer || renderer->type() != "graduatedSymbol" ) { // we're not going to use it - so let's delete the renderer delete renderer; mRenderer = new QgsGraduatedSymbolRendererV2( "", QgsRangeList() ); } else { mRenderer = static_cast<QgsGraduatedSymbolRendererV2*>( renderer ); } // setup user interface setupUi( this ); mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date ); mExpressionWidget->setLayer( mLayer ); cboGraduatedColorRamp->populate( mStyle ); // set project default color ramp QString defaultColorRamp = QgsProject::instance()->readEntry( "DefaultStyles", "/ColorRamp", "" ); if ( defaultColorRamp != "" ) { int index = cboGraduatedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive ); if ( index >= 0 ) 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() ) ); mGraduatedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() ); connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), this, SLOT( graduatedColumnChanged( QString ) ) ); connect( viewGraduated, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( rangesDoubleClicked( const QModelIndex & ) ) ); connect( viewGraduated, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( rangesClicked( const QModelIndex & ) ) ); 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() ) ); connect( btnDeleteAllClasses, SIGNAL( clicked() ), this, SLOT( deleteAllClasses() ) ); connect( btnGraduatedAdd, SIGNAL( clicked() ), this, SLOT( addClass() ) ); // 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; advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) ); mDataDefinedMenus = new QgsRendererV2DataDefinedMenus( advMenu, mLayer, mRenderer->rotationField(), mRenderer->sizeScaleField(), mRenderer->scaleMethod() ); connect( mDataDefinedMenus, SIGNAL( rotationFieldChanged( QString ) ), this, SLOT( rotationFieldChanged( QString ) ) ); connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) ); connect( mDataDefinedMenus, SIGNAL( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ), this, SLOT( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ) ); btnAdvanced->setMenu( advMenu ); }