Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- [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
  • Loading branch information
jef-n committed Jan 7, 2013
1 parent 4cffd07 commit 460f578
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 18 deletions.
7 changes: 5 additions & 2 deletions python/core/qgsvectorlayerimport.sip
Expand Up @@ -9,6 +9,7 @@ class QgsVectorLayerImport
%TypeHeaderCode
#include <qgsvectorlayerimport.h>
#include <qgsfield.h>
class QProgressDialog;
%End

public:
Expand Down Expand Up @@ -37,7 +38,8 @@ class QgsVectorLayerImport
bool onlySelected = false,
QString *errorMessage /Out/ = 0,
bool skipAttributeCreation = false,
QMap<QString, QVariant> *options = 0
QMap<QString, QVariant> *options = 0,
QProgressDialog *progress = 0
);

/** create a empty layer and add fields to it */
Expand All @@ -47,7 +49,8 @@ class QgsVectorLayerImport
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* crs,
bool overwrite = false,
const QMap<QString, QVariant> *options = 0
const QMap<QString, QVariant> *options = 0,
QProgressDialog *progress = 0
);

/** checks whether there were any errors */
Expand Down
32 changes: 28 additions & 4 deletions src/core/qgsvectorlayerimport.cpp
Expand Up @@ -25,6 +25,8 @@
#include "qgsvectorlayerimport.h"
#include "qgsproviderregistry.h"

#include <QProgressDialog>

#define FEATURE_BUFFER_SIZE 200

typedef QgsVectorLayerImport::ImportError createEmptyLayer_t(
Expand All @@ -45,8 +47,10 @@ QgsVectorLayerImport::QgsVectorLayerImport( const QString &uri,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* crs,
bool overwrite,
const QMap<QString, QVariant> *options )
const QMap<QString, QVariant> *options,
QProgressDialog *progress )
: mErrorCount( 0 )
, mProgress( progress )
{
mProvider = NULL;

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

QgsVectorDataProvider *vectorProvider = ( QgsVectorDataProvider* ) pReg->provider( providerKey, uri );
if ( !vectorProvider || !vectorProvider->isValid() )
if ( !vectorProvider || !vectorProvider->isValid() || ( vectorProvider->capabilities() & QgsVectorDataProvider::AddFeatures ) == 0 )
{
mError = ErrInvalidLayer;
mErrorMessage = QObject::tr( "Loading of layer failed" );
Expand Down Expand Up @@ -181,7 +185,8 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
bool onlySelected,
QString *errorMessage,
bool skipAttributeCreation,
QMap<QString, QVariant> *options )
QMap<QString, QVariant> *options,
QProgressDialog *progress )
{
const QgsCoordinateReferenceSystem* outputCRS;
QgsCoordinateTransform* ct = 0;
Expand Down Expand Up @@ -255,7 +260,7 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
}

QgsVectorLayerImport * writer =
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options );
new QgsVectorLayerImport( uri, providerKey, fields, wkbType, outputCRS, overwrite, options, progress );

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

if ( progress )
{
progress->setRange( 0, layer->featureCount() );
}

// write all features
while ( layer->nextFeature( fet ) )
{
if ( progress && progress->wasCanceled() )
{
if ( errorMessage )
{
*errorMessage += "\n" + QObject::tr( "Import was canceled at %1 of %2" ).arg( progress->value() ).arg( progress->maximum() );
}
break;
}

if ( writer->errorCount() > 1000 )
{
if ( errorMessage )
Expand Down Expand Up @@ -348,6 +367,11 @@ QgsVectorLayerImport::importLayer( QgsVectorLayer* layer,
}
}
n++;

if ( progress )
{
progress->setValue( n );
}
}

// flush the buffer to be sure that all features are written
Expand Down
9 changes: 7 additions & 2 deletions src/core/qgsvectorlayerimport.h
Expand Up @@ -22,6 +22,8 @@
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"

class QProgressDialog;

/** \ingroup core
* A convenience class for writing vector files to disk.
There are two possibilities how to use this class:
Expand Down Expand Up @@ -59,7 +61,8 @@ class CORE_EXPORT QgsVectorLayerImport
bool onlySelected = false,
QString *errorMessage = 0,
bool skipAttributeCreation = false,
QMap<QString, QVariant> *options = 0
QMap<QString, QVariant> *options = 0,
QProgressDialog *progress = 0
);

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

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

QgsFeatureList mFeatureBuffer;
QProgressDialog *mProgress;
};

#endif
2 changes: 1 addition & 1 deletion src/providers/mssql/qgsmssqlprovider.cpp
Expand Up @@ -1686,7 +1686,7 @@ QgsVectorLayerImport::ImportError QgsMssqlProvider::createEmptyLayer(
QString pk = primaryKey = "qgs_fid";
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
{
if ( fldIt.value().name() == pk )
if ( fldIt.value().name() == primaryKey )
{
// it already exists, try again with a new name
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );
Expand Down
58 changes: 50 additions & 8 deletions src/providers/postgres/qgspostgresdataitems.cpp
Expand Up @@ -22,18 +22,51 @@
#include "qgsapplication.h"

#include <QMessageBox>
#include <QProgressDialog>

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

// ---------------------------------------------------------------------------
QgsPGConnectionItem::QgsPGConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
, mColumnTypeThread( 0 )
{
mIcon = QgsApplication::getThemeIcon( "mIconConnect.png" );
}

QgsPGConnectionItem::~QgsPGConnectionItem()
{
stop();
}

void QgsPGConnectionItem::stop()
{
if ( mColumnTypeThread )
{
mColumnTypeThread->stop();
mColumnTypeThread->wait();
delete mColumnTypeThread;
mColumnTypeThread = 0;
}
}

void QgsPGConnectionItem::refresh()
{
QApplication::setOverrideCursor( Qt::WaitCursor );

stop();

foreach ( QgsDataItem *child, mChildren )
{
deleteChildItem( child );
}

foreach ( QgsDataItem *item, createChildren() )
{
addChildItem( item, true );
}

QApplication::restoreOverrideCursor();
}

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

mSchemaMap.clear();

mConn = QgsPostgresConn::connectDb( uri.connectionInfo(), true );
if ( !mConn )
return children;
Expand All @@ -62,7 +97,7 @@ QVector<QgsDataItem*> QgsPGConnectionItem::createChildren()
return children;
}

QgsGeomColumnTypeThread *columnTypeThread = 0;
stop();

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

if ( QgsPostgresConn::wkbTypeFromPostgis( layerProperty.type ) == QGis::WKBUnknown )
{
if ( !columnTypeThread )
if ( !mColumnTypeThread )
{
QgsPostgresConn *conn = QgsPostgresConn::connectDb( uri.connectionInfo(), true /* readonly */ );
if ( conn )
{
columnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );
mColumnTypeThread = new QgsGeomColumnTypeThread( conn, true /* use estimated metadata */ );

connect( columnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
connect( mColumnTypeThread, SIGNAL( setLayerType( QgsPostgresLayerProperty ) ),
this, SLOT( setLayerType( QgsPostgresLayerProperty ) ) );
connect( this, SIGNAL( addGeometryColumn( QgsPostgresLayerProperty ) ),
columnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
mColumnTypeThread, SLOT( addGeometryColumn( QgsPostgresLayerProperty ) ) );
}
}

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

if ( columnTypeThread )
columnTypeThread->start();
if ( mColumnTypeThread )
mColumnTypeThread->start();

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

qApp->setOverrideCursor( Qt::WaitCursor );

QProgressDialog *progress = new QProgressDialog( tr( "Copying features..." ), tr( "Abort" ), 0, 0, 0 );
progress->setWindowTitle( tr( "Import layer" ) );
progress->setWindowModality( Qt::WindowModal );
progress->show();

QStringList importResults;
bool hasError = false;
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
Expand All @@ -207,7 +247,7 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
QgsDebugMsg( "URI " + uri.uri() );
QgsVectorLayerImport::ImportError err;
QString importError;
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError );
err = QgsVectorLayerImport::importLayer( srcLayer, uri.uri(), "postgres", &srcLayer->crs(), false, &importError, false, 0, progress );
if ( err == QgsVectorLayerImport::NoError )
importResults.append( tr( "%1: OK!" ).arg( u.name ) );
else
Expand All @@ -225,6 +265,8 @@ bool QgsPGConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
delete srcLayer;
}

delete progress;

qApp->restoreOverrideCursor();

if ( hasError )
Expand Down
4 changes: 4 additions & 0 deletions src/providers/postgres/qgspostgresdataitems.h
Expand Up @@ -61,6 +61,8 @@ class QgsPGConnectionItem : public QgsDataCollectionItem

QgsPostgresConn *connection() const { return mConn; }

void refresh();

signals:
void addGeometryColumn( QgsPostgresLayerProperty );

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

private:
void stop();
QgsPostgresConn *mConn;
QMap<QString, QgsPGSchemaItem * > mSchemaMap;
QgsGeomColumnTypeThread *mColumnTypeThread;
};

class QgsPGSchemaItem : public QgsDataCollectionItem
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -3274,7 +3274,7 @@ QgsVectorLayerImport::ImportError QgsPostgresProvider::createEmptyLayer(
QString pk = primaryKey = "id";
for ( QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
{
if ( fldIt.value().name() == pk )
if ( fldIt.value().name() == primaryKey )
{
// it already exists, try again with a new name
primaryKey = QString( "%1_%2" ).arg( pk ).arg( index++ );
Expand Down

0 comments on commit 460f578

Please sign in to comment.