Skip to content

Commit

Permalink
Don't show 'Delete File' action in browser when right clicking
Browse files Browse the repository at this point in the history
a raster sublayer of a dataset

This should instead be a "Delete Layer" action to match OGR sublayers,
but GDAL itself only supports deleting raster layers from gpkg and
we have special handling for those in place.
  • Loading branch information
nyalldawson committed Jul 28, 2021
1 parent cb8fabd commit 2563dd8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 72 deletions.
123 changes: 52 additions & 71 deletions src/gui/providers/gdal/qgsgdalguiprovider.cpp
Expand Up @@ -47,19 +47,15 @@ QString QgsGdalItemGuiProvider::name()
return QStringLiteral( "gdal_items" );
}

void QgsGdalItemGuiProvider::onDeleteLayer( QgsDataItemGuiContext context )
void QgsGdalItemGuiProvider::onDeletePostgresRasterLayer( QgsDataItemGuiContext context )
{
QAction *s = qobject_cast<QAction *>( sender() );
QVariantMap data = s->data().toMap();
const QString uri = data[QStringLiteral( "uri" )].toString();
const QString path = data[QStringLiteral( "path" )].toString();
QPointer< QgsDataItem > parent = data[QStringLiteral( "parentItem" )].value<QPointer< QgsDataItem >>();

// Messages are different for files and tables
bool isPostgresRaster { uri.startsWith( QLatin1String( "PG:" ) ) };
const QString title = isPostgresRaster ?
tr( "Delete Table" ) :
tr( "Delete File" );
const QString title = tr( "Delete Table" );

// Check if the layer is in the project
const QgsMapLayer *projectLayer = nullptr;
Expand All @@ -74,82 +70,65 @@ void QgsGdalItemGuiProvider::onDeleteLayer( QgsDataItemGuiContext context )

if ( ! projectLayer )
{
const QString confirmMessage = isPostgresRaster ? tr( "Are you sure you want to delete table “%1”?" ).arg( path ) :
tr( "Are you sure you want to delete file “%1”?" ).arg( path );
const QString confirmMessage = tr( "Are you sure you want to delete table “%1”?" ).arg( path );

if ( QMessageBox::question( nullptr, title,
confirmMessage,
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;

if ( isPostgresRaster )
QString errorMessage;
bool deleted { false };
QgsProviderMetadata *postgresMetadata { QgsProviderRegistry::instance()->providerMetadata( QLatin1String( "postgres" ) ) };
if ( postgresMetadata )
{
QString errorMessage;
bool deleted { false };
QgsProviderMetadata *postgresMetadata { QgsProviderRegistry::instance()->providerMetadata( QLatin1String( "postgres" ) ) };
if ( postgresMetadata )
std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection { static_cast<QgsAbstractDatabaseProviderConnection *>( postgresMetadata->createConnection( uri, {} ) ) };
const QgsDataSourceUri dsUri { QgsDataSourceUri( uri ) };
if ( connection )
{
std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection { static_cast<QgsAbstractDatabaseProviderConnection *>( postgresMetadata->createConnection( uri, {} ) ) };
const QgsDataSourceUri dsUri { QgsDataSourceUri( uri ) };
if ( connection )
try
{
try
// Try hard to get the schema
QString schema = dsUri.schema();
if ( schema.isEmpty() )
{
// Try hard to get the schema
QString schema = dsUri.schema();
if ( schema.isEmpty() )
{
schema = dsUri.param( QStringLiteral( "schema" ) );
}
if ( schema.isEmpty() )
{
schema = QStringLiteral( "public" );
}

connection->dropRasterTable( schema, dsUri.table() );
deleted = true;

schema = dsUri.param( QStringLiteral( "schema" ) );
}
catch ( QgsProviderConnectionException &ex )
if ( schema.isEmpty() )
{
errorMessage = ex.what();
schema = QStringLiteral( "public" );
}

connection->dropRasterTable( schema, dsUri.table() );
deleted = true;

}
else
catch ( QgsProviderConnectionException &ex )
{
errorMessage = tr( "could not create a connection to the database" );
errorMessage = ex.what();
}
}
else
{
errorMessage = tr( "could not retrieve provider metadata" );
errorMessage = tr( "could not create a connection to the database" );
}
}
else
{
errorMessage = tr( "could not retrieve provider metadata" );
}

if ( deleted )
{
notify( title, tr( "Table deleted successfully." ), context, Qgis::MessageLevel::Success );
if ( parent )
parent->refresh();
}
else
{
notify( title, errorMessage.isEmpty() ?
tr( "Could not delete table." ) :
tr( "Could not delete table, reason: %1." ).arg( errorMessage ), context, Qgis::MessageLevel::Warning );
}
if ( deleted )
{
notify( title, tr( "Table deleted successfully." ), context, Qgis::MessageLevel::Success );
if ( parent )
parent->refresh();
}
else
{
if ( !QFile::remove( path ) )
{
notify( title, tr( "Could not delete file." ), context, Qgis::MessageLevel::Warning );
}
else
{
notify( title, tr( "File deleted successfully." ), context, Qgis::MessageLevel::Success );
if ( parent )
parent->refresh();
}
notify( title, errorMessage.isEmpty() ?
tr( "Could not delete table." ) :
tr( "Could not delete table, reason: %1." ).arg( errorMessage ), context, Qgis::MessageLevel::Warning );
}
}
else
Expand All @@ -167,19 +146,21 @@ void QgsGdalItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu
{
if ( layerItem->providerKey() == QLatin1String( "gdal" ) )
{
// Messages are different for files and tables
bool isPostgresRaster { layerItem->uri().startsWith( QLatin1String( "PG:" ) ) };
const QString message = isPostgresRaster ?
QObject::tr( "Delete Table “%1”…" ).arg( layerItem->name() ) :
QObject::tr( "Delete File “%1”…" ).arg( layerItem->name() );
QAction *actionDeleteLayer = new QAction( message, menu );
QVariantMap data;
data.insert( QStringLiteral( "uri" ), layerItem->uri() );
data.insert( QStringLiteral( "path" ), isPostgresRaster ? layerItem->name() : layerItem->path() );
data.insert( QStringLiteral( "parentItem" ), QVariant::fromValue( QPointer< QgsDataItem >( layerItem->parent() ) ) );
actionDeleteLayer->setData( data );
connect( actionDeleteLayer, &QAction::triggered, this, [ = ] { onDeleteLayer( context ); } );
menu->addAction( actionDeleteLayer );
// We only show a delete layer action for postgres rasters -- GDAL itself only supports
// deletion of raster layers from geopackage files, and we have special handling elsewhere for those
const bool isPostgresRaster { layerItem->uri().startsWith( QLatin1String( "PG:" ) ) };
if ( isPostgresRaster )
{
const QString message = QObject::tr( "Delete Table “%1”…" ).arg( layerItem->name() );
QAction *actionDeleteLayer = new QAction( message, menu );
QVariantMap data;
data.insert( QStringLiteral( "uri" ), layerItem->uri() );
data.insert( QStringLiteral( "path" ), layerItem->name() );
data.insert( QStringLiteral( "parentItem" ), QVariant::fromValue( QPointer< QgsDataItem >( layerItem->parent() ) ) );
actionDeleteLayer->setData( data );
connect( actionDeleteLayer, &QAction::triggered, this, [ = ] { onDeletePostgresRasterLayer( context ); } );
menu->addAction( actionDeleteLayer );
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/gui/providers/gdal/qgsgdalguiprovider.h
Expand Up @@ -47,7 +47,7 @@ class QgsGdalItemGuiProvider : public QObject, public QgsDataItemGuiProvider
const QList<QgsDataItem *> &selectedItems, QgsDataItemGuiContext context ) override;

protected slots:
void onDeleteLayer( QgsDataItemGuiContext context );
void onDeletePostgresRasterLayer( QgsDataItemGuiContext context );
};

class QgsGdalSourceWidgetProvider : public QgsProviderSourceWidgetProvider
Expand Down

0 comments on commit 2563dd8

Please sign in to comment.