From d9299e6bc0abee35177f11187ebdadca191384d6 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Thu, 28 Nov 2024 19:08:04 +0100 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20allow=20'Execute=20SQL=E2=80=A6'=20?= =?UTF-8?q?from=20the=20layer=20context=20menu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/qgsapplayertreeviewmenuprovider.cpp | 129 +++++++++++++------- 1 file changed, 87 insertions(+), 42 deletions(-) diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index 301a679da8a..0f2ab032842 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -157,7 +157,7 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() } else if ( QgsLayerTree::isLayer( node ) ) { - QgsMapLayer *layer = QgsLayerTree::toLayer( node )->layer(); + QPointer layer { QgsLayerTree::toLayer( node )->layer() }; QgsRasterLayer *rlayer = qobject_cast( layer ); QgsVectorLayer *vlayer = qobject_cast( layer ); QgsPointCloudLayer *pcLayer = qobject_cast( layer ); @@ -247,68 +247,113 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() } // No raster support in createSqlVectorLayer (yet) - if ( vlayer && vlayer->isSqlQuery() ) + if ( vlayer ) { const std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn { QgsMapLayerUtils::databaseConnection( layer ) }; if ( conn ) - menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/dbmanager.svg" ) ), tr( "Update SQL Layer…" ), menu, [ layer, this ] { - std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn2 { QgsMapLayerUtils::databaseConnection( layer ) }; - if ( conn2 ) + if ( vlayer->isSqlQuery() ) + menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/dbmanager.svg" ) ), tr( "Update SQL Layer…" ), menu, [ layer, this ] { - QgsDialog dialog; - dialog.setObjectName( QStringLiteral( "SqlUpdateDialog" ) ); - dialog.setWindowTitle( tr( "%1 — Update SQL" ).arg( layer->name() ) ); - QgsGui::enableAutoGeometryRestore( &dialog ); - QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions options { conn2->sqlOptions( layer->source() ) }; - options.layerName = layer->name(); - QgsQueryResultWidget *queryResultWidget { new QgsQueryResultWidget( &dialog, conn2.release() ) }; - queryResultWidget->setWidgetMode( QgsQueryResultWidget::QueryWidgetMode::QueryLayerUpdateMode ); - queryResultWidget->setSqlVectorLayerOptions( options ); - queryResultWidget->executeQuery(); - queryResultWidget->layout()->setContentsMargins( 0, 0, 0, 0 ); - dialog.layout()->addWidget( queryResultWidget ); - - connect( queryResultWidget, &QgsQueryResultWidget::createSqlVectorLayer, queryResultWidget, [queryResultWidget, layer, this ]( const QString &, const QString &, const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions & options ) + std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn2 { QgsMapLayerUtils::databaseConnection( layer ) }; + if ( conn2 ) { - ( void )this; - std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn3 { QgsMapLayerUtils::databaseConnection( layer ) }; - if ( conn3 ) + QgsDialog dialog; + dialog.setObjectName( QStringLiteral( "SqlUpdateDialog" ) ); + dialog.setWindowTitle( tr( "%1 — Update SQL" ).arg( layer->name() ) ); + QgsGui::enableAutoGeometryRestore( &dialog ); + QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions options { conn2->sqlOptions( layer->source() ) }; + options.layerName = layer->name(); + QgsQueryResultWidget *queryResultWidget { new QgsQueryResultWidget( &dialog, conn2.release() ) }; + queryResultWidget->setWidgetMode( QgsQueryResultWidget::QueryWidgetMode::QueryLayerUpdateMode ); + queryResultWidget->setSqlVectorLayerOptions( options ); + queryResultWidget->executeQuery(); + queryResultWidget->layout()->setContentsMargins( 0, 0, 0, 0 ); + dialog.layout()->addWidget( queryResultWidget ); + + connect( queryResultWidget, &QgsQueryResultWidget::createSqlVectorLayer, queryResultWidget, [queryResultWidget, layer, this ]( const QString &, const QString &, const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions & options ) { - try + ( void )this; + std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn3 { QgsMapLayerUtils::databaseConnection( layer ) }; + if ( conn3 ) { - std::unique_ptr sqlLayer { conn3->createSqlVectorLayer( options ) }; - if ( sqlLayer->isValid() ) + try { - layer->setDataSource( sqlLayer->source(), sqlLayer->name(), sqlLayer->dataProvider()->name(), QgsDataProvider::ProviderOptions() ); - queryResultWidget->notify( QObject::tr( "Layer Update Success" ), QObject::tr( "The SQL layer was updated successfully" ), Qgis::MessageLevel::Success ); - } - else - { - QString error { sqlLayer->dataProvider()->error().message( QgsErrorMessage::Format::Text ) }; - if ( error.isEmpty() ) + std::unique_ptr sqlLayer { conn3->createSqlVectorLayer( options ) }; + if ( sqlLayer->isValid() ) { - error = QObject::tr( "layer is not valid, check the log messages for more information" ); + layer->setDataSource( sqlLayer->source(), sqlLayer->name(), sqlLayer->dataProvider()->name(), QgsDataProvider::ProviderOptions() ); + queryResultWidget->notify( QObject::tr( "Layer Update Success" ), QObject::tr( "The SQL layer was updated successfully" ), Qgis::MessageLevel::Success ); } - queryResultWidget->notify( QObject::tr( "Layer Update Error" ), QObject::tr( "Error updating the SQL layer: %1" ).arg( error ), Qgis::MessageLevel::Critical ); + else + { + QString error { sqlLayer->dataProvider()->error().message( QgsErrorMessage::Format::Text ) }; + if ( error.isEmpty() ) + { + error = QObject::tr( "layer is not valid, check the log messages for more information" ); + } + queryResultWidget->notify( QObject::tr( "Layer Update Error" ), QObject::tr( "Error updating the SQL layer: %1" ).arg( error ), Qgis::MessageLevel::Critical ); + } + } + catch ( QgsProviderConnectionException &ex ) + { + queryResultWidget->notify( QObject::tr( "Layer Update Error" ), QObject::tr( "Error updating the SQL layer: %1" ).arg( ex.what() ), Qgis::MessageLevel::Critical ); } } - catch ( QgsProviderConnectionException &ex ) + + } ); + + dialog.exec(); + + } + } ); + + // SQL dialog + if ( conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::ExecuteSql ) ) + menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/dbmanager.svg" ) ), tr( "Execute SQL…" ), menu, [ layer, this ] + { + std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn2 { QgsMapLayerUtils::databaseConnection( layer ) }; + if ( conn2 ) + { + QgsDialog dialog; + dialog.setObjectName( QStringLiteral( "SqlExecuteDialog" ) ); + dialog.setWindowTitle( tr( "Execute SQL" ) ); + QgsGui::enableAutoGeometryRestore( &dialog ); + QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions options { conn2->sqlOptions( layer->source() ) }; + QgsQueryResultWidget *queryResultWidget { new QgsQueryResultWidget( &dialog, conn2.release() ) }; + queryResultWidget->setSqlVectorLayerOptions( options ); + queryResultWidget->executeQuery(); + queryResultWidget->layout()->setContentsMargins( 0, 0, 0, 0 ); + dialog.layout()->addWidget( queryResultWidget ); + + connect( queryResultWidget, &QgsQueryResultWidget::createSqlVectorLayer, queryResultWidget, [queryResultWidget, layer, this ]( const QString &, const QString &, const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions & options ) + { + ( void )this; + std::unique_ptr< QgsAbstractDatabaseProviderConnection> conn3 { QgsMapLayerUtils::databaseConnection( layer ) }; + if ( conn3 ) { - queryResultWidget->notify( QObject::tr( "Layer Update Error" ), QObject::tr( "Error updating the SQL layer: %1" ).arg( ex.what() ), Qgis::MessageLevel::Critical ); + try + { + QgsMapLayer *sqlLayer { conn3->createSqlVectorLayer( options ) }; + QgsProject::instance()->addMapLayers( { sqlLayer } ); + } + catch ( QgsProviderConnectionException &ex ) + { + queryResultWidget->notify( QObject::tr( "New SQL Layer Creation Error" ), QObject::tr( "Error creating the SQL layer: %1" ).arg( ex.what() ), Qgis::MessageLevel::Critical ); + } } - } - } ); + } ); - dialog.exec(); + dialog.exec(); - } - } ); + } + } ); + } } addCustomLayerActions( menu, layer ); - if ( layer && layer->type() == Qgis::LayerType::Vector && static_cast( layer )->providerType() == QLatin1String( "virtual" ) ) + if ( layer && vlayer && vlayer->providerType() == QLatin1String( "virtual" ) ) { menu->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddVirtualLayer.svg" ) ), tr( "Edit Virtual Layer…" ), QgisApp::instance(), &QgisApp::addVirtualLayer ); }