Skip to content

Commit

Permalink
Properly support OGR sublayers (with createChildren) to avoid #4400
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Oct 19, 2011
1 parent bfb4d0f commit f15622f
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 102 deletions.
1 change: 1 addition & 0 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,7 @@ QgsGdalLayerItem::QgsGdalLayerItem( QgsDataItem* parent,
: QgsLayerItem( parent, name, path, uri, QgsLayerItem::Raster, "gdal" )
{
mToolTip = uri;
mPopulated = true; // children are not expected
}

QgsGdalLayerItem::~QgsGdalLayerItem()
Expand Down
226 changes: 124 additions & 102 deletions src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2272,6 +2272,7 @@ QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem* parent,
: QgsLayerItem( parent, name, path, uri, layerType, "ogr" )
{
mToolTip = uri;
mPopulated = true; // children are not expected
}

QgsOgrLayerItem::~QgsOgrLayerItem()
Expand Down Expand Up @@ -2358,135 +2359,156 @@ bool QgsOgrLayerItem::setCrs( QgsCoordinateReferenceSystem crs )
return false;
}


static QgsOgrLayerItem* dataItemForLayer( QgsDataItem* parentItem, QString name, QString path, OGRDataSourceH hDataSource, int layerId )
{
OGRLayerH hLayer = OGR_DS_GetLayer( hDataSource, layerId );
OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer );

QgsLayerItem::LayerType layerType = QgsLayerItem::Vector;
int ogrType = getOgrGeomType( hLayer );
switch ( ogrType )
{
case wkbUnknown:
case wkbGeometryCollection:
break;
case wkbNone:
layerType = QgsLayerItem::TableLayer;
break;
case wkbPoint:
case wkbMultiPoint:
case wkbPoint25D:
case wkbMultiPoint25D:
layerType = QgsLayerItem::Point;
break;
case wkbLineString:
case wkbMultiLineString:
case wkbLineString25D:
case wkbMultiLineString25D:
layerType = QgsLayerItem::Line;
break;
case wkbPolygon:
case wkbMultiPolygon:
case wkbPolygon25D:
case wkbMultiPolygon25D:
layerType = QgsLayerItem::Polygon;
break;
default:
break;
}

QgsDebugMsg( QString( "ogrType = %1 layertype = %2" ).arg( ogrType ).arg( layerType ) );

QString layerUri = path;

if ( name.isEmpty() )
{
// we are in a collection
name = FROM8( OGR_FD_GetName( hDef ) );
QgsDebugMsg( "OGR layer name : " + name );

layerUri += "|layerid=" + QString::number( layerId );

path += "/" + name;
}

QgsDebugMsg( "OGR layer uri : " + layerUri );

return new QgsOgrLayerItem( parentItem, name, path, layerUri, layerType );
}

QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
{
if ( thePath.isEmpty() )
return 0;

QFileInfo info( thePath );
if ( info.isFile() )
if ( !info.isFile() )
return 0;

// We have to filter by extensions, otherwise e.g. all Shapefile files are displayed
// because OGR drive can open also .dbf, .shx.
QStringList myExtensions = fileExtensions();
if ( myExtensions.indexOf( info.suffix().toLower() ) < 0 )
{
// We have to filter by extensions, otherwise e.g. all Shapefile files are displayed
// because OGR drive can open also .dbf, .shx.
QStringList myExtensions = fileExtensions();
if ( myExtensions.indexOf( info.suffix().toLower() ) < 0 )
bool matches = false;
foreach( QString wildcard, wildcards() )
{
bool matches = false;
foreach( QString wildcard, wildcards() )
QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
if ( rx.exactMatch( info.fileName() ) )
{
QRegExp rx( wildcard, Qt::CaseInsensitive, QRegExp::Wildcard );
if ( rx.exactMatch( info.fileName() ) )
{
matches = true;
break;
}
matches = true;
break;
}
if ( !matches )
return 0;
}

// .dbf should probably appear if .shp is not present
if ( info.suffix().toLower() == "dbf" )
{
QString pathShp = thePath.left( thePath.count() - 4 ) + ".shp";
if ( QFileInfo( pathShp ).exists() )
return 0;
}
if ( !matches )
return 0;
}

OGRRegisterAll();
OGRSFDriverH hDriver;
OGRDataSourceH hDataSource = OGROpen( TO8F( thePath ), false, &hDriver );

if ( !hDataSource )
// .dbf should probably appear if .shp is not present
if ( info.suffix().toLower() == "dbf" )
{
QString pathShp = thePath.left( thePath.count() - 4 ) + ".shp";
if ( QFileInfo( pathShp ).exists() )
return 0;
}

QString driverName = OGR_Dr_GetName( hDriver );
QgsDebugMsg( "OGR Driver : " + driverName );
OGRRegisterAll();
OGRSFDriverH hDriver;
OGRDataSourceH hDataSource = OGROpen( TO8F( thePath ), false, &hDriver );

int numLayers = OGR_DS_GetLayerCount( hDataSource );
if ( !hDataSource )
return 0;

if ( numLayers == 0 )
{
OGR_DS_Destroy( hDataSource );
return 0;
}
QString driverName = OGR_Dr_GetName( hDriver );
QgsDebugMsg( "OGR Driver : " + driverName );

QgsDataCollectionItem * collection = 0;
if ( numLayers > 1 )
{
collection = new QgsDataCollectionItem( parentItem, info.fileName(), thePath );
}
int numLayers = OGR_DS_GetLayerCount( hDataSource );

for ( int i = 0; i < numLayers; i++ )
{
OGRLayerH hLayer = OGR_DS_GetLayer( hDataSource, i );
OGRFeatureDefnH hDef = OGR_L_GetLayerDefn( hLayer );
QgsDataItem* item = 0;

QgsLayerItem::LayerType layerType = QgsLayerItem::Vector;
int ogrType = getOgrGeomType( hLayer );
switch ( ogrType )
{
case wkbUnknown:
case wkbGeometryCollection:
break;
case wkbNone:
layerType = QgsLayerItem::TableLayer;
break;
case wkbPoint:
case wkbMultiPoint:
case wkbPoint25D:
case wkbMultiPoint25D:
layerType = QgsLayerItem::Point;
break;
case wkbLineString:
case wkbMultiLineString:
case wkbLineString25D:
case wkbMultiLineString25D:
layerType = QgsLayerItem::Line;
break;
case wkbPolygon:
case wkbMultiPolygon:
case wkbPolygon25D:
case wkbMultiPolygon25D:
layerType = QgsLayerItem::Polygon;
break;
default:
break;
}
if ( numLayers == 1 )
{
QString name = info.completeBaseName();
item = dataItemForLayer( parentItem, name, thePath, hDataSource, 0 );
}
else if ( numLayers > 1 )
{
item = new QgsOgrDataCollectionItem( parentItem, info.fileName(), thePath );
}

QgsDebugMsg( QString( "ogrType = %1 layertype = %2" ).arg( ogrType ).arg( layerType ) );
OGR_DS_Destroy( hDataSource );
return item;
}

QString name = info.completeBaseName();
QgsOgrDataCollectionItem::QgsOgrDataCollectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
}

QString layerName = FROM8( OGR_FD_GetName( hDef ) );
QgsDebugMsg( "OGR layer name : " + layerName );
QgsOgrDataCollectionItem::~QgsOgrDataCollectionItem()
{
}

QString path = thePath;
if ( numLayers > 1 )
{
name = layerName;
path += "/" + name;
}
QVector<QgsDataItem*> QgsOgrDataCollectionItem::createChildren()
{
QVector<QgsDataItem*> children;

QString layerUri = thePath;
if ( collection )
layerUri += "|layerid=" + QString::number( i );
QgsDebugMsg( "OGR layer uri : " + layerUri );
OGRSFDriverH hDriver;
OGRDataSourceH hDataSource = OGROpen( TO8F( mPath ), false, &hDriver );
if ( !hDataSource )
return children;
int numLayers = OGR_DS_GetLayerCount( hDataSource );

QgsOgrLayerItem * item = new QgsOgrLayerItem( collection ? collection : parentItem, name, path, layerUri, layerType );
if ( numLayers == 1 )
{
OGR_DS_Destroy( hDataSource );
return item;
}
collection->addChild( item );
}
collection->setPopulated();
OGR_DS_Destroy( hDataSource );
return collection;
for ( int i = 0; i < numLayers; i++ )
{
QgsOgrLayerItem* item = dataItemForLayer( this, QString(), mPath, hDataSource, i );
children.append( item );
}

return 0;
OGR_DS_Destroy( hDataSource );

return children;
}

QGISEXTERN QgsVectorLayerImport::ImportError createEmptyLayer(
Expand Down
9 changes: 9 additions & 0 deletions src/providers/ogr/qgsogrprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,12 @@ class QgsOgrLayerItem : public QgsLayerItem
Capability capabilities();
};

class QgsOgrDataCollectionItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsOgrDataCollectionItem( QgsDataItem* parent, QString name, QString path );
~QgsOgrDataCollectionItem();

QVector<QgsDataItem*> createChildren();
};

0 comments on commit f15622f

Please sign in to comment.