Skip to content
Permalink
Browse files

Use the OGR generic methods

  • Loading branch information
elpaso committed Sep 8, 2017
1 parent 1b72a0d commit 6e34681b7302f87438c0bffd7d251104a4cc8552
Showing with 17 additions and 218 deletions.
  1. +17 −188 src/providers/ogr/qgsgeopackagedataitems.cpp
  2. +0 −30 src/providers/ogr/qgsgeopackagedataitems.h
@@ -16,18 +16,18 @@
#include "sqlite3.h"

#include "qgsgeopackagedataitems.h"
#include "qgsgeopackageconnection.h"
#include "qgsogrdbconnection.h"
#include "qgslogger.h"
#include "qgssettings.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsogrprovider.h"
#include "qgsogrdataitems.h"
#include "qgsnewgeopackagelayerdialog.h"
#include "qgsmessageoutput.h"
#include "qgsvectorlayerexporter.h"
#include "qgsgeopackagerasterwritertask.h"
#include "gdal.h"

#include <QAction>
#include <QMessageBox>
@@ -62,10 +62,10 @@ QgsGeoPackageRootItem::~QgsGeoPackageRootItem()
QVector<QgsDataItem *> QgsGeoPackageRootItem::createChildren()
{
QVector<QgsDataItem *> connections;

Q_FOREACH ( const QString &connName, QgsGeoPackageConnection::connectionList() )
const QStringList connList( QgsOgrDbConnection::connectionList( QStringLiteral( "GPKG" ) ) );
for ( const QString &connName : connList )
{
QgsGeoPackageConnection connection( connName );
QgsOgrDbConnection connection( connName, QStringLiteral( "GPKG" ) );
QgsDataItem *conn = new QgsGeoPackageConnectionItem( this, connection.name(), connection.uri().encodedUri() );

connections.append( conn );
@@ -102,9 +102,10 @@ void QgsGeoPackageRootItem::connectionsChanged()

void QgsGeoPackageRootItem::newConnection()
{
// TODO use QgsFileWidget
QString path = QFileDialog::getOpenFileName( nullptr, tr( "Open GeoPackage" ), "", tr( "GeoPackage Database (*.gpkg)" ) );
storeConnection( path );
if ( QgsOgrDataCollectionItem::createConnection( QStringLiteral( "GeoPackage" ), QStringLiteral( "GeoPackage Database (*.gpkg)" ), QStringLiteral( "GPKG" ) ) )
{
refreshConnections();
}
}


@@ -115,36 +116,13 @@ void QgsGeoPackageRootItem::createDatabase()
dialog.setCrs( QgsProject::instance()->defaultCrsForNewLayers() );
if ( dialog.exec() == QDialog::Accepted )
{
storeConnection( dialog.databasePath() );
}
}
#endif

bool QgsGeoPackageRootItem::storeConnection( const QString &path )
{
QFileInfo fileInfo( path );
QString connName = fileInfo.fileName();
if ( ! path.isEmpty() )
{
bool ok = true;
while ( ok && ! QgsGeoPackageConnection( connName ).path( ).isEmpty( ) )
if ( QgsOgrDataCollectionItem::storeConnection( dialog.databasePath(), QStringLiteral( "GPKG" ) ) )
{

connName = QInputDialog::getText( nullptr, tr( "Cannot add connection '%1'" ).arg( connName ),
tr( "A connection with the same name already exists,\nplease provide a new name:" ), QLineEdit::Normal,
QLatin1String( "" ), &ok );
}
if ( ok && ! connName.isEmpty() )
{
QgsGeoPackageConnection connection( connName );
connection.setPath( path );
connection.save();
refreshConnections();
return true;
}
}
return false;
}
#endif


QgsGeoPackageConnectionItem::QgsGeoPackageConnectionItem( QgsDataItem *parent, QString name, QString path )
@@ -154,144 +132,21 @@ QgsGeoPackageConnectionItem::QgsGeoPackageConnectionItem( QgsDataItem *parent, Q
mCapabilities |= Collapse;
}

QList<QgsGeoPackageLayerInfo *> QgsGeoPackageConnectionItem::subLayers( const QString &path ) const
{

QList<QgsGeoPackageLayerInfo *> children;

// Vector layers
QgsVectorLayer layer( mPath, QStringLiteral( "ogr_tmp" ), QStringLiteral( "ogr" ) );
if ( ! layer.isValid( ) )
{
QgsDebugMsgLevel( tr( "Layer is not a valid GeoPackage Vector layer %1" ).arg( mPath ), 3 );
}
else
{
// Collect mixed-geom layers
QMultiMap<int, QStringList> subLayers;
Q_FOREACH ( const QString &descriptor, layer.dataProvider()->subLayers( ) )
{
QStringList pieces = descriptor.split( ':' );
subLayers.insert( pieces[0].toInt(), pieces );
}
int prevIdx = -1;
Q_FOREACH ( const int &idx, subLayers.keys( ) )
{
if ( idx == prevIdx )
{
continue;
}
prevIdx = idx;
QList<QStringList> values = subLayers.values( idx );
for ( int i = 0; i < values.size(); ++i )
{
QStringList pieces = values.at( i );
QString layerId = pieces[0];
QString name = pieces[1];
// QString featuresCount = pieces[2]; // Not used
QString geometryType = pieces[3];
QgsLayerItem::LayerType layerType;
layerType = layerTypeFromDb( geometryType );
// example URI for mixed-geoms geoms: '/path/gdal_sample_v1.2_no_extensions.gpkg|layerid=7|geometrytype=Point'
// example URI for mixed-geoms attr table: '/path/gdal_sample_v1.2_no_extensions.gpkg|layername=MyLayer|layerid=7'
// example URI for single geoms: '/path/gdal_sample_v1.2_no_extensions.gpkg|layerid=6'
QString uri;
// Check if it's a mixed geometry type
if ( i == 0 && values.size() > 1 )
{
uri = QStringLiteral( "%1|layerid=%2|layername=%3" ).arg( mPath, layerId, name );
children.append( new QgsGeoPackageLayerInfo( mPath, uri, name, QgsLayerItem::LayerType::TableLayer ) );
}
if ( layerType != QgsLayerItem::LayerType::NoType )
{
if ( geometryType.contains( QStringLiteral( "Collection" ), Qt::CaseInsensitive ) )
{
QgsDebugMsgLevel( QStringLiteral( "Layer %1 is a geometry collection: skipping %2" ).arg( name, mPath ), 3 );
}
else
{
if ( values.size() > 1 )
{
uri = QStringLiteral( "%1|layerid=%2|geometrytype=%3" ).arg( mPath, layerId, geometryType );
}
else
{
uri = QStringLiteral( "%1|layerid=%2" ).arg( mPath, layerId );
}
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Vector item %1 %2 %3" ).arg( name, uri, geometryType ), 3 );
children.append( new QgsGeoPackageLayerInfo( mPath, uri, name, layerType ) );
}
}
else
{
QgsDebugMsgLevel( QStringLiteral( "Layer type is not a supported GeoPackage Vector layer %1" ).arg( mPath ), 3 );
}
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Vector item %1 %2 %3" ).arg( name, uri, geometryType ), 3 );
}
}
}
// Raster layers
QgsRasterLayer rlayer( mPath, QStringLiteral( "gdal_tmp" ), QStringLiteral( "gdal" ), false );
if ( rlayer.dataProvider()->subLayers( ).size() > 0 )
{
Q_FOREACH ( const QString &uri, rlayer.dataProvider()->subLayers( ) )
{
QStringList pieces = uri.split( ':' );
QString name = pieces.value( pieces.length() - 1 );
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2 %3" ).arg( name, uri ), 3 );
children.append( new QgsGeoPackageLayerInfo( mPath, uri, name, QgsLayerItem::LayerType::Raster ) );
}
}
else if ( rlayer.isValid( ) )
{
// Get the identifier
GDALAllRegister();
// do not print errors, but write to debug
CPLPushErrorHandler( CPLQuietErrorHandler );
CPLErrorReset();
GDALDatasetH hDS = GDALOpen( mPath.toUtf8().constData(), GA_ReadOnly );
CPLPopErrorHandler();

if ( ! hDS )
{
QgsDebugMsg( QString( "GDALOpen error # %1 : %2 " ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );

}
else
{
QString uri( QStringLiteral( "GPKG:%1" ).arg( mPath ) );
QString name = GDALGetMetadataItem( hDS, "IDENTIFIER", NULL );
GDALClose( hDS );
// Fallback: will not be able to delete the table
if ( name.isEmpty() )
{
name = QFileInfo( mPath ).fileName();
}
else
{
uri += QStringLiteral( ":%1" ).arg( name );
}

QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2 %3" ).arg( name, mPath ), 3 );
children.append( new QgsGeoPackageLayerInfo( mPath, uri, name, QgsLayerItem::LayerType::Raster ) );
}
}
return children;
}

QVector<QgsDataItem *> QgsGeoPackageConnectionItem::createChildren()
{
QVector<QgsDataItem *> children;
QList<QgsGeoPackageLayerInfo *> layers = subLayers( mPath );
for ( const QgsGeoPackageLayerInfo *info : qgsAsConst( layers ) )
QList<QgsOgrDbLayerInfo *> layers = QgsOgrLayerItem::subLayers( mPath, QStringLiteral( "GPKG" ) );
for ( const QgsOgrDbLayerInfo *info : qgsAsConst( layers ) )
{
if ( info->type() == QgsLayerItem::LayerType::Raster )
if ( info->layerType() == QgsLayerItem::LayerType::Raster )
{
children.append( new QgsGeoPackageRasterLayerItem( this, info->name(), info->path(), info->uri() ) );
}
else
{
children.append( new QgsGeoPackageVectorLayerItem( this, info->name(), info->path(), info->uri(), info->type( ) ) );
children.append( new QgsGeoPackageVectorLayerItem( this, info->name(), info->path(), info->uri(), info->layerType( ) ) );
}
}
qDeleteAll( layers );
@@ -479,32 +334,6 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct
}


QgsLayerItem::LayerType QgsGeoPackageConnectionItem::layerTypeFromDb( const QString &geometryType )
{
if ( geometryType.contains( QStringLiteral( "Point" ), Qt::CaseInsensitive ) )
{
return QgsLayerItem::LayerType::Point;
}
else if ( geometryType.contains( QStringLiteral( "Polygon" ), Qt::CaseInsensitive ) )
{
return QgsLayerItem::LayerType::Polygon;
}
else if ( geometryType.contains( QStringLiteral( "LineString" ), Qt::CaseInsensitive ) )
{
return QgsLayerItem::LayerType::Line;
}
else if ( geometryType.contains( QStringLiteral( "Collection" ), Qt::CaseInsensitive ) )
{
return QgsLayerItem::LayerType::Vector;
}
// To be moved in a parent class that would also work for gdal and rasters
else if ( geometryType.contains( QStringLiteral( "Raster" ), Qt::CaseInsensitive ) )
{
return QgsLayerItem::LayerType::Raster;
}
return QgsLayerItem::LayerType::TableLayer;
}

bool QgsGeoPackageConnectionItem::deleteGeoPackageRasterLayer( const QString uri, QString &errCause )
{
bool result = false;
@@ -625,7 +454,7 @@ bool QgsGeoPackageConnectionItem::deleteGeoPackageRasterLayer( const QString uri

void QgsGeoPackageConnectionItem::deleteConnection()
{
QgsGeoPackageConnection::deleteConnection( name() );
QgsOgrDbConnection::deleteConnection( name(), QStringLiteral( "GeoPackage" ) );
mParent->refreshConnections();
}

@@ -635,7 +464,7 @@ void QgsGeoPackageConnectionItem::addTable()
QgsNewGeoPackageLayerDialog dialog( nullptr );
QFileInfo fileInfo( mPath );
QString connName = fileInfo.fileName();
QgsGeoPackageConnection connection( connName );
QgsOgrDbConnection connection( connName, QStringLiteral( "GeoPackage" ) );
if ( ! connection.path().isEmpty() )
{
dialog.setDatabasePath( connection.path() );
@@ -20,30 +20,6 @@
#include "qgsdataprovider.h"


/**
* Holds the information about a gpkg layer
*/
class QgsGeoPackageLayerInfo
{
public:
QgsGeoPackageLayerInfo( const QString &path, const QString &uri, const QString &name, const QgsLayerItem::LayerType &type )
: mPath( path )
, mUri( uri )
, mName( name )
, mType( type )
{
}
const QString path() const { return mPath; }
const QString uri() const { return mUri; }
const QString name() const { return mName; }
QgsLayerItem::LayerType type() const { return mType; }
private:
QString mPath;
QString mUri;
QString mName;
QgsLayerItem::LayerType mType = QgsLayerItem::LayerType::NoType;
};

/**
* \brief The QgsGeoPackageAbstractLayerItem class is the base class for GeoPackage raster and vector layers
*/
@@ -94,8 +70,6 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem

public:
QgsGeoPackageConnectionItem( QgsDataItem *parent, QString name, QString path );
//! Extract layers information from the geopackage
QList<QgsGeoPackageLayerInfo *> subLayers( const QString &path ) const;
QVector<QgsDataItem *> createChildren() override;
virtual bool equal( const QgsDataItem *other ) override;

@@ -142,10 +116,6 @@ class QgsGeoPackageRootItem : public QgsDataCollectionItem
void connectionsChanged();
void createDatabase();
#endif

private:
bool storeConnection( const QString &path );

};


0 comments on commit 6e34681

Please sign in to comment.
You can’t perform that action at this time.