Skip to content

Commit

Permalink
Expose columns to browser for PG, SL, GPKG and MSSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Jul 8, 2020
1 parent f00d209 commit 9125690
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 37 deletions.
13 changes: 8 additions & 5 deletions python/core/auto_generated/qgsdataitem.sip.in
Expand Up @@ -905,7 +905,7 @@ Creates a new data item from the specified path.
class QgsFieldsItem : QgsDataItem
{
%Docstring
A collection of fields item
A collection of field items

.. versionadded:: 3.16
%End
Expand All @@ -918,18 +918,21 @@ A collection of fields item
QgsFieldsItem( QgsDataItem *parent /TransferThis/,
const QString &name,
const QString &path,
const QString &connectionUri,
const QString &providerKey,
const QString schema,
const QString tableName );
const QString &schema,
const QString &tableName );
%Docstring
Constructor for QgsFieldsItem, with the specified ``parent`` item.

The ``path`` argument gives the item path in the browser tree. The ``path`` string can take any form,
but QgsDataItem items pointing to different logical locations should always use a different item ``path``.

The ``providerKey`` string (added in QGIS 3.12) can be used to specify the key for the QgsDataItemProvider that created this item.
The \connectionUri argument is the connection part of the layer URI that it is used internally to create
a connection and retrieve fields information.
The ``providerKey`` string can be used to specify the key for the QgsDataItemProvider that created this item.
The ``name`` argument specifies the text to show in the model for the item. A translated string should
be used wherever appropriate.
The ``schema`` and ``tableName`` are used to retrieve the field information from the ``connectionUri``.
%End

~QgsFieldsItem();
Expand Down
2 changes: 1 addition & 1 deletion src/core/providers/ogr/qgsgeopackagedataitems.cpp
Expand Up @@ -323,7 +323,7 @@ QgsGeoPackageVectorLayerItem::QgsGeoPackageVectorLayerItem( QgsDataItem *parent,
QVector<QgsDataItem *> QgsGeoPackageVectorLayerItem::createChildren()
{
QVector<QgsDataItem *> children;
children.push_back( new QgsFieldsItem( this, tr( "Columns" ), uri() + QStringLiteral( "/columns/ " ), providerKey(), QString(), name() ) );
children.push_back( new QgsFieldsItem( this, tr( "Columns" ), collection()->path() + QStringLiteral( "/columns/ " ), collection()->path(), providerKey(), QString(), name() ) );
return children;
}

Expand Down
40 changes: 32 additions & 8 deletions src/core/providers/ogr/qgsogrdataitems.cpp
Expand Up @@ -44,12 +44,36 @@
#include <gdal.h>

QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent,
const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer )
const QString &name,
const QString &path,
const QString &uri,
LayerType layerType,
const QString &driverName,
bool isSubLayer )
: QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "ogr" ) )
, mDriverName( driverName )
, mIsSubLayer( isSubLayer )
{
mIsSubLayer = isSubLayer;
mToolTip = uri;
setState( Populated ); // children are not expected
const bool isIndex { QRegularExpression( R"(=idx_[^_]+_[^_]+.*$)" ).match( uri ).hasMatch() };
setState( ( driverName == QStringLiteral( "SQLite" ) && ! isIndex ) ? NotPopulated : Populated ); // children are not expected except for sqlite
}


QVector<QgsDataItem *> QgsOgrLayerItem::createChildren()
{
QVector<QgsDataItem *> children;
// Geopackage is handled by QgsGeoPackageVectorLayerItem and QgsGeoPackageRasterLayerItem
// Proxy to spatialite provider data items because it implements the connections API
if ( mDriverName == QStringLiteral( "SQLite" ) )
{
children.push_back( new QgsFieldsItem( this, tr( "Columns" ),
path() + QStringLiteral( "/columns/ " ),
QStringLiteral( R"(dbname="%1")" ).arg( parent()->path().replace( '"', QStringLiteral( R"(\")" ) ) ),
QStringLiteral( "spatialite" ), QString(), name() ) );
}
return children;
}


Expand Down Expand Up @@ -171,14 +195,14 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
uri += QStringLiteral( "|geometrytype=" ) + geometryType;
}
QgsDebugMsgLevel( QStringLiteral( "Adding %1 Vector item %2 %3 %4" ).arg( driver, name, uri, geometryType ), 3 );
children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, layerType ) );
children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, layerType, driver ) );
}
}
else
{
QgsDebugMsgLevel( QStringLiteral( "Layer type is not a supported %1 Vector layer %2" ).arg( driver, path ), 3 );
uri = QStringLiteral( "%1|layerid=%2|layername=%3" ).arg( path, layerId, name );
children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, QgsLayerItem::LayerType::TableLayer ) );
children.append( new QgsOgrDbLayerInfo( path, uri, name, geometryColumn, geometryType, QgsLayerItem::LayerType::TableLayer, driver ) );
}
QgsDebugMsgLevel( QStringLiteral( "Adding %1 Vector item %2 %3 %4" ).arg( driver, name, uri, geometryType ), 3 );
}
Expand All @@ -198,7 +222,7 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
QStringList pieces = uri.split( ':' );
QString name = pieces.value( pieces.length() - 1 );
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2" ).arg( name, uri ), 3 );
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster, driver ) );
}
}
else if ( rlayer.isValid( ) )
Expand Down Expand Up @@ -232,7 +256,7 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
}

QgsDebugMsgLevel( QStringLiteral( "Adding %1 Raster item %2 %3" ).arg( driver, name, path ), 3 );
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster, driver ) );
}
}

Expand Down Expand Up @@ -321,7 +345,7 @@ static QgsOgrLayerItem *dataItemForLayer( QgsDataItem *parentItem, QString name,

QgsDebugMsgLevel( "OGR layer uri : " + layerUri, 2 );

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

// ----
Expand All @@ -342,7 +366,7 @@ QVector<QgsDataItem *> QgsOgrDataCollectionItem::createChildren()
CSLDestroy( papszOptions );

GDALDriverH hDriver = GDALGetDatasetDriver( hDataSource.get() );
QString driverName = QString::fromUtf8( GDALGetDriverShortName( hDriver ) );
const QString driverName = QString::fromUtf8( GDALGetDriverShortName( hDriver ) );
if ( driverName == QStringLiteral( "SQLite" ) )
{
skippedLayerNames = QgsSqliteUtils::systemTables();
Expand Down
19 changes: 17 additions & 2 deletions src/core/providers/ogr/qgsogrdataitems.h
Expand Up @@ -30,13 +30,20 @@
class CORE_EXPORT QgsOgrDbLayerInfo
{
public:
QgsOgrDbLayerInfo( const QString &path, const QString &uri, const QString &name, const QString &theGeometryColumn, const QString &theGeometryType, const QgsLayerItem::LayerType &theLayerType )
QgsOgrDbLayerInfo( const QString &path,
const QString &uri,
const QString &name,
const QString &theGeometryColumn,
const QString &theGeometryType,
const QgsLayerItem::LayerType &theLayerType,
const QString &driverName )
: mPath( path )
, mUri( uri )
, mName( name )
, mGeometryColumn( theGeometryColumn )
, mGeometryType( theGeometryType )
, mLayerType( theLayerType )
, mDriverName( driverName )
{
}
const QString path() const { return mPath; }
Expand All @@ -53,6 +60,7 @@ class CORE_EXPORT QgsOgrDbLayerInfo
QString mGeometryColumn;
QString mGeometryType;
QgsLayerItem::LayerType mLayerType = QgsLayerItem::LayerType::NoType;
QString mDriverName;
};

/**
Expand All @@ -74,7 +82,7 @@ class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem
{
Q_OBJECT
public:
QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer = false );
QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &driverName = QString(), bool isSubLayer = false );

QString layerName() const override;

Expand All @@ -87,11 +95,18 @@ class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
bool isSubLayer() const;

QVector<QgsDataItem *> createChildren() override;

private:
QString mDriverName;
bool mIsSubLayer;


};




class CORE_EXPORT QgsOgrDataCollectionItem final: public QgsDataCollectionItem
{
Q_OBJECT
Expand Down
8 changes: 5 additions & 3 deletions src/core/qgsdataitem.cpp
Expand Up @@ -115,12 +115,14 @@ QIcon QgsDataCollectionItem::iconDir()
QgsFieldsItem::QgsFieldsItem( QgsDataItem *parent,
const QString &name,
const QString &path,
const QString &connectionUri,
const QString &providerKey,
const QString schema,
const QString tableName )
const QString &schema,
const QString &tableName )
: QgsDataItem( QgsDataItem::Fields, parent, name, path, providerKey )
, mSchema( schema )
, mTableName( tableName )
, mConnectionUri( connectionUri )
{
mCapabilities |= ( Fertile | Collapse );
}
Expand All @@ -138,7 +140,7 @@ QVector<QgsDataItem *> QgsFieldsItem::createChildren()
QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey() ) };
if ( md )
{
QgsAbstractDatabaseProviderConnection *conn { static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( parent()->path( ), {} ) ) };
std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn { static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( mConnectionUri, {} ) ) };
if ( conn )
{
const QgsFields constFields { conn->fields( mSchema, mTableName ) };
Expand Down
15 changes: 10 additions & 5 deletions src/core/qgsdataitem.h
Expand Up @@ -899,7 +899,7 @@ class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem

/**
* \ingroup core
* A collection of fields item
* A collection of field items
* \since QGIS 3.16
*/
class CORE_EXPORT QgsFieldsItem : public QgsDataItem
Expand All @@ -912,17 +912,21 @@ class CORE_EXPORT QgsFieldsItem : public QgsDataItem
*
* The \a path argument gives the item path in the browser tree. The \a path string can take any form,
* but QgsDataItem items pointing to different logical locations should always use a different item \a path.
*
* The \a providerKey string (added in QGIS 3.12) can be used to specify the key for the QgsDataItemProvider that created this item.
* The \connectionUri argument is the connection part of the layer URI that it is used internally to create
* a connection and retrieve fields information.
* The \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
* The \a name argument specifies the text to show in the model for the item. A translated string should
* be used wherever appropriate.
* The \a schema and \a tableName are used to retrieve the field information from the \a connectionUri.
*
*/
QgsFieldsItem( QgsDataItem *parent SIP_TRANSFERTHIS,
const QString &name,
const QString &path,
const QString &connectionUri,
const QString &providerKey,
const QString schema,
const QString tableName );
const QString &schema,
const QString &tableName );

~QgsFieldsItem() override;

Expand All @@ -946,6 +950,7 @@ class CORE_EXPORT QgsFieldsItem : public QgsDataItem

QString mSchema;
QString mTableName;
QString mConnectionUri;
};


Expand Down
13 changes: 10 additions & 3 deletions src/providers/mssql/qgsmssqldataitems.cpp
Expand Up @@ -289,7 +289,7 @@ QVector<QgsDataItem *> QgsMssqlConnectionItem::createChildren()
//set all as populated -- we also need to do this for newly created items, because they won't yet be children of this item
for ( QgsDataItem *child : qgis::as_const( children ) )
{
child->setState( Populated );
//child->setState( Populated );
}
setAsPopulated();
}
Expand Down Expand Up @@ -481,7 +481,7 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
{
mCapabilities |= Delete;
mUri = createUri();
setState( Populated );
setState( NotPopulated );
}


Expand Down Expand Up @@ -597,6 +597,14 @@ QgsMssqlLayerItem *QgsMssqlSchemaItem::addLayer( const QgsMssqlLayerProperty &la
return layerItem;
}


QVector<QgsDataItem *> QgsMssqlLayerItem::createChildren()
{
QVector<QgsDataItem *> children;
children.push_back( new QgsFieldsItem( this, tr( "Columns" ), uri() + QStringLiteral( "/columns/ " ), createUri(), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) );
return children;
}

// ---------------------------------------------------------------------------
QgsMssqlRootItem::QgsMssqlRootItem( QgsDataItem *parent, const QString &name, const QString &path )
: QgsDataCollectionItem( parent, name, path, QStringLiteral( "MSSQL" ) )
Expand Down Expand Up @@ -658,4 +666,3 @@ bool QgsMssqlSchemaItem::layerCollection() const
{
return true;
}

6 changes: 5 additions & 1 deletion src/providers/mssql/qgsmssqldataitems.h
Expand Up @@ -108,7 +108,6 @@ class QgsMssqlSchemaItem : public QgsDataCollectionItem
void refresh() override {} // do not refresh directly
void addLayers( QgsDataItem *newLayers );

// QgsDataItem interface
public:
bool layerCollection() const override;
};
Expand All @@ -128,11 +127,16 @@ class QgsMssqlLayerItem : public QgsLayerItem

const QgsMssqlLayerProperty &layerInfo() const { return mLayerProperty; }

QVector<QgsDataItem *> createChildren() override;

private:
QgsMssqlLayerProperty mLayerProperty;
bool mDisableInvalidGeometryHandling = false;

};



//! Provider for GDAL root data item
class QgsMssqlDataItemProvider : public QgsDataItemProvider
{
Expand Down
16 changes: 8 additions & 8 deletions src/providers/postgres/qgspostgresdataitems.cpp
Expand Up @@ -316,7 +316,8 @@ QgsPGLayerItem::QgsPGLayerItem( QgsDataItem *parent, const QString &name, const
{
mCapabilities |= Delete | Fertile;
mUri = createUri();
setState( NotPopulated );
// No rasters for now
setState( layerProperty.isRaster ? Populated : NotPopulated );
Q_ASSERT( mLayerProperty.size() == 1 );
}

Expand Down Expand Up @@ -523,6 +524,12 @@ QgsPGLayerItem *QgsPGSchemaItem::createLayer( QgsPostgresLayerProperty layerProp
return layerItem;
}

QVector<QgsDataItem *> QgsPGLayerItem::createChildren()
{
QVector<QgsDataItem *> children;
children.push_back( new QgsFieldsItem( this, tr( "Columns" ), uri() + QStringLiteral( "/columns/ " ), createUri(), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) );
return children;
}

// ---------------------------------------------------------------------------
QgsPGRootItem::QgsPGRootItem( QgsDataItem *parent, const QString &name, const QString &path )
Expand Down Expand Up @@ -576,10 +583,3 @@ bool QgsPGSchemaItem::layerCollection() const
{
return true;
}

QVector<QgsDataItem *> QgsPGLayerItem::createChildren()
{
QVector<QgsDataItem *> children;
children.push_back( new QgsFieldsItem( this, tr( "Columns" ), uri() + QStringLiteral( "/columns/ " ), providerKey(), mLayerProperty.schemaName, mLayerProperty.tableName ) );
return children;
}
Expand Up @@ -330,7 +330,7 @@ QList<QgsSpatiaLiteProviderConnection::TableProperty> QgsSpatiaLiteProviderConne

if ( ! errCause.isEmpty() )
{
throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: %2" ).arg( pathFromUri() ).arg( errCause ) );
throw QgsProviderConnectionException( QObject::tr( "Error listing tables from %1: %2" ).arg( pathFromUri(), errCause ) );
}
// Filters
if ( flags )
Expand Down

0 comments on commit 9125690

Please sign in to comment.