Skip to content

Commit c27c890

Browse files
committed
[FEATURE]: Add WFS support for QGIS server. Provided by René-Luc D'Hont
1 parent a2ee769 commit c27c890

15 files changed

+1676
-9
lines changed

src/app/qgsprojectproperties.cpp

+46-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
175175
twIdentifyLayers->setCellWidget( i, 2, cb );
176176
}
177177

178-
grpWMSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
178+
grpOWSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
179179
mWMSTitle->setText( QgsProject::instance()->readEntry( "WMSServiceTitle", "/" ) );
180180
mWMSContactOrganization->setText( QgsProject::instance()->readEntry( "WMSContactOrganization", "/", "" ) );
181181
mWMSContactPerson->setText( QgsProject::instance()->readEntry( "WMSContactPerson", "/", "" ) );
@@ -229,6 +229,38 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
229229
bool addWktGeometry = QgsProject::instance()->readBoolEntry( "WMSAddWktGeometry", "/" );
230230
mAddWktGeometryCheckBox->setChecked( addWktGeometry );
231231

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+
232264
restoreState();
233265
}
234266

@@ -380,7 +412,7 @@ void QgsProjectProperties::apply()
380412

381413
QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", noIdentifyLayerList );
382414

383-
QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpWMSServiceCapabilities->isChecked() );
415+
QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpOWSServiceCapabilities->isChecked() );
384416
QgsProject::instance()->writeEntry( "WMSServiceTitle", "/", mWMSTitle->text() );
385417
QgsProject::instance()->writeEntry( "WMSContactOrganization", "/", mWMSContactOrganization->text() );
386418
QgsProject::instance()->writeEntry( "WMSContactPerson", "/", mWMSContactPerson->text() );
@@ -428,6 +460,18 @@ void QgsProjectProperties::apply()
428460

429461
QgsProject::instance()->writeEntry( "WMSAddWktGeometry", "/", mAddWktGeometryCheckBox->isChecked() );
430462

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+
431475
//todo XXX set canvas color
432476
emit refresh();
433477
}

src/core/qgsgeometry.cpp

+290
Original file line numberDiff line numberDiff line change
@@ -4185,6 +4185,296 @@ QString QgsGeometry::exportToWkt()
41854185
}
41864186
}
41874187

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+
41884478
bool QgsGeometry::exportWkbToGeos()
41894479
{
41904480
QgsDebugMsgLevel( "entered.", 3 );

src/core/qgsgeometry.h

+5
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,11 @@ class CORE_EXPORT QgsGeometry
361361
*/
362362
QString exportToWkt();
363363

364+
/** Exports the geometry to mGeoJSON
365+
@return true in case of success and false else
366+
*/
367+
QString exportToGeoJSON();
368+
364369
/* Accessor functions for getting geometry data */
365370

366371
/** return contents of the geometry as a point

src/mapserver/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ SET ( qgis_mapserv_SRCS
2828
qgssldparser.cpp
2929
qgssldrenderer.cpp
3030
qgswmsserver.cpp
31+
qgswfsserver.cpp
3132
qgsmapserviceexception.cpp
3233
qgsmslayercache.cpp
3334
qgsfilter.cpp

0 commit comments

Comments
 (0)