wfs-server-V4.patch
src/app/qgsprojectproperties.cpp | ||
---|---|---|
175 | 175 |
twIdentifyLayers->setCellWidget( i, 2, cb ); |
176 | 176 |
} |
177 | 177 | |
178 |
grpWMSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
|
|
178 |
grpOWSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
|
|
179 | 179 |
mWMSTitle->setText( QgsProject::instance()->readEntry( "WMSServiceTitle", "/" ) ); |
180 | 180 |
mWMSContactOrganization->setText( QgsProject::instance()->readEntry( "WMSContactOrganization", "/", "" ) ); |
181 | 181 |
mWMSContactPerson->setText( QgsProject::instance()->readEntry( "WMSContactPerson", "/", "" ) ); |
... | ... | |
229 | 229 |
bool addWktGeometry = QgsProject::instance()->readBoolEntry( "WMSAddWktGeometry", "/" ); |
230 | 230 |
mAddWktGeometryCheckBox->setChecked( addWktGeometry ); |
231 | 231 | |
232 |
QStringList wfsLayerIdList = QgsProject::instance()->readListEntry( "WFSLayers", "/" ); |
|
233 | ||
234 |
twWFSLayers->setColumnCount( 2 ); |
|
235 |
twWFSLayers->horizontalHeader()->setVisible( true ); |
|
236 |
twWFSLayers->setRowCount( mapLayers.size() ); |
|
237 | ||
238 |
i = 0; |
|
239 |
int j = 0; |
|
240 |
for ( QMap<QString, QgsMapLayer*>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); it++, i++ ) |
|
241 |
{ |
|
242 |
currentLayer = it.value(); |
|
243 |
if ( currentLayer->type() == QgsMapLayer::VectorLayer ) |
|
244 |
{ |
|
245 | ||
246 |
QTableWidgetItem *twi = new QTableWidgetItem( QString::number( j ) ); |
|
247 |
twWFSLayers->setVerticalHeaderItem( j, twi ); |
|
248 | ||
249 |
twi = new QTableWidgetItem( currentLayer->name() ); |
|
250 |
twi->setData( Qt::UserRole, it.key() ); |
|
251 |
twi->setFlags( twi->flags() & ~Qt::ItemIsEditable ); |
|
252 |
twWFSLayers->setItem( j, 0, twi ); |
|
253 | ||
254 |
QCheckBox *cb = new QCheckBox(); |
|
255 |
cb->setChecked( wfsLayerIdList.contains( currentLayer->id() ) ); |
|
256 |
twWFSLayers->setCellWidget( j, 1, cb ); |
|
257 |
j++; |
|
258 | ||
259 |
} |
|
260 |
} |
|
261 |
twWFSLayers->setRowCount( j ); |
|
262 |
twWFSLayers->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents ); |
|
263 | ||
232 | 264 |
restoreState(); |
233 | 265 |
} |
234 | 266 | |
... | ... | |
380 | 412 | |
381 | 413 |
QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", noIdentifyLayerList ); |
382 | 414 | |
383 |
QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpWMSServiceCapabilities->isChecked() );
|
|
415 |
QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpOWSServiceCapabilities->isChecked() );
|
|
384 | 416 |
QgsProject::instance()->writeEntry( "WMSServiceTitle", "/", mWMSTitle->text() ); |
385 | 417 |
QgsProject::instance()->writeEntry( "WMSContactOrganization", "/", mWMSContactOrganization->text() ); |
386 | 418 |
QgsProject::instance()->writeEntry( "WMSContactPerson", "/", mWMSContactPerson->text() ); |
... | ... | |
428 | 460 | |
429 | 461 |
QgsProject::instance()->writeEntry( "WMSAddWktGeometry", "/", mAddWktGeometryCheckBox->isChecked() ); |
430 | 462 | |
463 |
QStringList wfsLayerList; |
|
464 |
for ( int i = 0; i < twWFSLayers->rowCount(); i++ ) |
|
465 |
{ |
|
466 |
QCheckBox *cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( i, 1 ) ); |
|
467 |
if ( cb && cb->isChecked() ) |
|
468 |
{ |
|
469 |
QString id = twWFSLayers->item( i, 0 )->data( Qt::UserRole ).toString(); |
|
470 |
wfsLayerList << id; |
|
471 |
} |
|
472 |
} |
|
473 |
QgsProject::instance()->writeEntry( "WFSLayers", "/", wfsLayerList ); |
|
474 | ||
431 | 475 |
//todo XXX set canvas color |
432 | 476 |
emit refresh(); |
433 | 477 |
} |
src/core/qgsgeometry.cpp | ||
---|---|---|
4185 | 4185 |
} |
4186 | 4186 |
} |
4187 | 4187 | |
4188 |
QString QgsGeometry::exportToGeoJSON() |
|
4189 |
{ |
|
4190 |
QgsDebugMsg( "entered." ); |
|
4191 | ||
4192 |
// TODO: implement with GEOS |
|
4193 |
if ( mDirtyWkb ) |
|
4194 |
{ |
|
4195 |
exportGeosToWkb(); |
|
4196 |
} |
|
4197 | ||
4198 |
if ( !mGeometry ) |
|
4199 |
{ |
|
4200 |
QgsDebugMsg( "WKB geometry not available!" ); |
|
4201 |
return QString::null; |
|
4202 |
} |
|
4203 | ||
4204 |
QGis::WkbType wkbType; |
|
4205 |
bool hasZValue = false; |
|
4206 |
double *x, *y; |
|
4207 | ||
4208 |
QString mWkt; // TODO: rename |
|
4209 | ||
4210 |
// Will this really work when mGeometry[0] == 0 ???? I (gavin) think not. |
|
4211 |
//wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4]; |
|
4212 |
memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) ); |
|
4213 | ||
4214 |
switch ( wkbType ) |
|
4215 |
{ |
|
4216 |
case QGis::WKBPoint25D: |
|
4217 |
case QGis::WKBPoint: |
|
4218 |
{ |
|
4219 |
mWkt += "{ \"type\": \"Point\", \"coordinates\": ["; |
|
4220 |
x = ( double * )( mGeometry + 5 ); |
|
4221 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4222 |
mWkt += ", "; |
|
4223 |
y = ( double * )( mGeometry + 5 + sizeof( double ) ); |
|
4224 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4225 |
mWkt += "] }"; |
|
4226 |
return mWkt; |
|
4227 |
} |
|
4228 | ||
4229 |
case QGis::WKBLineString25D: |
|
4230 |
hasZValue = true; |
|
4231 |
case QGis::WKBLineString: |
|
4232 |
{ |
|
4233 |
QgsDebugMsg( "LINESTRING found" ); |
|
4234 |
unsigned char *ptr; |
|
4235 |
int *nPoints; |
|
4236 |
int idx; |
|
4237 | ||
4238 |
mWkt += "{ \"type\": \"LineString\", \"coordinates\": [ "; |
|
4239 |
// get number of points in the line |
|
4240 |
ptr = mGeometry + 5; |
|
4241 |
nPoints = ( int * ) ptr; |
|
4242 |
ptr = mGeometry + 1 + 2 * sizeof( int ); |
|
4243 |
for ( idx = 0; idx < *nPoints; ++idx ) |
|
4244 |
{ |
|
4245 |
if ( idx != 0 ) |
|
4246 |
{ |
|
4247 |
mWkt += ", "; |
|
4248 |
} |
|
4249 |
mWkt += "["; |
|
4250 |
x = ( double * ) ptr; |
|
4251 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4252 |
mWkt += ", "; |
|
4253 |
ptr += sizeof( double ); |
|
4254 |
y = ( double * ) ptr; |
|
4255 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4256 |
ptr += sizeof( double ); |
|
4257 |
if ( hasZValue ) |
|
4258 |
{ |
|
4259 |
ptr += sizeof( double ); |
|
4260 |
} |
|
4261 |
mWkt += "]"; |
|
4262 |
} |
|
4263 |
mWkt += " ] }"; |
|
4264 |
return mWkt; |
|
4265 |
} |
|
4266 | ||
4267 |
case QGis::WKBPolygon25D: |
|
4268 |
hasZValue = true; |
|
4269 |
case QGis::WKBPolygon: |
|
4270 |
{ |
|
4271 |
QgsDebugMsg( "POLYGON found" ); |
|
4272 |
unsigned char *ptr; |
|
4273 |
int idx, jdx; |
|
4274 |
int *numRings, *nPoints; |
|
4275 | ||
4276 |
mWkt += "{ \"type\": \"Polygon\", \"coordinates\": [ "; |
|
4277 |
// get number of rings in the polygon |
|
4278 |
numRings = ( int * )( mGeometry + 1 + sizeof( int ) ); |
|
4279 |
if ( !( *numRings ) ) // sanity check for zero rings in polygon |
|
4280 |
{ |
|
4281 |
return QString(); |
|
4282 |
} |
|
4283 |
int *ringStart; // index of first point for each ring |
|
4284 |
int *ringNumPoints; // number of points in each ring |
|
4285 |
ringStart = new int[*numRings]; |
|
4286 |
ringNumPoints = new int[*numRings]; |
|
4287 |
ptr = mGeometry + 1 + 2 * sizeof( int ); // set pointer to the first ring |
|
4288 |
for ( idx = 0; idx < *numRings; idx++ ) |
|
4289 |
{ |
|
4290 |
if ( idx != 0 ) |
|
4291 |
{ |
|
4292 |
mWkt += ", "; |
|
4293 |
} |
|
4294 |
mWkt += "[ "; |
|
4295 |
// get number of points in the ring |
|
4296 |
nPoints = ( int * ) ptr; |
|
4297 |
ringNumPoints[idx] = *nPoints; |
|
4298 |
ptr += 4; |
|
4299 | ||
4300 |
for ( jdx = 0; jdx < *nPoints; jdx++ ) |
|
4301 |
{ |
|
4302 |
if ( jdx != 0 ) |
|
4303 |
{ |
|
4304 |
mWkt += ", "; |
|
4305 |
} |
|
4306 |
mWkt += "["; |
|
4307 |
x = ( double * ) ptr; |
|
4308 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4309 |
mWkt += ", "; |
|
4310 |
ptr += sizeof( double ); |
|
4311 |
y = ( double * ) ptr; |
|
4312 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4313 |
ptr += sizeof( double ); |
|
4314 |
if ( hasZValue ) |
|
4315 |
{ |
|
4316 |
ptr += sizeof( double ); |
|
4317 |
} |
|
4318 |
mWkt += "]"; |
|
4319 |
} |
|
4320 |
mWkt += " ]"; |
|
4321 |
} |
|
4322 |
mWkt += " ] }"; |
|
4323 |
delete [] ringStart; |
|
4324 |
delete [] ringNumPoints; |
|
4325 |
return mWkt; |
|
4326 |
} |
|
4327 | ||
4328 |
case QGis::WKBMultiPoint25D: |
|
4329 |
hasZValue = true; |
|
4330 |
case QGis::WKBMultiPoint: |
|
4331 |
{ |
|
4332 |
unsigned char *ptr; |
|
4333 |
int idx; |
|
4334 |
int *nPoints; |
|
4335 | ||
4336 |
mWkt += "{ \"type\": \"MultiPoint\", \"coordinates\": [ "; |
|
4337 |
nPoints = ( int* )( mGeometry + 5 ); |
|
4338 |
ptr = mGeometry + 5 + sizeof( int ); |
|
4339 |
for ( idx = 0; idx < *nPoints; ++idx ) |
|
4340 |
{ |
|
4341 |
ptr += ( 1 + sizeof( int ) ); |
|
4342 |
if ( idx != 0 ) |
|
4343 |
{ |
|
4344 |
mWkt += ", "; |
|
4345 |
} |
|
4346 |
mWkt += "["; |
|
4347 |
x = ( double * )( ptr ); |
|
4348 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4349 |
mWkt += ", "; |
|
4350 |
ptr += sizeof( double ); |
|
4351 |
y = ( double * )( ptr ); |
|
4352 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4353 |
ptr += sizeof( double ); |
|
4354 |
if ( hasZValue ) |
|
4355 |
{ |
|
4356 |
ptr += sizeof( double ); |
|
4357 |
} |
|
4358 |
mWkt += "]"; |
|
4359 |
} |
|
4360 |
mWkt += " ] }"; |
|
4361 |
return mWkt; |
|
4362 |
} |
|
4363 | ||
4364 |
case QGis::WKBMultiLineString25D: |
|
4365 |
hasZValue = true; |
|
4366 |
case QGis::WKBMultiLineString: |
|
4367 |
{ |
|
4368 |
QgsDebugMsg( "MULTILINESTRING found" ); |
|
4369 |
unsigned char *ptr; |
|
4370 |
int idx, jdx, numLineStrings; |
|
4371 |
int *nPoints; |
|
4372 | ||
4373 |
mWkt += "{ \"type\": \"MultiLineString\", \"coordinates\": [ "; |
|
4374 |
numLineStrings = ( int )( mGeometry[5] ); |
|
4375 |
ptr = mGeometry + 9; |
|
4376 |
for ( jdx = 0; jdx < numLineStrings; jdx++ ) |
|
4377 |
{ |
|
4378 |
if ( jdx != 0 ) |
|
4379 |
{ |
|
4380 |
mWkt += ", "; |
|
4381 |
} |
|
4382 |
mWkt += "[ "; |
|
4383 |
ptr += 5; // skip type since we know its 2 |
|
4384 |
nPoints = ( int * ) ptr; |
|
4385 |
ptr += sizeof( int ); |
|
4386 |
for ( idx = 0; idx < *nPoints; idx++ ) |
|
4387 |
{ |
|
4388 |
if ( idx != 0 ) |
|
4389 |
{ |
|
4390 |
mWkt += ", "; |
|
4391 |
} |
|
4392 |
mWkt += "["; |
|
4393 |
x = ( double * ) ptr; |
|
4394 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4395 |
ptr += sizeof( double ); |
|
4396 |
mWkt += ", "; |
|
4397 |
y = ( double * ) ptr; |
|
4398 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4399 |
ptr += sizeof( double ); |
|
4400 |
if ( hasZValue ) |
|
4401 |
{ |
|
4402 |
ptr += sizeof( double ); |
|
4403 |
} |
|
4404 |
mWkt += "]"; |
|
4405 |
} |
|
4406 |
mWkt += " ]"; |
|
4407 |
} |
|
4408 |
mWkt += " ] }"; |
|
4409 |
return mWkt; |
|
4410 |
} |
|
4411 | ||
4412 |
case QGis::WKBMultiPolygon25D: |
|
4413 |
hasZValue = true; |
|
4414 |
case QGis::WKBMultiPolygon: |
|
4415 |
{ |
|
4416 |
QgsDebugMsg( "MULTIPOLYGON found" ); |
|
4417 |
unsigned char *ptr; |
|
4418 |
int idx, jdx, kdx; |
|
4419 |
int *numPolygons, *numRings, *nPoints; |
|
4420 | ||
4421 |
mWkt += "{ \"type\": \"MultiPolygon\", \"coordinates\": [ "; |
|
4422 |
ptr = mGeometry + 5; |
|
4423 |
numPolygons = ( int * ) ptr; |
|
4424 |
ptr = mGeometry + 9; |
|
4425 |
for ( kdx = 0; kdx < *numPolygons; kdx++ ) |
|
4426 |
{ |
|
4427 |
if ( kdx != 0 ) |
|
4428 |
{ |
|
4429 |
mWkt += ", "; |
|
4430 |
} |
|
4431 |
mWkt += "[ "; |
|
4432 |
ptr += 5; |
|
4433 |
numRings = ( int * ) ptr; |
|
4434 |
ptr += 4; |
|
4435 |
for ( idx = 0; idx < *numRings; idx++ ) |
|
4436 |
{ |
|
4437 |
if ( idx != 0 ) |
|
4438 |
{ |
|
4439 |
mWkt += ", "; |
|
4440 |
} |
|
4441 |
mWkt += "[ "; |
|
4442 |
nPoints = ( int * ) ptr; |
|
4443 |
ptr += 4; |
|
4444 |
for ( jdx = 0; jdx < *nPoints; jdx++ ) |
|
4445 |
{ |
|
4446 |
if ( jdx != 0 ) |
|
4447 |
{ |
|
4448 |
mWkt += ", "; |
|
4449 |
} |
|
4450 |
mWkt += "["; |
|
4451 |
x = ( double * ) ptr; |
|
4452 |
mWkt += QString::number( *x, 'f', 6 ); |
|
4453 |
ptr += sizeof( double ); |
|
4454 |
mWkt += ", "; |
|
4455 |
y = ( double * ) ptr; |
|
4456 |
mWkt += QString::number( *y, 'f', 6 ); |
|
4457 |
ptr += sizeof( double ); |
|
4458 |
if ( hasZValue ) |
|
4459 |
{ |
|
4460 |
ptr += sizeof( double ); |
|
4461 |
} |
|
4462 |
mWkt += "]"; |
|
4463 |
} |
|
4464 |
mWkt += " ]"; |
|
4465 |
} |
|
4466 |
mWkt += " ]"; |
|
4467 |
} |
|
4468 |
mWkt += " ] }"; |
|
4469 |
return mWkt; |
|
4470 |
} |
|
4471 | ||
4472 |
default: |
|
4473 |
QgsDebugMsg( "error: mGeometry type not recognized" ); |
|
4474 |
return QString::null; |
|
4475 |
} |
|
4476 |
} |
|
4477 | ||
4188 | 4478 |
bool QgsGeometry::exportWkbToGeos() |
4189 | 4479 |
{ |
4190 | 4480 |
QgsDebugMsgLevel( "entered.", 3 ); |
src/core/qgsgeometry.h | ||
---|---|---|
361 | 361 |
*/ |
362 | 362 |
QString exportToWkt(); |
363 | 363 | |
364 |
/** Exports the geometry to mGeoJSON |
|
365 |
@return true in case of success and false else |
|
366 |
*/ |
|
367 |
QString exportToGeoJSON(); |
|
368 | ||
364 | 369 |
/* Accessor functions for getting geometry data */ |
365 | 370 | |
366 | 371 |
/** return contents of the geometry as a point |
src/mapserver/CMakeLists.txt | ||
---|---|---|
28 | 28 |
qgssldparser.cpp |
29 | 29 |
qgssldrenderer.cpp |
30 | 30 |
qgswmsserver.cpp |
31 |
qgswfsserver.cpp |
|
31 | 32 |
qgsmapserviceexception.cpp |
32 | 33 |
qgsmslayercache.cpp |
33 | 34 |
qgsfilter.cpp |
src/mapserver/qgis_map_serv.cpp | ||
---|---|---|
26 | 26 |
#include "qgsproviderregistry.h" |
27 | 27 |
#include "qgslogger.h" |
28 | 28 |
#include "qgswmsserver.h" |
29 |
#include "qgswfsserver.h" |
|
29 | 30 |
#include "qgsmaprenderer.h" |
30 | 31 |
#include "qgsmapserviceexception.h" |
31 | 32 |
#include "qgsprojectparser.h" |
... | ... | |
264 | 265 | |
265 | 266 |
//request to WMS? |
266 | 267 |
QString serviceString; |
267 |
#ifndef QGISDEBUG |
|
268 |
serviceString = parameterMap.value( "SERVICE", "WMS" ); |
|
269 |
#else |
|
270 | 268 |
paramIt = parameterMap.find( "SERVICE" ); |
271 | 269 |
if ( paramIt == parameterMap.constEnd() ) |
272 | 270 |
{ |
271 |
#ifndef QGISDEBUG |
|
272 |
serviceString = parameterMap.value( "SERVICE", "WMS" ); |
|
273 |
#else |
|
273 | 274 |
QgsDebugMsg( "unable to find 'SERVICE' parameter, exiting..." ); |
274 | 275 |
theRequestHandler->sendServiceException( QgsMapServiceException( "ServiceNotSpecified", "Service not specified. The SERVICE parameter is mandatory" ) ); |
275 | 276 |
delete theRequestHandler; |
276 | 277 |
continue; |
278 |
#endif |
|
277 | 279 |
} |
278 | 280 |
else |
279 | 281 |
{ |
280 | 282 |
serviceString = paramIt.value(); |
281 | 283 |
} |
282 |
#endif |
|
283 | 284 | |
284 | 285 |
QgsWMSServer* theServer = 0; |
286 |
if ( serviceString == "WFS" ) |
|
287 |
{ |
|
288 |
delete theServer; |
|
289 |
QgsWFSServer* theServer = 0; |
|
290 |
try |
|
291 |
{ |
|
292 |
theServer = new QgsWFSServer( parameterMap ); |
|
293 |
} |
|
294 |
catch ( QgsMapServiceException e ) //admin.sld may be invalid |
|
295 |
{ |
|
296 |
theRequestHandler->sendServiceException( e ); |
|
297 |
continue; |
|
298 |
} |
|
299 | ||
300 |
theServer->setAdminConfigParser( adminConfigParser ); |
|
301 | ||
302 | ||
303 |
//request type |
|
304 |
QString request = parameterMap.value( "REQUEST" ); |
|
305 |
if ( request.isEmpty() ) |
|
306 |
{ |
|
307 |
//do some error handling |
|
308 |
QgsDebugMsg( "unable to find 'REQUEST' parameter, exiting..." ); |
|
309 |
theRequestHandler->sendServiceException( QgsMapServiceException( "OperationNotSupported", "Please check the value of the REQUEST parameter" ) ); |
|
310 |
delete theRequestHandler; |
|
311 |
delete theServer; |
|
312 |
continue; |
|
313 |
} |
|
314 | ||
315 |
if ( request == "GetCapabilities" ) |
|
316 |
{ |
|
317 |
QDomDocument capabilitiesDocument; |
|
318 |
try |
|
319 |
{ |
|
320 |
capabilitiesDocument = theServer->getCapabilities(); |
|
321 |
} |
|
322 |
catch ( QgsMapServiceException& ex ) |
|
323 |
{ |
|
324 |
theRequestHandler->sendServiceException( ex ); |
|
325 |
delete theRequestHandler; |
|
326 |
delete theServer; |
|
327 |
continue; |
|
328 |
} |
|
329 |
QgsDebugMsg( "sending GetCapabilities response" ); |
|
330 |
theRequestHandler->sendGetCapabilitiesResponse( capabilitiesDocument ); |
|
331 |
delete theRequestHandler; |
|
332 |
delete theServer; |
|
333 |
continue; |
|
334 |
} |
|
335 |
else if ( request == "DescribeFeatureType" ) |
|
336 |
{ |
|
337 |
QDomDocument describeDocument; |
|
338 |
try |
|
339 |
{ |
|
340 |
describeDocument = theServer->describeFeatureType(); |
|
341 |
} |
|
342 |
catch ( QgsMapServiceException& ex ) |
|
343 |
{ |
|
344 |
theRequestHandler->sendServiceException( ex ); |
|
345 |
delete theRequestHandler; |
|
346 |
delete theServer; |
|
347 |
continue; |
|
348 |
} |
|
349 |
QgsDebugMsg( "sending GetCapabilities response" ); |
|
350 |
theRequestHandler->sendGetCapabilitiesResponse( describeDocument ); |
|
351 |
delete theRequestHandler; |
|
352 |
delete theServer; |
|
353 |
continue; |
|
354 |
} |
|
355 |
else if ( request == "GetFeature" ) |
|
356 |
{ |
|
357 |
//output format for GetFeature |
|
358 |
QString outputFormat = parameterMap.value( "OUTPUTFORMAT" ); |
|
359 |
try |
|
360 |
{ |
|
361 |
if ( theServer->getFeature( *theRequestHandler, outputFormat ) != 0 ) |
|
362 |
{ |
|
363 |
delete theRequestHandler; |
|
364 |
delete theServer; |
|
365 |
continue; |
|
366 |
} else { |
|
367 |
delete theRequestHandler; |
|
368 |
delete theServer; |
|
369 |
continue; |
|
370 |
} |
|
371 |
} |
|
372 |
catch ( QgsMapServiceException& ex ) |
|
373 |
{ |
|
374 |
theRequestHandler->sendServiceException( ex ); |
|
375 |
delete theRequestHandler; |
|
376 |
delete theServer; |
|
377 |
continue; |
|
378 |
} |
|
379 |
} |
|
380 | ||
381 |
return 0; |
|
382 |
} |
|
383 | ||
285 | 384 |
try |
286 | 385 |
{ |
287 | 386 |
theServer = new QgsWMSServer( parameterMap, theMapRenderer ); |
src/mapserver/qgsconfigparser.h | ||
---|---|---|
42 | 42 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
43 | 43 |
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const = 0; |
44 | 44 | |
45 |
virtual void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const = 0; |
|
46 | ||
45 | 47 |
/**Returns one or possibly several maplayers for a given layer name and style. If there are several layers, the layers should be drawn in inverse list order. |
46 | 48 |
If no layers/style are found, an empty list is returned |
47 | 49 |
@param allowCache true if layer can be read from / written to cache*/ |
... | ... | |
87 | 89 | |
88 | 90 |
/**Returns an ID-list of layers which are not queryable*/ |
89 | 91 |
virtual QStringList identifyDisabledLayers() const { return QStringList(); } |
92 |
/**Returns an ID-list of layers which queryable in WFS service*/ |
|
93 |
virtual QStringList wfsLayers() const { return QStringList(); } |
|
90 | 94 | |
91 | 95 |
/**Returns a set of supported epsg codes for the capabilities document. An empty list means |
92 | 96 |
that all possible CRS should be advertised (which could result in very long capabilities documents)*/ |
src/mapserver/qgshttprequesthandler.cpp | ||
---|---|---|
288 | 288 |
sendHttpResponse( ba, formatToMimeType( mFormat ) ); |
289 | 289 |
} |
290 | 290 | |
291 |
bool QgsHttpRequestHandler::startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const |
|
292 |
{ |
|
293 |
if ( !ba ) |
|
294 |
{ |
|
295 |
return false; |
|
296 |
} |
|
297 | ||
298 |
if ( ba->size() < 1 ) |
|
299 |
{ |
|
300 |
return false; |
|
301 |
} |
|
302 | ||
303 |
QString format; |
|
304 |
if (infoFormat == "GeoJSON") |
|
305 |
format = "text/plain"; |
|
306 |
else |
|
307 |
format = "text/xml"; |
|
308 | ||
309 |
printf( "Content-Type: " ); |
|
310 |
printf( format.toLocal8Bit() ); |
|
311 |
printf( "\n" ); |
|
312 |
printf( "\n" ); |
|
313 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
314 |
return true; |
|
315 |
} |
|
316 | ||
317 |
void QgsHttpRequestHandler::sendGetFeatureResponse( QByteArray* ba ) const |
|
318 |
{ |
|
319 |
if ( !ba ) |
|
320 |
{ |
|
321 |
return; |
|
322 |
} |
|
323 | ||
324 |
if ( ba->size() < 1 ) |
|
325 |
{ |
|
326 |
return; |
|
327 |
} |
|
328 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
329 |
} |
|
330 | ||
331 |
void QgsHttpRequestHandler::endGetFeatureResponse( QByteArray* ba ) const |
|
332 |
{ |
|
333 |
if ( !ba ) |
|
334 |
{ |
|
335 |
return; |
|
336 |
} |
|
337 | ||
338 |
fwrite( ba->data(), ba->size(), 1, FCGI_stdout ); |
|
339 |
} |
|
340 | ||
291 | 341 |
void QgsHttpRequestHandler::requestStringToParameterMap( const QString& request, QMap<QString, QString>& parameters ) |
292 | 342 |
{ |
293 | 343 |
parameters.clear(); |
src/mapserver/qgshttprequesthandler.h | ||
---|---|---|
34 | 34 |
virtual void sendServiceException( const QgsMapServiceException& ex ) const; |
35 | 35 |
virtual void sendGetStyleResponse( const QDomDocument& doc ) const; |
36 | 36 |
virtual void sendGetPrintResponse( QByteArray* ba ) const; |
37 |
virtual bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const; |
|
38 |
virtual void sendGetFeatureResponse( QByteArray* ba ) const; |
|
39 |
virtual void endGetFeatureResponse( QByteArray* ba ) const; |
|
37 | 40 | |
38 | 41 |
protected: |
39 | 42 |
void sendHttpResponse( QByteArray* ba, const QString& format ) const; |
src/mapserver/qgsprojectparser.cpp | ||
---|---|---|
138 | 138 |
combineExtentAndCrsOfGroupChildren( layerParentElem, doc ); |
139 | 139 |
} |
140 | 140 | |
141 |
void QgsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const |
|
142 |
{ |
|
143 |
QStringList wfsLayersId = wfsLayers(); |
|
144 | ||
145 |
if ( mProjectLayerElements.size() < 1 ) |
|
146 |
{ |
|
147 |
return; |
|
148 |
} |
|
149 | ||
150 |
QMap<QString, QgsMapLayer *> layerMap; |
|
151 | ||
152 |
foreach( const QDomElement &elem, mProjectLayerElements ) |
|
153 |
{ |
|
154 |
QString type = elem.attribute( "type" ); |
|
155 |
if ( type == "vector" ) |
|
156 |
{ |
|
157 |
//QgsMapLayer *layer = createLayerFromElement( *layerIt ); |
|
158 |
QgsMapLayer *layer = createLayerFromElement( elem ); |
|
159 |
if ( layer && wfsLayersId.contains( layer->id() ) ) |
|
160 |
{ |
|
161 |
QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) ); |
|
162 |
layerMap.insert( layer->id(), layer ); |
|
163 | ||
164 |
QDomElement layerElem = doc.createElement( "FeatureType" ); |
|
165 |
QDomElement nameElem = doc.createElement( "Name" ); |
|
166 |
//We use the layer name even though it might not be unique. |
|
167 |
//Because the id sometimes contains user/pw information and the name is more descriptive |
|
168 |
QDomText nameText = doc.createTextNode( layer->name() ); |
|
169 |
nameElem.appendChild( nameText ); |
|
170 |
layerElem.appendChild( nameElem ); |
|
171 | ||
172 |
QDomElement titleElem = doc.createElement( "Title" ); |
|
173 |
QDomText titleText = doc.createTextNode( layer->name() ); |
|
174 |
titleElem.appendChild( titleText ); |
|
175 |
layerElem.appendChild( titleElem ); |
|
176 | ||
177 |
//appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() ); |
|
178 | ||
179 |
QDomElement srsElem = doc.createElement( "SRS" ); |
|
180 |
QDomText srsText = doc.createTextNode( layer->crs().authid() ); |
|
181 |
srsElem.appendChild( srsText ); |
|
182 |
layerElem.appendChild( srsElem ); |
|
183 | ||
184 |
QgsRectangle layerExtent = layer->extent(); |
|
185 |
QDomElement bBoxElement = doc.createElement( "LatLongBoundingBox" ); |
|
186 |
bBoxElement.setAttribute( "minx", QString::number( layerExtent.xMinimum() ) ); |
|
187 |
bBoxElement.setAttribute( "miny", QString::number( layerExtent.yMinimum() ) ); |
|
188 |
bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) ); |
|
189 |
bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) ); |
|
190 |
layerElem.appendChild( bBoxElement ); |
|
191 | ||
192 |
parentElement.appendChild(layerElem); |
|
193 |
} |
|
194 |
#if QGSMSDEBUG |
|
195 |
else |
|
196 |
{ |
|
197 |
QString buf; |
|
198 |
QTextStream s( &buf ); |
|
199 |
layerIt->save( s, 0 ); |
|
200 |
QgsMSDebugMsg( QString( "layer %1 not found or not in WFS Layers" ).arg( buf ) ); |
|
201 |
} |
|
202 |
#endif |
|
203 |
} |
|
204 |
} |
|
205 |
return; |
|
206 |
} |
|
207 | ||
141 | 208 |
void QgsProjectParser::addLayers( QDomDocument &doc, |
142 | 209 |
QDomElement &parentElem, |
143 | 210 |
const QDomElement &legendElem, |
... | ... | |
584 | 651 |
return disabledList; |
585 | 652 |
} |
586 | 653 | |
654 |
QStringList QgsProjectParser::wfsLayers() const |
|
655 |
{ |
|
656 |
QStringList wfsList; |
|
657 |
if ( !mXMLDoc ) |
|
658 |
{ |
|
659 |
return wfsList; |
|
660 |
} |
|
661 | ||
662 |
QDomElement qgisElem = mXMLDoc->documentElement(); |
|
663 |
if ( qgisElem.isNull() ) |
|
664 |
{ |
|
665 |
return wfsList; |
|
666 |
} |
|
667 |
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" ); |
|
668 |
if ( propertiesElem.isNull() ) |
|
669 |
{ |
|
670 |
return wfsList; |
|
671 |
} |
|
672 |
QDomElement wfsLayersElem = propertiesElem.firstChildElement( "WFSLayers" ); |
|
673 |
if ( wfsLayersElem.isNull() ) |
|
674 |
{ |
|
675 |
return wfsList; |
|
676 |
} |
|
677 |
QDomNodeList valueList = wfsLayersElem.elementsByTagName( "value" ); |
|
678 |
for ( int i = 0; i < valueList.size(); ++i ) |
|
679 |
{ |
|
680 |
wfsList << valueList.at( i ).toElement().text(); |
|
681 |
} |
|
682 |
return wfsList; |
|
683 |
} |
|
684 | ||
587 | 685 |
QStringList QgsProjectParser::supportedOutputCrsList() const |
588 | 686 |
{ |
589 | 687 |
QStringList crsList; |
src/mapserver/qgsprojectparser.h | ||
---|---|---|
38 | 38 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
39 | 39 |
virtual void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const; |
40 | 40 | |
41 |
virtual void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const; |
|
42 | ||
41 | 43 |
int numberOfLayers() const; |
42 | 44 | |
43 | 45 |
/**Returns one or possibly several maplayers for a given layer name and style. If no layers/style are found, an empty list is returned*/ |
... | ... | |
58 | 60 |
/**Returns an ID-list of layers which are not queryable (comes from <properties> -> <Identify> -> <disabledLayers in the project file*/ |
59 | 61 |
virtual QStringList identifyDisabledLayers() const; |
60 | 62 | |
63 |
/**Returns an ID-list of layers queryable for WFS service (comes from <properties> -> <WFSLayers> in the project file*/ |
|
64 |
virtual QStringList wfsLayers() const; |
|
65 | ||
61 | 66 |
/**Returns a set of supported epsg codes for the capabilities document. The list comes from the property <WMSEpsgList> in the project file. |
62 | 67 |
An empty set means that all possible CRS should be advertised (which could result in very long capabilities documents) |
63 | 68 |
Example: |
src/mapserver/qgsrequesthandler.h | ||
---|---|---|
41 | 41 |
virtual void sendServiceException( const QgsMapServiceException& ex ) const = 0; |
42 | 42 |
virtual void sendGetStyleResponse( const QDomDocument& doc ) const = 0; |
43 | 43 |
virtual void sendGetPrintResponse( QByteArray* ba ) const = 0; |
44 |
virtual bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) const = 0; |
|
45 |
virtual void sendGetFeatureResponse( QByteArray* ba ) const = 0; |
|
46 |
virtual void endGetFeatureResponse( QByteArray* ba ) const = 0; |
|
44 | 47 |
QString format() const { return mFormat; } |
45 | 48 |
protected: |
46 | 49 |
/**This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG')*/ |
src/mapserver/qgssldparser.h | ||
---|---|---|
56 | 56 |
/**Adds layer and style specific capabilities elements to the parent node. This includes the individual layers and styles, their description, native CRS, bounding boxes, etc.*/ |
57 | 57 |
void layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc ) const; |
58 | 58 | |
59 |
void featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const {}; |
|
60 | ||
59 | 61 |
/**Returns number of layers in configuration*/ |
60 | 62 |
int numberOfLayers() const; |
61 | 63 |
src/mapserver/qgswfsserver.cpp | ||
---|---|---|
1 |
#include "qgswfsserver.h" |
|
2 |
#include "qgsconfigparser.h" |
|
3 |
#include "qgscrscache.h" |
|
4 |
#include "qgsfield.h" |
|
5 |
#include "qgsgeometry.h" |
|
6 |
#include "qgsmaplayer.h" |
|
7 |
#include "qgsmaplayerregistry.h" |
|
8 |
#include "qgsmaprenderer.h" |
|
9 |
#include "qgsmaptopixel.h" |
|
10 |
#include "qgspallabeling.h" |
|
11 |
#include "qgsproject.h" |
|
12 |
#include "qgsrasterlayer.h" |
|
13 |
#include "qgsscalecalculator.h" |
|
14 |
#include "qgscoordinatereferencesystem.h" |
|
15 |
#include "qgsvectordataprovider.h" |
|
16 |
#include "qgsvectorlayer.h" |
|
17 |
#include "qgsfilter.h" |
|
18 |
#include "qgslogger.h" |
|
19 |
#include "qgsmapserviceexception.h" |
|
20 |
#include "qgssldparser.h" |
|
21 |
#include "qgssymbol.h" |
|
22 |
#include "qgssymbolv2.h" |
|
23 |
#include "qgsrenderer.h" |
|
24 |
#include "qgslegendmodel.h" |
|
25 |
#include "qgscomposerlegenditem.h" |
|
26 |
#include "qgslogger.h" |
|
27 |
#include "qgsrequesthandler.h" |
|
28 |
#include <QImage> |
|
29 |
#include <QPainter> |
|
30 |
#include <QStringList> |
|
31 |
#include <QTextStream> |
|
32 |
#include <QDir> |
|
33 | ||
34 |
//for printing |
|
35 |
#include "qgscomposition.h" |
|
36 |
#include <QBuffer> |
|
37 |
#include <QPrinter> |
|
38 |
#include <QSvgGenerator> |
|
39 |
#include <QUrl> |
|
40 |
#include <QPaintEngine> |
|
41 | ||
42 |
QgsWFSServer::QgsWFSServer( QMap<QString, QString> parameters ) |
|
43 |
: mParameterMap( parameters ) |
|
44 |
, mConfigParser( 0 ) |
|
45 |
{ |
|
46 |
} |
|
47 | ||
48 |
QgsWFSServer::~QgsWFSServer() |
|
49 |
{ |
|
50 |
} |
|
51 | ||
52 |
QgsWFSServer::QgsWFSServer() |
|
53 |
{ |
|
54 |
} |
|
55 | ||
56 |
QDomDocument QgsWFSServer::getCapabilities() |
|
57 |
{ |
|
58 |
QgsDebugMsg( "Entering." ); |
|
59 |
QDomDocument doc; |
|
60 |
//wfs:WFS_Capabilities element |
|
61 |
QDomElement wfsCapabilitiesElement = doc.createElement( "WFS_Capabilities"/*wms:WFS_Capabilities*/ ); |
|
62 |
wfsCapabilitiesElement.setAttribute( "xmlns", "http://www.opengis.net/wfs" ); |
|
63 |
wfsCapabilitiesElement.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); |
|
64 |
wfsCapabilitiesElement.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" ); |
|
65 |
wfsCapabilitiesElement.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" ); |
|
66 |
wfsCapabilitiesElement.setAttribute( "xmlns:gml", "http://www.opengis.net/gml" ); |
|
67 |
wfsCapabilitiesElement.setAttribute( "xmlns:ows", "http://www.opengis.net/ows" ); |
|
68 |
wfsCapabilitiesElement.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); |
|
69 |
wfsCapabilitiesElement.setAttribute( "version", "1.0.0" ); |
|
70 |
wfsCapabilitiesElement.setAttribute( "updateSequence", "0" ); |
|
71 |
doc.appendChild( wfsCapabilitiesElement ); |
|
72 | ||
73 |
if ( mConfigParser ) |
|
74 |
{ |
|
75 |
mConfigParser->serviceCapabilities( wfsCapabilitiesElement, doc ); |
|
76 |
} |
|
77 | ||
78 |
//wfs:Capability element |
|
79 |
QDomElement capabilityElement = doc.createElement( "Capability"/*wfs:Capability*/ ); |
|
80 |
wfsCapabilitiesElement.appendChild( capabilityElement ); |
|
81 |
|
|
82 |
//wfs:Request element |
|
83 |
QDomElement requestElement = doc.createElement( "Request"/*wfs:Request*/ ); |
|
84 |
capabilityElement.appendChild( requestElement ); |
|
85 |
//wfs:GetCapabilities |
|
86 |
QDomElement getCapabilitiesElement = doc.createElement( "GetCapabilities"/*wfs:GetCapabilities*/ ); |
|
87 |
requestElement.appendChild( getCapabilitiesElement ); |
|
88 |
QDomElement capabilitiesFormatElement = doc.createElement( "Format" );/*wfs:Format*/ |
|
89 |
getCapabilitiesElement.appendChild( capabilitiesFormatElement ); |
|
90 |
QDomText capabilitiesFormatText = doc.createTextNode( "text/xml" ); |
|
91 |
capabilitiesFormatElement.appendChild( capabilitiesFormatText ); |
|
92 | ||
93 |
QDomElement dcpTypeElement = doc.createElement( "DCPType"/*wfs:DCPType*/ ); |
|
94 |
getCapabilitiesElement.appendChild( dcpTypeElement ); |
|
95 |
QDomElement httpElement = doc.createElement( "HTTP"/*wfs:HTTP*/ ); |
|
96 |
dcpTypeElement.appendChild( httpElement ); |
|
97 | ||
98 |
//Prepare url |
|
99 |
//Some client requests already have http://<SERVER_NAME> in the REQUEST_URI variable |
|
100 |
QString hrefString; |
|
101 |
QString requestUrl = getenv( "REQUEST_URI" ); |
|
102 |
QUrl mapUrl( requestUrl ); |
|
103 |
mapUrl.setHost( QString( getenv( "SERVER_NAME" ) ) ); |
|
104 |
mapUrl.removeQueryItem( "REQUEST" ); |
|
105 |
mapUrl.removeQueryItem( "VERSION" ); |
|
106 |
mapUrl.removeQueryItem( "SERVICE" ); |
|
107 |
hrefString = mapUrl.toString(); |
|
108 | ||
109 |
//only Get supported for the moment |
|
110 |
QDomElement getElement = doc.createElement( "Get"/*wfs:Get*/ ); |
|
111 |
httpElement.appendChild( getElement ); |
|
112 |
QDomElement olResourceElement = doc.createElement( "OnlineResource"/*wfs:OnlineResource*/ ); |
|
113 |
olResourceElement.setAttribute( "xlink:type", "simple" ); |
|
114 |
requestUrl.truncate( requestUrl.indexOf( "?" ) + 1 ); |
|
115 |
olResourceElement.setAttribute( "xlink:href", hrefString ); |
|
116 |
getElement.appendChild( olResourceElement ); |
|
117 | ||
118 |
//wfs:DescribeFeatureType |
|
119 |
QDomElement describeFeatureTypeElement = doc.createElement( "DescribeFeatureType"/*wfs:DescribeFeatureType*/ ); |
|
120 |
requestElement.appendChild( describeFeatureTypeElement ); |
|
121 |
QDomElement schemaDescriptionLanguageElement = doc.createElement( "SchemaDescriptionLanguage"/*wfs:SchemaDescriptionLanguage*/ ); |
|
122 |
describeFeatureTypeElement.appendChild( schemaDescriptionLanguageElement ); |
|
123 |
QDomElement xmlSchemaElement = doc.createElement( "XMLSCHEMA"/*wfs:XMLSCHEMA*/ ); |
|
124 |
schemaDescriptionLanguageElement.appendChild( xmlSchemaElement ); |
|
125 |
QDomElement describeFeatureTypeDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' |
|
126 |
describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypeElement ); |
|
127 | ||
128 |
//wfs:GetFeature |
|
129 |
QDomElement getFeatureElement = doc.createElement( "GetFeature"/*wfs:GetFeature*/ ); |
|
130 |
requestElement.appendChild( getFeatureElement ); |
|
131 |
QDomElement getFeatureFormatElement = doc.createElement( "ResultFormat" );/*wfs:ResultFormat*/ |
|
132 |
getFeatureElement.appendChild( getFeatureFormatElement ); |
|
133 |
QDomElement gmlFormatElement = doc.createElement( "GML2" );/*wfs:GML2*/ |
|
134 |
getFeatureFormatElement.appendChild( gmlFormatElement ); |
|
135 |
QDomElement geojsonFormatElement = doc.createElement( "GeoJSON" );/*wfs:GeoJSON*/ |
|
136 |
getFeatureFormatElement.appendChild( geojsonFormatElement ); |
|
137 |
QDomElement getFeatureDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities' |
|
138 |
getFeatureElement.appendChild( getFeatureDhcTypeElement ); |
|
139 | ||
140 |
//wfs:FeatureTypeList element |
|
141 |
QDomElement featureTypeListElement = doc.createElement( "FeatureTypeList"/*wfs:FeatureTypeList*/ ); |
|
142 |
capabilityElement.appendChild( featureTypeListElement ); |
|
143 |
//wfs:Operations element |
|
144 |
QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ ); |
|
145 |
featureTypeListElement.appendChild( operationsElement ); |
|
146 |
//wfs:Query element |
|
147 |
QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ ); |
|
148 |
operationsElement.appendChild( queryElement ); |
|
149 |
/* |
|
150 |
* Adding layer liste in featureTypeListElement |
|
151 |
*/ |
|
152 |
if ( mConfigParser ) |
|
153 |
{ |
|
154 |
mConfigParser->featureTypeList( featureTypeListElement, doc ); |
|
155 |
} |
|
156 | ||
157 |
/* |
|
158 |
* Adding ogc:Filter_Capabilities in capabilityElement |
|
159 |
*/ |
|
160 |
//ogc:Filter_Capabilities element |
|
161 |
QDomElement filterCapabilitiesElement = doc.createElement( "ogc:Filter_Capabilities"/*ogc:Filter_Capabilities*/ ); |
|
162 |
capabilityElement.appendChild( filterCapabilitiesElement ); |
|
163 |
QDomElement spatialCapabilitiesElement = doc.createElement( "ogc:Spatial_Capabilities"/*ogc:Spatial_Capabilities*/ ); |
|
164 |
filterCapabilitiesElement.appendChild( spatialCapabilitiesElement ); |
|
165 |
QDomElement spatialOperatorsElement = doc.createElement( "ogc:Spatial_Operators"/*ogc:Spatial_Operators*/ ); |
|
166 |
spatialCapabilitiesElement.appendChild( spatialOperatorsElement ); |
|
167 |
QDomElement ogcBboxElement = doc.createElement( "ogc:BBOX"/*ogc:BBOX*/ ); |
|
168 |
spatialOperatorsElement.appendChild( ogcBboxElement ); |
|
169 |
QDomElement scalarCapabilitiesElement = doc.createElement( "ogc:Scalar_Capabilities"/*ogc:Scalar_Capabilities*/ ); |
|
170 |
filterCapabilitiesElement.appendChild( scalarCapabilitiesElement ); |
|
171 |
QDomElement comparisonOperatorsElement = doc.createElement( "ogc:Comparison_Operators"/*ogc:Comparison_Operators*/ ); |
|
172 |
scalarCapabilitiesElement.appendChild( comparisonOperatorsElement ); |
|
173 |
QDomElement simpleComparisonsElement = doc.createElement( "ogc:Simple_Comparisons"/*ogc:Simple_Comparisons*/ ); |
|
174 |
comparisonOperatorsElement.appendChild( simpleComparisonsElement ); |
|
175 |
return doc; |
|
176 |
} |
|
177 | ||
178 |
QDomDocument QgsWFSServer::describeFeatureType() |
|
179 |
{ |
|
180 |
QgsDebugMsg( "Entering." ); |
|
181 |
QDomDocument doc; |
|
182 |
//xsd:schema |
|
183 |
QDomElement schemaElement = doc.createElement( "schema"/*xsd:schema*/ ); |
|
184 |
schemaElement.setAttribute( "xmlns", "http://www.w3.org/2001/XMLSchema" ); |
|
185 |
schemaElement.setAttribute( "xmlns:xsd", "http://www.w3.org/2001/XMLSchema" ); |
|
186 |
schemaElement.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" ); |
|
187 |
schemaElement.setAttribute( "xmlns:gml", "http://www.opengis.net/gml" ); |
|
188 |
schemaElement.setAttribute( "xmlns:qgs", "http://www.qgis.org/gml" ); |
|
189 |
schemaElement.setAttribute( "targetNamespace", "http://www.qgis.org/gml" ); |
|
190 |
doc.appendChild( schemaElement ); |
|
191 | ||
192 |
//xsd:import |
|
193 |
QDomElement importElement = doc.createElement( "import"/*xsd:import*/ ); |
|
194 |
importElement.setAttribute( "namespace", "http://www.opengis.net/gml" ); |
|
195 |
importElement.setAttribute( "schemaLocation", "http://schemas.opengis.net/gml/2.1.2/feature.xsd" ); |
|
196 |
schemaElement.appendChild( importElement ); |
|
197 | ||
198 |
//read TYPENAME |
|
199 |
QString typeName; |
|
200 |
QMap<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" ); |
|
201 |
if ( type_name_it != mParameterMap.end() ) |
|
202 |
{ |
|
203 |
typeName = type_name_it.value(); |
|
204 |
} |
|
205 |
else |
|
206 |
{ |
|
207 |
return doc; |
|
208 |
} |
|
209 | ||
210 |
QStringList wfsLayersId = mConfigParser->wfsLayers(); |
|
211 |
QMap< QString, QMap< int, QString > > aliasInfo = mConfigParser->layerAliasInfo(); |
|
212 |
QMap< QString, QSet<QString> > hiddenAttributes = mConfigParser->hiddenAttributes(); |
|
213 |
|
|
214 |
QList<QgsMapLayer*> layerList; |
|
215 |
QgsMapLayer* currentLayer = 0; |
|
216 | ||
217 |
layerList = mConfigParser->mapLayerFromStyle( typeName, "" ); |
|
218 |
currentLayer = layerList.at( 0 ); |
|
219 |
|
|
220 |
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer ); |
|
221 |
if ( layer && wfsLayersId.contains( layer->id() ) ) |
|
222 |
{ |
|
223 |
//is there alias info for this vector layer? |
|
224 |
QMap< int, QString > layerAliasInfo; |
|
225 |
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() ); |
|
226 |
if ( aliasIt != aliasInfo.constEnd() ) |
|
227 |
{ |
|
228 |
layerAliasInfo = aliasIt.value(); |
|
229 |
} |
|
230 | ||
231 |
//hidden attributes for this layer |
|
232 |
QSet<QString> layerHiddenAttributes; |
|
233 |
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() ); |
|
234 |
if ( hiddenIt != hiddenAttributes.constEnd() ) |
|
235 |
{ |
|
236 |
layerHiddenAttributes = hiddenIt.value(); |
|
237 |
} |
|
238 |
|
|
239 |
//do a select with searchRect and go through all the features |
|
240 |
QgsVectorDataProvider* provider = layer->dataProvider(); |
|
241 |
if ( !provider ) |
|
242 |
{ |
|
243 |
return doc; |
|
244 |
} |
|
245 | ||
246 |
typeName = typeName.replace( QString(" "), QString("_") ); |
|
247 |
|
|
248 |
//xsd:element |
|
249 |
QDomElement elementElem = doc.createElement( "element"/*xsd:element*/ ); |
|
250 |
elementElem.setAttribute( "name", typeName ); |
|
251 |
elementElem.setAttribute( "type", "qgs:" + typeName + "Type" ); |
|
252 |
elementElem.setAttribute( "substitutionGroup", "gml:_Feature" ); |
|
253 |
schemaElement.appendChild( elementElem ); |
|
254 | ||
255 |
//xsd:complexType |
|
256 |
QDomElement complexTypeElem = doc.createElement( "complexType"/*xsd:complexType*/ ); |
|
257 |
complexTypeElem.setAttribute( "name", typeName + "Type" ); |
|
258 |
schemaElement.appendChild( complexTypeElem ); |
|
259 | ||
260 |
//xsd:complexType |
|
261 |
QDomElement complexContentElem = doc.createElement( "complexContent"/*xsd:complexContent*/ ); |
|
262 |
complexTypeElem.appendChild( complexContentElem ); |
|
263 | ||
264 |
//xsd:extension |
|
265 |
QDomElement extensionElem = doc.createElement( "extension"/*xsd:extension*/ ); |
|
266 |
extensionElem.setAttribute( "base", "gml:AbstractFeatureType" ); |
|
267 |
complexContentElem.appendChild( extensionElem ); |
|
268 | ||
269 |
//xsd:sequence |
|
270 |
QDomElement sequenceElem = doc.createElement( "sequence"/*xsd:sequence*/ ); |
|
271 |
extensionElem.appendChild( sequenceElem ); |
|
272 | ||
273 |
//xsd:element |
|
274 |
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ ); |
|
275 |
geomElem.setAttribute( "name", "geometry" ); |
|
276 |
geomElem.setAttribute( "type", "gml:GeometryPropertyType" ); |
|
277 |
geomElem.setAttribute( "minOccurs", "0" ); |
|
278 |
geomElem.setAttribute( "maxOccurs", "1" ); |
|
279 |
sequenceElem.appendChild( geomElem ); |
|
280 | ||
281 |
const QgsFieldMap& fields = provider->fields(); |
|
282 |
for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it ) |
|
283 |
{ |
|
284 | ||
285 |
QString attributeName = it.value().name(); |
|
286 |
//skip attribute if it has edit type 'hidden' |
|
287 |
if ( layerHiddenAttributes.contains( attributeName ) ) |
|
288 |
{ |
|
289 |
continue; |
|
290 |
} |
|
291 | ||
292 |
//xsd:element |
|
293 |
QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ ); |
|
294 |
geomElem.setAttribute( "name", attributeName ); |
|
295 |
if ( it.value().type() == 2 ) |
|
296 |
geomElem.setAttribute( "type", "integer" ); |
|
297 |
else if ( it.value().type() == 6 ) |
|
298 |
geomElem.setAttribute( "type", "double" ); |
|
299 |
else |
|
300 |
geomElem.setAttribute( "type", "string" ); |
|
301 | ||
302 |
sequenceElem.appendChild( geomElem ); |
|
303 | ||
304 |
//check if the attribute name should be replaced with an alias |
|
305 |
QMap<int, QString>::const_iterator aliasIt = layerAliasInfo.find( it.key() ); |
|
306 |
if ( aliasIt != layerAliasInfo.constEnd() ) |
|
307 |
{ |
|
308 |
geomElem.setAttribute( "alias", aliasIt.value() ); |
|
309 |
} |
|
310 | ||
311 |
} |
|
312 |
} |
|
313 | ||
314 |
return doc; |
|
315 |
} |
|
316 | ||
317 |
int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format ) |
|
318 |
{ |
|
319 |
QgsDebugMsg( "Info format is:" + infoFormat ); |
|
320 | ||
321 |
//read TYPENAME |
|
322 |
QMap<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" ); |
|
323 |
if ( type_name_it != mParameterMap.end() ) |
|
324 |
{ |
|
325 |
mTypeName = type_name_it.value(); |
|
326 |
} |
|
327 |
else |
|
328 |
{ |
|
329 |
return 1; |
|
330 |
} |
|
331 | ||
332 |
QStringList wfsLayersId = mConfigParser->wfsLayers(); |
|
333 |
QMap< QString, QMap< int, QString > > aliasInfo = mConfigParser->layerAliasInfo(); |
|
334 |
QMap< QString, QSet<QString> > hiddenAttributes = mConfigParser->hiddenAttributes(); |
|
335 |
|
|
336 |
QList<QgsMapLayer*> layerList; |
|
337 |
QgsMapLayer* currentLayer = 0; |
|
338 | ||
339 |
layerList = mConfigParser->mapLayerFromStyle( mTypeName, "" ); |
|
340 |
currentLayer = layerList.at( 0 ); |
|
341 |
|
|
342 |
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer ); |
|
343 |
if ( layer && wfsLayersId.contains( layer->id() ) ) |
|
344 |
{ |
|
345 |
//is there alias info for this vector layer? |
|
346 |
QMap< int, QString > layerAliasInfo; |
|
347 |
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() ); |
|
348 |
if ( aliasIt != aliasInfo.constEnd() ) |
|
349 |
{ |
|
350 |
layerAliasInfo = aliasIt.value(); |
|
351 |
} |
|
352 | ||
353 |
//hidden attributes for this layer |
|
354 |
QSet<QString> layerHiddenAttributes; |
|
355 |
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() ); |
|
356 |
if ( hiddenIt != hiddenAttributes.constEnd() ) |
|
357 |
{ |
|
358 |
layerHiddenAttributes = hiddenIt.value(); |
|
359 |
} |
|
360 |
|
|
361 |
//do a select with searchRect and go through all the features |
|
362 |
QgsVectorDataProvider* provider = layer->dataProvider(); |
|
363 |
if ( !provider ) |
|
364 |
{ |
|
365 |
return 2; |
|
366 |
} |
|
367 | ||
368 |
QgsFeature feature; |
|
369 |
QgsAttributeMap featureAttributes; |
|
370 |
const QgsFieldMap& fields = provider->fields(); |
|
371 | ||
372 |
//map extent |
|
373 |
QgsRectangle searchRect = layer->extent(); |
|
374 | ||
375 |
//read FEATUREDID |
|
376 |
bool fidOk = false; |
|
377 |
QString fid; |
|
378 |
QMap<QString, QString>::const_iterator fidIt = mParameterMap.find( "FEATUREID" ); |
|
379 |
if ( fidIt != mParameterMap.end() ) { |
|
380 |
fidOk = true; |
|
381 |
fid = fidIt.value(); |
|
382 |
} |
|
383 | ||
384 |
//read FILTER |
|
385 |
bool filterOk = false; |
|
386 |
QDomDocument filter; |
|
387 |
QMap<QString, QString>::const_iterator filterIt = mParameterMap.find( "FILTER" ); |
|
388 |
if ( filterIt != mParameterMap.end() ) { |
|
389 |
try { |
|
390 |
QString errorMsg; |
|
391 |
if ( !filter.setContent( filterIt.value(), true, &errorMsg ) ) |
|
392 |
{ |
|
393 |
QgsDebugMsg( "soap request parse error" ); |
|
394 |
QgsDebugMsg( "error message: " + errorMsg ); |
|
395 |
QgsDebugMsg( "the xml string was:" ); |
|
396 |
QgsDebugMsg( filterIt.value() ); |
|
397 |
} |
|
398 |
else |
|
399 |
{ |
|
400 |
filterOk = true; |
|
401 |
} |
|
402 |
} catch(QgsMapServiceException& e ) { |
|
403 |
filterOk = false; |
|
404 |
} |
|
405 |
} |
|
406 | ||
407 | ||
408 |
bool conversionSuccess; |
|
409 |
double minx, miny, maxx, maxy; |
|
410 |
bool bboxOk = false; |
|
411 |
//read BBOX |
|
412 |
QMap<QString, QString>::const_iterator bbIt = mParameterMap.find( "BBOX" ); |
|
413 |
if ( bbIt == mParameterMap.end() ) |
|
414 |
{ |
|
415 |
minx = 0; miny = 0; maxx = 0; maxy = 0; |
|
416 |
} |
|
417 |
else |
|
418 |
{ |
|
419 |
bboxOk = true; |
|
420 |
QString bbString = bbIt.value(); |
|
421 |
minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess ); |
|
422 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
423 |
miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess ); |
|
424 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
425 |
maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess ); |
|
426 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
427 |
maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess ); |
|
428 |
if ( !conversionSuccess ) {bboxOk = false;} |
|
429 |
} |
|
430 | ||
431 |
//read MAXFEATURES |
|
432 |
long maxFeat = layer->featureCount(); |
|
433 |
long featureCounter = 0; |
|
434 |
QMap<QString, QString>::const_iterator mfIt = mParameterMap.find( "MAXFEATURES" ); |
|
435 |
if ( mfIt != mParameterMap.end() ) |
|
436 |
{ |
|
437 |
QString mfString = mfIt.value(); |
|
438 |
bool mfOk; |
|
439 |
maxFeat = mfString.toLong(&mfOk, 10); |
|
440 |
if ( !mfOk ) { maxFeat = layer->featureCount(); } |
|
441 |
} |
|
442 | ||
443 |
//read PROPERTYNAME |
|
444 |
mWithGeom = true; |
|
445 |
QgsAttributeList attrIndexes = provider->attributeIndexes(); |
|
446 |
QMap<QString, QString>::const_iterator pnIt = mParameterMap.find( "PROPERTYNAME" ); |
|
447 |
if ( pnIt != mParameterMap.end() ) |
|
448 |
{ |
|
449 |
QStringList attrList = pnIt.value().split( "," ); |
|
450 |
if ( attrList.size() > 0 ) |
|
451 |
{ |
|
452 |
mWithGeom = false; |
|
453 |
QStringList::const_iterator alstIt; |
|
454 |
QList<int> idxList; |
|
455 |
QMap<QString, int> fieldMap = provider->fieldNameMap(); |
|
456 |
QMap<QString, int>::const_iterator fieldIt; |
|
457 |
QString fieldName; |
|
458 |
for ( alstIt = attrList.begin(); alstIt != attrList.end(); ++alstIt ) |
|
459 |
{ |
|
460 |
fieldName = *alstIt; |
|
461 |
fieldIt = fieldMap.find( fieldName ); |
|
462 |
if ( fieldIt != fieldMap.end() ) |
|
463 |
{ |
|
464 |
idxList.append( fieldIt.value() ); |
|
465 |
} |
|
466 |
else if ( fieldName == "geometry" ) |
|
467 |
{ |
|
468 |
mWithGeom = true; |
|
469 |
} |
|
470 |
} |
|
471 |
if ( idxList.size() > 0 || mWithGeom) |
|
472 |
{ |
|
473 |
attrIndexes = idxList; |
|
474 |
} |
|
475 |
else |
|
476 |
{ |
|
477 |
mWithGeom = true; |
|
478 |
} |
|
479 |
} |
|
480 |
} |
|
481 |
|
|
482 |
QgsCoordinateReferenceSystem layerCrs = layer->crs(); |
|
483 |
|
|
484 |
startGetFeature( request, format ); |
|
485 | ||
486 |
if ( fidOk ) |
|
487 |
{ |
|
488 |
provider->featureAtId( fid.toInt(), feature, mWithGeom, attrIndexes ); |
|
489 |
sendGetFeature( request, format, &feature, 0, layerCrs, fields, layerHiddenAttributes); |
|
490 |
} |
|
491 |
else if ( filterOk ) |
|
492 |
{ |
|
493 |
provider->select( attrIndexes, searchRect, mWithGeom, true ); |
|
494 |
try { |
|
495 |
QgsFilter* mFilter = QgsFilter::createFilterFromXml( filter.firstChild().toElement().firstChild().toElement(), layer ); |
|
496 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat ) |
|
497 |
{ |
|
498 |
if ( mFilter ) |
|
499 |
{ |
|
500 |
if ( mFilter->evaluate( feature ) ) |
|
501 |
{ |
|
502 |
sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes); |
|
503 |
++featureCounter; |
|
504 |
} |
|
505 |
} |
|
506 |
else |
|
507 |
{ |
|
508 |
sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes); |
|
509 |
++featureCounter; |
|
510 |
} |
|
511 |
} |
|
512 |
delete mFilter; |
|
513 |
} catch(QgsMapServiceException& e ) { |
|
514 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat ) |
|
515 |
{ |
|
516 |
sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes); |
|
517 |
++featureCounter; |
|
518 |
} |
|
519 |
} |
|
520 |
} |
|
521 |
else |
|
522 |
{ |
|
523 |
if ( bboxOk ) |
|
524 |
searchRect.set( minx, miny, maxx, maxy ); |
|
525 |
provider->select( attrIndexes, searchRect, mWithGeom, true ); |
|
526 |
while ( provider->nextFeature( feature ) && featureCounter < maxFeat ) |
|
527 |
{ |
|
528 |
sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes); |
|
529 |
++featureCounter; |
|
530 |
} |
|
531 |
} |
|
532 |
|
|
533 |
endGetFeature( request, format ); |
|
534 |
} |
|
535 |
else |
|
536 |
{ |
|
537 |
return 2; |
|
538 |
} |
|
539 |
return 0; |
|
540 |
} |
|
541 | ||
542 |
void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& format ) |
|
543 |
{ |
|
544 |
QByteArray result; |
|
545 |
QString fcString; |
|
546 |
if ( format == "GeoJSON" ) |
|
547 |
{ |
|
548 |
fcString = "{\"type\": \"FeatureCollection\",\n"; |
|
549 |
fcString += " \"features\": [\n"; |
|
550 |
result = fcString.toUtf8(); |
|
551 |
request.startGetFeatureResponse(&result, format); |
|
552 |
} |
|
553 |
else |
|
554 |
{ |
|
555 |
//wfs:FeatureCollection |
|
556 |
fcString = "<wfs:FeatureCollection"; |
|
557 |
fcString += " xmlns=\"http://www.opengis.net/wfs\""; |
|
558 |
fcString += " xmlns:wfs=\"http://www.opengis.net/wfs\""; |
|
559 |
fcString += " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""; |
|
560 |
fcString += " xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\""; |
|
561 |
fcString += " xmlns:ogc=\"http://www.opengis.net/ogc\""; |
|
562 |
fcString += " xmlns:gml=\"http://www.opengis.net/gml\""; |
|
563 |
fcString += " xmlns:ows=\"http://www.opengis.net/ows\""; |
|
564 |
fcString += " xmlns:xlink=\"http://www.w3.org/1999/xlink\""; |
|
565 |
fcString += " xmlns:qgs=\"http://www.qgis.org/gml\""; |
|
566 |
fcString += ">"; |
|
567 |
result = fcString.toUtf8(); |
|
568 |
request.startGetFeatureResponse(&result, format); |
|
569 |
} |
|
570 |
fcString = ""; |
|
571 |
} |
|
572 | ||
573 |
void QgsWFSServer::sendGetFeature( QgsRequestHandler& request, const QString& format, QgsFeature* feat, int featIdx, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> hiddenAttributes) /*const*/ |
|
574 |
{ |
|
575 |
QByteArray result; |
|
576 |
if ( format == "GeoJSON" ) |
|
577 |
{ |
|
578 |
QString fcString; |
|
579 |
if (featIdx == 0) |
|
580 |
fcString += " "; |
|
581 |
else |
|
582 |
fcString += " ,"; |
|
583 |
fcString += createFeatureGeoJSON(feat, crs, fields, hiddenAttributes); |
|
584 |
fcString += "\n"; |
|
585 | ||
586 |
result = fcString.toUtf8(); |
|
587 |
request.sendGetFeatureResponse( &result ); |
|
588 |
fcString = ""; |
|
589 |
} |
|
590 |
else |
|
591 |
{ |
|
592 |
QDomDocument gmlDoc; |
|
593 |
QDomElement featureElement = createFeatureElem(feat, gmlDoc, crs, fields, hiddenAttributes); |
|
594 |
gmlDoc.appendChild(featureElement); |
|
595 | ||
596 |
result = gmlDoc.toByteArray(); |
|
597 |
request.sendGetFeatureResponse( &result ); |
|
598 |
gmlDoc.removeChild(featureElement); |
|
599 |
} |
|
600 |
} |
|
601 | ||
602 |
void QgsWFSServer::endGetFeature( QgsRequestHandler& request, const QString& format ) |
|
603 |
{ |
|
604 |
QByteArray result; |
|
605 |
QString fcString; |
|
606 |
if ( format == "GeoJSON" ) |
|
607 |
{ |
|
608 |
fcString += " ]\n"; |
|
609 |
fcString += "}"; |
|
610 | ||
611 |
result = fcString.toUtf8(); |
|
612 |
request.endGetFeatureResponse( &result ); |
|
613 |
fcString = ""; |
|
614 |
} |
|
615 |
else |
|
616 |
{ |
|
617 |
fcString = "</wfs:FeatureCollection>"; |
|
618 |
result = fcString.toUtf8(); |
|
619 |
request.endGetFeatureResponse( &result ); |
|
620 |
fcString = ""; |
|
621 |
} |
|
622 |
} |
|
623 | ||
624 |
QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet<QString> hiddenAttributes) /*const*/ |
|
625 |
{ |
|
626 |
QString fStr = "{\"type\": \"Feature\",\n"; |
|
627 | ||
628 |
fStr += " \"id\": "; |
|
629 |
fStr += QString::number( feat->id() ); |
|
630 |
fStr += ",\n"; |
|
631 | ||
632 |
QgsGeometry* geom = feat->geometry(); |
|
633 |
if ( geom && mWithGeom ) |
|
634 |
{ |
|
635 |
fStr += " \"geometry\": "; |
|
636 |
fStr += geom->exportToGeoJSON(); |
|
637 |
fStr += ",\n"; |
|
638 |
} |
|
639 | ||
640 |
//read all attribute values from the feature |
|
641 |
fStr += " \"properties\": {\n"; |
|
642 |
QgsAttributeMap featureAttributes = feat->attributeMap(); |
|
643 |
int attributeCounter = 0; |
|
644 |
for ( QgsAttributeMap::const_iterator it = featureAttributes.begin(); it != featureAttributes.end(); ++it ) |
|
645 |
{ |
|
646 |
QString attributeName = fields[it.key()].name(); |
|
647 |
//skip attribute if it has edit type 'hidden' |
|
648 |
if ( hiddenAttributes.contains( attributeName ) ) |
|
649 |
{ |
|
650 |
continue; |
|
651 |
} |
|
652 | ||
653 |
if (attributeCounter == 0) |
|
654 |
fStr += " \""; |
|
655 |
else |
|
656 |
fStr += " ,\""; |
|
657 |
fStr += attributeName; |
|
658 |
fStr += "\": "; |
|
659 |
if (it->type() == 6 || it->type() == 2) |
|
660 |
{ |