mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
[FEATURE] Data-defined size and rotation for single symbol renderer in symbology-ng. (ticket #2585)
Developed by for Faunalia (http://www.faunalia.it) with funding from Regione Toscana - Sistema Informativo per la Gestione del Territorio e dell' Ambiente [RT-SIGTA]". For the project: "Sviluppo di prodotti software GIS open-source basati sui prodotti QuantumGIS e Postgis (CIG 037728516E) git-svn-id: http://svn.osgeo.org/qgis/trunk@13389 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
aa18abc3c6
commit
02df126b90
@ -133,6 +133,12 @@ public:
|
|||||||
QgsSymbolV2* symbol() const;
|
QgsSymbolV2* symbol() const;
|
||||||
void setSymbol(QgsSymbolV2* s /Transfer/);
|
void setSymbol(QgsSymbolV2* s /Transfer/);
|
||||||
|
|
||||||
|
void setRotationField(QString fieldName);
|
||||||
|
QString rotationField() const;
|
||||||
|
|
||||||
|
void setSizeScaleField(QString fieldName);
|
||||||
|
QString sizeScaleField() const;
|
||||||
|
|
||||||
virtual QString dump();
|
virtual QString dump();
|
||||||
|
|
||||||
virtual QgsFeatureRendererV2* clone() /Factory/;
|
virtual QgsFeatureRendererV2* clone() /Factory/;
|
||||||
@ -453,7 +459,7 @@ class QgsSymbolV2RenderContext
|
|||||||
%End
|
%End
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u , qreal alpha = 1.0, bool selected = false );
|
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u , qreal alpha = 1.0, bool selected = false, int renderHints = 0 );
|
||||||
~QgsSymbolV2RenderContext();
|
~QgsSymbolV2RenderContext();
|
||||||
|
|
||||||
QgsRenderContext& renderContext();
|
QgsRenderContext& renderContext();
|
||||||
@ -468,6 +474,11 @@ class QgsSymbolV2RenderContext
|
|||||||
bool selected() const;
|
bool selected() const;
|
||||||
void setSelected( bool selected ) const;
|
void setSelected( bool selected ) const;
|
||||||
|
|
||||||
|
int renderHints() const;
|
||||||
|
void setRenderHints( int hints );
|
||||||
|
|
||||||
|
// Colour used for selections
|
||||||
|
|
||||||
static QColor selectionColor();
|
static QColor selectionColor();
|
||||||
|
|
||||||
double outputLineWidth(double width) const;
|
double outputLineWidth(double width) const;
|
||||||
@ -510,6 +521,12 @@ public:
|
|||||||
Fill
|
Fill
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RenderHint
|
||||||
|
{
|
||||||
|
DataDefinedSizeScale = 1,
|
||||||
|
DataDefinedRotation = 2
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~QgsSymbolV2();
|
virtual ~QgsSymbolV2();
|
||||||
|
|
||||||
//! return new default symbol for specified geometry type
|
//! return new default symbol for specified geometry type
|
||||||
@ -556,6 +573,12 @@ public:
|
|||||||
OutputUnit outputUnit() const;
|
OutputUnit outputUnit() const;
|
||||||
void setOutputUnit( OutputUnit u );
|
void setOutputUnit( OutputUnit u );
|
||||||
|
|
||||||
|
qreal alpha() const;
|
||||||
|
void setAlpha( qreal alpha );
|
||||||
|
|
||||||
|
int renderHints() const;
|
||||||
|
void setRenderHints( int hints );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QgsSymbolV2(SymbolType type, QgsSymbolLayerV2List layers /Transfer/); // can't be instantiated
|
QgsSymbolV2(SymbolType type, QgsSymbolLayerV2List layers /Transfer/); // can't be instantiated
|
||||||
|
|
||||||
|
@ -68,102 +68,72 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex
|
|||||||
mBrush = QBrush( mColor );
|
mBrush = QBrush( mColor );
|
||||||
mPen = QPen( mBorderColor );
|
mPen = QPen( mBorderColor );
|
||||||
mPen.setWidthF( context.outputLineWidth( mPen.widthF() ) );
|
mPen.setWidthF( context.outputLineWidth( mPen.widthF() ) );
|
||||||
|
|
||||||
QColor selColor = context.selectionColor();
|
QColor selColor = context.selectionColor();
|
||||||
mSelBrush = QBrush( selColor );
|
mSelBrush = QBrush( selColor );
|
||||||
mSelPen = QPen( selColor == mColor ? selColor : mBorderColor );
|
mSelPen = QPen( selColor == mColor ? selColor : mBorderColor );
|
||||||
mSelPen.setWidthF( mPen.widthF() );
|
mSelPen.setWidthF( mPen.widthF() );
|
||||||
|
|
||||||
mPolygon.clear();
|
bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation;
|
||||||
|
bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale;
|
||||||
|
|
||||||
double scaledSize = context.outputPixelSize( mSize );
|
// use either QPolygonF or QPainterPath for drawing
|
||||||
double half = scaledSize / 2.0;
|
// TODO: find out whether drawing directly doesn't bring overhead - if not, use it for all shapes
|
||||||
|
if ( !prepareShape() ) // drawing as a polygon
|
||||||
|
{
|
||||||
|
if ( preparePath() ) // drawing as a painter path
|
||||||
|
{
|
||||||
|
// some markers can't be drawn as a polygon (circle, cross)
|
||||||
|
// For these set the selected border color to the selected color
|
||||||
|
|
||||||
if ( mName == "rectangle" )
|
if ( mName != "circle" )
|
||||||
{
|
mSelPen.setColor( selColor );
|
||||||
mPolygon = QPolygonF( QRectF( QPointF( -half, -half ), QPointF( half, half ) ) );
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsDebugMsg( "unknown symbol" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( mName == "diamond" )
|
|
||||||
{
|
|
||||||
mPolygon << QPointF( -half, 0 ) << QPointF( 0, half )
|
|
||||||
<< QPointF( half, 0 ) << QPointF( 0, -half );
|
|
||||||
}
|
|
||||||
else if ( mName == "pentagon" )
|
|
||||||
{
|
|
||||||
mPolygon << QPointF( half * sin( DEG2RAD( 288.0 ) ), - half * cos( DEG2RAD( 288.0 ) ) )
|
|
||||||
<< QPointF( half * sin( DEG2RAD( 216.0 ) ), - half * cos( DEG2RAD( 216.0 ) ) )
|
|
||||||
<< QPointF( half * sin( DEG2RAD( 144.0 ) ), - half * cos( DEG2RAD( 144.0 ) ) )
|
|
||||||
<< QPointF( half * sin( DEG2RAD( 72.0 ) ), - half * cos( DEG2RAD( 72.0 ) ) )
|
|
||||||
<< QPointF( 0, - half );
|
|
||||||
}
|
|
||||||
else if ( mName == "triangle" )
|
|
||||||
{
|
|
||||||
mPolygon << QPointF( -half, half ) << QPointF( half, half ) << QPointF( 0, -half );
|
|
||||||
}
|
|
||||||
else if ( mName == "equilateral_triangle" )
|
|
||||||
{
|
|
||||||
mPolygon << QPointF( half * sin( DEG2RAD( 240.0 ) ), - half * cos( DEG2RAD( 240.0 ) ) )
|
|
||||||
<< QPointF( half * sin( DEG2RAD( 120.0 ) ), - half * cos( DEG2RAD( 120.0 ) ) )
|
|
||||||
<< QPointF( 0, -half );
|
|
||||||
}
|
|
||||||
else if ( mName == "star" )
|
|
||||||
{
|
|
||||||
double sixth = half / 6;
|
|
||||||
|
|
||||||
mPolygon << QPointF( 0, -half )
|
QMatrix transform;
|
||||||
<< QPointF( -sixth, -sixth )
|
|
||||||
<< QPointF( -half, -sixth )
|
|
||||||
<< QPointF( -sixth, 0 )
|
|
||||||
<< QPointF( -half, half )
|
|
||||||
<< QPointF( 0, + sixth )
|
|
||||||
<< QPointF( half, half )
|
|
||||||
<< QPointF( + sixth, 0 )
|
|
||||||
<< QPointF( half, -sixth )
|
|
||||||
<< QPointF( + sixth, -sixth );
|
|
||||||
}
|
|
||||||
else if ( mName == "regular_star" )
|
|
||||||
{
|
|
||||||
double r = half;
|
|
||||||
double inner_r = r * cos( DEG2RAD( 72.0 ) ) / cos( DEG2RAD( 36.0 ) );
|
|
||||||
|
|
||||||
mPolygon << QPointF( inner_r * sin( DEG2RAD( 324.0 ) ), - inner_r * cos( DEG2RAD( 324.0 ) ) ) // 324
|
// scale the shape (if the size is not going to be modified)
|
||||||
<< QPointF( r * sin( DEG2RAD( 288.0 ) ) , - r * cos( DEG2RAD( 288 ) ) ) // 288
|
if ( !hasDataDefinedSize )
|
||||||
<< QPointF( inner_r * sin( DEG2RAD( 252.0 ) ), - inner_r * cos( DEG2RAD( 252.0 ) ) ) // 252
|
|
||||||
<< QPointF( r * sin( DEG2RAD( 216.0 ) ) , - r * cos( DEG2RAD( 216.0 ) ) ) // 216
|
|
||||||
<< QPointF( 0, inner_r ) // 180
|
|
||||||
<< QPointF( r * sin( DEG2RAD( 144.0 ) ) , - r * cos( DEG2RAD( 144.0 ) ) ) // 144
|
|
||||||
<< QPointF( inner_r * sin( DEG2RAD( 108.0 ) ), - inner_r * cos( DEG2RAD( 108.0 ) ) ) // 108
|
|
||||||
<< QPointF( r * sin( DEG2RAD( 72.0 ) ) , - r * cos( DEG2RAD( 72.0 ) ) ) // 72
|
|
||||||
<< QPointF( inner_r * sin( DEG2RAD( 36.0 ) ), - inner_r * cos( DEG2RAD( 36.0 ) ) ) // 36
|
|
||||||
<< QPointF( 0, -half ); // 0
|
|
||||||
}
|
|
||||||
else if ( mName == "arrow" )
|
|
||||||
{
|
{
|
||||||
double eight = half / 4;
|
double scaledSize = context.outputPixelSize( mSize );
|
||||||
double quarter = half / 2;
|
double half = scaledSize / 2.0;
|
||||||
|
transform.scale( half, half );
|
||||||
|
}
|
||||||
|
|
||||||
mPolygon << QPointF( 0, -half )
|
// rotate if the rotation is not going to be changed during the rendering
|
||||||
<< QPointF( quarter, -quarter )
|
if ( !hasDataDefinedRotation && mAngle != 0 )
|
||||||
<< QPointF( eight, -quarter )
|
{
|
||||||
<< QPointF( eight, half )
|
transform.rotate( mAngle );
|
||||||
<< QPointF( -eight, half )
|
}
|
||||||
<< QPointF( -eight, -quarter )
|
|
||||||
<< QPointF( -quarter, -quarter );
|
if ( !mPolygon.isEmpty() )
|
||||||
|
mPolygon = transform.map( mPolygon );
|
||||||
|
else
|
||||||
|
mPath = transform.map( mPath );
|
||||||
|
|
||||||
|
if ( !hasDataDefinedRotation && !hasDataDefinedSize )
|
||||||
|
{
|
||||||
|
// we can use the cached marker
|
||||||
|
// TODO: use caching only when drawing to screen (not printer)
|
||||||
|
prepareCache( context );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// some markers can't be drawn as a polygon (circle, cross)
|
mCache = QImage();
|
||||||
// For these set the selected border color to the selected color
|
mSelCache = QImage();
|
||||||
|
|
||||||
if ( mName != "circle" ) mSelPen.setColor( selColor );
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rotate if needed
|
|
||||||
if ( mAngle != 0 )
|
|
||||||
mPolygon = QMatrix().rotate( mAngle ).map( mPolygon );
|
|
||||||
|
|
||||||
// cache the marker
|
void QgsSimpleMarkerSymbolLayerV2::prepareCache( QgsSymbolV2RenderContext& context )
|
||||||
// TODO: use caching only when drawing to screen (not printer)
|
{
|
||||||
// TODO: decide whether to use QImage or QPixmap - based on the render context
|
double scaledSize = context.outputPixelSize( mSize );
|
||||||
|
|
||||||
// calculate necessary image size for the cache
|
// calculate necessary image size for the cache
|
||||||
double pw = (( mPen.widthF() == 0 ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen
|
double pw = (( mPen.widthF() == 0 ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen
|
||||||
@ -185,6 +155,8 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex
|
|||||||
|
|
||||||
// Construct the selected version of the Cache
|
// Construct the selected version of the Cache
|
||||||
|
|
||||||
|
QColor selColor = context.selectionColor();
|
||||||
|
|
||||||
mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
|
mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
|
||||||
mSelCache.fill( 0 );
|
mSelCache.fill( 0 );
|
||||||
|
|
||||||
@ -224,6 +196,127 @@ void QgsSimpleMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsSimpleMarkerSymbolLayerV2::prepareShape()
|
||||||
|
{
|
||||||
|
mPolygon.clear();
|
||||||
|
|
||||||
|
if ( mName == "rectangle" )
|
||||||
|
{
|
||||||
|
mPolygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "diamond" )
|
||||||
|
{
|
||||||
|
mPolygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
|
||||||
|
<< QPointF( 1, 0 ) << QPointF( 0, -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "pentagon" )
|
||||||
|
{
|
||||||
|
mPolygon << QPointF( sin( DEG2RAD( 288.0 ) ), - cos( DEG2RAD( 288.0 ) ) )
|
||||||
|
<< QPointF( sin( DEG2RAD( 216.0 ) ), - cos( DEG2RAD( 216.0 ) ) )
|
||||||
|
<< QPointF( sin( DEG2RAD( 144.0 ) ), - cos( DEG2RAD( 144.0 ) ) )
|
||||||
|
<< QPointF( sin( DEG2RAD( 72.0 ) ), - cos( DEG2RAD( 72.0 ) ) )
|
||||||
|
<< QPointF( 0, -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "triangle" )
|
||||||
|
{
|
||||||
|
mPolygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "equilateral_triangle" )
|
||||||
|
{
|
||||||
|
mPolygon << QPointF( sin( DEG2RAD( 240.0 ) ), - cos( DEG2RAD( 240.0 ) ) )
|
||||||
|
<< QPointF( sin( DEG2RAD( 120.0 ) ), - cos( DEG2RAD( 120.0 ) ) )
|
||||||
|
<< QPointF( 0, -1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "star" )
|
||||||
|
{
|
||||||
|
double sixth = 1.0 / 3;
|
||||||
|
|
||||||
|
mPolygon << QPointF( 0, -1 )
|
||||||
|
<< QPointF( -sixth, -sixth )
|
||||||
|
<< QPointF( -1, -sixth )
|
||||||
|
<< QPointF( -sixth, 0 )
|
||||||
|
<< QPointF( -1, 1 )
|
||||||
|
<< QPointF( 0, + sixth )
|
||||||
|
<< QPointF( 1, 1 )
|
||||||
|
<< QPointF( + sixth, 0 )
|
||||||
|
<< QPointF( 1, -sixth )
|
||||||
|
<< QPointF( + sixth, -sixth );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "regular_star" )
|
||||||
|
{
|
||||||
|
double inner_r = cos( DEG2RAD( 72.0 ) ) / cos( DEG2RAD( 36.0 ) );
|
||||||
|
|
||||||
|
mPolygon << QPointF( inner_r * sin( DEG2RAD( 324.0 ) ), - inner_r * cos( DEG2RAD( 324.0 ) ) ) // 324
|
||||||
|
<< QPointF( sin( DEG2RAD( 288.0 ) ) , - cos( DEG2RAD( 288 ) ) ) // 288
|
||||||
|
<< QPointF( inner_r * sin( DEG2RAD( 252.0 ) ), - inner_r * cos( DEG2RAD( 252.0 ) ) ) // 252
|
||||||
|
<< QPointF( sin( DEG2RAD( 216.0 ) ) , - cos( DEG2RAD( 216.0 ) ) ) // 216
|
||||||
|
<< QPointF( 0, inner_r ) // 180
|
||||||
|
<< QPointF( sin( DEG2RAD( 144.0 ) ) , - cos( DEG2RAD( 144.0 ) ) ) // 144
|
||||||
|
<< QPointF( inner_r * sin( DEG2RAD( 108.0 ) ), - inner_r * cos( DEG2RAD( 108.0 ) ) ) // 108
|
||||||
|
<< QPointF( sin( DEG2RAD( 72.0 ) ) , - cos( DEG2RAD( 72.0 ) ) ) // 72
|
||||||
|
<< QPointF( inner_r * sin( DEG2RAD( 36.0 ) ), - inner_r * cos( DEG2RAD( 36.0 ) ) ) // 36
|
||||||
|
<< QPointF( 0, -1 ); // 0
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "arrow" )
|
||||||
|
{
|
||||||
|
double eight = 1.0 / 4;
|
||||||
|
double quarter = 1.0 / 2;
|
||||||
|
|
||||||
|
mPolygon << QPointF( 0, -1 )
|
||||||
|
<< QPointF( 0.5, -0.5 )
|
||||||
|
<< QPointF( 0.25, -0.25 )
|
||||||
|
<< QPointF( 0.25, 1 )
|
||||||
|
<< QPointF( -0.25, 1 )
|
||||||
|
<< QPointF( -0.25, -0.5 )
|
||||||
|
<< QPointF( -0.5, -0.5 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsSimpleMarkerSymbolLayerV2::preparePath()
|
||||||
|
{
|
||||||
|
mPath = QPainterPath();
|
||||||
|
|
||||||
|
if ( mName == "circle" )
|
||||||
|
{
|
||||||
|
mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "cross" )
|
||||||
|
{
|
||||||
|
mPath.moveTo( -1, 0 );
|
||||||
|
mPath.lineTo( 1, 0 ); // horizontal
|
||||||
|
mPath.moveTo( 0, -1 );
|
||||||
|
mPath.lineTo( 0, 1 ); // vertical
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "cross2" )
|
||||||
|
{
|
||||||
|
mPath.moveTo( -1, -1 );
|
||||||
|
mPath.lineTo( 1, 1 );
|
||||||
|
mPath.moveTo( 1, -1 );
|
||||||
|
mPath.lineTo( -1, 1 );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( mName == "line" )
|
||||||
|
{
|
||||||
|
mPath.moveTo( 0, -1 );
|
||||||
|
mPath.lineTo( 0, 1 ); // vertical line
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
|
void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context )
|
||||||
{
|
{
|
||||||
QgsRenderContext& rc = context.renderContext();
|
QgsRenderContext& rc = context.renderContext();
|
||||||
@ -233,11 +326,48 @@ void QgsSimpleMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage &img = context.selected() ? mSelCache : mCache;
|
bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation;
|
||||||
double s = img.width() / context.renderContext().rasterScaleFactor();
|
bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale;
|
||||||
p->drawImage( QRectF( point.x() - s / 2.0 + context.outputLineWidth( mOffset.x() ),
|
|
||||||
point.y() - s / 2.0 + context.outputLineWidth( mOffset.y() ),
|
if ( !hasDataDefinedRotation && !hasDataDefinedSize )
|
||||||
s, s ), img );
|
{
|
||||||
|
// we will use cached image
|
||||||
|
QImage &img = context.selected() ? mSelCache : mCache;
|
||||||
|
double s = img.width() / context.renderContext().rasterScaleFactor();
|
||||||
|
p->drawImage( QRectF( point.x() - s / 2.0 + context.outputLineWidth( mOffset.x() ),
|
||||||
|
point.y() - s / 2.0 + context.outputLineWidth( mOffset.y() ),
|
||||||
|
s, s ), img );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMatrix transform;
|
||||||
|
|
||||||
|
// move to the desired position
|
||||||
|
transform.translate( point.x() + context.outputLineWidth( mOffset.x() ),
|
||||||
|
point.y() + context.outputLineWidth( mOffset.y() ) );
|
||||||
|
|
||||||
|
// resize if necessary
|
||||||
|
if ( hasDataDefinedSize )
|
||||||
|
{
|
||||||
|
double scaledSize = context.outputPixelSize( mSize );
|
||||||
|
double half = scaledSize / 2.0;
|
||||||
|
transform.scale( half, half );
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotate if necessary
|
||||||
|
if ( mAngle != 0 )
|
||||||
|
{
|
||||||
|
transform.rotate( mAngle );
|
||||||
|
}
|
||||||
|
|
||||||
|
p->setBrush( context.selected() ? mSelBrush : mBrush );
|
||||||
|
p->setPen( context.selected() ? mSelPen : mPen );
|
||||||
|
|
||||||
|
if ( !mPolygon.isEmpty() )
|
||||||
|
p->drawPolygon( transform.map( mPolygon ) );
|
||||||
|
else
|
||||||
|
p->drawPath( transform.map( mPath ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -268,37 +398,8 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double scaledSize = context.outputPixelSize( mSize );
|
p->drawPath( mPath );
|
||||||
double half = scaledSize / 2.0;
|
|
||||||
if ( mAngle != 0 )
|
|
||||||
{
|
|
||||||
p->save();
|
|
||||||
p->rotate( mAngle );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mName == "circle" )
|
|
||||||
{
|
|
||||||
p->drawEllipse( QRectF( -half, -half, half*2, half*2 ) ); // x,y,w,h
|
|
||||||
}
|
|
||||||
else if ( mName == "cross" )
|
|
||||||
{
|
|
||||||
p->drawLine( QPointF( -half, 0 ), QPointF( half, 0 ) ); // horizontal
|
|
||||||
p->drawLine( QPointF( 0, -half ), QPointF( 0, half ) ); // vertical
|
|
||||||
}
|
|
||||||
else if ( mName == "cross2" )
|
|
||||||
{
|
|
||||||
p->drawLine( QPointF( -half, -half ), QPointF( half, half ) );
|
|
||||||
p->drawLine( QPointF( -half, half ), QPointF( half, -half ) );
|
|
||||||
}
|
|
||||||
else if ( mName == "line" )
|
|
||||||
{
|
|
||||||
p->drawLine( QPointF( 0, -half ), QPointF( 0, half ) ); // vertical line
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mAngle != 0 )
|
|
||||||
p->restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -363,6 +464,8 @@ void QgsSvgMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
|
|||||||
selPainter.setPen( Qt::NoPen );
|
selPainter.setPen( Qt::NoPen );
|
||||||
selPainter.drawEllipse( QPointF( 0, 0 ), pictureSize*0.6, pictureSize*0.6 );
|
selPainter.drawEllipse( QPointF( 0, 0 ), pictureSize*0.6, pictureSize*0.6 );
|
||||||
renderer.render( &selPainter, rect );
|
renderer.render( &selPainter, rect );
|
||||||
|
|
||||||
|
mOrigSize = mSize; // save in case the size would be data defined
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSvgMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
|
void QgsSvgMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
|
||||||
@ -382,15 +485,18 @@ void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Re
|
|||||||
QPointF outputOffset = QPointF( context.outputLineWidth( mOffset.x() ), context.outputLineWidth( mOffset.y() ) );
|
QPointF outputOffset = QPointF( context.outputLineWidth( mOffset.x() ), context.outputLineWidth( mOffset.y() ) );
|
||||||
p->translate( point + outputOffset );
|
p->translate( point + outputOffset );
|
||||||
|
|
||||||
|
if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
|
||||||
|
{
|
||||||
|
double s = mSize / mOrigSize;
|
||||||
|
p->scale( s, s );
|
||||||
|
}
|
||||||
|
|
||||||
if ( mAngle != 0 )
|
if ( mAngle != 0 )
|
||||||
p->rotate( mAngle );
|
p->rotate( mAngle );
|
||||||
|
|
||||||
QPicture &pct = context.selected() ? mSelPicture : mPicture;
|
QPicture &pct = context.selected() ? mSelPicture : mPicture;
|
||||||
p->drawPicture( 0, 0, pct );
|
p->drawPicture( 0, 0, pct );
|
||||||
|
|
||||||
if ( mAngle != 0 )
|
|
||||||
p->rotate( -mAngle );
|
|
||||||
|
|
||||||
p->restore();
|
p->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +661,7 @@ void QgsFontMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context
|
|||||||
QFontMetrics fm( mFont );
|
QFontMetrics fm( mFont );
|
||||||
mChrOffset = QPointF( fm.width( mChr ) / 2, -fm.ascent() / 2 );
|
mChrOffset = QPointF( fm.width( mChr ) / 2, -fm.ascent() / 2 );
|
||||||
|
|
||||||
|
mOrigSize = mSize; // save in case the size would be data defined
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsFontMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
|
void QgsFontMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
|
||||||
@ -572,6 +678,13 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2R
|
|||||||
|
|
||||||
p->save();
|
p->save();
|
||||||
p->translate( point );
|
p->translate( point );
|
||||||
|
|
||||||
|
if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
|
||||||
|
{
|
||||||
|
double s = mSize / mOrigSize;
|
||||||
|
p->scale( s, s );
|
||||||
|
}
|
||||||
|
|
||||||
if ( mAngle != 0 )
|
if ( mAngle != 0 )
|
||||||
p->rotate( mAngle );
|
p->rotate( mAngle );
|
||||||
|
|
||||||
|
@ -53,10 +53,16 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
|
|||||||
|
|
||||||
void drawMarker( QPainter* p, QgsSymbolV2RenderContext& context );
|
void drawMarker( QPainter* p, QgsSymbolV2RenderContext& context );
|
||||||
|
|
||||||
|
bool prepareShape();
|
||||||
|
bool preparePath();
|
||||||
|
|
||||||
|
void prepareCache( QgsSymbolV2RenderContext& context );
|
||||||
|
|
||||||
QColor mBorderColor;
|
QColor mBorderColor;
|
||||||
QPen mPen;
|
QPen mPen;
|
||||||
QBrush mBrush;
|
QBrush mBrush;
|
||||||
QPolygonF mPolygon;
|
QPolygonF mPolygon;
|
||||||
|
QPainterPath mPath;
|
||||||
QString mName;
|
QString mName;
|
||||||
QImage mCache;
|
QImage mCache;
|
||||||
QPen mSelPen;
|
QPen mSelPen;
|
||||||
@ -114,6 +120,7 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
|
|||||||
QString mPath;
|
QString mPath;
|
||||||
QPicture mPicture;
|
QPicture mPicture;
|
||||||
QPicture mSelPicture;
|
QPicture mSelPicture;
|
||||||
|
double mOrigSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -170,6 +177,7 @@ class CORE_EXPORT QgsFontMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
|
|||||||
|
|
||||||
QPointF mChrOffset;
|
QPointF mChrOffset;
|
||||||
QFont mFont;
|
QFont mFont;
|
||||||
|
double mOrigSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,11 +4,16 @@
|
|||||||
#include "qgssymbolv2.h"
|
#include "qgssymbolv2.h"
|
||||||
#include "qgssymbollayerv2utils.h"
|
#include "qgssymbollayerv2utils.h"
|
||||||
|
|
||||||
|
#include "qgslogger.h"
|
||||||
|
#include "qgsfeature.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
#include <QDomElement>
|
#include <QDomElement>
|
||||||
|
|
||||||
QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2( QgsSymbolV2* symbol )
|
QgsSingleSymbolRendererV2::QgsSingleSymbolRendererV2( QgsSymbolV2* symbol )
|
||||||
: QgsFeatureRendererV2( "singleSymbol" )
|
: QgsFeatureRendererV2( "singleSymbol" ),
|
||||||
|
mTempSymbol( NULL )
|
||||||
{
|
{
|
||||||
mSymbol = symbol;
|
mSymbol = symbol;
|
||||||
}
|
}
|
||||||
@ -20,22 +25,93 @@ QgsSingleSymbolRendererV2::~QgsSingleSymbolRendererV2()
|
|||||||
|
|
||||||
QgsSymbolV2* QgsSingleSymbolRendererV2::symbolForFeature( QgsFeature& feature )
|
QgsSymbolV2* QgsSingleSymbolRendererV2::symbolForFeature( QgsFeature& feature )
|
||||||
{
|
{
|
||||||
return mSymbol;
|
if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 )
|
||||||
|
return mSymbol;
|
||||||
|
|
||||||
|
double rotation = 0;
|
||||||
|
double sizeScale = 1;
|
||||||
|
if ( mRotationFieldIdx != -1 )
|
||||||
|
{
|
||||||
|
rotation = feature.attributeMap()[mRotationFieldIdx].toDouble();
|
||||||
|
}
|
||||||
|
if ( mSizeScaleFieldIdx != -1 )
|
||||||
|
{
|
||||||
|
sizeScale = feature.attributeMap()[mSizeScaleFieldIdx].toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mTempSymbol->type() == QgsSymbolV2::Marker )
|
||||||
|
{
|
||||||
|
QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( mTempSymbol );
|
||||||
|
if ( mRotationFieldIdx != -1 )
|
||||||
|
markerSymbol->setAngle( rotation );
|
||||||
|
if ( mSizeScaleFieldIdx != -1 )
|
||||||
|
markerSymbol->setSize( sizeScale * mOrigSize );
|
||||||
|
}
|
||||||
|
else if ( mTempSymbol->type() == QgsSymbolV2::Line )
|
||||||
|
{
|
||||||
|
QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( mTempSymbol );
|
||||||
|
if ( mSizeScaleFieldIdx != -1 )
|
||||||
|
lineSymbol->setWidth( sizeScale * mOrigSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTempSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSingleSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
|
void QgsSingleSymbolRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
|
||||||
{
|
{
|
||||||
|
mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
|
||||||
|
mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );
|
||||||
|
|
||||||
mSymbol->startRender( context );
|
mSymbol->startRender( context );
|
||||||
|
|
||||||
|
if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
|
||||||
|
{
|
||||||
|
// we are going to need a temporary symbol
|
||||||
|
mTempSymbol = mSymbol->clone();
|
||||||
|
|
||||||
|
int hints = 0;
|
||||||
|
if ( mRotationFieldIdx != -1 ) hints |= QgsSymbolV2::DataDefinedRotation;
|
||||||
|
if ( mSizeScaleFieldIdx != -1 ) hints |= QgsSymbolV2::DataDefinedSizeScale;
|
||||||
|
mTempSymbol->setRenderHints( hints );
|
||||||
|
|
||||||
|
mTempSymbol->startRender( context );
|
||||||
|
|
||||||
|
if ( mSymbol->type() == QgsSymbolV2::Marker )
|
||||||
|
{
|
||||||
|
mOrigSize = static_cast<QgsMarkerSymbolV2*>( mSymbol )->size();
|
||||||
|
}
|
||||||
|
else if ( mSymbol->type() == QgsSymbolV2::Line )
|
||||||
|
{
|
||||||
|
mOrigSize = static_cast<QgsLineSymbolV2*>( mSymbol )->width();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOrigSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSingleSymbolRendererV2::stopRender( QgsRenderContext& context )
|
void QgsSingleSymbolRendererV2::stopRender( QgsRenderContext& context )
|
||||||
{
|
{
|
||||||
mSymbol->stopRender( context );
|
mSymbol->stopRender( context );
|
||||||
|
|
||||||
|
if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
|
||||||
|
{
|
||||||
|
// we are going to need a temporary symbol
|
||||||
|
mTempSymbol->stopRender( context );
|
||||||
|
delete mTempSymbol;
|
||||||
|
mTempSymbol = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QString> QgsSingleSymbolRendererV2::usedAttributes()
|
QList<QString> QgsSingleSymbolRendererV2::usedAttributes()
|
||||||
{
|
{
|
||||||
return QList<QString>();
|
QList<QString> lst;
|
||||||
|
if ( !mRotationField.isEmpty() )
|
||||||
|
lst.append( mRotationField );
|
||||||
|
if ( !mSizeScaleField.isEmpty() )
|
||||||
|
lst.append( mSizeScaleField );
|
||||||
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbolV2* QgsSingleSymbolRendererV2::symbol() const
|
QgsSymbolV2* QgsSingleSymbolRendererV2::symbol() const
|
||||||
@ -58,6 +134,8 @@ QgsFeatureRendererV2* QgsSingleSymbolRendererV2::clone()
|
|||||||
{
|
{
|
||||||
QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( mSymbol->clone() );
|
QgsSingleSymbolRendererV2* r = new QgsSingleSymbolRendererV2( mSymbol->clone() );
|
||||||
r->setUsingSymbolLevels( usingSymbolLevels() );
|
r->setUsingSymbolLevels( usingSymbolLevels() );
|
||||||
|
r->setRotationField( rotationField() );
|
||||||
|
r->setSizeScaleField( sizeScaleField() );
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +162,14 @@ QgsFeatureRendererV2* QgsSingleSymbolRendererV2::create( QDomElement& element )
|
|||||||
// delete symbols if there are any more
|
// delete symbols if there are any more
|
||||||
QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
|
QgsSymbolLayerV2Utils::clearSymbolMap( symbolMap );
|
||||||
|
|
||||||
|
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
|
// TODO: symbol levels
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -99,6 +185,14 @@ QDomElement QgsSingleSymbolRendererV2::save( QDomDocument& doc )
|
|||||||
QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
|
QDomElement symbolsElem = QgsSymbolLayerV2Utils::saveSymbols( symbols, "symbols", doc );
|
||||||
rendererElem.appendChild( symbolsElem );
|
rendererElem.appendChild( symbolsElem );
|
||||||
|
|
||||||
|
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;
|
return rendererElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,12 @@ class CORE_EXPORT QgsSingleSymbolRendererV2 : public QgsFeatureRendererV2
|
|||||||
QgsSymbolV2* symbol() const;
|
QgsSymbolV2* symbol() const;
|
||||||
void setSymbol( QgsSymbolV2* s );
|
void setSymbol( QgsSymbolV2* s );
|
||||||
|
|
||||||
|
void setRotationField( QString fieldName ) { mRotationField = fieldName; }
|
||||||
|
QString rotationField() const { return mRotationField; }
|
||||||
|
|
||||||
|
void setSizeScaleField( QString fieldName ) { mSizeScaleField = fieldName; }
|
||||||
|
QString sizeScaleField() const { return mSizeScaleField; }
|
||||||
|
|
||||||
virtual QString dump();
|
virtual QString dump();
|
||||||
|
|
||||||
virtual QgsFeatureRendererV2* clone();
|
virtual QgsFeatureRendererV2* clone();
|
||||||
@ -43,6 +49,13 @@ class CORE_EXPORT QgsSingleSymbolRendererV2 : public QgsFeatureRendererV2
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
QgsSymbolV2* mSymbol;
|
QgsSymbolV2* mSymbol;
|
||||||
|
QString mRotationField;
|
||||||
|
QString mSizeScaleField;
|
||||||
|
|
||||||
|
// temporary stuff for rendering
|
||||||
|
int mRotationFieldIdx, mSizeScaleFieldIdx;
|
||||||
|
QgsSymbolV2* mTempSymbol;
|
||||||
|
double mOrigSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers )
|
QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers )
|
||||||
: mType( type ), mLayers( layers ), mOutputUnit( MM ), mAlpha( 1.0 )
|
: mType( type ), mLayers( layers ), mOutputUnit( MM ), mAlpha( 1.0 ), mRenderHints( 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
// check they're all correct symbol layers
|
// check they're all correct symbol layers
|
||||||
@ -127,14 +127,14 @@ bool QgsSymbolV2::changeSymbolLayer( int index, QgsSymbolLayerV2* layer )
|
|||||||
|
|
||||||
void QgsSymbolV2::startRender( QgsRenderContext& context )
|
void QgsSymbolV2::startRender( QgsRenderContext& context )
|
||||||
{
|
{
|
||||||
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
|
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints );
|
||||||
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
|
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
|
||||||
( *it )->startRender( symbolContext );
|
( *it )->startRender( symbolContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSymbolV2::stopRender( QgsRenderContext& context )
|
void QgsSymbolV2::stopRender( QgsRenderContext& context )
|
||||||
{
|
{
|
||||||
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha );
|
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints );
|
||||||
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
|
for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
|
||||||
( *it )->stopRender( symbolContext );
|
( *it )->stopRender( symbolContext );
|
||||||
}
|
}
|
||||||
@ -245,8 +245,8 @@ QgsSymbolLayerV2List QgsSymbolV2::cloneLayers() const
|
|||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
||||||
QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected )
|
QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected, int renderHints )
|
||||||
: mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha ), mSelected( selected )
|
: mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -347,7 +347,7 @@ double QgsMarkerSymbolV2::size()
|
|||||||
|
|
||||||
void QgsMarkerSymbolV2::renderPoint( const QPointF& point, QgsRenderContext& context, int layer, bool selected )
|
void QgsMarkerSymbolV2::renderPoint( const QPointF& point, QgsRenderContext& context, int layer, bool selected )
|
||||||
{
|
{
|
||||||
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected );
|
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints );
|
||||||
if ( layer != -1 )
|
if ( layer != -1 )
|
||||||
{
|
{
|
||||||
if ( layer >= 0 && layer < mLayers.count() )
|
if ( layer >= 0 && layer < mLayers.count() )
|
||||||
@ -416,7 +416,7 @@ double QgsLineSymbolV2::width()
|
|||||||
|
|
||||||
void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, QgsRenderContext& context, int layer, bool selected )
|
void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, QgsRenderContext& context, int layer, bool selected )
|
||||||
{
|
{
|
||||||
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected );
|
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints );
|
||||||
if ( layer != -1 )
|
if ( layer != -1 )
|
||||||
{
|
{
|
||||||
if ( layer >= 0 && layer < mLayers.count() )
|
if ( layer >= 0 && layer < mLayers.count() )
|
||||||
@ -452,7 +452,7 @@ QgsFillSymbolV2::QgsFillSymbolV2( QgsSymbolLayerV2List layers )
|
|||||||
|
|
||||||
void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsRenderContext& context, int layer, bool selected )
|
void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsRenderContext& context, int layer, bool selected )
|
||||||
{
|
{
|
||||||
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected );
|
QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints );
|
||||||
if ( layer != -1 )
|
if ( layer != -1 )
|
||||||
{
|
{
|
||||||
if ( layer >= 0 && layer < mLayers.count() )
|
if ( layer >= 0 && layer < mLayers.count() )
|
||||||
|
@ -35,6 +35,12 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
Fill
|
Fill
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RenderHint
|
||||||
|
{
|
||||||
|
DataDefinedSizeScale = 1,
|
||||||
|
DataDefinedRotation = 2
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~QgsSymbolV2();
|
virtual ~QgsSymbolV2();
|
||||||
|
|
||||||
//! return new default symbol for specified geometry type
|
//! return new default symbol for specified geometry type
|
||||||
@ -84,6 +90,9 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
qreal alpha() const { return mAlpha; }
|
qreal alpha() const { return mAlpha; }
|
||||||
void setAlpha( qreal alpha ) { mAlpha = alpha; }
|
void setAlpha( qreal alpha ) { mAlpha = alpha; }
|
||||||
|
|
||||||
|
void setRenderHints( int hints ) { mRenderHints = hints; }
|
||||||
|
int renderHints() { return mRenderHints; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers ); // can't be instantiated
|
QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers ); // can't be instantiated
|
||||||
|
|
||||||
@ -96,6 +105,8 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
|
|
||||||
/**Symbol opacity (in the range 0 - 1)*/
|
/**Symbol opacity (in the range 0 - 1)*/
|
||||||
qreal mAlpha;
|
qreal mAlpha;
|
||||||
|
|
||||||
|
int mRenderHints;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@ -103,7 +114,7 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
class CORE_EXPORT QgsSymbolV2RenderContext
|
class CORE_EXPORT QgsSymbolV2RenderContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u , qreal alpha = 1.0, bool selected = false );
|
QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u , qreal alpha = 1.0, bool selected = false, int renderHints = 0 );
|
||||||
~QgsSymbolV2RenderContext();
|
~QgsSymbolV2RenderContext();
|
||||||
|
|
||||||
QgsRenderContext& renderContext() { return mRenderContext; }
|
QgsRenderContext& renderContext() { return mRenderContext; }
|
||||||
@ -118,6 +129,9 @@ class CORE_EXPORT QgsSymbolV2RenderContext
|
|||||||
bool selected() const { return mSelected; }
|
bool selected() const { return mSelected; }
|
||||||
void setSelected( bool selected ) { mSelected = selected; }
|
void setSelected( bool selected ) { mSelected = selected; }
|
||||||
|
|
||||||
|
int renderHints() const { return mRenderHints; }
|
||||||
|
void setRenderHints( int hints ) { mRenderHints = hints; }
|
||||||
|
|
||||||
// Colour used for selections
|
// Colour used for selections
|
||||||
|
|
||||||
static QColor selectionColor();
|
static QColor selectionColor();
|
||||||
@ -133,6 +147,7 @@ class CORE_EXPORT QgsSymbolV2RenderContext
|
|||||||
QgsSymbolV2::OutputUnit mOutputUnit;
|
QgsSymbolV2::OutputUnit mOutputUnit;
|
||||||
qreal mAlpha;
|
qreal mAlpha;
|
||||||
bool mSelected;
|
bool mSelected;
|
||||||
|
int mRenderHints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,10 +3,13 @@
|
|||||||
#include "qgssinglesymbolrendererv2.h"
|
#include "qgssinglesymbolrendererv2.h"
|
||||||
#include "qgssymbolv2.h"
|
#include "qgssymbolv2.h"
|
||||||
|
|
||||||
|
#include "qgslogger.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
|
||||||
#include "qgssymbolv2selectordialog.h"
|
#include "qgssymbolv2selectordialog.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
QgsRendererV2Widget* QgsSingleSymbolRendererV2Widget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
|
QgsRendererV2Widget* QgsSingleSymbolRendererV2Widget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
|
||||||
{
|
{
|
||||||
return new QgsSingleSymbolRendererV2Widget( layer, style, renderer );
|
return new QgsSingleSymbolRendererV2Widget( layer, style, renderer );
|
||||||
@ -43,6 +46,44 @@ QgsSingleSymbolRendererV2Widget::QgsSingleSymbolRendererV2Widget( QgsVectorLayer
|
|||||||
layout->addWidget( mSelector );
|
layout->addWidget( mSelector );
|
||||||
setLayout( layout );
|
setLayout( layout );
|
||||||
|
|
||||||
|
// 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSingleSymbolRendererV2Widget::~QgsSingleSymbolRendererV2Widget()
|
QgsSingleSymbolRendererV2Widget::~QgsSingleSymbolRendererV2Widget()
|
||||||
@ -66,3 +107,50 @@ void QgsSingleSymbolRendererV2Widget::changeSingleSymbol()
|
|||||||
mRenderer->setSymbol( mSingleSymbol->clone() );
|
mRenderer->setSymbol( mSingleSymbol->clone() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsSingleSymbolRendererV2Widget::rotationFieldSelected()
|
||||||
|
{
|
||||||
|
QObject* s = sender();
|
||||||
|
if ( s == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QAction* a = qobject_cast<QAction*>( 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()
|
||||||
|
{
|
||||||
|
QObject* s = sender();
|
||||||
|
if ( s == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QAction* a = qobject_cast<QAction*>( 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
class QgsSingleSymbolRendererV2;
|
class QgsSingleSymbolRendererV2;
|
||||||
class QgsSymbolV2SelectorDialog;
|
class QgsSymbolV2SelectorDialog;
|
||||||
|
|
||||||
|
class QMenu;
|
||||||
|
|
||||||
class GUI_EXPORT QgsSingleSymbolRendererV2Widget : public QgsRendererV2Widget
|
class GUI_EXPORT QgsSingleSymbolRendererV2Widget : public QgsRendererV2Widget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -22,10 +24,20 @@ class GUI_EXPORT QgsSingleSymbolRendererV2Widget : public QgsRendererV2Widget
|
|||||||
public slots:
|
public slots:
|
||||||
void changeSingleSymbol();
|
void changeSingleSymbol();
|
||||||
|
|
||||||
|
void rotationFieldSelected();
|
||||||
|
void sizeScaleFieldSelected();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void populateMenu( QMenu* menu, const char* slot, QString fieldName );
|
||||||
|
void updateMenu( QMenu* menu, QString fieldName );
|
||||||
|
|
||||||
QgsSingleSymbolRendererV2* mRenderer;
|
QgsSingleSymbolRendererV2* mRenderer;
|
||||||
QgsSymbolV2SelectorDialog* mSelector;
|
QgsSymbolV2SelectorDialog* mSelector;
|
||||||
QgsSymbolV2* mSingleSymbol;
|
QgsSymbolV2* mSingleSymbol;
|
||||||
|
|
||||||
|
QMenu* mRotationMenu;
|
||||||
|
QMenu* mSizeScaleMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,15 +14,18 @@
|
|||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
QgsSymbolV2SelectorDialog::QgsSymbolV2SelectorDialog( QgsSymbolV2* symbol, QgsStyleV2* style, QWidget* parent, bool embedded )
|
QgsSymbolV2SelectorDialog::QgsSymbolV2SelectorDialog( QgsSymbolV2* symbol, QgsStyleV2* style, QWidget* parent, bool embedded )
|
||||||
: QDialog( parent )
|
: QDialog( parent ), mAdvancedMenu( NULL )
|
||||||
{
|
{
|
||||||
mStyle = style;
|
mStyle = style;
|
||||||
mSymbol = symbol;
|
mSymbol = symbol;
|
||||||
|
|
||||||
setupUi( this );
|
setupUi( this );
|
||||||
|
|
||||||
|
btnAdvanced->hide(); // advanced button is hidden by default
|
||||||
|
|
||||||
// can be embedded in renderer properties dialog
|
// can be embedded in renderer properties dialog
|
||||||
if ( embedded )
|
if ( embedded )
|
||||||
{
|
{
|
||||||
@ -262,3 +265,14 @@ void QgsSymbolV2SelectorDialog::displayTransparency( double alpha )
|
|||||||
double transparencyPercent = ( 1 - alpha ) * 100;
|
double transparencyPercent = ( 1 - alpha ) * 100;
|
||||||
mTransparencyLabel->setText( tr( "Transparency: %1%" ).arg(( int ) transparencyPercent ) );
|
mTransparencyLabel->setText( tr( "Transparency: %1%" ).arg(( int ) transparencyPercent ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMenu* QgsSymbolV2SelectorDialog::advancedMenu()
|
||||||
|
{
|
||||||
|
if ( mAdvancedMenu == NULL )
|
||||||
|
{
|
||||||
|
mAdvancedMenu = new QMenu;
|
||||||
|
btnAdvanced->setMenu( mAdvancedMenu );
|
||||||
|
btnAdvanced->show();
|
||||||
|
}
|
||||||
|
return mAdvancedMenu;
|
||||||
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
class QgsStyleV2;
|
class QgsStyleV2;
|
||||||
class QgsSymbolV2;
|
class QgsSymbolV2;
|
||||||
|
|
||||||
|
class QMenu;
|
||||||
|
|
||||||
class GUI_EXPORT QgsSymbolV2SelectorDialog : public QDialog, private Ui::QgsSymbolV2SelectorDialogBase
|
class GUI_EXPORT QgsSymbolV2SelectorDialog : public QDialog, private Ui::QgsSymbolV2SelectorDialogBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -16,6 +18,9 @@ class GUI_EXPORT QgsSymbolV2SelectorDialog : public QDialog, private Ui::QgsSymb
|
|||||||
public:
|
public:
|
||||||
QgsSymbolV2SelectorDialog( QgsSymbolV2* symbol, QgsStyleV2* style, QWidget* parent = NULL, bool embedded = false );
|
QgsSymbolV2SelectorDialog( QgsSymbolV2* symbol, QgsStyleV2* style, QWidget* parent = NULL, bool embedded = false );
|
||||||
|
|
||||||
|
//! return menu for "advanced" button - create it if doesn't exist and show the advanced button
|
||||||
|
QMenu* advancedMenu();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void populateSymbolView();
|
void populateSymbolView();
|
||||||
void updateSymbolPreview();
|
void updateSymbolPreview();
|
||||||
@ -46,6 +51,7 @@ class GUI_EXPORT QgsSymbolV2SelectorDialog : public QDialog, private Ui::QgsSymb
|
|||||||
protected:
|
protected:
|
||||||
QgsStyleV2* mStyle;
|
QgsStyleV2* mStyle;
|
||||||
QgsSymbolV2* mSymbol;
|
QgsSymbolV2* mSymbol;
|
||||||
|
QMenu* mAdvancedMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
<enum>QFrame::Box</enum>
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
@ -221,6 +221,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnAdvanced">
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnAddToStyle">
|
<widget class="QPushButton" name="btnAddToStyle">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user