From 0236dbf8acfcf492f4aa57003078443c1084f433 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 27 Aug 2025 14:20:49 +0200 Subject: [PATCH 1/3] add create or delete spatial index to the manage menu --- .../browser/qgsinbuiltdataitemproviders.cpp | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/app/browser/qgsinbuiltdataitemproviders.cpp b/src/app/browser/qgsinbuiltdataitemproviders.cpp index dd3d3716ecb..8fa52c73042 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.cpp +++ b/src/app/browser/qgsinbuiltdataitemproviders.cpp @@ -1956,6 +1956,110 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * } } ); } + + if ( isTable && conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::DeleteSpatialIndex ) ) + { + QAction *createSpatialIndexAction = new QAction( tr( "Create Spatial Index" ), menu ); + QAction *deleteSpatialIndexAction = new QAction( tr( "Delete Spatial Index" ), menu ); + + QgsAbstractDatabaseProviderConnection::TableProperty tableProperty = conn->table( item->parent()->name(), item->name() ); + + bool indexExist = conn->spatialIndexExists( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); + + // this action should sit in the Manage menu. If one does not exist, create it now + bool foundExistingManageMenu = false; + QList actions = menu->actions(); + for ( QAction *action : std::as_const( actions ) ) + { + if ( action->text() == tr( "Manage" ) ) + { + if ( indexExist ) + { + action->menu()->addAction( deleteSpatialIndexAction ); + } + else + { + action->menu()->addAction( createSpatialIndexAction ); + } + foundExistingManageMenu = true; + break; + } + } + if ( !foundExistingManageMenu ) + { + QMenu *manageLayerMenu = new QMenu( tr( "Manage" ), menu ); + if ( indexExist ) + { + manageLayerMenu->addAction( deleteSpatialIndexAction ); + } + else + { + manageLayerMenu->addAction( createSpatialIndexAction ); + } + menu->addMenu( manageLayerMenu ); + } + + const QString connectionUri = conn->uri(); + const QString providerKey = conn->providerKey(); + + connect( createSpatialIndexAction, &QAction::triggered, createSpatialIndexAction, [providerKey, connectionUri, tableProperty, context] { + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey ) }; + if ( !md ) + return; + + std::unique_ptr conn2( qgis::down_cast( md->createConnection( connectionUri, QVariantMap() ) ) ); + + QString errCause; + try + { + QgsTemporaryCursorOverride override( Qt::WaitCursor ); + conn2->createSpatialIndex( tableProperty.schema(), tableProperty.tableName() ); + } + catch ( QgsProviderConnectionException &ex ) + { + errCause = ex.what(); + } + + if ( !errCause.isEmpty() ) + { + notify( tr( "Cannot create spatial index on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), errCause, context, Qgis::MessageLevel::Critical ); + return; + } + else if ( context.messageBar() ) + { + context.messageBar()->pushMessage( tr( "Spatial index created on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), Qgis::MessageLevel::Success ); + } + } ); + + connect( deleteSpatialIndexAction, &QAction::triggered, deleteSpatialIndexAction, [providerKey, connectionUri, tableProperty, context] { + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey ) }; + if ( !md ) + return; + + std::unique_ptr conn2( qgis::down_cast( md->createConnection( connectionUri, QVariantMap() ) ) ); + + QString errCause; + try + { + QgsTemporaryCursorOverride override( Qt::WaitCursor ); + conn2->deleteSpatialIndex( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); + } + catch ( QgsProviderConnectionException &ex ) + { + errCause = ex.what(); + } + + if ( !errCause.isEmpty() ) + { + notify( tr( "Cannot delete spatial index on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), errCause, context, Qgis::MessageLevel::Critical ); + return; + } + else if ( context.messageBar() ) + { + context.messageBar()->pushMessage( tr( "Spatial index deleted on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), Qgis::MessageLevel::Success ); + } + } ); + } } } From 75244b898835ec5bb1aa46c291fb898834e84048 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 27 Aug 2025 14:24:19 +0200 Subject: [PATCH 2/3] make const --- src/app/browser/qgsinbuiltdataitemproviders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/browser/qgsinbuiltdataitemproviders.cpp b/src/app/browser/qgsinbuiltdataitemproviders.cpp index 8fa52c73042..d0393742055 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.cpp +++ b/src/app/browser/qgsinbuiltdataitemproviders.cpp @@ -1964,7 +1964,7 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * QgsAbstractDatabaseProviderConnection::TableProperty tableProperty = conn->table( item->parent()->name(), item->name() ); - bool indexExist = conn->spatialIndexExists( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); + const bool indexExist = conn->spatialIndexExists( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); // this action should sit in the Manage menu. If one does not exist, create it now bool foundExistingManageMenu = false; From 2d19b91f40bc77eeb9df8b890c48de0c5e018777 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Thu, 28 Aug 2025 08:01:51 +0200 Subject: [PATCH 3/3] add confirmation dialog to deleting spatial index --- .../browser/qgsinbuiltdataitemproviders.cpp | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/app/browser/qgsinbuiltdataitemproviders.cpp b/src/app/browser/qgsinbuiltdataitemproviders.cpp index d0393742055..5514b836e22 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.cpp +++ b/src/app/browser/qgsinbuiltdataitemproviders.cpp @@ -1960,7 +1960,7 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * if ( isTable && conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::CreateSpatialIndex ) && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::DeleteSpatialIndex ) ) { QAction *createSpatialIndexAction = new QAction( tr( "Create Spatial Index" ), menu ); - QAction *deleteSpatialIndexAction = new QAction( tr( "Delete Spatial Index" ), menu ); + QAction *deleteSpatialIndexAction = new QAction( tr( "Delete Spatial Index…" ), menu ); QgsAbstractDatabaseProviderConnection::TableProperty tableProperty = conn->table( item->parent()->name(), item->name() ); @@ -2032,31 +2032,34 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * } ); connect( deleteSpatialIndexAction, &QAction::triggered, deleteSpatialIndexAction, [providerKey, connectionUri, tableProperty, context] { - QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey ) }; - if ( !md ) - return; + if ( QMessageBox::question( nullptr, tr( "Delete Spatial Index" ), tr( "Are you sure that you want to delete spatial index from %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes ) + { + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerKey ) }; + if ( !md ) + return; - std::unique_ptr conn2( qgis::down_cast( md->createConnection( connectionUri, QVariantMap() ) ) ); + std::unique_ptr conn2( qgis::down_cast( md->createConnection( connectionUri, QVariantMap() ) ) ); - QString errCause; - try - { - QgsTemporaryCursorOverride override( Qt::WaitCursor ); - conn2->deleteSpatialIndex( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); - } - catch ( QgsProviderConnectionException &ex ) - { - errCause = ex.what(); - } + QString errCause; + try + { + QgsTemporaryCursorOverride override( Qt::WaitCursor ); + conn2->deleteSpatialIndex( tableProperty.schema(), tableProperty.tableName(), tableProperty.geometryColumn() ); + } + catch ( QgsProviderConnectionException &ex ) + { + errCause = ex.what(); + } - if ( !errCause.isEmpty() ) - { - notify( tr( "Cannot delete spatial index on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), errCause, context, Qgis::MessageLevel::Critical ); - return; - } - else if ( context.messageBar() ) - { - context.messageBar()->pushMessage( tr( "Spatial index deleted on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), Qgis::MessageLevel::Success ); + if ( !errCause.isEmpty() ) + { + notify( tr( "Cannot delete spatial index on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), errCause, context, Qgis::MessageLevel::Critical ); + return; + } + else if ( context.messageBar() ) + { + context.messageBar()->pushMessage( tr( "Spatial index deleted on %1.%2" ).arg( tableProperty.schema(), tableProperty.tableName() ), Qgis::MessageLevel::Success ); + } } } ); }