File browser: use GeoPackage items for gpkg files

This commit is contained in:
Alessandro Pasotti 2017-09-15 19:12:45 +02:00
parent 9f1f3ead1e
commit ab74ecc3ad
3 changed files with 117 additions and 27 deletions

View File

@ -120,7 +120,7 @@ void QgsGeoPackageRootItem::createDatabase()
#endif
QgsGeoPackageConnectionItem::QgsGeoPackageConnectionItem( QgsDataItem *parent, const QString &name, const QString &path )
QgsGeoPackageCollectionItem::QgsGeoPackageCollectionItem( QgsDataItem *parent, const QString &name, const QString &path )
: QgsDataCollectionItem( parent, name, path )
, mPath( path )
{
@ -129,7 +129,7 @@ QgsGeoPackageConnectionItem::QgsGeoPackageConnectionItem( QgsDataItem *parent, c
QVector<QgsDataItem *> QgsGeoPackageConnectionItem::createChildren()
QVector<QgsDataItem *> QgsGeoPackageCollectionItem::createChildren()
{
QVector<QgsDataItem *> children;
const auto layers = QgsOgrLayerItem::subLayers( mPath, QStringLiteral( "GPKG" ) );
@ -148,30 +148,31 @@ QVector<QgsDataItem *> QgsGeoPackageConnectionItem::createChildren()
return children;
}
bool QgsGeoPackageConnectionItem::equal( const QgsDataItem *other )
bool QgsGeoPackageCollectionItem::equal( const QgsDataItem *other )
{
if ( type() != other->type() )
{
return false;
}
const QgsGeoPackageConnectionItem *o = dynamic_cast<const QgsGeoPackageConnectionItem *>( other );
const QgsGeoPackageCollectionItem *o = dynamic_cast<const QgsGeoPackageCollectionItem *>( other );
return o && mPath == o->mPath && mName == o->mName;
}
#ifdef HAVE_GUI
QList<QAction *> QgsGeoPackageConnectionItem::actions()
QList<QAction *> QgsGeoPackageCollectionItem::actions()
{
QList<QAction *> lst;
QAction *actionDeleteConnection = new QAction( tr( "Remove connection" ), this );
connect( actionDeleteConnection, &QAction::triggered, this, &QgsGeoPackageConnectionItem::deleteConnection );
lst.append( actionDeleteConnection );
// Add to stored connections
QAction *actionAddConnection = new QAction( tr( "Add connection" ), this );
connect( actionAddConnection, &QAction::triggered, this, &QgsGeoPackageCollectionItem::addConnection );
lst.append( actionAddConnection );
// Add table to existing DB
QAction *actionAddTable = new QAction( tr( "Create a new layer or table..." ), this );
connect( actionAddTable, &QAction::triggered, this, &QgsGeoPackageConnectionItem::addTable );
connect( actionAddTable, &QAction::triggered, this, &QgsGeoPackageCollectionItem::addTable );
lst.append( actionAddTable );
return lst;
@ -180,7 +181,7 @@ QList<QAction *> QgsGeoPackageConnectionItem::actions()
bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
bool QgsGeoPackageCollectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
{
if ( !QgsMimeDataUtils::isUriList( data ) )
@ -327,7 +328,7 @@ bool QgsGeoPackageConnectionItem::handleDrop( const QMimeData *data, Qt::DropAct
}
bool QgsGeoPackageConnectionItem::deleteGeoPackageRasterLayer( const QString &uri, QString &errCause )
bool QgsGeoPackageCollectionItem::deleteGeoPackageRasterLayer( const QString &uri, QString &errCause )
{
bool result = false;
// Better safe than sorry
@ -444,6 +445,40 @@ bool QgsGeoPackageConnectionItem::deleteGeoPackageRasterLayer( const QString &ur
return result;
}
QgsGeoPackageConnectionItem::QgsGeoPackageConnectionItem( QgsDataItem *parent, const QString &name, const QString &path )
: QgsGeoPackageCollectionItem( parent, name, path )
{
}
bool QgsGeoPackageConnectionItem::equal( const QgsDataItem *other )
{
if ( type() != other->type() )
{
return false;
}
const QgsGeoPackageConnectionItem *o = dynamic_cast<const QgsGeoPackageConnectionItem *>( other );
return o && mPath == o->mPath && mName == o->mName;
}
#ifdef HAVE_GUI
QList<QAction *> QgsGeoPackageConnectionItem::actions()
{
QList<QAction *> lst;
QAction *actionDeleteConnection = new QAction( tr( "Remove connection" ), this );
connect( actionDeleteConnection, &QAction::triggered, this, &QgsGeoPackageConnectionItem::deleteConnection );
lst.append( actionDeleteConnection );
// Add table to existing DB
QAction *actionAddTable = new QAction( tr( "Create a new layer or table..." ), this );
connect( actionAddTable, &QAction::triggered, this, &QgsGeoPackageConnectionItem::addTable );
lst.append( actionAddTable );
return lst;
}
void QgsGeoPackageConnectionItem::deleteConnection()
{
@ -451,8 +486,8 @@ void QgsGeoPackageConnectionItem::deleteConnection()
mParent->refreshConnections();
}
#ifdef HAVE_GUI
void QgsGeoPackageConnectionItem::addTable()
void QgsGeoPackageCollectionItem::addTable()
{
QgsNewGeoPackageLayerDialog dialog( nullptr );
QFileInfo fileInfo( mPath );
@ -472,6 +507,14 @@ void QgsGeoPackageConnectionItem::addTable()
QgsDebugMsg( QStringLiteral( "Cannot add Table: connection %1 does not exists or the path is empy!" ).arg( connName ) );
}
}
void QgsGeoPackageCollectionItem::addConnection()
{
QgsOgrDbConnection connection( mName, QStringLiteral( "GeoPackage" ) );
connection.save();
emit connectionsChanged();
}
#endif
#ifdef HAVE_GUI
@ -554,7 +597,7 @@ QgsGeoPackageRasterLayerItem::QgsGeoPackageRasterLayerItem( QgsDataItem *parent,
bool QgsGeoPackageRasterLayerItem::executeDeleteLayer( QString &errCause )
{
return QgsGeoPackageConnectionItem::deleteGeoPackageRasterLayer( mUri, errCause );
return QgsGeoPackageCollectionItem::deleteGeoPackageRasterLayer( mUri, errCause );
}

View File

@ -64,12 +64,16 @@ class QgsGeoPackageVectorLayerItem : public QgsGeoPackageAbstractLayerItem
};
class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
/**
* \brief The QgsGeoPackageCollectionItem class is the base class for
* GeoPackage container
*/
class QgsGeoPackageCollectionItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsGeoPackageConnectionItem( QgsDataItem *parent, const QString &name, const QString &path );
QgsGeoPackageCollectionItem( QgsDataItem *parent, const QString &name, const QString &path );
QVector<QgsDataItem *> createChildren() override;
virtual bool equal( const QgsDataItem *other ) override;
@ -87,9 +91,8 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
public slots:
#ifdef HAVE_GUI
void editConnection();
void deleteConnection();
void addTable();
void addConnection();
#endif
protected:
@ -97,6 +100,31 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
};
/**
* \brief The QgsGeoPackageConnectionItem class adds the stored
* connection management to QgsGeoPackageCollectionItem
*/
class QgsGeoPackageConnectionItem : public QgsGeoPackageCollectionItem
{
Q_OBJECT
public:
QgsGeoPackageConnectionItem( QgsDataItem *parent, const QString &name, const QString &path );
virtual bool equal( const QgsDataItem *other ) override;
#ifdef HAVE_GUI
QList<QAction *> actions() override;
#endif
public slots:
#ifdef HAVE_GUI
void editConnection();
void deleteConnection();
#endif
};
class QgsGeoPackageRootItem : public QgsDataCollectionItem
{
Q_OBJECT

View File

@ -22,6 +22,7 @@
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsgeopackagedataitems.h"
#include <QFileInfo>
#include <QTextStream>
@ -567,9 +568,19 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
#endif
}
// return item without testing if:
// scanExtSetting
// or zipfile and scan zip == "Basic scan"
// Filters out the OGR/GDAL supported formats that can contain multiple layers
// and should be treated like a DB: GeoPackage and SQLite
// NOTE: this formats are scanned for rasters too and they must
// be skipped by "gdal" provider or the rasters will be listed
// twice. ogrSupportedDbLayersExtensions must be kept in sync
// with the companion variable (same name) in the gdal provider
// class
// TODO: add more OGR supported multiple layers formats here!
QStringList ogrSupportedDbLayersExtensions;
ogrSupportedDbLayersExtensions << QLatin1String( "gpkg" ) << QLatin1String( "sqlite" ) << QLatin1String( "db" );
// Fast track: return item without testing if:
// scanExtSetting or zipfile and scan zip == "Basic scan"
if ( scanExtSetting ||
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) )
{
@ -596,13 +607,18 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
// Handle collections
// Check if the layer has sublayers by comparing the extension
QgsDataItem *item;
QStringList multipleLayersExtensions;
// TODO: add more OGR supported multiple layers formats here!
multipleLayersExtensions << QLatin1String( "gpkg" ) << QLatin1String( "sqlite" ) << QLatin1String( "db" );
if ( ! multipleLayersExtensions.contains( suffix ) )
if ( ! ogrSupportedDbLayersExtensions.contains( suffix ) )
{
item = new QgsOgrLayerItem( parentItem, name, path, path, QgsLayerItem::Vector );
}
else if ( suffix.compare( QLatin1String( "gpkg" ), Qt::CaseInsensitive ) == 0 )
{
item = new QgsGeoPackageCollectionItem( parentItem, name, path );
}
else
{
item = new QgsOgrDataCollectionItem( parentItem, name, path );
}
if ( item )
return item;
@ -625,10 +641,9 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
QgsDebugMsgLevel( QString( "GDAL Driver : %1" ).arg( GDALGetDriverShortName( hDriver ) ), 2 );
int numLayers = GDALDatasetGetLayerCount( hDataSource );
QgsDataItem *item = nullptr;
int numLayers = OGR_DS_GetLayerCount( hDataSource );
if ( numLayers == 1 )
{
QgsDebugMsgLevel( QString( "using name = %1" ).arg( name ), 2 );
@ -639,6 +654,10 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
QgsDebugMsgLevel( QString( "using name = %1" ).arg( name ), 2 );
item = new QgsOgrDataCollectionItem( parentItem, name, path );
}
else if ( suffix.compare( QLatin1String( "gpkg" ), Qt::CaseInsensitive ) == 0 )
{
item = new QgsGeoPackageCollectionItem( parentItem, name, path );
}
GDALClose( hDataSource );
return item;