QGIS API Documentation 3.43.0-Master (9e873c7bc91)
qgsdataitemguiproviderutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdataitemguiproviderutils.cpp
3 --------------------------------------
4 Date : June 2024
5 Copyright : (C) 2024 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "qgsdataitem.h"
20#include "qgsmessagebar.h"
22#include "qgsapplication.h"
23#include "qgstaskmanager.h"
24#include "qgsmessagebaritem.h"
25#include "qgsmessageoutput.h"
27#include "qgsproviderregistry.h"
28#include "qgsprovidermetadata.h"
29
30#include <QPointer>
31#include <QMessageBox>
32#include <QPushButton>
33
34void QgsDataItemGuiProviderUtils::deleteConnectionsPrivate( const QStringList &connectionNames, const std::function<void( const QString & )> &deleteConnection, QPointer<QgsDataItem> firstParent )
35{
36 if ( connectionNames.size() > 1 )
37 {
38 if ( QMessageBox::question( nullptr, QObject::tr( "Remove Connections" ), QObject::tr( "Are you sure you want to remove all %1 selected connections?" ).arg( connectionNames.size() ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
39 return;
40 }
41 else
42 {
43 if ( QMessageBox::question( nullptr, QObject::tr( "Remove Connection" ), QObject::tr( "Are you sure you want to remove the connection to “%1”?" ).arg( connectionNames.at( 0 ) ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
44 return;
45 }
46
47 for ( const QString &connectionName : std::as_const( connectionNames ) )
48 {
49 deleteConnection( connectionName );
50 }
51
52 if ( firstParent )
53 firstParent->refreshConnections();
54}
55
56const QString QgsDataItemGuiProviderUtils::uniqueName( const QString &name, const QStringList &connectionNames )
57{
58 int i = 0;
59 QString newConnectionName( name );
60 while ( connectionNames.contains( newConnectionName ) )
61 {
62 ++i;
63 newConnectionName = QObject::tr( "%1 (copy %2)" ).arg( name ).arg( i );
64 }
65
66 return newConnectionName;
67}
68
69bool QgsDataItemGuiProviderUtils::handleDropUriForConnection( std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection, const QgsMimeDataUtils::Uri &sourceUri, const QString &destinationSchema, QgsDataItemGuiContext context, const QString &shortTitle, const QString &longTitle, const QVariantMap &destinationProviderOptions, const std::function<void()> &onSuccessfulCompletion, const std::function<void( Qgis::VectorExportResult, const QString & )> &onError, QObject *connectionContext )
70{
71 if ( !connection )
72 return false;
73
74 const QString connectionUri = connection->uri();
75 const QString connectionProvider = connection->providerKey();
76
77 QgsDbImportVectorLayerDialog dialog( connection.release(), context.messageBar() ? context.messageBar()->parentWidget() : nullptr );
78 dialog.setMapCanvas( context.mapCanvas() );
79 dialog.setSourceUri( sourceUri );
80 dialog.setDestinationSchema( destinationSchema );
81 if ( !dialog.exec() )
82 return false;
83
84 std::unique_ptr< QgsVectorLayerExporterTask > exportTask = dialog.createExporterTask( destinationProviderOptions );
85 if ( !exportTask )
86 return false;
87
88 const QString destSchema = dialog.schema();
89 const QString destTableName = dialog.tableName();
90 const QString tableComment = dialog.tableComment();
91
92 auto pushError = [shortTitle, longTitle, context]( const QString &error ) {
93 QgsMessageBarItem *item = new QgsMessageBarItem( shortTitle, QObject::tr( "Import failed." ), Qgis::MessageLevel::Warning, 0, nullptr );
94 QPushButton *detailsButton = new QPushButton( QObject::tr( "Details…" ) );
95 QObject::connect( detailsButton, &QPushButton::clicked, detailsButton, [=] {
97 output->setTitle( longTitle );
99 output->showMessage();
100 } );
101 item->layout()->addWidget( detailsButton );
103 };
104
105 // when export is successful:
106 QObject::connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, connectionContext, [onSuccessfulCompletion, connectionUri, longTitle, pushError, connectionProvider, destSchema, destTableName, tableComment, shortTitle, context]() {
107 if ( !tableComment.isEmpty() )
108 {
109 std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection;
110 try
111 {
112 QgsProviderMetadata *md = QgsProviderRegistry::instance()->providerMetadata( connectionProvider );
113 connection.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( connectionUri, {} ) ) );
114 }
115 catch ( QgsProviderConnectionException &e )
116 {
117 pushError( QObject::tr( "Could not retrieve connection details:\n\n%1" ).arg( e.what() ) );
118 return;
119 }
120
121 try
122 {
123 connection->setTableComment( destSchema, destTableName, tableComment );
124 }
125 catch ( QgsProviderConnectionException &e )
126 {
127 pushError( QObject::tr( "Failed to set new table comment!\n\n" ) + e.what() );
128 return;
129 }
130 }
131
132 context.messageBar()->pushSuccess( shortTitle, QObject::tr( "Import was successful." ) );
133 onSuccessfulCompletion();
134 } );
135
136 // when an error occurs:
137 QObject::connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, connectionContext, [onError, shortTitle, pushError, longTitle]( Qgis::VectorExportResult error, const QString &errorMessage ) {
138 if ( error != Qgis::VectorExportResult::UserCanceled )
139 {
140 pushError( QObject::tr( "Failed to import layer!\n\n" ) + errorMessage );
141 }
142
143 onError( error, errorMessage );
144 } );
145
146 QgsApplication::taskManager()->addTask( exportTask.release() );
147 return true;
148}
149
150void QgsDataItemGuiProviderUtils::handleImportVectorLayerForConnection( std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection, const QString &destinationSchema, QgsDataItemGuiContext context, const QString &shortTitle, const QString &longTitle, const QVariantMap &destinationProviderOptions, const std::function<void()> &onSuccessfulCompletion, const std::function<void( Qgis::VectorExportResult, const QString & )> &onError, QObject *connectionContext )
151{
152 if ( !connection )
153 return;
154
155 const QString connectionUri = connection->uri();
156 const QString connectionProvider = connection->providerKey();
157
158 QgsDbImportVectorLayerDialog dialog( connection.release(), context.messageBar() ? context.messageBar()->parentWidget() : nullptr );
159 dialog.setMapCanvas( context.mapCanvas() );
160 dialog.setDestinationSchema( destinationSchema );
161 if ( !dialog.exec() )
162 return;
163
164 std::unique_ptr< QgsVectorLayerExporterTask > exportTask = dialog.createExporterTask( destinationProviderOptions );
165 if ( !exportTask )
166 return;
167
168 const QString destSchema = dialog.schema();
169 const QString destTableName = dialog.tableName();
170 const QString tableComment = dialog.tableComment();
171
172 auto pushError = [shortTitle, longTitle, context]( const QString &error ) {
173 QgsMessageBarItem *item = new QgsMessageBarItem( shortTitle, QObject::tr( "Import failed." ), Qgis::MessageLevel::Warning, 0, nullptr );
174 QPushButton *detailsButton = new QPushButton( QObject::tr( "Details…" ) );
175 QObject::connect( detailsButton, &QPushButton::clicked, detailsButton, [=] {
177 output->setTitle( longTitle );
179 output->showMessage();
180 } );
181 item->layout()->addWidget( detailsButton );
183 };
184
185 // when export is successful:
186 QObject::connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, connectionContext, [onSuccessfulCompletion, connectionUri, longTitle, pushError, connectionProvider, destSchema, destTableName, tableComment, shortTitle, context]() {
187 if ( !tableComment.isEmpty() )
188 {
189 std::unique_ptr<QgsAbstractDatabaseProviderConnection> connection;
190 try
191 {
192 QgsProviderMetadata *md = QgsProviderRegistry::instance()->providerMetadata( connectionProvider );
193 connection.reset( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( connectionUri, {} ) ) );
194 }
195 catch ( QgsProviderConnectionException &e )
196 {
197 pushError( QObject::tr( "Could not retrieve connection details:\n\n%1" ).arg( e.what() ) );
198 return;
199 }
200
201 try
202 {
203 connection->setTableComment( destSchema, destTableName, tableComment );
204 }
205 catch ( QgsProviderConnectionException &e )
206 {
207 pushError( QObject::tr( "Failed to set new table comment!\n\n" ) + e.what() );
208 return;
209 }
210 }
211
212 context.messageBar()->pushSuccess( shortTitle, QObject::tr( "Import was successful." ) );
213 onSuccessfulCompletion();
214 } );
215
216 // when an error occurs:
217 QObject::connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, connectionContext, [onError, shortTitle, pushError, longTitle]( Qgis::VectorExportResult error, const QString &errorMessage ) {
218 if ( error != Qgis::VectorExportResult::UserCanceled )
219 {
220 pushError( QObject::tr( "Failed to import layer!\n\n" ) + errorMessage );
221 }
222
223 onError( error, errorMessage );
224 } );
225
226 QgsApplication::taskManager()->addTask( exportTask.release() );
227}
VectorExportResult
Vector layer export result codes.
Definition qgis.h:1013
@ Warning
Warning message.
Definition qgis.h:156
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
Encapsulates the context in which a QgsDataItem is shown within the application GUI.
QgsMessageBar * messageBar() const
Returns the associated message bar.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the item.
static void handleImportVectorLayerForConnection(std::unique_ptr< QgsAbstractDatabaseProviderConnection > connection, const QString &destinationSchema, QgsDataItemGuiContext context, const QString &shortTitle, const QString &longTitle, const QVariantMap &destinationProviderOptions, const std::function< void()> &onSuccessfulCompletion, const std::function< void(Qgis::VectorExportResult error, const QString &errorMessage)> &onError, QObject *connectionContext)
Handles importing a vector layer for connection items.
static const QString uniqueName(const QString &name, const QStringList &connectionNames)
Check if connection with name exists in connectionNames list and then try to append a number to it to...
static bool handleDropUriForConnection(std::unique_ptr< QgsAbstractDatabaseProviderConnection > connection, const QgsMimeDataUtils::Uri &sourceUri, const QString &destinationSchema, QgsDataItemGuiContext context, const QString &shortTitle, const QString &longTitle, const QVariantMap &destinationProviderOptions, const std::function< void()> &onSuccessfulCompletion, const std::function< void(Qgis::VectorExportResult error, const QString &errorMessage)> &onError, QObject *connectionContext)
Handles dropping a vector layer for connection items.
A generic dialog for customising vector layer import options for database connections.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas to associate with the dialog.
Represents an item shown within a QgsMessageBar widget.
QgsMessageBarItem * pushWidget(QWidget *widget, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=0)
Display a widget as a message on the bar, after hiding the currently visible one and putting it in a ...
void pushSuccess(const QString &title, const QString &message)
Pushes a success message with default timeout to the message bar.
Interface for showing messages from QGIS in GUI independent way.
virtual void showMessage(bool blocking=true)=0
display the message to the user and deletes itself
static QgsMessageOutput * createMessageOutput()
function that returns new class derived from QgsMessageOutput (don't forget to delete it then if show...
virtual void setMessage(const QString &message, MessageType msgType)=0
Sets message, it won't be displayed until.
virtual void setTitle(const QString &title)=0
Sets title for the messages.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void exportComplete()
Emitted when exporting the layer is successfully completed.
void errorOccurred(Qgis::VectorExportResult error, const QString &errorMessage)
Emitted when an error occurs which prevented the layer being exported (or if the task is canceled).