[FEATURE] Add option to symbology to prevent clipping of features
This option (located under the symbol advanced menu) disables the automatic clipping of lines/polygons to the canvas extent. In some cases this clipping results in unfavourable symbology (eg centroid fills where the centroid must always be the actual feature's centroid). (fix #9757)
@ -229,8 +229,8 @@ class QgsFeatureRendererV2
|
|||||||
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
|
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
|
||||||
|
|
||||||
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
|
||||||
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
|
||||||
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
|
||||||
|
|
||||||
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
|
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
|
||||||
|
|
||||||
|
@ -130,6 +130,26 @@ class QgsSymbolV2
|
|||||||
void setRenderHints( int hints );
|
void setRenderHints( int hints );
|
||||||
int renderHints() const;
|
int renderHints() const;
|
||||||
|
|
||||||
|
/**Sets whether features drawn by the symbol should be clipped to the render context's
|
||||||
|
* extent. If this option is enabled then features which are partially outside the extent
|
||||||
|
* will be clipped. This speeds up rendering of the feature, but may have undesirable
|
||||||
|
* side effects for certain symbol types.
|
||||||
|
* @param clipFeaturesToExtent set to true to enable clipping (defaults to true)
|
||||||
|
* @note added in QGIS 2.9
|
||||||
|
* @see clipFeaturesToExtent
|
||||||
|
*/
|
||||||
|
void setClipFeaturesToExtent( bool clipFeaturesToExtent );
|
||||||
|
|
||||||
|
/**Returns whether features drawn by the symbol will be clipped to the render context's
|
||||||
|
* extent. If this option is enabled then features which are partially outside the extent
|
||||||
|
* will be clipped. This speeds up rendering of the feature, but may have undesirable
|
||||||
|
* side effects for certain symbol types.
|
||||||
|
* @returns true if features will be clipped
|
||||||
|
* @note added in QGIS 2.9
|
||||||
|
* @see setClipFeaturesToExtent
|
||||||
|
*/
|
||||||
|
double clipFeaturesToExtent() const;
|
||||||
|
|
||||||
QSet<QString> usedAttributes() const;
|
QSet<QString> usedAttributes() const;
|
||||||
|
|
||||||
void setLayer( const QgsVectorLayer* layer );
|
void setLayer( const QgsVectorLayer* layer );
|
||||||
|
@ -58,20 +58,21 @@ const unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderCont
|
|||||||
return wkbPtr;
|
return wkbPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb )
|
const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
|
||||||
{
|
{
|
||||||
QgsConstWkbPtr wkbPtr( wkb );
|
QgsConstWkbPtr wkbPtr( wkb + 1 );
|
||||||
unsigned int wkbType, nPoints;
|
unsigned int wkbType, nPoints;
|
||||||
wkbPtr >> wkbType >> nPoints;
|
wkbPtr >> wkbType >> nPoints;
|
||||||
|
|
||||||
bool hasZValue = wkbType == QGis::WKBLineString25D;
|
bool hasZValue = wkbType == QGis::WKBLineString25D;
|
||||||
|
|
||||||
double x, y;
|
double x = 0.0;
|
||||||
|
double y = 0.0;
|
||||||
const QgsCoordinateTransform* ct = context.coordinateTransform();
|
const QgsCoordinateTransform* ct = context.coordinateTransform();
|
||||||
const QgsMapToPixel& mtp = context.mapToPixel();
|
const QgsMapToPixel& mtp = context.mapToPixel();
|
||||||
|
|
||||||
//apply clipping for large lines to achieve a better rendering performance
|
//apply clipping for large lines to achieve a better rendering performance
|
||||||
if ( nPoints > 1 )
|
if ( clipToExtent && nPoints > 1 )
|
||||||
{
|
{
|
||||||
const QgsRectangle& e = context.extent();
|
const QgsRectangle& e = context.extent();
|
||||||
double cw = e.width() / 10; double ch = e.height() / 10;
|
double cw = e.width() / 10; double ch = e.height() / 10;
|
||||||
@ -108,7 +109,7 @@ const unsigned char* QgsFeatureRendererV2::_getLineString( QPolygonF& pts, QgsRe
|
|||||||
return wkbPtr;
|
return wkbPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb )
|
const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
|
||||||
{
|
{
|
||||||
QgsConstWkbPtr wkbPtr( wkb + 1 );
|
QgsConstWkbPtr wkbPtr( wkb + 1 );
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ const unsigned char* QgsFeatureRendererV2::_getPolygon( QPolygonF& pts, QList<QP
|
|||||||
|
|
||||||
//clip close to view extent, if needed
|
//clip close to view extent, if needed
|
||||||
QRectF ptsRect = poly.boundingRect();
|
QRectF ptsRect = poly.boundingRect();
|
||||||
if ( !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect );
|
if ( clipToExtent && !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect );
|
||||||
|
|
||||||
//transform the QPolygonF to screen coordinates
|
//transform the QPolygonF to screen coordinates
|
||||||
if ( ct )
|
if ( ct )
|
||||||
@ -271,7 +272,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QPolygonF pts;
|
QPolygonF pts;
|
||||||
_getLineString( pts, context, geom->asWkb() );
|
_getLineString( pts, context, geom->asWkb(), symbol->clipFeaturesToExtent() );
|
||||||
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
|
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
|
||||||
|
|
||||||
if ( drawVertexMarker )
|
if ( drawVertexMarker )
|
||||||
@ -289,7 +290,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
}
|
}
|
||||||
QPolygonF pts;
|
QPolygonF pts;
|
||||||
QList<QPolygonF> holes;
|
QList<QPolygonF> holes;
|
||||||
_getPolygon( pts, holes, context, geom->asWkb() );
|
_getPolygon( pts, holes, context, geom->asWkb(), symbol->clipFeaturesToExtent() );
|
||||||
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
|
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
|
||||||
|
|
||||||
if ( drawVertexMarker )
|
if ( drawVertexMarker )
|
||||||
@ -306,7 +307,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsConstWkbPtr wkbPtr( geom->asWkb() + 5 );
|
QgsConstWkbPtr wkbPtr( geom->asWkb() + 1 + sizeof( int ) );
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
wkbPtr >> num;
|
wkbPtr >> num;
|
||||||
const unsigned char* ptr = wkbPtr;
|
const unsigned char* ptr = wkbPtr;
|
||||||
@ -332,7 +333,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsConstWkbPtr wkbPtr( geom->asWkb() + 5 );
|
QgsConstWkbPtr wkbPtr( geom->asWkb() + 1 + sizeof( int ) );
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
wkbPtr >> num;
|
wkbPtr >> num;
|
||||||
const unsigned char* ptr = wkbPtr;
|
const unsigned char* ptr = wkbPtr;
|
||||||
@ -340,7 +341,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
|
|
||||||
for ( unsigned int i = 0; i < num; ++i )
|
for ( unsigned int i = 0; i < num; ++i )
|
||||||
{
|
{
|
||||||
ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr ) );
|
ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, symbol->clipFeaturesToExtent() ) );
|
||||||
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
|
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
|
||||||
|
|
||||||
if ( drawVertexMarker )
|
if ( drawVertexMarker )
|
||||||
@ -358,7 +359,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsConstWkbPtr wkbPtr( geom->asWkb() + 5 );
|
QgsConstWkbPtr wkbPtr( geom->asWkb() + 1 + sizeof( int ) );
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
wkbPtr >> num;
|
wkbPtr >> num;
|
||||||
const unsigned char* ptr = wkbPtr;
|
const unsigned char* ptr = wkbPtr;
|
||||||
@ -367,7 +368,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
|
|||||||
|
|
||||||
for ( unsigned int i = 0; i < num; ++i )
|
for ( unsigned int i = 0; i < num; ++i )
|
||||||
{
|
{
|
||||||
ptr = _getPolygon( pts, holes, context, ptr );
|
ptr = _getPolygon( pts, holes, context, ptr, symbol->clipFeaturesToExtent() );
|
||||||
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
|
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
|
||||||
|
|
||||||
if ( drawVertexMarker )
|
if ( drawVertexMarker )
|
||||||
|
@ -251,8 +251,8 @@ class CORE_EXPORT QgsFeatureRendererV2
|
|||||||
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
|
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
|
||||||
|
|
||||||
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb );
|
||||||
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
|
||||||
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb );
|
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent = true );
|
||||||
|
|
||||||
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
|
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
|
||||||
|
|
||||||
|
@ -940,6 +940,7 @@ QgsSymbolV2* QgsSymbolLayerV2Utils::loadSymbol( const QDomElement &element )
|
|||||||
symbol->setMapUnitScale( mapUnitScale );
|
symbol->setMapUnitScale( mapUnitScale );
|
||||||
}
|
}
|
||||||
symbol->setAlpha( element.attribute( "alpha", "1.0" ).toDouble() );
|
symbol->setAlpha( element.attribute( "alpha", "1.0" ).toDouble() );
|
||||||
|
symbol->setClipFeaturesToExtent( element.attribute( "clip_to_extent", "1" ).toInt() );
|
||||||
|
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
@ -993,6 +994,7 @@ QDomElement QgsSymbolLayerV2Utils::saveSymbol( QString name, QgsSymbolV2* symbol
|
|||||||
symEl.setAttribute( "type", _nameForSymbolType( symbol->type() ) );
|
symEl.setAttribute( "type", _nameForSymbolType( symbol->type() ) );
|
||||||
symEl.setAttribute( "name", name );
|
symEl.setAttribute( "name", name );
|
||||||
symEl.setAttribute( "alpha", QString::number( symbol->alpha() ) );
|
symEl.setAttribute( "alpha", QString::number( symbol->alpha() ) );
|
||||||
|
symEl.setAttribute( "clip_to_extent", symbol->clipFeaturesToExtent() ? "1" : "0" );
|
||||||
QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
|
QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
|
||||||
|
|
||||||
for ( int i = 0; i < symbol->symbolLayerCount(); i++ )
|
for ( int i = 0; i < symbol->symbolLayerCount(); i++ )
|
||||||
|
@ -40,6 +40,7 @@ QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers )
|
|||||||
, mLayers( layers )
|
, mLayers( layers )
|
||||||
, mAlpha( 1.0 )
|
, mAlpha( 1.0 )
|
||||||
, mRenderHints( 0 )
|
, mRenderHints( 0 )
|
||||||
|
, mClipFeaturesToExtent( true )
|
||||||
, mLayer( 0 )
|
, mLayer( 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -631,6 +632,7 @@ QgsSymbolV2* QgsMarkerSymbolV2::clone() const
|
|||||||
QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
|
QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
|
||||||
cloneSymbol->setAlpha( mAlpha );
|
cloneSymbol->setAlpha( mAlpha );
|
||||||
cloneSymbol->setLayer( mLayer );
|
cloneSymbol->setLayer( mLayer );
|
||||||
|
cloneSymbol->setClipFeaturesToExtent( mClipFeaturesToExtent );
|
||||||
return cloneSymbol;
|
return cloneSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,6 +730,7 @@ QgsSymbolV2* QgsLineSymbolV2::clone() const
|
|||||||
QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
|
QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
|
||||||
cloneSymbol->setAlpha( mAlpha );
|
cloneSymbol->setAlpha( mAlpha );
|
||||||
cloneSymbol->setLayer( mLayer );
|
cloneSymbol->setLayer( mLayer );
|
||||||
|
cloneSymbol->setClipFeaturesToExtent( mClipFeaturesToExtent );
|
||||||
return cloneSymbol;
|
return cloneSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,6 +837,7 @@ QgsSymbolV2* QgsFillSymbolV2::clone() const
|
|||||||
QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
|
QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
|
||||||
cloneSymbol->setAlpha( mAlpha );
|
cloneSymbol->setAlpha( mAlpha );
|
||||||
cloneSymbol->setLayer( mLayer );
|
cloneSymbol->setLayer( mLayer );
|
||||||
|
cloneSymbol->setClipFeaturesToExtent( mClipFeaturesToExtent );
|
||||||
return cloneSymbol;
|
return cloneSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,26 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
void setRenderHints( int hints ) { mRenderHints = hints; }
|
void setRenderHints( int hints ) { mRenderHints = hints; }
|
||||||
int renderHints() const { return mRenderHints; }
|
int renderHints() const { return mRenderHints; }
|
||||||
|
|
||||||
|
/**Sets whether features drawn by the symbol should be clipped to the render context's
|
||||||
|
* extent. If this option is enabled then features which are partially outside the extent
|
||||||
|
* will be clipped. This speeds up rendering of the feature, but may have undesirable
|
||||||
|
* side effects for certain symbol types.
|
||||||
|
* @param clipFeaturesToExtent set to true to enable clipping (defaults to true)
|
||||||
|
* @note added in QGIS 2.9
|
||||||
|
* @see clipFeaturesToExtent
|
||||||
|
*/
|
||||||
|
void setClipFeaturesToExtent( bool clipFeaturesToExtent ) { mClipFeaturesToExtent = clipFeaturesToExtent; }
|
||||||
|
|
||||||
|
/**Returns whether features drawn by the symbol will be clipped to the render context's
|
||||||
|
* extent. If this option is enabled then features which are partially outside the extent
|
||||||
|
* will be clipped. This speeds up rendering of the feature, but may have undesirable
|
||||||
|
* side effects for certain symbol types.
|
||||||
|
* @returns true if features will be clipped
|
||||||
|
* @note added in QGIS 2.9
|
||||||
|
* @see setClipFeaturesToExtent
|
||||||
|
*/
|
||||||
|
double clipFeaturesToExtent() const { return mClipFeaturesToExtent; }
|
||||||
|
|
||||||
QSet<QString> usedAttributes() const;
|
QSet<QString> usedAttributes() const;
|
||||||
|
|
||||||
void setLayer( const QgsVectorLayer* layer ) { mLayer = layer; }
|
void setLayer( const QgsVectorLayer* layer ) { mLayer = layer; }
|
||||||
@ -182,6 +202,7 @@ class CORE_EXPORT QgsSymbolV2
|
|||||||
qreal mAlpha;
|
qreal mAlpha;
|
||||||
|
|
||||||
int mRenderHints;
|
int mRenderHints;
|
||||||
|
bool mClipFeaturesToExtent;
|
||||||
|
|
||||||
const QgsVectorLayer* mLayer; //current vectorlayer
|
const QgsVectorLayer* mLayer; //current vectorlayer
|
||||||
|
|
||||||
|
@ -35,7 +35,10 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
|
|
||||||
QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent ) : QWidget( parent )
|
QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent )
|
||||||
|
: QWidget( parent )
|
||||||
|
, mAdvancedMenu( 0 )
|
||||||
|
, mClipFeaturesAction( 0 )
|
||||||
{
|
{
|
||||||
mSymbol = symbol;
|
mSymbol = symbol;
|
||||||
mStyle = style;
|
mStyle = style;
|
||||||
@ -47,9 +50,17 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* sty
|
|||||||
btnAdvanced->hide(); // advanced button is hidden by default
|
btnAdvanced->hide(); // advanced button is hidden by default
|
||||||
if ( menu ) // show it if there is a menu pointer
|
if ( menu ) // show it if there is a menu pointer
|
||||||
{
|
{
|
||||||
btnAdvanced->setMenu( menu );
|
mAdvancedMenu = menu;
|
||||||
btnAdvanced->show();
|
btnAdvanced->show();
|
||||||
|
btnAdvanced->setMenu( mAdvancedMenu );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btnAdvanced->setMenu( new QMenu( this ) );
|
||||||
|
}
|
||||||
|
mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this );
|
||||||
|
mClipFeaturesAction->setCheckable( true );
|
||||||
|
connect( mClipFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( clipFeaturesToggled( bool ) ) );
|
||||||
|
|
||||||
// populate the groups
|
// populate the groups
|
||||||
groupsCombo->addItem( "" );
|
groupsCombo->addItem( "" );
|
||||||
@ -163,6 +174,15 @@ void QgsSymbolsListWidget::openStyleManager()
|
|||||||
populateSymbolView();
|
populateSymbolView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsSymbolsListWidget::clipFeaturesToggled( bool checked )
|
||||||
|
{
|
||||||
|
if ( !mSymbol )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mSymbol->setClipFeaturesToExtent( checked );
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
|
||||||
void QgsSymbolsListWidget::setSymbolColor( const QColor& color )
|
void QgsSymbolsListWidget::setSymbolColor( const QColor& color )
|
||||||
{
|
{
|
||||||
mSymbol->setColor( color );
|
mSymbol->setColor( color );
|
||||||
@ -294,6 +314,21 @@ void QgsSymbolsListWidget::updateSymbolInfo()
|
|||||||
mTransparencySlider->setValue( transparency * 255 );
|
mTransparencySlider->setValue( transparency * 255 );
|
||||||
displayTransparency( mSymbol->alpha() );
|
displayTransparency( mSymbol->alpha() );
|
||||||
mTransparencySlider->blockSignals( false );
|
mTransparencySlider->blockSignals( false );
|
||||||
|
|
||||||
|
if ( mSymbol->type() == QgsSymbolV2::Line || mSymbol->type() == QgsSymbolV2::Fill )
|
||||||
|
{
|
||||||
|
//add clip features option for line or fill symbols
|
||||||
|
btnAdvanced->menu()->addAction( mClipFeaturesAction );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btnAdvanced->menu()->removeAction( mClipFeaturesAction );
|
||||||
|
}
|
||||||
|
btnAdvanced->setVisible( mAdvancedMenu || !btnAdvanced->menu()->isEmpty() );
|
||||||
|
|
||||||
|
mClipFeaturesAction->blockSignals( true );
|
||||||
|
mClipFeaturesAction->setChecked( mSymbol->clipFeaturesToExtent() );
|
||||||
|
mClipFeaturesAction->blockSignals( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
|
void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
|
||||||
|
@ -47,6 +47,7 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
|
|||||||
void on_groupsCombo_editTextChanged( const QString &text );
|
void on_groupsCombo_editTextChanged( const QString &text );
|
||||||
|
|
||||||
void openStyleManager();
|
void openStyleManager();
|
||||||
|
void clipFeaturesToggled( bool checked );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed();
|
void changed();
|
||||||
@ -54,6 +55,8 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
|
|||||||
protected:
|
protected:
|
||||||
QgsSymbolV2* mSymbol;
|
QgsSymbolV2* mSymbol;
|
||||||
QgsStyleV2* mStyle;
|
QgsStyleV2* mStyle;
|
||||||
|
QMenu* mAdvancedMenu;
|
||||||
|
QAction* mClipFeaturesAction;
|
||||||
|
|
||||||
void populateSymbolView();
|
void populateSymbolView();
|
||||||
void populateSymbols( QStringList symbols );
|
void populateSymbols( QStringList symbols );
|
||||||
|
@ -20,11 +20,17 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
//qgis includes...
|
//qgis includes...
|
||||||
|
#include "qgsmultirenderchecker.h"
|
||||||
#include <qgsapplication.h>
|
#include <qgsapplication.h>
|
||||||
#include "qgsconfig.h"
|
#include "qgsconfig.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgsvectorcolorrampv2.h"
|
#include "qgsvectorcolorrampv2.h"
|
||||||
#include "qgscptcityarchive.h"
|
#include "qgscptcityarchive.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsmaplayerregistry.h"
|
||||||
|
#include "qgslinesymbollayerv2.h"
|
||||||
|
#include "qgsfillsymbollayerv2.h"
|
||||||
|
#include "qgssinglesymbolrendererv2.h"
|
||||||
|
|
||||||
#include "qgsstylev2.h"
|
#include "qgsstylev2.h"
|
||||||
|
|
||||||
@ -40,10 +46,18 @@ class TestStyleV2 : public QObject
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
QString mReport;
|
||||||
|
|
||||||
QgsStyleV2 *mStyle;
|
QgsStyleV2 *mStyle;
|
||||||
QString mTestDataDir;
|
QString mTestDataDir;
|
||||||
|
|
||||||
|
QgsMapSettings mMapSettings;
|
||||||
|
QgsVectorLayer * mpPointsLayer;
|
||||||
|
QgsVectorLayer * mpLinesLayer;
|
||||||
|
QgsVectorLayer * mpPolysLayer;
|
||||||
|
|
||||||
bool testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected );
|
bool testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected );
|
||||||
|
bool imageCheck( QgsMapSettings &ms, const QString &testName );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
@ -54,11 +68,14 @@ class TestStyleV2 : public QObject
|
|||||||
void cleanup() {}// will be called after every testfunction.
|
void cleanup() {}// will be called after every testfunction.
|
||||||
// void initStyles();
|
// void initStyles();
|
||||||
|
|
||||||
|
void testCanvasClip();
|
||||||
void testCreateColorRamps();
|
void testCreateColorRamps();
|
||||||
void testLoadColorRamps();
|
void testLoadColorRamps();
|
||||||
void testSaveLoad();
|
void testSaveLoad();
|
||||||
void testParseColor();
|
void testParseColor();
|
||||||
void testParseColorList();
|
void testParseColorList();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TestStyleV2::TestStyleV2()
|
TestStyleV2::TestStyleV2()
|
||||||
@ -96,6 +113,44 @@ void TestStyleV2::initTestCase()
|
|||||||
|
|
||||||
// cpt-city ramp, small selection available in <testdir>/cpt-city
|
// cpt-city ramp, small selection available in <testdir>/cpt-city
|
||||||
QgsCptCityArchive::initArchives();
|
QgsCptCityArchive::initArchives();
|
||||||
|
|
||||||
|
//
|
||||||
|
//create a point layer that will be used in all tests...
|
||||||
|
//
|
||||||
|
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
||||||
|
mTestDataDir = myDataDir + QDir::separator();
|
||||||
|
QString myPointsFileName = mTestDataDir + "points.shp";
|
||||||
|
QFileInfo myPointFileInfo( myPointsFileName );
|
||||||
|
mpPointsLayer = new QgsVectorLayer( myPointFileInfo.filePath(),
|
||||||
|
myPointFileInfo.completeBaseName(), "ogr" );
|
||||||
|
// Register the layer with the registry
|
||||||
|
QgsMapLayerRegistry::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mpPointsLayer );
|
||||||
|
|
||||||
|
//
|
||||||
|
//create a poly layer that will be used in all tests...
|
||||||
|
//
|
||||||
|
QString myPolysFileName = mTestDataDir + "polys.shp";
|
||||||
|
QFileInfo myPolyFileInfo( myPolysFileName );
|
||||||
|
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
|
||||||
|
myPolyFileInfo.completeBaseName(), "ogr" );
|
||||||
|
// Register the layer with the registry
|
||||||
|
QgsMapLayerRegistry::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mpPolysLayer );
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a line layer that will be used in all tests...
|
||||||
|
//
|
||||||
|
QString myLinesFileName = mTestDataDir + "lines.shp";
|
||||||
|
QFileInfo myLineFileInfo( myLinesFileName );
|
||||||
|
mpLinesLayer = new QgsVectorLayer( myLineFileInfo.filePath(),
|
||||||
|
myLineFileInfo.completeBaseName(), "ogr" );
|
||||||
|
// Register the layer with the registry
|
||||||
|
QgsMapLayerRegistry::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mpLinesLayer );
|
||||||
|
|
||||||
|
mReport += "<h1>StyleV2 Tests</h1>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestStyleV2::cleanupTestCase()
|
void TestStyleV2::cleanupTestCase()
|
||||||
@ -104,6 +159,76 @@ void TestStyleV2::cleanupTestCase()
|
|||||||
// mStyle->save();
|
// mStyle->save();
|
||||||
delete mStyle;
|
delete mStyle;
|
||||||
QgsApplication::exitQgis();
|
QgsApplication::exitQgis();
|
||||||
|
|
||||||
|
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html";
|
||||||
|
QFile myFile( myReportFile );
|
||||||
|
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
|
||||||
|
{
|
||||||
|
QTextStream myQTextStream( &myFile );
|
||||||
|
myQTextStream << mReport;
|
||||||
|
myFile.close();
|
||||||
|
//QDesktopServices::openUrl( "file:///" + myReportFile );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestStyleV2::imageCheck( QgsMapSettings& ms, const QString& testName )
|
||||||
|
{
|
||||||
|
QgsMultiRenderChecker checker;
|
||||||
|
checker.setControlName( "expected_" + testName );
|
||||||
|
checker.setMapSettings( ms );
|
||||||
|
bool result = checker.runTest( testName, 0 );
|
||||||
|
mReport += checker.report();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestStyleV2::testCanvasClip()
|
||||||
|
{
|
||||||
|
//test rendering with and without clip to canvas enabled
|
||||||
|
QgsMapSettings ms;
|
||||||
|
QgsRectangle extent( -110.0, 25.0, -90, 40.0 );
|
||||||
|
ms.setExtent( extent );
|
||||||
|
ms.setFlag( QgsMapSettings::ForceVectorOutput );
|
||||||
|
|
||||||
|
//line
|
||||||
|
mReport += "<h2>Line canvas clip</h2>\n";
|
||||||
|
ms.setLayers( QStringList() << mpLinesLayer->id() );
|
||||||
|
|
||||||
|
QgsMarkerLineSymbolLayerV2* markerLine = new QgsMarkerLineSymbolLayerV2();
|
||||||
|
markerLine->setPlacement( QgsMarkerLineSymbolLayerV2:: CentralPoint );
|
||||||
|
QgsLineSymbolV2* lineSymbol = new QgsLineSymbolV2();
|
||||||
|
lineSymbol->changeSymbolLayer( 0, markerLine );
|
||||||
|
QgsSingleSymbolRendererV2* renderer = new QgsSingleSymbolRendererV2( lineSymbol );
|
||||||
|
mpLinesLayer->setRendererV2( renderer );
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
lineSymbol->setClipFeaturesToExtent( true );
|
||||||
|
result = imageCheck( ms, "stylev2_linecanvasclip" );
|
||||||
|
QVERIFY( result );
|
||||||
|
|
||||||
|
lineSymbol->setClipFeaturesToExtent( false );
|
||||||
|
result = imageCheck( ms, "stylev2_linecanvasclip_off" );
|
||||||
|
QVERIFY( result );
|
||||||
|
|
||||||
|
//poly
|
||||||
|
mReport += "<h2>Polygon canvas clip</h2>\n";
|
||||||
|
ms.setLayers( QStringList() << mpPolysLayer->id() );
|
||||||
|
|
||||||
|
QgsCentroidFillSymbolLayerV2* centroidFill = new QgsCentroidFillSymbolLayerV2();
|
||||||
|
QgsFillSymbolV2* fillSymbol = new QgsFillSymbolV2();
|
||||||
|
fillSymbol->changeSymbolLayer( 0, centroidFill );
|
||||||
|
renderer = new QgsSingleSymbolRendererV2( fillSymbol );
|
||||||
|
mpPolysLayer->setRendererV2( renderer );
|
||||||
|
|
||||||
|
extent = QgsRectangle( -106.0, 29.0, -94, 36.0 );
|
||||||
|
ms.setExtent( extent );
|
||||||
|
|
||||||
|
fillSymbol->setClipFeaturesToExtent( true );
|
||||||
|
result = imageCheck( ms, "stylev2_polycanvasclip" );
|
||||||
|
QVERIFY( result );
|
||||||
|
|
||||||
|
fillSymbol->setClipFeaturesToExtent( false );
|
||||||
|
result = imageCheck( ms, "stylev2_polycanvasclip_off" );
|
||||||
|
QVERIFY( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestStyleV2::testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected )
|
bool TestStyleV2::testValidColor( QgsVectorColorRampV2 *ramp, double value, QColor expected )
|
||||||
|
BIN
tests/testdata/control_images/expected_stylev2_linecanvasclip/expected_stylev2_linecanvasclip.png
vendored
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.0 KiB |
BIN
tests/testdata/control_images/expected_stylev2_polycanvasclip/expected_stylev2_polycanvasclip.png
vendored
Normal file
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.6 KiB |