49 changes: 35 additions & 14 deletions src/core/symbology-ng/qgsellipsesymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,41 @@ class CORE_EXPORT QgsEllipseSymbolLayerV2: public QgsMarkerSymbolLayerV2
void setSymbolName( const QString& name ) { mSymbolName = name; }
QString symbolName() const { return mSymbolName; }

void setSymbolNameField( int index, const QString& field );
const QPair<int, QString>& symbolNameField() const { return mSymbolNameField; }
void setSymbolNameField( const QString& field ) { mSymbolNameField = field; }
const QString& symbolNameField() const { return mSymbolNameField; }

void setSymbolWidth( double w ) { mSymbolWidth = w; }
double symbolWidth() const { return mSymbolWidth; }

void setWidthField( int index, const QString& field );
const QPair<int, QString>& widthField() const { return mWidthField; }
void setWidthField( const QString& field ) { mWidthField = field; }
const QString& widthField() const { return mWidthField; }

void setSymbolHeight( double h ) { mSymbolHeight = h; }
double symbolHeight() const { return mSymbolHeight; }

void setHeightField( int index, const QString& field );
const QPair<int, QString>& heightField() const { return mHeightField; }
void setHeightField( const QString& field ) { mHeightField = field; }
const QString& heightField() const { return mHeightField; }

void setRotationField( int index, const QString& field );
const QPair<int, QString>& rotationField() const { return mRotationField; }
void setRotationField( const QString& field ) { mRotationField = field; }
const QString& rotationField() const { return mRotationField; }

void setOutlineWidth( double w ) { mOutlineWidth = w; }
double outlineWidth() const { return mOutlineWidth; }

void setOutlineWidthField( int index, const QString& field );
const QPair<int, QString>& outlineWidthField() const { return mOutlineWidthField; }
void setOutlineWidthField( const QString& field ) { mOutlineWidthField = field; }
const QString& outlineWidthField() const { return mOutlineWidthField; }

void setFillColor( const QColor& c ) { mFillColor = c;}
QColor fillColor() const { return mFillColor; }

void setFillColorField( int index, const QString& field );
const QPair<int, QString>& fillColorField() const { return mFillColorField; }
void setFillColorField( const QString& field ) { mFillColorField = field; }
const QString& fillColorField() const { return mFillColorField; }

void setOutlineColor( const QColor& c ) { mOutlineColor = c; }
QColor outlineColor() const { return mOutlineColor; }

void setOutlineColorField( int index, const QString& field );
const QPair<int, QString>& outlineColorField() const { return mOutlineColorField; }
void setOutlineColorField( const QString& field ) { mOutlineColorField = field; }
const QString& outlineColorField() const { return mOutlineColorField; }

QSet<QString> usedAttributes() const;

Expand All @@ -69,6 +69,7 @@ class CORE_EXPORT QgsEllipseSymbolLayerV2: public QgsMarkerSymbolLayerV2
QColor mOutlineColor;
double mOutlineWidth;

#if 0
/**Take width from attribute (-1 if fixed width)*/
QPair<int, QString> mWidthField;
/**Take height from attribute (-1 if fixed height)*/
Expand All @@ -83,6 +84,26 @@ class CORE_EXPORT QgsEllipseSymbolLayerV2: public QgsMarkerSymbolLayerV2
QPair<int, QString> mOutlineColorField;
/**Take shape name from attribute (-1 if fixed shape type)*/
QPair<int, QString> mSymbolNameField;
#endif //0

//data defined property fields
QString mWidthField;
QString mHeightField;
QString mRotationField;
QString mOutlineWidthField;
QString mFillColorField;
QString mOutlineColorField;
QString mSymbolNameField;

//field indices for data defined properties
//resolved in startRender method
int mWidthIndex;
int mHeightIndex;
int mRotationIndex;
int mOutlineWidthIndex;
int mFillColorIndex;
int mOutlineColorIndex;
int mSymbolNameIndex;

QPainterPath mPainterPath;

Expand Down
6 changes: 3 additions & 3 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,14 @@ void QgsGraduatedSymbolRendererV2::startRender( QgsRenderContext& context, const
QgsRangeList::iterator it = mRanges.begin();
for ( ; it != mRanges.end(); ++it )
{
it->symbol()->startRender( context );
it->symbol()->startRender( context, vlayer );

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 );
tempSymbol->startRender( context, vlayer );
mTempSymbols[ it->symbol()] = tempSymbol;
}
}
Expand All @@ -200,7 +200,7 @@ void QgsGraduatedSymbolRendererV2::stopRender( QgsRenderContext& context )
{
QgsRangeList::iterator it = mRanges.begin();
for ( ; it != mRanges.end(); ++it )
it->symbol()->startRender( context );
it->symbol()->stopRender( context );

// cleanup mTempSymbols
#if QT_VERSION < 0x40600
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgspointdisplacementrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const

if ( mCenterSymbol )
{
mCenterSymbol->startRender( context );
mCenterSymbol->startRender( context, vlayer );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVe
QgsExpression* exp = rule->filter();
if ( exp )
exp->prepare( pendingFields );
rule->symbol()->startRender( context );
rule->symbol()->startRender( context, vlayer );
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void QgsSingleSymbolRendererV2::startRender( QgsRenderContext& context, const Qg
mRotationFieldIdx = mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField );
mSizeScaleFieldIdx = mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField );

mSymbol->startRender( context );
mSymbol->startRender( context, vlayer );

if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
{
Expand All @@ -86,7 +86,7 @@ void QgsSingleSymbolRendererV2::startRender( QgsRenderContext& context, const Qg
hints |= QgsSymbolV2::DataDefinedSizeScale;
mTempSymbol->setRenderHints( hints );

mTempSymbol->startRender( context );
mTempSymbol->startRender( context, vlayer );

if ( mSymbol->type() == QgsSymbolV2::Marker )
{
Expand Down
3 changes: 3 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "qgsmarkersymbollayerv2.h"
#include "qgslinesymbollayerv2.h"
#include "qgsfillsymbollayerv2.h"
#include "qgsvectorfieldsymbollayer.h"

QgsSymbolLayerV2Registry* QgsSymbolLayerV2Registry::mInstance = NULL;

Expand All @@ -26,6 +27,8 @@ QgsSymbolLayerV2Registry::QgsSymbolLayerV2Registry()
QgsFontMarkerSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "EllipseMarker", QObject::tr( "Ellipse marker" ), QgsSymbolV2::Marker,
QgsEllipseSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "VectorField", QObject::tr( "Vector Field marker" ), QgsSymbolV2::Marker,
QgsVectorFieldSymbolLayer::create ) );

addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleFill", QObject::tr( "Simple fill" ), QgsSymbolV2::Fill,
QgsSimpleFillSymbolLayerV2::create ) );
Expand Down
5 changes: 3 additions & 2 deletions src/core/symbology-ng/qgssymbolv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,10 @@ bool QgsSymbolV2::changeSymbolLayer( int index, QgsSymbolLayerV2* layer )
}


void QgsSymbolV2::startRender( QgsRenderContext& context )
void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsVectorLayer* layer )
{
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints );
symbolContext.setLayer( layer );
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
( *it )->startRender( symbolContext );
}
Expand Down Expand Up @@ -282,7 +283,7 @@ QSet<QString> QgsSymbolV2::usedAttributes() const
////////////////////

QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected, int renderHints, const QgsFeature* f )
: mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints ), mFeature( f )
: mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints ), mFeature( f ), mLayer( 0 )
{

}
Expand Down
7 changes: 6 additions & 1 deletion src/core/symbology-ng/qgssymbolv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class QPolygonF;
class QgsFeature;
class QgsSymbolLayerV2;
class QgsRenderContext;
class QgsVectorLayer;

typedef QMap<QString, QString> QgsStringMap;
typedef QList<QgsSymbolLayerV2*> QgsSymbolLayerV2List;
Expand Down Expand Up @@ -74,7 +75,7 @@ class CORE_EXPORT QgsSymbolV2
bool changeSymbolLayer( int index, QgsSymbolLayerV2* layer );


void startRender( QgsRenderContext& context );
void startRender( QgsRenderContext& context, const QgsVectorLayer* layer = 0 );
void stopRender( QgsRenderContext& context );

void setColor( const QColor& color );
Expand Down Expand Up @@ -150,6 +151,9 @@ class CORE_EXPORT QgsSymbolV2RenderContext
void setFeature( const QgsFeature* f ) { mFeature = f; }
const QgsFeature* feature() const { return mFeature; }

void setLayer( const QgsVectorLayer* layer ) { mLayer = layer; }
const QgsVectorLayer* layer() const { return mLayer; }

// Color used for selections
static QColor selectionColor();

Expand All @@ -166,6 +170,7 @@ class CORE_EXPORT QgsSymbolV2RenderContext
bool mSelected;
int mRenderHints;
const QgsFeature* mFeature; //current feature
const QgsVectorLayer* mLayer; //current vectorlayer
};


Expand Down
224 changes: 224 additions & 0 deletions src/core/symbology-ng/qgsvectorfieldsymbollayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/***************************************************************************
qgsvectorfieldsymbollayer.cpp
-----------------------------
begin : Octorer 25, 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsvectorfieldsymbollayer.h"
#include "qgsvectorlayer.h"

QgsVectorFieldSymbolLayer::QgsVectorFieldSymbolLayer(): mXAttribute( "" ), mYAttribute( "" ), mScale( 1.0 ),
mVectorFieldType( Cartesian ), mAngleOrientation( ClockwiseFromNorth ), mAngleUnits( Degrees ), mXIndex( -1 ), mYIndex( -1 )
{
setSubSymbol( new QgsLineSymbolV2() );
}

QgsVectorFieldSymbolLayer::~QgsVectorFieldSymbolLayer()
{
}

QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::create( const QgsStringMap& properties )
{
QgsVectorFieldSymbolLayer* symbolLayer = new QgsVectorFieldSymbolLayer();
if ( properties.contains( "x_attribute" ) )
{
symbolLayer->setXAttribute( properties["x_attribute"] );
}
if ( properties.contains( "y_attribute" ) )
{
symbolLayer->setYAttribute( properties["y_attribute"] );
}
if ( properties.contains( "scale" ) )
{
symbolLayer->setScale( properties["scale"].toDouble() );
}
if ( properties.contains( "vector_field_type" ) )
{
symbolLayer->setVectorFieldType(( VectorFieldType )( properties["vector_field_type"].toInt() ) );
}
if ( properties.contains( "angle_orientation" ) )
{
symbolLayer->setAngleOrientation(( AngleOrientation )( properties["angle_orientation"].toInt() ) );
}
if ( properties.contains( "angle_units" ) )
{
symbolLayer->setAngleUnits(( AngleUnits )( properties["angle_units"].toInt() ) );
}
return symbolLayer;
}

bool QgsVectorFieldSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
{
if ( symbol->type() == QgsSymbolV2::Line )
{
mLineSymbol = static_cast<QgsLineSymbolV2*>( symbol );
return true;
}
return false;
}

void QgsVectorFieldSymbolLayer::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
{
if ( !mLineSymbol )
{
return;
}

const QgsFeature* f = context.feature();
if ( !f )
{
//preview
QPolygonF line;
line << QPointF( 0, 50 );
line << QPointF( 100, 50 );
mLineSymbol->renderPolyline( line, 0, context.renderContext() );
}

double xComponent = 0;
double yComponent = 0;

double xVal = 0;
if ( mXIndex != -1 )
{
xVal = f->attributeMap()[mXIndex].toDouble();
}
double yVal = 0;
if ( mYIndex != -1 )
{
yVal = f->attributeMap()[mYIndex].toDouble();
}

switch ( mVectorFieldType )
{
case Cartesian:
xComponent = context.outputLineWidth( xVal );
yComponent = context.outputLineWidth( yVal );
break;
case Polar:
convertPolarToCartesian( xVal, yVal, xComponent, yComponent );
xComponent = context.outputLineWidth( xComponent );
yComponent = context.outputLineWidth( yComponent );
break;
case Height:
xComponent = 0;
yComponent = context.outputLineWidth( yVal );
break;
default:
break;
}

xComponent *= mScale;
yComponent *= mScale;

QPolygonF line;
line << point;
line << QPointF( point.x() + xComponent, point.y() - yComponent );
mLineSymbol->renderPolyline( line, f, context.renderContext() );
}

void QgsVectorFieldSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
{
if ( mLineSymbol )
{
mLineSymbol->startRender( context.renderContext() );
}

const QgsVectorLayer* layer = context.layer();
if ( layer )
{
mXIndex = layer->fieldNameIndex( mXAttribute );
mYIndex = layer->fieldNameIndex( mYAttribute );
}
else
{
mXIndex = -1;
mYIndex = -1;
}
}

void QgsVectorFieldSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
{
if ( mLineSymbol )
{
mLineSymbol->stopRender( context.renderContext() );
}
}

QgsSymbolLayerV2* QgsVectorFieldSymbolLayer::clone() const
{
QgsSymbolLayerV2* clonedLayer = QgsVectorFieldSymbolLayer::create( properties() );
if ( mLineSymbol )
{
clonedLayer->setSubSymbol( mLineSymbol->clone() );
}
return clonedLayer;
}

QgsStringMap QgsVectorFieldSymbolLayer::properties() const
{
QgsStringMap properties;
properties["x_attribute"] = mXAttribute;
properties["y_attribute"] = mYAttribute;
properties["scale"] = QString::number( mScale );
properties["vector_field_type"] = QString::number( mVectorFieldType );
properties["angle_orientation"] = QString::number( mAngleOrientation );
properties["angle_units"] = QString::number( mAngleUnits );
return properties;
}

void QgsVectorFieldSymbolLayer::drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size )
{
if ( mLineSymbol )
{
mLineSymbol->drawPreviewIcon( context.renderContext().painter(), size );
}
}

QSet<QString> QgsVectorFieldSymbolLayer::usedAttributes() const
{
QSet<QString> attributes;
if ( !mXAttribute.isEmpty() )
{
attributes.insert( mXAttribute );
}
if ( !mYAttribute.isEmpty() )
{
attributes.insert( mYAttribute );
}
return attributes;
}

void QgsVectorFieldSymbolLayer::convertPolarToCartesian( double length, double angle, double& x, double& y ) const
{
//convert angle to degree and to north orientation
if ( mAngleOrientation == CounterclockwiseFromEast )
{
if ( angle <= 90 )
{
angle = 90 - angle;
}
else
{
angle = 360 - angle + 90;
}
}

if ( mAngleUnits == Degrees )
{
angle = angle * M_PI / 180.0;
}

x = length * sin( angle );
y = length * cos( angle );
}
99 changes: 99 additions & 0 deletions src/core/symbology-ng/qgsvectorfieldsymbollayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/***************************************************************************
qgsvectorfieldsymbollayer.h
-------------------------
begin : Octorer 25, 2011
copyright : (C) 2011 by Marco Hugentobler
email : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSVECTORFIELDSYMBOLLAYER_H
#define QGSVECTORFIELDSYMBOLLAYER_H

#include "qgssymbollayerv2.h"

/**A symbol layer class for displaying displacement arrows based on point layer attributes*/
class CORE_EXPORT QgsVectorFieldSymbolLayer: public QgsMarkerSymbolLayerV2
{
public:
enum VectorFieldType
{
Cartesian = 0,
Polar,
Height
};

enum AngleOrientation
{
ClockwiseFromNorth = 0,
CounterclockwiseFromEast
};

enum AngleUnits
{
Degrees = 0,
Radians
};

QgsVectorFieldSymbolLayer();
~QgsVectorFieldSymbolLayer();

static QgsSymbolLayerV2* create( const QgsStringMap& properties = QgsStringMap() );

QString layerType() const { return "VectorField"; }

bool setSubSymbol( QgsSymbolV2* symbol );
QgsSymbolV2* subSymbol() { return mLineSymbol; }

void renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context );
void startRender( QgsSymbolV2RenderContext& context );
void stopRender( QgsSymbolV2RenderContext& context );

QgsSymbolLayerV2* clone() const;
QgsStringMap properties() const;

void drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size );

QSet<QString> usedAttributes() const;

//setters and getters
void setXAttribute( const QString& attribute ) { mXAttribute = attribute; }
QString xAttribute() const { return mXAttribute; }
void setYAttribute( const QString& attribute ) { mYAttribute = attribute; }
QString yAttribute() const { return mYAttribute; }
void setScale( double s ) { mScale = s; }
double scale() const { return mScale; }
void setVectorFieldType( VectorFieldType type ) { mVectorFieldType = type; }
VectorFieldType vectorFieldType() const { return mVectorFieldType; }
void setAngleOrientation( AngleOrientation orientation ) { mAngleOrientation = orientation; }
AngleOrientation angleOrientation() const { return mAngleOrientation; }
void setAngleUnits( AngleUnits units ) { mAngleUnits = units; }
AngleUnits angleUnits() const { return mAngleUnits; }

private:
QString mXAttribute;
QString mYAttribute;
double mScale;
VectorFieldType mVectorFieldType;
AngleOrientation mAngleOrientation;
AngleUnits mAngleUnits;

QgsLineSymbolV2* mLineSymbol;

//Attribute indices are resolved in startRender method
int mXIndex;
int mYIndex;

//Converts length/angle to cartesian x/y
void convertPolarToCartesian( double length, double angle, double& x, double& y ) const;
};

#endif // QGSVECTORFIELDSYMBOLLAYER_H
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ symbology-ng/characterwidget.cpp
symbology-ng/qgsstylev2exportimportdialog.cpp
symbology-ng/qgsellipsesymbollayerv2widget.cpp
symbology-ng/qgspointdisplacementrendererwidget.cpp
symbology-ng/qgsvectorfieldsymbollayerwidget.cpp

attributetable/qgsattributetablemodel.cpp
attributetable/qgsattributetablememorymodel.cpp
Expand Down Expand Up @@ -100,6 +101,7 @@ symbology-ng/qgsbrushstylecombobox.h
symbology-ng/qgsstylev2exportimportdialog.h
symbology-ng/qgsellipsesymbollayerv2widget.h
symbology-ng/qgspointdisplacementrendererwidget.h
symbology-ng/qgsvectorfieldsymbollayerwidget.h

attributetable/qgsattributetableview.h
attributetable/qgsattributetablemodel.h
Expand Down
71 changes: 50 additions & 21 deletions src/gui/symbology-ng/qgsellipsesymbollayerv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,33 +55,62 @@ void QgsEllipseSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
blockComboSignals( true );
if ( mLayer )
{
if ( mLayer->widthField().first != -1 )

if ( mLayer->widthField().isEmpty() )
{
mDDSymbolWidthComboBox->setCurrentIndex( 0 );
}
else
{
mDDSymbolWidthComboBox->setCurrentIndex( mDDSymbolWidthComboBox->findText( mLayer->widthField() ) );
}
if ( mLayer->heightField().isEmpty() )
{
mDDSymbolHeightComboBox->setCurrentIndex( 0 );
}
else
{
mDDSymbolHeightComboBox->setCurrentIndex( mDDSymbolHeightComboBox->findText( mLayer->heightField() ) );
}
if ( mLayer->rotationField().isEmpty() )
{
mDDRotationComboBox->setCurrentIndex( 0 );
}
else
{
mDDRotationComboBox->setCurrentIndex( mDDRotationComboBox->findText( mLayer->rotationField() ) );
}
if ( mLayer->outlineWidthField().isEmpty() )
{
mDDOutlineWidthComboBox->setCurrentIndex( 0 );
}
else
{
mDDSymbolWidthComboBox->setCurrentIndex( mDDSymbolWidthComboBox->findText( mLayer->widthField().second ) );
mDDOutlineWidthComboBox->setCurrentIndex( mDDOutlineWidthComboBox->findText( mLayer->outlineWidthField() ) );
}
if ( mLayer->heightField().first != -1 )
if ( mLayer->fillColorField().isEmpty() )
{
mDDSymbolHeightComboBox->setCurrentIndex( mDDSymbolHeightComboBox->findText( mLayer->heightField().second ) );
mDDFillColorComboBox->setCurrentIndex( 0 );
}
if ( mLayer->rotationField().first != -1 )
else
{
mDDRotationComboBox->setCurrentIndex( mDDRotationComboBox->findText( mLayer->rotationField().second ) );
mDDFillColorComboBox->setCurrentIndex( mDDFillColorComboBox->findText( mLayer->fillColorField() ) );
}
if ( mLayer->outlineWidthField().first != -1 )
if ( mLayer->outlineColorField().isEmpty() )
{
mDDOutlineWidthComboBox->setCurrentIndex( mDDOutlineWidthComboBox->findText( mLayer->outlineWidthField().second ) );
mDDOutlineColorComboBox->setCurrentIndex( 0 );
}
if ( mLayer->fillColorField().first != -1 )
else
{
mDDFillColorComboBox->setCurrentIndex( mDDFillColorComboBox->findText( mLayer->fillColorField().second ) );
mDDOutlineColorComboBox->setCurrentIndex( mDDOutlineColorComboBox->findText( mLayer->outlineColorField() ) );
}
if ( mLayer->outlineColorField().first != -1 )
if ( mLayer->symbolNameField().isEmpty() )
{
mDDOutlineColorComboBox->setCurrentIndex( mDDOutlineColorComboBox->findText( mLayer->outlineColorField().second ) );
mDDShapeComboBox->setCurrentIndex( 0 );
}
if ( mLayer->symbolNameField().first != -1 )
else
{
mDDShapeComboBox->setCurrentIndex( mDDShapeComboBox->findText( mLayer->symbolNameField().second ) );
mDDShapeComboBox->setCurrentIndex( mDDShapeComboBox->findText( mLayer->symbolNameField() ) );
}
}
blockComboSignals( false );
Expand Down Expand Up @@ -208,7 +237,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDSymbolWidthComboBox_currentIndexChange
{
if ( mLayer )
{
mLayer->setWidthField( mDDSymbolWidthComboBox->itemData( idx ).toInt(), mDDSymbolWidthComboBox->itemText( idx ) );
mLayer->setWidthField( mDDSymbolWidthComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -217,7 +246,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDSymbolHeightComboBox_currentIndexChang
{
if ( mLayer )
{
mLayer->setHeightField( mDDSymbolHeightComboBox->itemData( idx ).toInt(), mDDSymbolHeightComboBox->itemText( idx ) );
mLayer->setHeightField( mDDSymbolHeightComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -226,7 +255,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDRotationComboBox_currentIndexChanged(
{
if ( mLayer )
{
mLayer->setRotationField( mDDRotationComboBox->itemData( idx ).toInt(), mDDRotationComboBox->itemText( idx ) );
mLayer->setRotationField( mDDRotationComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -235,7 +264,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDOutlineWidthComboBox_currentIndexChang
{
if ( mLayer )
{
mLayer->setOutlineWidthField( mDDOutlineWidthComboBox->itemData( idx ).toInt(), mDDOutlineWidthComboBox->itemText( idx ) );
mLayer->setOutlineWidthField( mDDOutlineWidthComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -244,7 +273,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDFillColorComboBox_currentIndexChanged(
{
if ( mLayer )
{
mLayer->setFillColorField( mDDFillColorComboBox->itemData( idx ).toInt(), mDDFillColorComboBox->itemText( idx ) );
mLayer->setFillColorField( mDDFillColorComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -253,7 +282,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDOutlineColorComboBox_currentIndexChang
{
if ( mLayer )
{
mLayer->setOutlineColorField( mDDOutlineColorComboBox->itemData( idx ).toInt(), mDDOutlineColorComboBox->itemText( idx ) );
mLayer->setOutlineColorField( mDDOutlineColorComboBox->itemText( idx ) );
emit changed();
}
}
Expand All @@ -262,7 +291,7 @@ void QgsEllipseSymbolLayerV2Widget::on_mDDShapeComboBox_currentIndexChanged( int
{
if ( mLayer )
{
mLayer->setSymbolNameField( mDDShapeComboBox->itemData( idx ).toInt(), mDDShapeComboBox->itemText( idx ) );
mLayer->setSymbolNameField( mDDShapeComboBox->itemText( idx ) );
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/gui/symbology-ng/qgssymbolv2propertiesdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "qgssymbollayerv2widget.h"
#include "qgsellipsesymbollayerv2widget.h"
#include "qgsvectorfieldsymbollayerwidget.h"
#include "qgssymbolv2.h" //for the unit


Expand Down Expand Up @@ -92,6 +93,7 @@ static void _initWidgetFunctions()
_initWidgetFunction( "SvgMarker", QgsSvgMarkerSymbolLayerV2Widget::create );
_initWidgetFunction( "FontMarker", QgsFontMarkerSymbolLayerV2Widget::create );
_initWidgetFunction( "EllipseMarker", QgsEllipseSymbolLayerV2Widget::create );
_initWidgetFunction( "VectorField", QgsVectorFieldSymbolLayerWidget::create );

_initWidgetFunction( "SimpleFill", QgsSimpleFillSymbolLayerV2Widget::create );
_initWidgetFunction( "SVGFill", QgsSVGFillSymbolLayerWidget::create );
Expand Down
210 changes: 210 additions & 0 deletions src/gui/symbology-ng/qgsvectorfieldsymbollayerwidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#include "qgsvectorfieldsymbollayerwidget.h"
#include "qgssymbolv2propertiesdialog.h"
#include "qgsvectorfieldsymbollayer.h"
#include "qgsvectorlayer.h"

QgsVectorFieldSymbolLayerWidget::QgsVectorFieldSymbolLayerWidget( const QgsVectorLayer* vl, QWidget* parent ): QgsSymbolLayerV2Widget( parent, vl ), mLayer( 0 )
{
setupUi( this );
if ( mVectorLayer )
{
const QgsFieldMap& fm = mVectorLayer->pendingFields();
QgsFieldMap::const_iterator fieldIt = fm.constBegin();
mXAttributeComboBox->addItem( "" );
mYAttributeComboBox->addItem( "" );
for ( ; fieldIt != fm.constEnd(); ++fieldIt )
{
QString fieldName = fieldIt.value().name();
mXAttributeComboBox->addItem( fieldName );
mYAttributeComboBox->addItem( fieldName );
}
}
}

QgsVectorFieldSymbolLayerWidget::~QgsVectorFieldSymbolLayerWidget()
{
}

void QgsVectorFieldSymbolLayerWidget::setSymbolLayer( QgsSymbolLayerV2* layer )
{
if ( layer->layerType() != "VectorField" )
{
return;
}
mLayer = static_cast<QgsVectorFieldSymbolLayer*>( layer );
if ( !mLayer )
{
return;
}

mXAttributeComboBox->setCurrentIndex( mXAttributeComboBox->findText( mLayer->xAttribute() ) );
mYAttributeComboBox->setCurrentIndex( mYAttributeComboBox->findText( mLayer->yAttribute() ) );
mScaleSpinBox->setValue( mLayer->scale() );

QgsVectorFieldSymbolLayer::VectorFieldType type = mLayer->vectorFieldType();
if ( type == QgsVectorFieldSymbolLayer::Cartesian )
{
mCartesianRadioButton->setChecked( true );
}
else if ( type == QgsVectorFieldSymbolLayer::Polar )
{
mPolarRadioButton->setChecked( true );
}
else if ( type == QgsVectorFieldSymbolLayer::Height )
{
mHeightRadioButton->setChecked( true );
}

QgsVectorFieldSymbolLayer::AngleOrientation orientation = mLayer->angleOrientation();
if ( orientation == QgsVectorFieldSymbolLayer::ClockwiseFromNorth )
{
mClockwiseFromNorthRadioButton->setChecked( true );
}
else if ( orientation == QgsVectorFieldSymbolLayer::CounterclockwiseFromEast )
{
mCounterclockwiseFromEastRadioButton->setChecked( true );
}

QgsVectorFieldSymbolLayer::AngleUnits angleUnits = mLayer->angleUnits();
if ( angleUnits == QgsVectorFieldSymbolLayer::Degrees )
{
mDegreesRadioButton->setChecked( true );
}
else if ( angleUnits == QgsVectorFieldSymbolLayer::Radians )
{
mRadiansRadioButton->setChecked( true );
}
updateMarkerIcon();
}

QgsSymbolLayerV2* QgsVectorFieldSymbolLayerWidget::symbolLayer()
{
return mLayer;
}

void QgsVectorFieldSymbolLayerWidget::on_mScaleSpinBox_valueChanged( double d )
{
if ( mLayer )
{
mLayer->setScale( d );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mXAttributeComboBox_currentIndexChanged( int index )
{
if ( mLayer )
{
mLayer->setXAttribute( mXAttributeComboBox->itemText( index ) );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mYAttributeComboBox_currentIndexChanged( int index )
{
if ( mLayer )
{
mLayer->setYAttribute( mYAttributeComboBox->itemText( index ) );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mLineStylePushButton_clicked()
{
if ( !mLayer )
{
return;
}

QgsSymbolV2PropertiesDialog dlg( mLayer->subSymbol(), mVectorLayer, this );
if ( dlg.exec() == QDialog::Rejected )
{
return;
}

updateMarkerIcon();
emit changed();
}

void QgsVectorFieldSymbolLayerWidget::updateMarkerIcon()
{
if ( mLayer )
{
QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( mLayer->subSymbol(), mLineStylePushButton->iconSize() );
mLineStylePushButton->setIcon( icon );
}
}

void QgsVectorFieldSymbolLayerWidget::on_mCartesianRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setVectorFieldType( QgsVectorFieldSymbolLayer::Cartesian );
mXAttributeComboBox->setEnabled( true );
mYAttributeComboBox->setEnabled( true );
mXAttributeLabel->setText( tr( "X attribute" ) );
mYAttributeLabel->setText( tr( "Y attribute" ) );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mPolarRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setVectorFieldType( QgsVectorFieldSymbolLayer::Polar );
mXAttributeComboBox->setEnabled( true );
mYAttributeComboBox->setEnabled( true );
mXAttributeLabel->setText( tr( "Length attribute" ) );
mYAttributeLabel->setText( tr( "Angle attribute" ) );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mHeightRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setVectorFieldType( QgsVectorFieldSymbolLayer::Height );
mXAttributeLabel->setText( "" );
mXAttributeComboBox->setEnabled( false );
mYAttributeLabel->setText( tr( "Height attribute" ) );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mDegreesRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setAngleUnits( QgsVectorFieldSymbolLayer::Degrees );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mRadiansRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setAngleUnits( QgsVectorFieldSymbolLayer::Radians );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mClockwiseFromNorthRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setAngleOrientation( QgsVectorFieldSymbolLayer::ClockwiseFromNorth );
emit changed();
}
}

void QgsVectorFieldSymbolLayerWidget::on_mCounterclockwiseFromEastRadioButton_toggled( bool checked )
{
if ( mLayer && checked )
{
mLayer->setAngleOrientation( QgsVectorFieldSymbolLayer::CounterclockwiseFromEast );
emit changed();
}
}
40 changes: 40 additions & 0 deletions src/gui/symbology-ng/qgsvectorfieldsymbollayerwidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef QGSVECTORFIELDSYMBOLLAYERWIDGET_H
#define QGSVECTORFIELDSYMBOLLAYERWIDGET_H

#include "qgssymbollayerv2widget.h"
#include "ui_widget_vectorfield.h"

class QgsVectorFieldSymbolLayer;

class GUI_EXPORT QgsVectorFieldSymbolLayerWidget: public QgsSymbolLayerV2Widget, private Ui::WidgetVectorFieldBase
{
Q_OBJECT
public:
QgsVectorFieldSymbolLayerWidget( const QgsVectorLayer* vl, QWidget* parent = 0 );
~QgsVectorFieldSymbolLayerWidget();

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsVectorFieldSymbolLayerWidget( vl ); }

// from base class
virtual void setSymbolLayer( QgsSymbolLayerV2* layer );
virtual QgsSymbolLayerV2* symbolLayer();

protected:
QgsVectorFieldSymbolLayer* mLayer;
void updateMarkerIcon();

private slots:
void on_mScaleSpinBox_valueChanged( double d );
void on_mXAttributeComboBox_currentIndexChanged( int index );
void on_mYAttributeComboBox_currentIndexChanged( int index );
void on_mLineStylePushButton_clicked();
void on_mCartesianRadioButton_toggled( bool checked );
void on_mPolarRadioButton_toggled( bool checked );
void on_mHeightRadioButton_toggled( bool checked );
void on_mDegreesRadioButton_toggled( bool checked );
void on_mRadiansRadioButton_toggled( bool checked );
void on_mClockwiseFromNorthRadioButton_toggled( bool checked );
void on_mCounterclockwiseFromEastRadioButton_toggled( bool checked );
};

#endif // QGSVECTORFIELDSYMBOLLAYERWIDGET_H
4 changes: 4 additions & 0 deletions src/gui/symbology-ng/qgsvectorfieldwidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#ifndef QGSVECTORFIELDWIDGET_H
#define QGSVECTORFIELDWIDGET_H

#endif // QGSVECTORFIELDWIDGET_H
141 changes: 141 additions & 0 deletions src/ui/symbollayer/widget_vectorfield.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WidgetVectorFieldBase</class>
<widget class="QWidget" name="WidgetVectorFieldBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>291</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="mXAttributeLabel">
<property name="text">
<string>X attribute</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mXAttributeComboBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mYAttributeLabel">
<property name="text">
<string>Y attribute</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="mYAttributeComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mScaleLabel">
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="mScaleSpinBox"/>
</item>
<item row="4" column="0" rowspan="2" colspan="2">
<widget class="QGroupBox" name="mFieldTypeGroupBox">
<property name="title">
<string>Vector field type</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="mCartesianRadioButton">
<property name="text">
<string>Cartesian</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="mPolarRadioButton">
<property name="text">
<string>Polar</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="mHeightRadioButton">
<property name="text">
<string>Height only</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QGroupBox" name="mAngleUnitsGroupBox">
<property name="title">
<string>Angle units</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="mDegreesRadioButton">
<property name="text">
<string>Degrees</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="mRadiansRadioButton">
<property name="text">
<string>Radians</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="2" colspan="2">
<widget class="QGroupBox" name="mAngleOrientationGroupBox">
<property name="title">
<string>Angle orientation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QRadioButton" name="mCounterclockwiseFromEastRadioButton">
<property name="text">
<string>Counterclockwise from east</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mClockwiseFromNorthRadioButton">
<property name="text">
<string>Clockwise from north</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="mLineStyleLabel">
<property name="text">
<string>LineStyle</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QPushButton" name="mLineStylePushButton">
<property name="text">
<string>change</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>