Skip to content

Commit 9bbabcf

Browse files
committedSep 25, 2018
Add test
Add onStyleChanged Add if mRenderContext when necessary Orderer renderer if and add enableInvisibleFeature
1 parent 458fa17 commit 9bbabcf

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed
 

‎python/core/auto_generated/qgstracer.sip.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ Sets the ``crs`` and ``transformContext`` used for tracing.
5858
void setRenderContext( const QgsRenderContext *renderContext );
5959
%Docstring
6060
Sets the ``renderContext`` used for tracing only on visible features.
61+
62+
.. versionadded:: 3.4
6163
%End
6264

6365
QgsRectangle extent() const;

‎src/core/qgstracer.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgsvectorlayer.h"
2525
#include "qgsexception.h"
2626
#include "qgsrenderer.h"
27+
#include "qgssettings.h"
2728

2829
#include <queue>
2930
#include <vector>
@@ -459,8 +460,7 @@ QgsTracer::QgsTracer() = default;
459460
bool QgsTracer::initGraph()
460461
{
461462
if ( mGraph )
462-
return true;
463-
// already initialized
463+
return true; // already initialized
464464

465465
mHasTopologyProblem = false;
466466

@@ -475,15 +475,17 @@ bool QgsTracer::initGraph()
475475

476476
t1.start();
477477
int featuresCounted = 0;
478+
bool enableInvisibleFeature = QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool();
478479
for ( QgsVectorLayer *vl : qgis::as_const( mLayers ) )
479480
{
480481
QgsFeatureRequest request;
481482

482483
bool filter = false;
483-
std::unique_ptr< QgsFeatureRenderer > renderer( vl->renderer() ? vl->renderer()->clone() : nullptr );
484+
std::unique_ptr< QgsFeatureRenderer > renderer;
484485
QgsRenderContext *ctx = nullptr;
485-
if ( mRenderContext )
486+
if ( !enableInvisibleFeature && mRenderContext )
486487
{
488+
renderer.reset( vl->renderer() ? vl->renderer()->clone() : nullptr );
487489
mRenderContext->expressionContext() << QgsExpressionContextUtils::layerScope( vl );
488490
ctx = mRenderContext.get();
489491
if ( renderer )
@@ -602,6 +604,7 @@ void QgsTracer::setLayers( const QList<QgsVectorLayer *> &layers )
602604
disconnect( layer, &QgsVectorLayer::geometryChanged, this, &QgsTracer::onGeometryChanged );
603605
disconnect( layer, &QgsVectorLayer::attributeValueChanged, this, &QgsTracer::onAttributeValueChanged );
604606
disconnect( layer, &QgsVectorLayer::dataChanged, this, &QgsTracer::onDataChanged );
607+
disconnect( layer, &QgsVectorLayer::styleChanged, this, &QgsTracer::onStyleChanged );
605608
disconnect( layer, &QObject::destroyed, this, &QgsTracer::onLayerDestroyed );
606609
}
607610

@@ -702,14 +705,21 @@ void QgsTracer::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVaria
702705
Q_UNUSED( fid );
703706
Q_UNUSED( idx );
704707
Q_UNUSED( value );
705-
invalidateGraph();
708+
if ( mRenderContext )
709+
invalidateGraph();
706710
}
707711

708712
void QgsTracer::onDataChanged( )
709713
{
710714
invalidateGraph();
711715
}
712716

717+
void QgsTracer::onStyleChanged( )
718+
{
719+
if ( mRenderContext )
720+
invalidateGraph();
721+
}
722+
713723
void QgsTracer::onLayerDestroyed( QObject *obj )
714724
{
715725
// remove the layer before it is completely invalid (static_cast should be the safest cast)

‎src/core/qgstracer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class CORE_EXPORT QgsTracer : public QObject
7070

7171
/**
7272
* Sets the \a renderContext used for tracing only on visible features.
73+
* \since QGIS 3.4
7374
*/
7475
void setRenderContext( const QgsRenderContext *renderContext );
7576

@@ -169,6 +170,7 @@ class CORE_EXPORT QgsTracer : public QObject
169170
void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
170171
void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
171172
void onDataChanged( );
173+
void onStyleChanged( );
172174
void onLayerDestroyed( QObject *obj );
173175

174176
private:

‎tests/src/core/testqgstracer.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
#include <qgstracer.h>
2121
#include <qgsvectorlayer.h>
2222
#include "qgsproject.h"
23+
#include "qgscategorizedsymbolrenderer.h"
24+
#include "qgssettings.h"
25+
#include "qgslayertree.h"
26+
#include "qgslayertreemodel.h"
27+
#include "qgsmapsettings.h"
28+
#include "qgssnappingutils.h"
2329

2430
class TestQgsTracer : public QObject
2531
{
@@ -36,6 +42,7 @@ class TestQgsTracer : public QObject
3642
void testReprojection();
3743
void testCurved();
3844
void testOffset();
45+
void testInvisible();
3946

4047
private:
4148

@@ -156,6 +163,97 @@ void TestQgsTracer::testSimple()
156163
delete vl;
157164
}
158165

166+
void TestQgsTracer::testInvisible()
167+
{
168+
QgsVectorLayer *mVL = new QgsVectorLayer( QStringLiteral( "Linestring?field=fld:int" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
169+
QgsFeature f1, f2, f3, f4;
170+
int idx = mVL->fields().indexFromName( QStringLiteral( "fld" ) );
171+
QVERIFY( idx != -1 );
172+
f1.initAttributes( 1 );
173+
f2.initAttributes( 1 );
174+
f3.initAttributes( 1 );
175+
f4.initAttributes( 1 );
176+
177+
/* This shape - nearly a square (one side is shifted to have exactly one shortest
178+
* path between corners):
179+
* 0,10 +----+ 20,10
180+
* | /
181+
* 0,0 +--+ 10,0
182+
*/
183+
QgsGeometry geom = QgsGeometry::fromWkt( "LINESTRING(0 0, 0 10)" );
184+
f1.setGeometry( geom );
185+
f1.setAttribute( idx, QVariant( 2 ) );
186+
geom = QgsGeometry::fromWkt( "LINESTRING(0 0, 10 0)" );
187+
f2.setGeometry( geom );
188+
f2.setAttribute( idx, QVariant( 1 ) );
189+
geom = QgsGeometry::fromWkt( "LINESTRING(0 10, 20 10)" );
190+
f3.setGeometry( geom );
191+
f3.setAttribute( idx, QVariant( 1 ) );
192+
geom = QgsGeometry::fromWkt( "LINESTRING(10 0, 20 10)" );
193+
f4.setGeometry( geom );
194+
f4.setAttribute( idx, QVariant( 1 ) );
195+
QgsFeatureList flist;
196+
flist << f1 << f2 << f3 << f4;
197+
198+
mVL->dataProvider()->addFeatures( flist );
199+
200+
QgsProject::instance()->addMapLayer( mVL );
201+
202+
QgsCategorizedSymbolRenderer *renderer = new QgsCategorizedSymbolRenderer();
203+
renderer->setClassAttribute( QStringLiteral( "fld" ) );
204+
renderer->setSourceSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::LineGeometry ) );
205+
renderer->addCategory( QgsRendererCategory( "2", QgsSymbol::defaultSymbol( QgsWkbTypes::LineGeometry ), QStringLiteral( "2" ) ) );
206+
mVL->setRenderer( renderer );
207+
208+
//create legend with symbology nodes for categorized renderer
209+
QgsLayerTree *root = new QgsLayerTree();
210+
QgsLayerTreeLayer *n = new QgsLayerTreeLayer( mVL );
211+
root->addChildNode( n );
212+
QgsLayerTreeModel *m = new QgsLayerTreeModel( root, nullptr );
213+
m->refreshLayerLegend( n );
214+
215+
QList<QgsLayerTreeModelLegendNode *> nodes = m->layerLegendNodes( n );
216+
QCOMPARE( nodes.length(), 1 );
217+
//uncheck all and test that all nodes are unchecked
218+
static_cast< QgsSymbolLegendNode * >( nodes.at( 0 ) )->uncheckAllItems();
219+
Q_FOREACH ( QgsLayerTreeModelLegendNode *ln, nodes )
220+
{
221+
QVERIFY( ln->data( Qt::CheckStateRole ) == Qt::Unchecked );
222+
}
223+
224+
QgsMapSettings mapSettings;
225+
mapSettings.setOutputSize( QSize( 100, 100 ) );
226+
mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) );
227+
QVERIFY( mapSettings.hasValidSettings() );
228+
mapSettings.setLayers( QList<QgsMapLayer *>() << mVL );
229+
230+
QgsSnappingUtils u;
231+
u.setMapSettings( mapSettings );
232+
u.setEnableSnappingForInvisibleFeature( false );
233+
u.setCurrentLayer( mVL );
234+
235+
QgsSnappingConfig snappingConfig = u.config();
236+
snappingConfig.setEnabled( true );
237+
snappingConfig.setTolerance( 10 );
238+
snappingConfig.setUnits( QgsTolerance::Pixels );
239+
snappingConfig.setMode( QgsSnappingConfig::ActiveLayer );
240+
u.setConfig( snappingConfig );
241+
QgsTracer tracer;
242+
tracer.setLayers( QList<QgsVectorLayer *>() << mVL );
243+
244+
QgsPolylineXY points1 = tracer.findShortestPath( QgsPointXY( 10, 0 ), QgsPointXY( 0, 10 ) );
245+
QCOMPARE( points1.count(), 3 );
246+
QCOMPARE( points1[0], QgsPointXY( 10, 0 ) );
247+
QCOMPARE( points1[1], QgsPointXY( 0, 0 ) );
248+
QCOMPARE( points1[2], QgsPointXY( 0, 10 ) );
249+
250+
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
251+
tracer.setRenderContext( &renderContext );
252+
points1 = tracer.findShortestPath( QgsPointXY( 10, 0 ), QgsPointXY( 0, 10 ) );
253+
QCOMPARE( points1.count(), 0 );
254+
255+
}
256+
159257
void TestQgsTracer::testPolygon()
160258
{
161259
// the same shape as in testSimple() but with just one polygon ring

0 commit comments

Comments
 (0)
Please sign in to comment.