24
24
#include " qgsgeometryengine.h"
25
25
#include " qgsexpressioncontextutils.h"
26
26
#include " qgsmaplayerstyle.h"
27
+ #include " qgsvectorlayerfeatureiterator.h"
27
28
28
29
QgsMapHitTest::QgsMapHitTest ( const QgsMapSettings &settings, const QgsGeometry &polygon, const LayerFilterExpression &layerFilterExpression )
29
30
: mSettings( settings )
@@ -65,8 +66,6 @@ void QgsMapHitTest::run()
65
66
{
66
67
if ( !vl->isInScaleRange ( mSettings .scale () ) )
67
68
{
68
- mHitTest [vl] = SymbolSet (); // no symbols -> will not be shown
69
- mHitTestRuleKey [vl] = SymbolSet ();
70
69
continue ;
71
70
}
72
71
@@ -75,39 +74,65 @@ void QgsMapHitTest::run()
75
74
}
76
75
77
76
context.expressionContext () << QgsExpressionContextUtils::layerScope ( vl );
78
- SymbolSet &usedSymbols = mHitTest [vl];
79
- SymbolSet &usedSymbolsRuleKey = mHitTestRuleKey [vl];
80
- runHitTestLayer ( vl, usedSymbols, usedSymbolsRuleKey, context );
77
+ SymbolSet &usedSymbols = mHitTest [vl->id ()];
78
+ SymbolSet &usedSymbolsRuleKey = mHitTestRuleKey [vl->id ()];
79
+
80
+ QgsMapLayerStyleOverride styleOverride ( vl );
81
+ if ( mSettings .layerStyleOverrides ().contains ( vl->id () ) )
82
+ styleOverride.setOverrideStyle ( mSettings .layerStyleOverrides ().value ( vl->id () ) );
83
+
84
+ std::unique_ptr< QgsVectorLayerFeatureSource > source = std::make_unique< QgsVectorLayerFeatureSource >( vl );
85
+ runHitTestFeatureSource ( source.get (),
86
+ vl->id (), vl->crs (), vl->fields (), vl->renderer (),
87
+ usedSymbols, usedSymbolsRuleKey, context,
88
+ nullptr );
81
89
}
82
90
83
91
painter.end ();
84
92
}
85
93
94
+ QMap<QString, QSet<QString> > QgsMapHitTest::results () const
95
+ {
96
+ return mHitTestRuleKey ;
97
+ }
98
+
86
99
bool QgsMapHitTest::symbolVisible ( QgsSymbol *symbol, QgsVectorLayer *layer ) const
87
100
{
88
- if ( !symbol || !layer || ! mHitTest . contains ( layer ) )
101
+ if ( !symbol || !layer )
89
102
return false ;
90
103
91
- return mHitTest .value ( layer ).contains ( QgsSymbolLayerUtils::symbolProperties ( symbol ) );
104
+ auto it = mHitTest .constFind ( layer->id () );
105
+ if ( it == mHitTest .constEnd () )
106
+ return false ;
107
+
108
+ return it->contains ( QgsSymbolLayerUtils::symbolProperties ( symbol ) );
92
109
}
93
110
94
111
bool QgsMapHitTest::legendKeyVisible ( const QString &ruleKey, QgsVectorLayer *layer ) const
95
112
{
96
- if ( !layer || ! mHitTestRuleKey . contains ( layer ) )
113
+ if ( !layer )
97
114
return false ;
98
115
99
- return mHitTestRuleKey .value ( layer ).contains ( ruleKey );
116
+ auto it = mHitTestRuleKey .constFind ( layer->id () );
117
+ if ( it == mHitTestRuleKey .constEnd () )
118
+ return false ;
119
+
120
+ return it->contains ( ruleKey );
100
121
}
101
122
102
- void QgsMapHitTest::runHitTestLayer ( QgsVectorLayer *vl, SymbolSet &usedSymbols, SymbolSet &usedSymbolsRuleKey, QgsRenderContext &context )
123
+ void QgsMapHitTest::runHitTestFeatureSource ( QgsAbstractFeatureSource *source,
124
+ const QString &layerId,
125
+ const QgsCoordinateReferenceSystem &crs,
126
+ const QgsFields &fields,
127
+ const QgsFeatureRenderer *renderer,
128
+ SymbolSet &usedSymbols,
129
+ SymbolSet &usedSymbolsRuleKey,
130
+ QgsRenderContext &context,
131
+ QgsFeedback *feedback )
103
132
{
104
- QgsMapLayerStyleOverride styleOverride ( vl );
105
- if ( mSettings .layerStyleOverrides ().contains ( vl->id () ) )
106
- styleOverride.setOverrideStyle ( mSettings .layerStyleOverrides ().value ( vl->id () ) );
107
-
108
- std::unique_ptr< QgsFeatureRenderer > r ( vl->renderer ()->clone () );
133
+ std::unique_ptr< QgsFeatureRenderer > r ( renderer->clone () );
109
134
const bool moreSymbolsPerFeature = r->capabilities () & QgsFeatureRenderer::MoreSymbolsPerFeature;
110
- r->startRender ( context, vl-> fields () );
135
+ r->startRender ( context, fields );
111
136
112
137
// shortcut early if we know that there's nothing visible
113
138
if ( r->canSkipRender () )
@@ -125,8 +150,10 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer *vl, SymbolSet &usedSymbols,
125
150
}
126
151
127
152
QgsFeatureRequest request;
153
+ if ( feedback )
154
+ request.setFeedback ( feedback );
128
155
129
- const QString rendererFilterExpression = r->filter ( vl-> fields () );
156
+ const QString rendererFilterExpression = r->filter ( fields );
130
157
if ( !rendererFilterExpression.isEmpty () )
131
158
{
132
159
request.setFilterExpression ( rendererFilterExpression );
@@ -137,25 +164,30 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer *vl, SymbolSet &usedSymbols,
137
164
QgsGeometry transformedPolygon = mPolygon ;
138
165
if ( !mOnlyExpressions && !mPolygon .isNull () )
139
166
{
140
- if ( mSettings .destinationCrs () != vl-> crs () )
167
+ if ( mSettings .destinationCrs () != crs )
141
168
{
142
- const QgsCoordinateTransform ct ( mSettings .destinationCrs (), vl-> crs () , mSettings .transformContext () );
169
+ const QgsCoordinateTransform ct ( mSettings .destinationCrs (), crs, mSettings .transformContext () );
143
170
transformedPolygon.transform ( ct );
144
171
}
145
172
}
146
173
147
- std::unique_ptr<QgsExpression> expr;
148
- if ( mLayerFilterExpression .contains ( vl->id () ) )
174
+ if ( feedback && feedback->isCanceled () )
149
175
{
150
- const QString expression = mLayerFilterExpression [vl-> id ()] ;
151
- expr. reset ( new QgsExpression ( expression ) ) ;
152
- expr-> prepare ( &context. expressionContext () );
176
+ r-> stopRender ( context ) ;
177
+ return ;
178
+ }
153
179
154
- requiredAttributes.unite ( expr->referencedColumns () );
180
+ if ( auto it = mLayerFilterExpression .constFind ( layerId ); it != mLayerFilterExpression .constEnd () )
181
+ {
182
+ const QString expression = *it;
183
+ QgsExpression expr ( expression );
184
+ expr.prepare ( &context.expressionContext () );
185
+
186
+ requiredAttributes.unite ( expr.referencedColumns () );
155
187
request.combineFilterExpression ( expression );
156
188
}
157
189
158
- request.setSubsetOfAttributes ( requiredAttributes, vl-> fields () );
190
+ request.setSubsetOfAttributes ( requiredAttributes, fields );
159
191
160
192
std::unique_ptr< QgsGeometryEngine > polygonEngine;
161
193
if ( !mOnlyExpressions )
@@ -172,14 +204,24 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer *vl, SymbolSet &usedSymbols,
172
204
polygonEngine->prepareGeometry ();
173
205
}
174
206
}
175
- QgsFeatureIterator fi = vl->getFeatures ( request );
207
+
208
+ if ( feedback && feedback->isCanceled () )
209
+ {
210
+ r->stopRender ( context );
211
+ return ;
212
+ }
213
+
214
+ QgsFeatureIterator fi = source->getFeatures ( request );
176
215
177
216
usedSymbols.clear ();
178
217
usedSymbolsRuleKey.clear ();
179
218
180
219
QgsFeature f;
181
220
while ( fi.nextFeature ( f ) )
182
221
{
222
+ if ( feedback && feedback->isCanceled () )
223
+ break ;
224
+
183
225
// filter out elements outside of the polygon
184
226
if ( f.hasGeometry () && polygonEngine )
185
227
{
0 commit comments