Skip to content

Commit 460f578

Browse files
committed
- [API] add optional progress dialog to QgsVectorLayerImport
- postgres/mssql: fix primary key generation on import (fixes #6907) - fix crash on browser refresh after vector layer import
1 parent 4cffd07 commit 460f578

File tree

7 files changed

+96
-18
lines changed

7 files changed

+96
-18
lines changed

python/core/qgsvectorlayerimport.sip

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class QgsVectorLayerImport
99
%TypeHeaderCode
1010
#include <qgsvectorlayerimport.h>
1111
#include <qgsfield.h>
12+
class QProgressDialog;
1213
%End
1314

1415
public:
@@ -37,7 +38,8 @@ class QgsVectorLayerImport
3738
bool onlySelected = false,
3839
QString *errorMessage /Out/ = 0,
3940
bool skipAttributeCreation = false,
40-
QMap<QString, QVariant> *options = 0
41+
QMap<QString, QVariant> *options = 0,
42+
QProgressDialog *progress = 0
4143
);
4244

4345
/** create a empty layer and add fields to it */
@@ -47,7 +49,8 @@ class QgsVectorLayerImport
4749
QGis::WkbType geometryType,
4850
const QgsCoordinateReferenceSystem* crs,
4951
bool overwrite = false,
50-
const QMap<QString, QVariant> *options = 0
52+
const QMap<QString, QVariant> *options = 0,
53+
QProgressDialog *progress = 0
5154
);
5255

5356
/** checks whether there were any errors */

src/core/qgsvectorlayerimport.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "qgsvectorlayerimport.h"
2626
#include "qgsproviderregistry.h"
2727

28+
#include <QProgressDialog>
29+
2830
#define FEATURE_BUFFER_SIZE 200
2931

3032
typedef QgsVectorLayerImport::ImportError createEmptyLayer_t(
@@ -45,8 +47,10 @@ QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
4547
QGis::WkbType geometryType,
4648
const QgsCoordinateReferenceSystem* crs,
4749
bool overwrite,
48-
const QMap<QString, QVariant> *options )
50+
const QMap<QString, QVariant> *options,
51+
QProgressDialog *progress )
4952
: mErrorCount( 0 )
53+
, mProgress( progress )
5054
{
5155
mProvider = NULL;
5256

@@ -83,7 +87,7 @@ QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
8387
QgsDebugMsg( "Created empty layer" );
8488

8589
QgsVectorDataProvider *vectorProvider = ( QgsVectorDataProvider* ) pReg->provider( providerKey, uri );
86-
if ( !vectorProvider || !vectorProvider->isValid() )
90+
if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
8791
{
8892
mError = ErrInvalidLayer;
8993
mErrorMessage = QObject::tr( "Loading of layer failed" );
@@ -181,7 +185,8 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
181185
bool onlySelected,
182186
QString *errorMessage,
183187
bool skipAttributeCreation,
184-
QMap<QString, QVariant> *options )
188+
QMap<QString, QVariant> *options,
189+
QProgressDialog *progress )
185190
{
186191
const QgsCoordinateReferenceSystem* outputCRS;
187192
QgsCoordinateTransform* ct = 0;
@@ -255,7 +260,7 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
255260
}
256261

257262
QgsVectorLayerImport * writer =
258-
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options );
263+
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options, progress );
259264

260265
// check whether file creation was successful
261266
ImportError err = writer->hasError();
@@ -298,9 +303,23 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
298303
*errorMessage = QObject::tr( "Feature write errors:" );
299304
}
300305

306+
if ( progress )
307+
{
308+
progress->setRange( 0, layer->featureCount() );
309+
}
310+
301311
// write all features
302312
while ( layer->nextFeature( fet ) )
303313
{
314+
if ( progress && progress->wasCanceled() )
315+
{
316+
if ( errorMessage )
317+
{
318+
*errorMessage += "\n" + QObject::tr( "Import was canceled at %1 of %2" ).arg( progress->value() ).arg( progress->maximum() );
319+
}
320+
break;
321+
}
322+
304323
if ( writer->errorCount() > 1000 )
305324
{
306325
if ( errorMessage )
@@ -348,6 +367,11 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
348367
}
349368
}
350369
n++;
370+
371+
if ( progress )
372+
{
373+
progress->setValue( n );
374+
}
351375
}
352376

353377
// flush the buffer to be sure that all features are written

src/core/qgsvectorlayerimport.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgsvectordataprovider.h"
2323
#include "qgsvectorlayer.h"
2424

25+
class QProgressDialog;
26+
2527
/** \ingroup core
2628
* A convenience class for writing vector files to disk.
2729
There are two possibilities how to use this class:
@@ -59,7 +61,8 @@ class CORE_EXPORT QgsVectorLayerImport
5961
bool onlySelected = false,
6062
QString *errorMessage = 0,
6163
bool skipAttributeCreation = false,
62-
QMap<QString, QVariant> *options = 0
64+
QMap<QString, QVariant> *options = 0,
65+
QProgressDialog *progress = 0
6366
);
6467

6568
/** create a empty layer and add fields to it */
@@ -69,7 +72,8 @@ class CORE_EXPORT QgsVectorLayerImport
6972
QGis::WkbType geometryType,
7073
const QgsCoordinateReferenceSystem* crs,
7174
bool overwrite = false,
72-
const QMap<QString, QVariant> *options = 0
75+
const QMap<QString, QVariant> *options = 0,
76+
QProgressDialog *progress = 0
7377
);
7478

7579
/** checks whether there were any errors */
@@ -102,6 +106,7 @@ class CORE_EXPORT QgsVectorLayerImport
102106
QMap<int, int> mOldToNewAttrIdx;
103107

104108
QgsFeatureList mFeatureBuffer;
109+
QProgressDialog *mProgress;
105110
};
106111

107112
#endif

src/providers/mssql/qgsmssqlprovider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,7 +1686,7 @@ QgsVectorLayerImport::ImportError QgsMssqlProvider::createEmptyLayer(
16861686
QString pk = primaryKey = "qgs_fid";
16871687
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
16881688
{
1689-
if ( fldIt.value().name() == pk )
1689+
if ( fldIt.value().name() == primaryKey )
16901690
{
16911691
// it already exists, try again with a new name
16921692
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );

src/providers/postgres/qgspostgresdataitems.cpp

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,51 @@
2222
#include "qgsapplication.h"
2323

2424
#include <QMessageBox>
25+
#include <QProgressDialog>
2526

2627
QGISEXTERN bool deleteLayer( const QString& uri, QString& errCause );
2728

2829
// ---------------------------------------------------------------------------
2930
QgsPGConnectionItem::QgsPGConnectionItem( QgsDataItem* parent, QString name, QString path )
3031
: QgsDataCollectionItem( parent, name, path )
32+
, mColumnTypeThread( 0 )
3133
{
3234
mIcon = QgsApplication::getThemeIcon( "mIconConnect.png" );
3335
}
3436

3537
QgsPGConnectionItem::~QgsPGConnectionItem()
3638
{
39+
stop();
40+
}
41+
42+
void QgsPGConnectionItem::stop()
43+
{
44+
if ( mColumnTypeThread )
45+
{
46+
mColumnTypeThread->stop();
47+
mColumnTypeThread->wait();
48+
delete mColumnTypeThread;
49+
mColumnTypeThread = 0;
50+
}
51+
}
52+
53+
void QgsPGConnectionItem::refresh()
54+
{
55+
QApplication::setOverrideCursor( Qt::WaitCursor );
56+
57+
stop();
58+
59+
foreach ( QgsDataItem *child, mChildren )
60+
{
61+
deleteChildItem( child );
62+
}
63+
64+
foreach ( QgsDataItem *item, createChildren() )
65+
{
66+
addChildItem( item, true );
67+
}
68+
69+
QApplication::restoreOverrideCursor();
3770
}
3871

3972
QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
@@ -42,6 +75,8 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
4275
QVector<QgsDataItem*> children;
4376
QgsDataSourceURI uri = QgsPostgresConn::connUri( mName );
4477

78+
mSchemaMap.clear();
79+
4580
mConn = QgsPostgresConn::connectDb( uri.connectionInfo(), true );
4681
if ( !mConn )
4782
return children;
@@ -62,7 +97,7 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
6297
return children;
6398
}
6499

65-
QgsGeomColumnTypeThread *columnTypeThread = 0;
100+
stop();
66101

67102
foreach ( QgsPostgresLayerProperty layerProperty, layerProperties )
68103
{
@@ -76,17 +111,17 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
76111

77112
if ( QgsPostgresConn::wkbTypeFromPostgis( layerProperty.type ) == QGis::WKBUnknown )
78113
{
79-
if ( !columnTypeThread )
114+
if ( !mColumnTypeThread )
80115
{
81116
QgsPostgresConn *conn = QgsPostgresConn::connectDb( uri.connectionInfo(), true /* readonly */ );
82117
if ( conn )
83118
{
84-
columnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );
119+
mColumnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );
85120

86-
connect( columnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
121+
connect( mColumnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
87122
this, SLOT( setLayerType( QgsPostgresLayerProperty ) ) );
88123
connect( this, SIGNAL( addGeometryColumn( QgsPostgresLayerProperty ) ),
89-
columnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
124+
mColumnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
90125
}
91126
}
92127

@@ -98,8 +133,8 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
98133
schemaItem->addLayer( layerProperty );
99134
}
100135

101-
if ( columnTypeThread )
102-
columnTypeThread->start();
136+
if ( mColumnTypeThread )
137+
mColumnTypeThread->start();
103138

104139
return children;
105140
}
@@ -186,6 +221,11 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
186221

187222
qApp->setOverrideCursor( Qt::WaitCursor );
188223

224+
QProgressDialog *progress = new QProgressDialog( tr( "Copying features..." ), tr( "Abort" ), 0, 0, 0 );
225+
progress->setWindowTitle( tr( "Import layer" ) );
226+
progress->setWindowModality( Qt::WindowModal );
227+
progress->show();
228+
189229
QStringList importResults;
190230
bool hasError = false;
191231
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
@@ -207,7 +247,7 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
207247
QgsDebugMsg( "URI " + uri.uri() );
208248
QgsVectorLayerImport::ImportError err;
209249
QString importError;
210-
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError );
250+
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError, false, 0, progress );
211251
if ( err == QgsVectorLayerImport::NoError )
212252
importResults.append( tr( "%1: OK!" ).arg( u.name ) );
213253
else
@@ -225,6 +265,8 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
225265
delete srcLayer;
226266
}
227267

268+
delete progress;
269+
228270
qApp->restoreOverrideCursor();
229271

230272
if ( hasError )

src/providers/postgres/qgspostgresdataitems.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class QgsPGConnectionItem : public QgsDataCollectionItem
6161

6262
QgsPostgresConn *connection() const { return mConn; }
6363

64+
void refresh();
65+
6466
signals:
6567
void addGeometryColumn( QgsPostgresLayerProperty );
6668

@@ -71,8 +73,10 @@ class QgsPGConnectionItem : public QgsDataCollectionItem
7173
void setLayerType( QgsPostgresLayerProperty layerProperty );
7274

7375
private:
76+
void stop();
7477
QgsPostgresConn *mConn;
7578
QMap<QString, QgsPGSchemaItem * > mSchemaMap;
79+
QgsGeomColumnTypeThread *mColumnTypeThread;
7680
};
7781

7882
class QgsPGSchemaItem : public QgsDataCollectionItem

src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3274,7 +3274,7 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
32743274
QString pk = primaryKey = "id";
32753275
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
32763276
{
3277-
if ( fldIt.value().name() == pk )
3277+
if ( fldIt.value().name() == primaryKey )
32783278
{
32793279
// it already exists, try again with a new name
32803280
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );

0 commit comments

Comments
 (0)