From 628e95ff98735aaee74793c35e5b394f9c877eb9 Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Fri, 11 Jun 2021 10:30:32 +0200 Subject: [PATCH] Forward databaseConnection to parent item for layer items ... and preset SQL in query dialog --- .../browser/qgslayeritem.sip.in | 2 + .../browser/qgsinbuiltdataitemproviders.cpp | 44 ++++++++++++++++--- src/core/browser/qgslayeritem.cpp | 9 ++++ src/core/browser/qgslayeritem.h | 1 + 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/python/core/auto_generated/browser/qgslayeritem.sip.in b/python/core/auto_generated/browser/qgslayeritem.sip.in index fc03a5fb038..9c37b022cc8 100644 --- a/python/core/auto_generated/browser/qgslayeritem.sip.in +++ b/python/core/auto_generated/browser/qgslayeritem.sip.in @@ -140,6 +140,8 @@ Returns icon for point cloud layer :return: the layer name %End + virtual QgsAbstractDatabaseProviderConnection *databaseConnection() const; + }; diff --git a/src/app/browser/qgsinbuiltdataitemproviders.cpp b/src/app/browser/qgsinbuiltdataitemproviders.cpp index 6ba848484aa..0e40d7477ff 100644 --- a/src/app/browser/qgsinbuiltdataitemproviders.cpp +++ b/src/app/browser/qgsinbuiltdataitemproviders.cpp @@ -1060,32 +1060,62 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * } ); menu->addAction( newTableAction ); } + } + + // SQL dialog + if ( item->databaseConnection() ) + { + std::unique_ptr conn( item->databaseConnection() ); if ( conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::ExecuteSql ) ) { QAction *sqlAction = new QAction( QObject::tr( "Run SQL command…" ), menu ); - QObject::connect( sqlAction, &QAction::triggered, collectionItem, [ collectionItem, context ] + QObject::connect( sqlAction, &QAction::triggered, item, [ item, context ] { - std::unique_ptr conn2( collectionItem->databaseConnection() ); + std::unique_ptr conn2( item->databaseConnection() ); // This should never happen but let's play safe if ( ! conn2 ) { - QgsMessageLog::logMessage( tr( "Connection to the database (%1) was lost." ).arg( collectionItem->name() ) ); + QgsMessageLog::logMessage( tr( "Connection to the database (%1) was lost." ).arg( item->name() ) ); return; } + + // Create the SQL dialog: this might become an independent class dialog in the future, for now + // we are still prototyping the features that this dialog will have. + QgsDialog dialog; dialog.setObjectName( QStringLiteral( "SQLCommandsDialog" ) ); - dialog.setWindowTitle( tr( "%1 — Run SQL Commands" ).arg( collectionItem->name() ) ); + dialog.setWindowTitle( tr( "%1 — Run SQL Commands" ).arg( item->name() ) ); + + // If this is a layer item (or below the hierarchy) we can pre-set the query to something + // meaningful + QString sql; + + if ( qobject_cast( item ) ) + { + if ( conn2->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::Schemas ) ) + { + // Ok, this is gross: we lack a connection API for quoting properly... + sql = QStringLiteral( "SELECT * FROM %1.%2 LIMIT 10" ).arg( QgsSqliteUtils::quotedIdentifier( item->parent()->name() ), QgsSqliteUtils::quotedIdentifier( item->name() ) ); + } + else + { + // Ok, this is gross: we lack a connection API for quoting properly... + sql = QStringLiteral( "SELECT * FROM %1 LIMIT 10" ).arg( QgsSqliteUtils::quotedIdentifier( item->name() ) ); + } + } + QgsGui::enableAutoGeometryRestore( &dialog ); QgsQueryResultWidget *widget { new QgsQueryResultWidget( &dialog, conn2.release() ) }; + widget->setQuery( sql ); widget->layout()->setMargin( 0 ); dialog.layout()->addWidget( widget ); - connect( widget, &QgsQueryResultWidget::createSqlVectorLayer, widget, [ collectionItem, context ]( const QString &, const QString &, const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions & options ) + connect( widget, &QgsQueryResultWidget::createSqlVectorLayer, widget, [ item, context ]( const QString &, const QString &, const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions & options ) { - std::unique_ptr conn3( collectionItem->databaseConnection() ); + std::unique_ptr conn3( item->databaseConnection() ); try { QgsMapLayer *sqlLayer { conn3->createSqlVectorLayer( options ) }; @@ -1098,6 +1128,8 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu * } ); dialog.exec(); + + } ); menu->addAction( sqlAction ); } diff --git a/src/core/browser/qgslayeritem.cpp b/src/core/browser/qgslayeritem.cpp index b00a2e43472..f23bbf47b63 100644 --- a/src/core/browser/qgslayeritem.cpp +++ b/src/core/browser/qgslayeritem.cpp @@ -66,6 +66,15 @@ QIcon QgsLayerItem::iconPointCloud() return QgsIconUtils::iconPointCloud(); } +QgsAbstractDatabaseProviderConnection *QgsLayerItem::databaseConnection() const +{ + if ( parent() ) + { + return parent()->databaseConnection(); + } + return nullptr; +} + QIcon QgsLayerItem::iconDefault() { return QgsIconUtils::iconDefaultLayer(); diff --git a/src/core/browser/qgslayeritem.h b/src/core/browser/qgslayeritem.h index f1fb46830a1..288f64f71e7 100644 --- a/src/core/browser/qgslayeritem.h +++ b/src/core/browser/qgslayeritem.h @@ -140,6 +140,7 @@ class CORE_EXPORT QgsLayerItem : public QgsDataItem static QIcon iconPointCloud(); //! \returns the layer name virtual QString layerName() const { return name(); } + QgsAbstractDatabaseProviderConnection *databaseConnection() const override; };