Skip to content
Permalink
Browse files

Add geom col capabilities and create spatial index

  • Loading branch information
elpaso committed Jul 16, 2020
1 parent f4ccbf2 commit 1ac91c1f2ecee7de300d194d7aa749a7ae8c08a4
@@ -4,3 +4,6 @@
QgsAbstractDatabaseProviderConnection.Capability.baseClass = QgsAbstractDatabaseProviderConnection
QgsAbstractDatabaseProviderConnection.Capabilities.baseClass = QgsAbstractDatabaseProviderConnection
Capabilities = QgsAbstractDatabaseProviderConnection # dirty hack since SIP seems to introduce the flags in module
QgsAbstractDatabaseProviderConnection.GeometryColumnCapability.baseClass = QgsAbstractDatabaseProviderConnection
QgsAbstractDatabaseProviderConnection.GeometryColumnCapabilities.baseClass = QgsAbstractDatabaseProviderConnection
GeometryColumnCapabilities = QgsAbstractDatabaseProviderConnection # dirty hack since SIP seems to introduce the flags in module
@@ -238,10 +238,20 @@ This information is calculated from the geometry columns types.
DeleteFieldCascade,
AddField,
};

typedef QFlags<QgsAbstractDatabaseProviderConnection::Capability> Capabilities;


enum GeometryColumnCapability
{
Z,
M,
SinglePart,
Curves
};

typedef QFlags<QgsAbstractDatabaseProviderConnection::GeometryColumnCapability> GeometryColumnCapabilities;


QgsAbstractDatabaseProviderConnection( const QString &name );
%Docstring
Creates a new connection with ``name`` by reading its configuration from the settings.
@@ -263,6 +273,13 @@ The connection is not automatically stored in the settings.
Returns connection capabilities
%End

virtual GeometryColumnCapabilities geometryColumnCapabilities();
%Docstring
Returns connection geomerty column capabilities (Z, M, SinglePart, Curves)

.. versionadded:: 3.16
%End


virtual QString tableUri( const QString &schema, const QString &name ) const throw( QgsProviderConnectionException );
%Docstring
@@ -92,6 +92,12 @@ Returns the geometry type
void setFields( const QgsFields &fields );
%Docstring
Sets the fields to ``fields``
%End

bool createSpatialIndex();
%Docstring
Returns ``True`` if spatialindex checkbox is cheched
@return
%End

QStringList validationErrors() const;
@@ -877,6 +877,7 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *
const QString schemaName { dlg.schemaName() };
const QString geometryColumn { dlg.geometryColumnName() };
const QgsWkbTypes::Type geometryType { dlg.geometryType() };
const bool createSpatialIndex { dlg.createSpatialIndex() };
const QgsCoordinateReferenceSystem crs { dlg.crs( ) };
// This flag tells to the provider that field types do not need conversion
QMap<QString, QVariant> options { { QStringLiteral( "skipConvertFields" ), true } };
@@ -892,6 +893,10 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *
try
{
conn2->createVectorTable( schemaName, tableName, fields, geometryType, crs, true, &options );
if ( createSpatialIndex && conn2->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) )
{
conn2->createSpatialIndex( schemaName, tableName );
}
// Ok, here is the trick: we cannot refresh the connection item because the refresh is not
// recursive.
// So, we check if the item is a schema or not, if it's not it means we initiated the new table from
@@ -324,6 +324,13 @@ void QgsGeoPackageProviderConnection::setDefaultCapabilities()
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,4,0)
mCapabilities |= Capability::DropRasterTable;
#endif
mGeometryColumnCapabilities =
{
GeometryColumnCapability::Z,
GeometryColumnCapability::M,
GeometryColumnCapability::SinglePart,
GeometryColumnCapability::Curves
};
}

QList<QVariantList> QgsGeoPackageProviderConnection::executeGdalSqlPrivate( const QString &sql ) const
@@ -36,6 +36,11 @@ QgsAbstractDatabaseProviderConnection::Capabilities QgsAbstractDatabaseProviderC
return mCapabilities;
}

QgsAbstractDatabaseProviderConnection::GeometryColumnCapabilities QgsAbstractDatabaseProviderConnection::geometryColumnCapabilities()
{
return mGeometryColumnCapabilities;
}

QString QgsAbstractDatabaseProviderConnection::tableUri( const QString &schema, const QString &name ) const
{
Q_UNUSED( schema )
@@ -272,7 +272,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
};

/**
* The Capability enum represent the operations supported by the connection
* The Capability enum represents the operations supported by the connection
*/
enum Capability
{
@@ -298,11 +298,26 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
DeleteFieldCascade = 1 << 20, //!< Can delete an existing field/column with cascade
AddField = 1 << 21, //!< Can add a new field/column
};

Q_ENUM( Capability )
Q_DECLARE_FLAGS( Capabilities, Capability )
Q_FLAG( Capabilities )

/**
* The GeometryColumnCapability enum represents the geomery column features supported by the connection
* \since QGIS 3.16
*/
enum GeometryColumnCapability
{
Z = 1 << 1, //! Supports Z dimension
M = 1 << 2, //! Supports M dimension
SinglePart = 1 << 3, //! Multi and single part types are distinct types
Curves = 1 << 4 //! Supports curves
};

Q_ENUM( GeometryColumnCapability )
Q_DECLARE_FLAGS( GeometryColumnCapabilities, GeometryColumnCapability )
Q_FLAG( GeometryColumnCapabilities )

/**
* Creates a new connection with \a name by reading its configuration from the settings.
* If a connection with this name cannot be found, an empty connection will be returned.
@@ -324,6 +339,12 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
Capabilities capabilities() const;

/**
* Returns connection geomerty column capabilities (Z, M, SinglePart, Curves)
* \since QGIS 3.16
*/
virtual GeometryColumnCapabilities geometryColumnCapabilities();

// Operations interface

/**
@@ -561,6 +582,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
///@endcond

Capabilities mCapabilities = nullptr SIP_SKIP;
GeometryColumnCapabilities mGeometryColumnCapabilities = nullptr SIP_SKIP;
QString mProviderKey;

};
@@ -92,6 +92,13 @@ QgsNewVectorTableDialog::QgsNewVectorTableDialog( QgsAbstractDatabaseProviderCon
mSchemaLabel->hide();
}

if ( ! mConnection->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) )
{
mSpatialIndexChk->setChecked( false );
mSpatialIndexChk->hide();
mSpatialIndexLabel->hide();
}

// Initial load of table names
updateTableNames( mSchemaCbo->currentText() );

@@ -122,17 +129,48 @@ QgsNewVectorTableDialog::QgsNewVectorTableDialog( QgsAbstractDatabaseProviderCon
validate();
} );

// Hardcode geometry types
// TODO: this information should really come from the connection through the provider but there is no API for that yet
// geometry types
const bool hasSinglePart { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::SinglePart ) };
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconTableLayer.svg" ) ), tr( "No Geometry" ), QString() );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Type::Point );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "Line" ), QgsWkbTypes::Type::LineString );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "Polygon" ), QgsWkbTypes::Type::Polygon );
if ( hasSinglePart )
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPointLayer.svg" ) ), tr( "Point" ), QgsWkbTypes::Type::Point );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPointLayer.svg" ) ), tr( "MultiPoint" ), QgsWkbTypes::Type::MultiPoint );
if ( hasSinglePart )
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "Line" ), QgsWkbTypes::Type::LineString );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "MultiLine" ), QgsWkbTypes::Type::MultiLineString );
if ( hasSinglePart )
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "Polygon" ), QgsWkbTypes::Type::Polygon );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "MultiPolygon" ), QgsWkbTypes::Type::MultiPolygon );

if ( conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::Curves ) )
{
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "CompoundCurve" ), QgsWkbTypes::Type::CompoundCurve );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "CurvePolygon" ), QgsWkbTypes::Type::CurvePolygon );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconLineLayer.svg" ) ), tr( "MultiCurve" ), QgsWkbTypes::Type::MultiCurve );
mGeomTypeCbo->addItem( QgsApplication::getThemeIcon( QStringLiteral( "mIconPolygonLayer.svg" ) ), tr( "MultiSurface" ), QgsWkbTypes::Type::MultiSurface );
}

mGeomTypeCbo->setCurrentIndex( 0 );

const bool hasZ { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::Z ) };
const bool hasM { conn->geometryColumnCapabilities().testFlag( QgsAbstractDatabaseProviderConnection::GeometryColumnCapability::M ) };
if ( ! hasM )
{
mHasMChk->setEnabled( false );
mHasMChk->setChecked( false );
}
if ( ! hasZ )
{
mHasZChk->setEnabled( false );
mHasZChk->setChecked( false );
}
if ( ! hasM && ! hasM )
{
mHasZChk->setVisible( false );
mHasMChk->setVisible( false );
mDimensionsLabel->setVisible( false );
}

connect( mFieldsTableView->selectionModel(), &QItemSelectionModel::selectionChanged, mFieldsTableView, [ = ]( const QItemSelection & selected, const QItemSelection & )
{
if ( ! selected.isEmpty() )
@@ -284,6 +322,11 @@ void QgsNewVectorTableDialog::setFields( const QgsFields &fields )
}
}

bool QgsNewVectorTableDialog::createSpatialIndex()
{
return mSpatialIndexChk->isChecked();
}

QStringList QgsNewVectorTableDialog::validationErrors() const
{
return mValidationErrors;
@@ -110,6 +110,12 @@ class GUI_EXPORT QgsNewVectorTableDialog : public QDialog, private Ui_QgsNewVect
*/
void setFields( const QgsFields &fields );

/**
* Returns TRUE if spatialindex checkbox is cheched
* @return
*/
bool createSpatialIndex();

/**
* Returns the validation errors or an empty list if the dialog is valid
*/
@@ -88,6 +88,12 @@ void QgsMssqlProviderConnection::setDefaultCapabilities()
Capability::DeleteFieldCascade,
Capability::AddField
};
mGeometryColumnCapabilities =
{
GeometryColumnCapability::Z,
GeometryColumnCapability::M,
GeometryColumnCapability::Curves
};
}

void QgsMssqlProviderConnection::dropTablePrivate( const QString &schema, const QString &name ) const
@@ -72,6 +72,13 @@ void QgsPostgresProviderConnection::setDefaultCapabilities()
Capability::DeleteFieldCascade,
Capability::AddField
};
mGeometryColumnCapabilities =
{
GeometryColumnCapability::Z,
GeometryColumnCapability::M,
GeometryColumnCapability::SinglePart,
GeometryColumnCapability::Curves
};
}

void QgsPostgresProviderConnection::dropTablePrivate( const QString &schema, const QString &name ) const
@@ -365,6 +365,12 @@ void QgsSpatiaLiteProviderConnection::setDefaultCapabilities()
Capability::DeleteField,
Capability::AddField
};
mGeometryColumnCapabilities =
{
GeometryColumnCapability::Z,
GeometryColumnCapability::M,
GeometryColumnCapability::SinglePart,
};
}

QList<QVariantList> QgsSpatiaLiteProviderConnection::executeSqlPrivate( const QString &sql ) const
@@ -79,7 +79,7 @@ def test_dialog(self):
self.assertFalse(has_m_chk.isEnabled())

# 2 is linestring
geom_type_combo.setCurrentIndex(2)
geom_type_combo.setCurrentIndex(3)
self.assertTrue(geom_name_le.isEnabled())
self.assertTrue(has_z_chk.isEnabled())
self.assertTrue(has_m_chk.isEnabled())

0 comments on commit 1ac91c1

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