Skip to content
Permalink
Browse files

Expose columns to browser for PG, SL, GPKG and MSSQL

  • Loading branch information
elpaso committed Jul 8, 2020
1 parent f00d209 commit 9125690340169bcebd3bad5798623d716e8aec44
@@ -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
@@ -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();
@@ -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;
}

@@ -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;
}


@@ -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 );
}
@@ -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( ) )
@@ -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 ) );
}
}

@@ -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 );
}

// ----
@@ -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();
@@ -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; }
@@ -53,6 +60,7 @@ class CORE_EXPORT QgsOgrDbLayerInfo
QString mGeometryColumn;
QString mGeometryType;
QgsLayerItem::LayerType mLayerType = QgsLayerItem::LayerType::NoType;
QString mDriverName;
};

/**
@@ -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;

@@ -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
@@ -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 );
}
@@ -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 ) };
@@ -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
@@ -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;

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

QString mSchema;
QString mTableName;
QString mConnectionUri;
};


@@ -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();
}
@@ -481,7 +481,7 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
{
mCapabilities |= Delete;
mUri = createUri();
setState( Populated );
setState( NotPopulated );
}


@@ -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" ) )
@@ -658,4 +666,3 @@ bool QgsMssqlSchemaItem::layerCollection() const
{
return true;
}

@@ -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;
};
@@ -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
{
@@ -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 );
}

@@ -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 )
@@ -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;
}
@@ -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 )

0 comments on commit 9125690

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