3 changes: 3 additions & 0 deletions python/core/qgsvectorlayer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ class QgsVectorLayer : QgsMapLayer
/** Select all the features */
void selectAll();

/** Get all feature Ids */
QgsFeatureIds allFeatureIds();

/**
* Invert selection of features found within the search rectangle (in layer's coordinates)
*
Expand Down
21 changes: 21 additions & 0 deletions src/core/qgscoordinatereferencesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
// split on spaces followed by a plus sign (+) to deal
// also with parameters containing spaces (e.g. +nadgrids)
// make sure result is trimmed (#5598)
QStringList myParams;
foreach ( QString param, myProj4String.split( QRegExp( "\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
{
QString arg = QString( "' '||parameters||' ' LIKE %1" ).arg( quotedValue( QString( "% %1 %" ).arg( param.trimmed() ) ) );
Expand All @@ -618,6 +619,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
{
sql += delim + arg;
delim = " AND ";
myParams << param.trimmed();
}
}

Expand All @@ -631,6 +633,25 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
// datum might have disappeared in definition - retry without it
myRecord = getRecord( sql + " order by deprecated" );
}

if ( !myRecord.empty() )
{
// Bugfix 8487 : test param lists are equal, except for +datum
QStringList foundParams;
foreach ( QString param, myRecord["parameters"].split( QRegExp( "\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
{
if ( !param.startsWith( "+datum=" ) )
foundParams << param.trimmed();
}

myParams.sort();
foundParams.sort();

if ( myParams != foundParams )
{
myRecord.clear();
}
}
}

if ( !myRecord.empty() )
Expand Down
40 changes: 22 additions & 18 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,27 +792,17 @@ void QgsVectorLayer::modifySelection( QgsFeatureIds selectIds, QgsFeatureIds des

void QgsVectorLayer::invertSelection()
{
// copy the ids of selected features to tmp
QgsFeatureIds tmp = mSelectedFeatureIds;

QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
.setFlags( QgsFeatureRequest::NoGeometry )
.setSubsetOfAttributes( QgsAttributeList() ) );

QgsFeatureIds ids;

QgsFeature fet;
while ( fit.nextFeature( fet ) )
{
ids << fet.id();
}

QgsFeatureIds ids = allFeatureIds();
ids.subtract( mSelectedFeatureIds );

setSelectedFeatures( ids );
}

void QgsVectorLayer::selectAll()
{
setSelectedFeatures( allFeatureIds() );
}

QgsFeatureIds QgsVectorLayer::allFeatureIds()
{
QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
.setFlags( QgsFeatureRequest::NoGeometry )
Expand All @@ -826,7 +816,7 @@ void QgsVectorLayer::selectAll()
ids << fet.id();
}

setSelectedFeatures( ids );
return ids;
}

void QgsVectorLayer::invertSelectionInRectangle( QgsRectangle & rect )
Expand Down Expand Up @@ -2682,9 +2672,23 @@ bool QgsVectorLayer::rollBack( bool deleteBuffer )
void QgsVectorLayer::setSelectedFeatures( const QgsFeatureIds& ids )
{
QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - ids;
// TODO: check whether features with these ID exist

mSelectedFeatureIds = ids;

QgsFeatureIds allIds = allFeatureIds();
QgsFeatureIds::iterator id = mSelectedFeatureIds.begin();
while ( id != mSelectedFeatureIds.end() )
{
if ( !allIds.contains( *id ) )
{
id = mSelectedFeatureIds.erase( id );
}
else
{
++id;
}
}

// invalidate cache
setCacheImage( 0 );

Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Select all the features */
void selectAll();

/** Get all feature Ids */
QgsFeatureIds allFeatureIds();

/**
* Invert selection of features found within the search rectangle (in layer's coordinates)
*
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgsrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ QgsLegendSymbologyList QgsFeatureRendererV2::legendSymbologyItems( QSize iconSiz

QgsLegendSymbolList QgsFeatureRendererV2::legendSymbolItems( double scaleDenominator )
{
Q_UNUSED( scaleDenominator );
return QgsLegendSymbolList();
}

Expand Down
8 changes: 4 additions & 4 deletions src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@


QgsRuleBasedRendererV2::Rule::Rule(QgsSymbolV2* symbol, int scaleMinDenom, int scaleMaxDenom, QString filterExp, QString label, QString description , bool elseRule)
: mParent( NULL ), mSymbol( symbol ),
mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom ),
mFilterExp( filterExp ), mLabel( label ), mDescription( description ),
mFilter( NULL ), mElseRule( elseRule )
: mParent( NULL ), mSymbol( symbol )
, mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom )
, mFilterExp( filterExp ), mLabel( label ), mDescription( description )
, mElseRule( elseRule ), mFilter( NULL )
{
initFilter();
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresconn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ QString QgsPostgresConn::postgisTypeFilter( QString geomCol, QGis::WkbType geomT
case QGis::WKBPolygon25D:
case QGis::WKBMultiPolygon:
case QGis::WKBMultiPolygon25D:
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM')" ).arg( geomCol );
return QString( "upper(geometrytype(%1)) IN ('POLYGON','MULTIPOLYGON','POLYGONM','MULTIPOLYGONM', 'POLYHEDRALSURFACE', 'TIN')" ).arg( geomCol );
case QGis::WKBNoGeometry:
return QString( "geometrytype(%1) IS NULL" ).arg( geomCol );
case QGis::WKBUnknown:
Expand Down
124 changes: 119 additions & 5 deletions src/providers/postgres/qgspostgresfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,8 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )

if ( fetchGeometry )
{
query += QString( "%1(%2(%3%4),'%5')" )
query += QString( "%1(%2%3,'%4')" )
.arg( P->mConnectionRO->majorVersion() < 2 ? "asbinary" : "st_asbinary" )
.arg( P->mConnectionRO->majorVersion() < 2 ? "force_2d"
: P->mConnectionRO->majorVersion() > 2 || P->mConnectionRO->minorVersion() > 0 ? "st_force2d"
: "st_force_2d" )
.arg( P->quotedIdentifier( P->mGeometryColumn ) )
.arg( P->mSpatialColType == sctGeography ? "::geometry" : "" )
.arg( P->endianString() );
Expand Down Expand Up @@ -362,7 +359,124 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
memset( featureGeom, 0, returnedLength + 1 );
memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength );
feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );

// modify 2.5D WKB types to make them compliant with OGR
unsigned int wkbType;
memcpy( &wkbType, featureGeom + 1, sizeof( wkbType) );

// convert unsupported types to supported ones
switch ( wkbType )
{
case 15:
// 2D polyhedral => multipolygon
wkbType = 6;
break;
case 1015:
// 3D polyhedral => multipolygon
wkbType = 1006;
break;
case 17:
// 2D triangle => polygon
wkbType = 3;
break;
case 1017:
// 3D triangle => polygon
wkbType = 1003;
break;
case 16:
// 2D TIN => multipolygon
wkbType = 6;
break;
case 1016:
// TIN => multipolygon
wkbType = 1006;
break;
}
// convert from postgis types to qgis types
if ( wkbType >= 1000 )
{
wkbType = wkbType - 1000 + QGis::WKBPoint25D - 1;
}
memcpy( featureGeom + 1, &wkbType, sizeof( wkbType) );

// change wkb type of inner geometries
if ( wkbType == QGis::WKBMultiPoint25D ||
wkbType == QGis::WKBMultiLineString25D ||
wkbType == QGis::WKBMultiPolygon25D )
{
unsigned int numGeoms = *(( int* )( featureGeom + 5 ));
unsigned char* wkb = featureGeom + 9;
for ( unsigned int i = 0; i < numGeoms; ++i )
{
unsigned int localType;
memcpy( &localType, wkb + 1, sizeof( localType) );
switch ( localType )
{
case 15:
// 2D polyhedral => multipolygon
localType = 6;
break;
case 1015:
// 3D polyhedral => multipolygon
localType = 1006;
break;
case 17:
// 2D triangle => polygon
localType = 3;
break;
case 1017:
// 3D triangle => polygon
localType = 1003;
break;
case 16:
// 2D TIN => multipolygon
localType = 6;
break;
case 1016:
// TIN => multipolygon
localType = 1006;
break;
}
if ( localType >= 1000 )
{
localType = localType - 1000 + QGis::WKBPoint25D - 1;
}
memcpy( wkb + 1, &localType, sizeof( localType) );

// skip endian and type info
wkb += sizeof( unsigned int ) + 1;

// skip coordinates
switch ( wkbType )
{
case QGis::WKBMultiPoint25D:
wkb += sizeof( double ) * 3;
break;
case QGis::WKBMultiLineString25D:
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
}
break;
default:
case QGis::WKBMultiPolygon25D:
{
unsigned int nRings = *(( int* ) wkb );
wkb += sizeof( nRings );
for ( unsigned int j = 0; j < nRings; ++j )
{
unsigned int nPoints = *(( int* ) wkb );
wkb += sizeof( nPoints );
wkb += sizeof( double ) * 3 * nPoints;
}
}
break;
}
}
}

feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 );
}
else
{
Expand Down