diff --git a/python/core/symbology-ng-core.sip b/python/core/symbology-ng-core.sip index fde8df2c4f9..f53d580949e 100644 --- a/python/core/symbology-ng-core.sip +++ b/python/core/symbology-ng-core.sip @@ -249,6 +249,16 @@ public: QgsVectorColorRampV2* sourceColorRamp(); void setSourceColorRamp(QgsVectorColorRampV2* ramp /Transfer/); + //! @note added in 1.6 + void setRotationField( QString fieldName ); + //! @note added in 1.6 + QString rotationField() const; + + //! @note added in 1.6 + void setSizeScaleField( QString fieldName ); + //! @note added in 1.6 + QString sizeScaleField() const; + protected: QgsSymbolV2* symbolForValue(QVariant value); @@ -348,6 +358,16 @@ public: QgsVectorColorRampV2* sourceColorRamp(); void setSourceColorRamp(QgsVectorColorRampV2* ramp /Transfer/); + //! @note added in 1.6 + void setRotationField( QString fieldName ); + //! @note added in 1.6 + QString rotationField() const; + + //! @note added in 1.6 + void setSizeScaleField( QString fieldName ); + //! @note added in 1.6 + QString sizeScaleField() const; + protected: QgsSymbolV2* symbolForValue(double value); }; diff --git a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp index 8c8170abb89..4e90eb873bf 100644 --- a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp +++ b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp @@ -120,8 +120,8 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value ) QgsDebugMsg( "attribute value not found: " + value.toString() ); return NULL; } - else - return *it; + + return *it; } QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& feature ) @@ -134,8 +134,40 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu return NULL; } - // find the right category - return symbolForValue( *ita ); + // find the right symbol for the category + QgsSymbolV2* symbol = symbolForValue( *ita ); + + if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 ) + return symbol; // no data-defined rotation/scaling - just return the symbol + + // find out rotation, size scale + double rotation = 0; + double sizeScale = 1; + if ( mRotationFieldIdx != -1 ) + rotation = attrMap[mRotationFieldIdx].toDouble(); + if ( mSizeScaleFieldIdx != -1 ) + sizeScale = attrMap[mSizeScaleFieldIdx].toDouble(); + + // take a temporary symbol (or create it if doesn't exist) + QgsSymbolV2* tempSymbol = mTempSymbols[ita->toString()]; + + // modify the temporary symbol and return it + if ( tempSymbol->type() == QgsSymbolV2::Marker ) + { + QgsMarkerSymbolV2* markerSymbol = static_cast( tempSymbol ); + if ( mRotationFieldIdx != -1 ) + markerSymbol->setAngle( rotation ); + if ( mSizeScaleFieldIdx != -1 ) + markerSymbol->setSize( sizeScale * static_cast( symbol )->size() ); + } + else if ( tempSymbol->type() == QgsSymbolV2::Line ) + { + QgsLineSymbolV2* lineSymbol = static_cast( tempSymbol ); + if ( mSizeScaleFieldIdx != -1 ) + lineSymbol->setWidth( sizeScale * static_cast( symbol )->width() ); + } + + return tempSymbol; } int QgsCategorizedSymbolRendererV2::categoryIndexForValue( QVariant val ) @@ -206,9 +238,24 @@ void QgsCategorizedSymbolRendererV2::startRender( QgsRenderContext& context, con // find out classification attribute index from name mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1; + mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) ); + mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) ); + QgsCategoryList::iterator it = mCategories.begin(); for ( ; it != mCategories.end(); ++it ) + { it->symbol()->startRender( context ); + + if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 ) + { + QgsSymbolV2* tempSymbol = it->symbol()->clone(); + tempSymbol->setRenderHints(( mRotationFieldIdx != -1 ? QgsSymbolV2::DataDefinedRotation : 0 ) | + ( mSizeScaleFieldIdx != -1 ? QgsSymbolV2::DataDefinedSizeScale : 0 ) ); + tempSymbol->startRender( context ); + mTempSymbols[ it->value().toString()] = tempSymbol; + } + } + } void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context ) @@ -216,12 +263,25 @@ void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context ) QgsCategoryList::iterator it = mCategories.begin(); for ( ; it != mCategories.end(); ++it ) it->symbol()->stopRender( context ); + + // cleanup mTempSymbols + QHash::iterator it2 = mTempSymbols.begin(); + for ( ; it2 != mTempSymbols.end(); ++it2 ) + { + it2.value()->stopRender( context ); + delete it2.value(); + } + mTempSymbols.clear(); } QList QgsCategorizedSymbolRendererV2::usedAttributes() { QList lst; lst.append( mAttrName ); + if ( !mRotationField.isEmpty() ) + lst.append( mRotationField ); + if ( !mSizeScaleField.isEmpty() ) + lst.append( mSizeScaleField ); return lst; } @@ -241,6 +301,8 @@ QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::clone() if ( mSourceColorRamp ) r->setSourceColorRamp( mSourceColorRamp->clone() ); r->setUsingSymbolLevels( usingSymbolLevels() ); + r->setRotationField( rotationField() ); + r->setSizeScaleField( sizeScaleField() ); return r; } @@ -308,6 +370,14 @@ QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::create( QDomElement& eleme r->setSourceColorRamp( QgsSymbolLayerV2Utils::loadColorRamp( sourceColorRampElem ) ); } + QDomElement rotationElem = element.firstChildElement( "rotation" ); + if ( !rotationElem.isNull() ) + r->setRotationField( rotationElem.attribute( "field" ) ); + + QDomElement sizeScaleElem = element.firstChildElement( "sizescale" ); + if ( !sizeScaleElem.isNull() ) + r->setSizeScaleField( sizeScaleElem.attribute( "field" ) ); + // TODO: symbol levels return r; } @@ -360,6 +430,14 @@ QDomElement QgsCategorizedSymbolRendererV2::save( QDomDocument& doc ) rendererElem.appendChild( colorRampElem ); } + QDomElement rotationElem = doc.createElement( "rotation" ); + rotationElem.setAttribute( "field", mRotationField ); + rendererElem.appendChild( rotationElem ); + + QDomElement sizeScaleElem = doc.createElement( "sizescale" ); + sizeScaleElem.setAttribute( "field", mSizeScaleField ); + rendererElem.appendChild( sizeScaleElem ); + return rendererElem; } diff --git a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.h b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.h index 3ab926c9133..b3fa72840c4 100644 --- a/src/core/symbology-ng/qgscategorizedsymbolrendererv2.h +++ b/src/core/symbology-ng/qgscategorizedsymbolrendererv2.h @@ -96,18 +96,34 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2 QgsVectorColorRampV2* sourceColorRamp(); void setSourceColorRamp( QgsVectorColorRampV2* ramp ); + //! @note added in 1.6 + void setRotationField( QString fieldName ) { mRotationField = fieldName; } + //! @note added in 1.6 + QString rotationField() const { return mRotationField; } + + //! @note added in 1.6 + void setSizeScaleField( QString fieldName ) { mSizeScaleField = fieldName; } + //! @note added in 1.6 + QString sizeScaleField() const { return mSizeScaleField; } + protected: QString mAttrName; QgsCategoryList mCategories; QgsSymbolV2* mSourceSymbol; QgsVectorColorRampV2* mSourceColorRamp; + QString mRotationField; + QString mSizeScaleField; //! attribute index (derived from attribute name in startRender) int mAttrNum; + int mRotationFieldIdx, mSizeScaleFieldIdx; //! hashtable for faster access to symbols QHash mSymbolHash; + //! temporary symbols, used for data-defined rotation and scaling + QHash mTempSymbols; + void rebuildHash(); QgsSymbolV2* symbolForValue( QVariant value ); diff --git a/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp b/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp index 109547b413e..6056b054971 100644 --- a/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp +++ b/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp @@ -120,8 +120,39 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature } // find the right category - return symbolForValue( ita->toDouble() ); + QgsSymbolV2* symbol = symbolForValue( ita->toDouble() ); + + if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 ) + return symbol; // no data-defined rotation/scaling - just return the symbol + + // find out rotation, size scale + double rotation = 0; + double sizeScale = 1; + if ( mRotationFieldIdx != -1 ) + rotation = attrMap[mRotationFieldIdx].toDouble(); + if ( mSizeScaleFieldIdx != -1 ) + sizeScale = attrMap[mSizeScaleFieldIdx].toDouble(); + + // take a temporary symbol (or create it if doesn't exist) + QgsSymbolV2* tempSymbol = mTempSymbols[symbol]; + + // modify the temporary symbol and return it + if ( tempSymbol->type() == QgsSymbolV2::Marker ) + { + QgsMarkerSymbolV2* markerSymbol = static_cast( tempSymbol ); + if ( mRotationFieldIdx != -1 ) + markerSymbol->setAngle( rotation ); + if ( mSizeScaleFieldIdx != -1 ) + markerSymbol->setSize( sizeScale * static_cast( symbol )->size() ); + } + else if ( tempSymbol->type() == QgsSymbolV2::Line ) + { + QgsLineSymbolV2* lineSymbol = static_cast( tempSymbol ); + if ( mSizeScaleFieldIdx != -1 ) + lineSymbol->setWidth( sizeScale * static_cast( symbol )->width() ); + } + return tempSymbol; } void QgsGraduatedSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer ) @@ -129,9 +160,23 @@ void QgsGraduatedSymbolRendererV2::startRender( QgsRenderContext& context, const // find out classification attribute index from name mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1; + mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) ); + mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) ); + QgsRangeList::iterator it = mRanges.begin(); for ( ; it != mRanges.end(); ++it ) + { it->symbol()->startRender( context ); + + if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 ) + { + QgsSymbolV2* tempSymbol = it->symbol()->clone(); + tempSymbol->setRenderHints(( mRotationFieldIdx != -1 ? QgsSymbolV2::DataDefinedRotation : 0 ) | + ( mSizeScaleFieldIdx != -1 ? QgsSymbolV2::DataDefinedSizeScale : 0 ) ); + tempSymbol->startRender( context ); + mTempSymbols[ it->symbol()] = tempSymbol; + } + } } void QgsGraduatedSymbolRendererV2::stopRender( QgsRenderContext& context ) @@ -139,12 +184,25 @@ void QgsGraduatedSymbolRendererV2::stopRender( QgsRenderContext& context ) QgsRangeList::iterator it = mRanges.begin(); for ( ; it != mRanges.end(); ++it ) it->symbol()->startRender( context ); + + // cleanup mTempSymbols + QHash::iterator it2 = mTempSymbols.begin(); + for ( ; it2 != mTempSymbols.end(); ++it2 ) + { + it2.value()->stopRender( context ); + delete it2.value(); + } + mTempSymbols.clear(); } QList QgsGraduatedSymbolRendererV2::usedAttributes() { QList lst; lst.append( mAttrName ); + if ( !mRotationField.isEmpty() ) + lst.append( mRotationField ); + if ( !mSizeScaleField.isEmpty() ) + lst.append( mSizeScaleField ); return lst; } @@ -196,6 +254,8 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::clone() if ( mSourceColorRamp ) r->setSourceColorRamp( mSourceColorRamp->clone() ); r->setUsingSymbolLevels( usingSymbolLevels() ); + r->setRotationField( rotationField() ); + r->setSizeScaleField( sizeScaleField() ); return r; } @@ -392,6 +452,14 @@ QgsFeatureRendererV2* QgsGraduatedSymbolRendererV2::create( QDomElement& element r->setMode( Quantile ); } + QDomElement rotationElem = element.firstChildElement( "rotation" ); + if ( !rotationElem.isNull() ) + r->setRotationField( rotationElem.attribute( "field" ) ); + + QDomElement sizeScaleElem = element.firstChildElement( "sizescale" ); + if ( !sizeScaleElem.isNull() ) + r->setSizeScaleField( sizeScaleElem.attribute( "field" ) ); + // TODO: symbol levels return r; } @@ -458,6 +526,14 @@ QDomElement QgsGraduatedSymbolRendererV2::save( QDomDocument& doc ) rendererElem.appendChild( modeElem ); } + QDomElement rotationElem = doc.createElement( "rotation" ); + rotationElem.setAttribute( "field", mRotationField ); + rendererElem.appendChild( rotationElem ); + + QDomElement sizeScaleElem = doc.createElement( "sizescale" ); + sizeScaleElem.setAttribute( "field", mSizeScaleField ); + rendererElem.appendChild( sizeScaleElem ); + return rendererElem; } diff --git a/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h b/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h index d53e9123c60..34566b529af 100644 --- a/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h +++ b/src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h @@ -107,15 +107,31 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2 QgsVectorColorRampV2* sourceColorRamp(); void setSourceColorRamp( QgsVectorColorRampV2* ramp ); + //! @note added in 1.6 + void setRotationField( QString fieldName ) { mRotationField = fieldName; } + //! @note added in 1.6 + QString rotationField() const { return mRotationField; } + + //! @note added in 1.6 + void setSizeScaleField( QString fieldName ) { mSizeScaleField = fieldName; } + //! @note added in 1.6 + QString sizeScaleField() const { return mSizeScaleField; } + protected: QString mAttrName; QgsRangeList mRanges; Mode mMode; QgsSymbolV2* mSourceSymbol; QgsVectorColorRampV2* mSourceColorRamp; + QString mRotationField; + QString mSizeScaleField; //! attribute index (derived from attribute name in startRender) int mAttrNum; + int mRotationFieldIdx, mSizeScaleFieldIdx; + + //! temporary symbols, used for data-defined rotation and scaling + QHash mTempSymbols; QgsSymbolV2* symbolForValue( double value ); }; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 8f5f34e73cf..2073e102884 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -65,6 +65,7 @@ symbology-ng/qgssinglesymbolrendererv2widget.h symbology-ng/qgscategorizedsymbolrendererv2widget.h symbology-ng/qgsgraduatedsymbolrendererv2widget.h symbology-ng/qgsrulebasedrendererv2widget.h +symbology-ng/qgsrendererv2widget.h symbology-ng/qgsrendererv2propertiesdialog.h symbology-ng/qgsstylev2managerdialog.h symbology-ng/qgssymbollevelsv2dialog.h diff --git a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp index cf4435a5e8a..f10ad2bc163 100644 --- a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp +++ b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp @@ -12,6 +12,7 @@ #include "qgsvectorlayer.h" #include "qgsvectordataprovider.h" // for uniqueValues +#include #include #include #include @@ -69,6 +70,14 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV // update GUI from renderer updateUiFromRenderer(); + + // menus for data-defined rotation/size + QMenu* advMenu = new QMenu; + mDataDefinedMenus = new QgsRendererV2DataDefinedMenus( advMenu, mLayer->pendingFields(), + mRenderer->rotationField(), mRenderer->sizeScaleField() ); + connect( mDataDefinedMenus, SIGNAL( rotationFieldChanged( QString ) ), this, SLOT( rotationFieldChanged( QString ) ) ); + connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) ); + btnAdvanced->setMenu( advMenu ); } QgsCategorizedSymbolRendererV2Widget::~QgsCategorizedSymbolRendererV2Widget() @@ -406,3 +415,13 @@ void QgsCategorizedSymbolRendererV2Widget::addCategory() addCategory( cat ); mRenderer->addCategory( cat ); } + +void QgsCategorizedSymbolRendererV2Widget::rotationFieldChanged( QString fldName ) +{ + mRenderer->setRotationField( fldName ); +} + +void QgsCategorizedSymbolRendererV2Widget::sizeScaleFieldChanged( QString fldName ) +{ + mRenderer->setSizeScaleField( fldName ); +} diff --git a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.h b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.h index c9271b5f9cc..06e6cbfe8b6 100644 --- a/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.h +++ b/src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.h @@ -31,6 +31,9 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg void deleteAllCategories(); void changeCurrentValue( QStandardItem * item ); + void rotationFieldChanged( QString fldName ); + void sizeScaleFieldChanged( QString fldName ); + protected slots: void addCategory(); @@ -63,6 +66,8 @@ class GUI_EXPORT QgsCategorizedSymbolRendererV2Widget : public QgsRendererV2Widg QgsSymbolV2* mCategorizedSymbol; + QgsRendererV2DataDefinedMenus* mDataDefinedMenus; + private: QString mOldClassificationAttribute; }; diff --git a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp index 832452b85a1..fe0eb72f9b0 100644 --- a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp +++ b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp @@ -13,6 +13,7 @@ #include "qgsludialog.h" +#include #include #include #include @@ -67,6 +68,14 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto // initialize from previously set renderer updateUiFromRenderer(); + + // menus for data-defined rotation/size + QMenu* advMenu = new QMenu; + mDataDefinedMenus = new QgsRendererV2DataDefinedMenus( advMenu, mLayer->pendingFields(), + mRenderer->rotationField(), mRenderer->sizeScaleField() ); + connect( mDataDefinedMenus, SIGNAL( rotationFieldChanged( QString ) ), this, SLOT( rotationFieldChanged( QString ) ) ); + connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) ); + btnAdvanced->setMenu( advMenu ); } QgsGraduatedSymbolRendererV2Widget::~QgsGraduatedSymbolRendererV2Widget() @@ -333,3 +342,13 @@ void QgsGraduatedSymbolRendererV2Widget::changeCurrentValue( QStandardItem * ite mRenderer->updateRangeLabel( idx, label ); } } + +void QgsGraduatedSymbolRendererV2Widget::rotationFieldChanged( QString fldName ) +{ + mRenderer->setRotationField( fldName ); +} + +void QgsGraduatedSymbolRendererV2Widget::sizeScaleFieldChanged( QString fldName ) +{ + mRenderer->setSizeScaleField( fldName ); +} diff --git a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h index 19a71c1ac25..a403bfaa1c0 100644 --- a/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h +++ b/src/gui/symbology-ng/qgsgraduatedsymbolrendererv2widget.h @@ -34,6 +34,9 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget /**Removes a class from the classification*/ void deleteCurrentClass(); + void rotationFieldChanged( QString fldName ); + void sizeScaleFieldChanged( QString fldName ); + protected: void updateUiFromRenderer(); @@ -60,6 +63,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererV2Widget : public QgsRendererV2Widget int mRowSelected; + QgsRendererV2DataDefinedMenus* mDataDefinedMenus; }; diff --git a/src/gui/symbology-ng/qgsrendererv2widget.cpp b/src/gui/symbology-ng/qgsrendererv2widget.cpp index 6587ed20a2e..4e6a0b1e4cd 100644 --- a/src/gui/symbology-ng/qgsrendererv2widget.cpp +++ b/src/gui/symbology-ng/qgsrendererv2widget.cpp @@ -5,3 +5,99 @@ QgsRendererV2Widget::QgsRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* sty : QWidget(), mLayer( layer ), mStyle( style ) { } + + + +//////////// + +//#include +#include "qgsfield.h" +#include + +QgsRendererV2DataDefinedMenus::QgsRendererV2DataDefinedMenus( QMenu* menu, const QgsFieldMap& flds, QString rotationField, QString sizeScaleField ) + : QObject( menu ), mFlds( flds ) +{ + mRotationMenu = new QMenu( tr( "Rotation field" ) ); + mSizeScaleMenu = new QMenu( tr( "Size scale field" ) ); + + populateMenu( mRotationMenu, SLOT( rotationFieldSelected() ), rotationField ); + populateMenu( mSizeScaleMenu, SLOT( sizeScaleFieldSelected() ), sizeScaleField ); + + menu->addMenu( mRotationMenu ); + menu->addMenu( mSizeScaleMenu ); +} + +void QgsRendererV2DataDefinedMenus::populateMenu( QMenu* menu, const char* slot, QString fieldName ) +{ + QAction* aNo = menu->addAction( tr( "- no field -" ), this, slot ); + aNo->setCheckable( true ); + menu->addSeparator(); + + bool hasField = false; + //const QgsFieldMap& flds = mLayer->pendingFields(); + for ( QgsFieldMap::const_iterator it = mFlds.begin(); it != mFlds.end(); ++it ) + { + const QgsField& fld = it.value(); + if ( fld.type() == QVariant::Int || fld.type() == QVariant::Double ) + { + QAction* a = menu->addAction( fld.name(), this, slot ); + a->setCheckable( true ); + if ( fieldName == fld.name() ) + { + a->setChecked( true ); + hasField = true; + } + } + } + + if ( !hasField ) + aNo->setChecked( true ); +} + +void QgsRendererV2DataDefinedMenus::rotationFieldSelected() +{ + QObject* s = sender(); + if ( s == NULL ) + return; + + QAction* a = qobject_cast( s ); + if ( a == NULL ) + return; + + QString fldName = a->text(); + + updateMenu( mRotationMenu, fldName ); + + if ( fldName == tr( "- no field -" ) ) + fldName = QString(); + + emit rotationFieldChanged( fldName ); +} + +void QgsRendererV2DataDefinedMenus::sizeScaleFieldSelected() +{ + QObject* s = sender(); + if ( s == NULL ) + return; + + QAction* a = qobject_cast( s ); + if ( a == NULL ) + return; + + QString fldName = a->text(); + + updateMenu( mSizeScaleMenu, fldName ); + + if ( fldName == tr( "- no field -" ) ) + fldName = QString(); + + emit sizeScaleFieldChanged( fldName ); +} + +void QgsRendererV2DataDefinedMenus::updateMenu( QMenu* menu, QString fieldName ) +{ + foreach( QAction* a, menu->actions() ) + { + a->setChecked( a->text() == fieldName ); + } +} diff --git a/src/gui/symbology-ng/qgsrendererv2widget.h b/src/gui/symbology-ng/qgsrendererv2widget.h index 44695b835e0..4b5da298bb3 100644 --- a/src/gui/symbology-ng/qgsrendererv2widget.h +++ b/src/gui/symbology-ng/qgsrendererv2widget.h @@ -35,4 +35,44 @@ class GUI_EXPORT QgsRendererV2Widget : public QWidget QgsStyleV2* mStyle; }; + +//////////// + +#include + +class QMenu; +class QgsField; + +typedef QMap QgsFieldMap; + +/** +Utility class for prividing GUI for data-defined rendering. +*/ +class QgsRendererV2DataDefinedMenus : public QObject +{ + Q_OBJECT + + public: + + QgsRendererV2DataDefinedMenus( QMenu* menu, const QgsFieldMap& flds, QString rotationField, QString sizeScaleField ); + + void populateMenu( QMenu* menu, const char* slot, QString fieldName ); + void updateMenu( QMenu* menu, QString fieldName ); + + public slots: + + void rotationFieldSelected(); + void sizeScaleFieldSelected(); + + signals: + + void rotationFieldChanged( QString fldName ); + void sizeScaleFieldChanged( QString fldName ); + + protected: + QMenu* mRotationMenu; + QMenu* mSizeScaleMenu; + const QgsFieldMap& mFlds; +}; + #endif // QGSRENDERERV2WIDGET_H diff --git a/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.cpp b/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.cpp index f4697b82408..c59bbd92f79 100644 --- a/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.cpp +++ b/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.cpp @@ -49,41 +49,10 @@ QgsSingleSymbolRendererV2Widget::QgsSingleSymbolRendererV2Widget( QgsVectorLayer // advanced actions - data defined rendering QMenu* advMenu = mSelector->advancedMenu(); - mRotationMenu = new QMenu( tr( "Rotation field" ) ); - mSizeScaleMenu = new QMenu( tr( "Size scale field" ) ); - - populateMenu( mRotationMenu, SLOT( rotationFieldSelected() ), mRenderer->rotationField() ); - populateMenu( mSizeScaleMenu, SLOT( sizeScaleFieldSelected() ), mRenderer->sizeScaleField() ); - - advMenu->addMenu( mRotationMenu ); - advMenu->addMenu( mSizeScaleMenu ); -} - -void QgsSingleSymbolRendererV2Widget::populateMenu( QMenu* menu, const char* slot, QString fieldName ) -{ - QAction* aNo = menu->addAction( tr( "- no field -" ), this, slot ); - aNo->setCheckable( true ); - menu->addSeparator(); - - bool hasField = false; - const QgsFieldMap& flds = mLayer->pendingFields(); - for ( QgsFieldMap::const_iterator it = flds.begin(); it != flds.end(); ++it ) - { - const QgsField& fld = it.value(); - if ( fld.type() == QVariant::Int || fld.type() == QVariant::Double ) - { - QAction* a = menu->addAction( fld.name(), this, slot ); - a->setCheckable( true ); - if ( fieldName == fld.name() ) - { - a->setChecked( true ); - hasField = true; - } - } - } - - if ( !hasField ) - aNo->setChecked( true ); + mDataDefinedMenus = new QgsRendererV2DataDefinedMenus( advMenu, mLayer->pendingFields(), + mRenderer->rotationField(), mRenderer->sizeScaleField() ); + connect( mDataDefinedMenus, SIGNAL( rotationFieldChanged( QString ) ), this, SLOT( rotationFieldChanged( QString ) ) ); + connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) ); } QgsSingleSymbolRendererV2Widget::~QgsSingleSymbolRendererV2Widget() @@ -107,50 +76,12 @@ void QgsSingleSymbolRendererV2Widget::changeSingleSymbol() mRenderer->setSymbol( mSingleSymbol->clone() ); } -void QgsSingleSymbolRendererV2Widget::rotationFieldSelected() +void QgsSingleSymbolRendererV2Widget::rotationFieldChanged( QString fldName ) { - QObject* s = sender(); - if ( s == NULL ) - return; - - QAction* a = qobject_cast( s ); - if ( a == NULL ) - return; - - QString fldName = a->text(); - - updateMenu( mRotationMenu, fldName ); - - if ( fldName == tr( "- no field -" ) ) - fldName = QString(); - mRenderer->setRotationField( fldName ); } -void QgsSingleSymbolRendererV2Widget::sizeScaleFieldSelected() +void QgsSingleSymbolRendererV2Widget::sizeScaleFieldChanged( QString fldName ) { - QObject* s = sender(); - if ( s == NULL ) - return; - - QAction* a = qobject_cast( s ); - if ( a == NULL ) - return; - - QString fldName = a->text(); - - updateMenu( mSizeScaleMenu, fldName ); - - if ( fldName == tr( "- no field -" ) ) - fldName = QString(); - mRenderer->setSizeScaleField( fldName ); } - -void QgsSingleSymbolRendererV2Widget::updateMenu( QMenu* menu, QString fieldName ) -{ - foreach( QAction* a, menu->actions() ) - { - a->setChecked( a->text() == fieldName ); - } -} diff --git a/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.h b/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.h index 45b0ea4d142..e3de8fc5966 100644 --- a/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.h +++ b/src/gui/symbology-ng/qgssinglesymbolrendererv2widget.h @@ -24,20 +24,16 @@ class GUI_EXPORT QgsSingleSymbolRendererV2Widget : public QgsRendererV2Widget public slots: void changeSingleSymbol(); - void rotationFieldSelected(); - void sizeScaleFieldSelected(); + void rotationFieldChanged( QString fldName ); + void sizeScaleFieldChanged( QString fldName ); protected: - void populateMenu( QMenu* menu, const char* slot, QString fieldName ); - void updateMenu( QMenu* menu, QString fieldName ); - QgsSingleSymbolRendererV2* mRenderer; QgsSymbolV2SelectorDialog* mSelector; QgsSymbolV2* mSingleSymbol; - QMenu* mRotationMenu; - QMenu* mSizeScaleMenu; + QgsRendererV2DataDefinedMenus* mDataDefinedMenus; }; diff --git a/src/ui/qgscategorizedsymbolrendererv2widget.ui b/src/ui/qgscategorizedsymbolrendererv2widget.ui index 66581e8e090..5679fa02b47 100644 --- a/src/ui/qgscategorizedsymbolrendererv2widget.ui +++ b/src/ui/qgscategorizedsymbolrendererv2widget.ui @@ -158,6 +158,13 @@ + + + + Advanced + + + diff --git a/src/ui/qgsgraduatedsymbolrendererv2widget.ui b/src/ui/qgsgraduatedsymbolrendererv2widget.ui index db661403d51..f3f2879a903 100644 --- a/src/ui/qgsgraduatedsymbolrendererv2widget.ui +++ b/src/ui/qgsgraduatedsymbolrendererv2widget.ui @@ -173,6 +173,13 @@ + + + + Advanced + + +