Skip to content

Commit a6cad4d

Browse files
committed
New Shapefile Layer dialog: avoid warning message on user cancel
Also add better error message reporting, and deprecate horrible API. (cherry picked from commit 9a723d9)
1 parent dbd7512 commit a6cad4d

File tree

6 files changed

+149
-24
lines changed

6 files changed

+149
-24
lines changed

python/gui/auto_generated/qgsnewvectorlayerdialog.sip.in

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,46 @@ class QgsNewVectorLayerDialog: QDialog
1717
%End
1818
public:
1919

20-
static QString runAndCreateLayer( QWidget *parent = 0, QString *enc = 0, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
20+
static QString runAndCreateLayer( QWidget *parent = 0, QString *enc = 0, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(),
21+
const QString &initialPath = QString() ) /Deprecated/;
2122
%Docstring
2223
Runs the dialog and creates a layer matching the dialog parameters.
2324

25+
If the ``initialPath`` argument is specified, then the dialog will default to the specified filename.
26+
2427
:return: fileName on success, empty string use aborted, QString() if creation failed
28+
29+
.. deprecated:: in QGIS 3.4.5 - use execAndCreateLayer() instead.
30+
%End
31+
32+
static QString execAndCreateLayer( QString &errorMessage /Out/, QWidget *parent = 0, const QString &initialPath = QString(), QString *encoding /Out/ = 0, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
33+
%Docstring
34+
Runs the dialog and creates a layer matching the dialog parameters.
35+
36+
If the ``initialPath`` argument is specified, then the dialog will default to the specified filename.
37+
38+
Returns a filename if the dialog was accepted, or an empty string if the dialog was canceled.
39+
If the dialog was accepted but an error occurred while creating the file, then the function will
40+
return an empty string and ``errorMessage`` will contain the error message.
41+
42+
If ``encoding`` is specified, it will be set to the encoding of the created file.
43+
44+
:param errorMessage: will be set to any error message encountered during layer creation
45+
:param parent: parent widget for dialog
46+
:param initialPath: initial file path to show in dialog
47+
:param encoding: if specified, will be set to file encoding of created layer
48+
:param crs: default layer CRS to show in dialog
49+
50+
:return: Newly created file name, or an empty string if user canceled or an error occurred.
51+
52+
53+
.. versionadded:: 3.4.5
2554
%End
2655

2756
QgsNewVectorLayerDialog( QWidget *parent /TransferThis/ = 0, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
57+
%Docstring
58+
New dialog constructor.
59+
%End
2860
~QgsNewVectorLayerDialog();
2961
QgsWkbTypes::Type selectedType() const;
3062
%Docstring
@@ -42,9 +74,21 @@ Returns the file format for storage
4274
%Docstring
4375
Returns the file format for storage
4476
%End
77+
4578
QString filename() const;
4679
%Docstring
4780
Returns the name for the new layer
81+
82+
.. seealso:: :py:func:`setFilename`
83+
%End
84+
85+
void setFilename( const QString &filename );
86+
%Docstring
87+
Sets the initial file name to show in the dialog.
88+
89+
.. seealso:: :py:func:`filename`
90+
91+
.. versionadded:: 3.4.5
4892
%End
4993

5094
QgsCoordinateReferenceSystem crs() const;

src/app/qgisapp.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5602,7 +5602,8 @@ void QgisApp::fileNewFromTemplateAction( QAction *qAction )
56025602
void QgisApp::newVectorLayer()
56035603
{
56045604
QString enc;
5605-
QString fileName = QgsNewVectorLayerDialog::runAndCreateLayer( this, &enc, QgsProject::instance()->defaultCrsForNewLayers() );
5605+
QString error;
5606+
QString fileName = QgsNewVectorLayerDialog::execAndCreateLayer( error, this, QString(), &enc, QgsProject::instance()->defaultCrsForNewLayers() );
56065607

56075608
if ( !fileName.isEmpty() )
56085609
{
@@ -5612,12 +5613,12 @@ void QgisApp::newVectorLayer()
56125613
//todo: the last parameter will change accordingly to layer type
56135614
addVectorLayers( fileNames, enc, QStringLiteral( "file" ) );
56145615
}
5615-
else if ( fileName.isNull() )
5616+
else if ( !error.isEmpty() )
56165617
{
5617-
QLabel *msgLabel = new QLabel( tr( "Layer creation failed. Please check the <a href=\"#messageLog\">message log</a> for further information." ), messageBar() );
5618+
QLabel *msgLabel = new QLabel( tr( "Layer creation failed: %1" ).arg( error ), messageBar() );
56185619
msgLabel->setWordWrap( true );
56195620
connect( msgLabel, &QLabel::linkActivated, mLogDock, &QWidget::show );
5620-
QgsMessageBarItem *item = new QgsMessageBarItem( msgLabel, Qgis::Warning );
5621+
QgsMessageBarItem *item = new QgsMessageBarItem( msgLabel, Qgis::Critical );
56215622
messageBar()->pushItem( item );
56225623
}
56235624
}

src/gui/qgsnewvectorlayerdialog.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include <QComboBox>
3131
#include <QLibrary>
3232
#include <QFileDialog>
33-
33+
#include <QMessageBox>
3434

3535
QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFlags fl )
3636
: QDialog( parent, fl )
@@ -105,6 +105,7 @@ QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFla
105105

106106
mFileName->setStorageMode( QgsFileWidget::SaveFile );
107107
mFileName->setFilter( QgsVectorFileWriter::filterForDriver( mFileFormatComboBox->currentData( Qt::UserRole ).toString() ) );
108+
mFileName->setConfirmOverwrite( false );
108109
mFileName->setDialogTitle( tr( "Save Layer As" ) );
109110
mFileName->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() );
110111
connect( mFileName, &QgsFileWidget::fileChanged, this, [ = ]
@@ -246,22 +247,43 @@ QString QgsNewVectorLayerDialog::filename() const
246247
return mFileName->filePath();
247248
}
248249

250+
void QgsNewVectorLayerDialog::setFilename( const QString &filename )
251+
{
252+
mFileName->setFilePath( filename );
253+
}
254+
249255
void QgsNewVectorLayerDialog::checkOk()
250256
{
251257
bool ok = ( !mFileName->filePath().isEmpty() && mAttributeView->topLevelItemCount() > 0 );
252258
mOkButton->setEnabled( ok );
253259
}
254260

255261
// this is static
256-
QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pEnc, const QgsCoordinateReferenceSystem &crs )
262+
QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pEnc, const QgsCoordinateReferenceSystem &crs, const QString &initialPath )
263+
{
264+
QString error;
265+
QString res = execAndCreateLayer( error, parent, initialPath, pEnc, crs );
266+
if ( res.isEmpty() && error.isEmpty() )
267+
res = QString( "" ); // maintain gross earlier API compatibility
268+
return res;
269+
}
270+
271+
QString QgsNewVectorLayerDialog::execAndCreateLayer( QString &errorMessage, QWidget *parent, const QString &initialPath, QString *encoding, const QgsCoordinateReferenceSystem &crs )
257272
{
273+
errorMessage.clear();
258274
QgsNewVectorLayerDialog geomDialog( parent );
259275
geomDialog.setCrs( crs );
276+
if ( !initialPath.isEmpty() )
277+
geomDialog.setFilename( initialPath );
260278
if ( geomDialog.exec() == QDialog::Rejected )
261279
{
262280
return QString();
263281
}
264282

283+
if ( QFile::exists( geomDialog.filename() ) && QMessageBox::warning( parent, tr( "New ShapeFile Layer" ), tr( "The layer already exists. Are you sure you want to overwrite the existing file?" ),
284+
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel ) != QMessageBox::Yes )
285+
return QString();
286+
265287
QgsWkbTypes::Type geometrytype = geomDialog.selectedType();
266288
QString fileformat = geomDialog.selectedFileFormat();
267289
QString enc = geomDialog.selectedFileEncoding();
@@ -289,33 +311,35 @@ QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pE
289311
QgsDebugMsg( QStringLiteral( "ogr provider loaded" ) );
290312

291313
typedef bool ( *createEmptyDataSourceProc )( const QString &, const QString &, const QString &, QgsWkbTypes::Type,
292-
const QList< QPair<QString, QString> > &, const QgsCoordinateReferenceSystem & );
314+
const QList< QPair<QString, QString> > &, const QgsCoordinateReferenceSystem &, QString & );
293315
createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( myLib->resolve( "createEmptyDataSource" ) );
294316
if ( createEmptyDataSource )
295317
{
296318
if ( geometrytype != QgsWkbTypes::Unknown )
297319
{
298320
QgsCoordinateReferenceSystem srs = geomDialog.crs();
299-
if ( !createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, srs ) )
321+
if ( !createEmptyDataSource( fileName, fileformat, enc, geometrytype, attributes, srs, errorMessage ) )
300322
{
301323
return QString();
302324
}
303325
}
304326
else
305327
{
306-
QgsDebugMsg( QStringLiteral( "geometry type not recognised" ) );
328+
errorMessage = QObject::tr( "Geometry type not recognised" );
329+
QgsDebugMsg( errorMessage );
307330
return QString();
308331
}
309332
}
310333
else
311334
{
312-
QgsDebugMsg( QStringLiteral( "Resolving newEmptyDataSource(...) failed" ) );
335+
errorMessage = QObject::tr( "Resolving newEmptyDataSource(...) failed" );
336+
QgsDebugMsg( errorMessage );
313337
return QString();
314338
}
315339
}
316340

317-
if ( pEnc )
318-
*pEnc = enc;
341+
if ( encoding )
342+
*encoding = enc;
319343

320344
return fileName;
321345
}
@@ -324,3 +348,4 @@ void QgsNewVectorLayerDialog::showHelp()
324348
{
325349
QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-shapefile-layer" ) );
326350
}
351+

src/gui/qgsnewvectorlayerdialog.h

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
#include "qgsguiutils.h"
2222
#include "qgshelp.h"
2323

24-
#include "qgis.h"
24+
#include "qgswkbtypes.h"
2525
#include "qgis_gui.h"
26+
#include "qgis_sip.h"
2627

2728
/**
2829
* \ingroup gui
@@ -36,10 +37,42 @@ class GUI_EXPORT QgsNewVectorLayerDialog: public QDialog, private Ui::QgsNewVect
3637

3738
/**
3839
* Runs the dialog and creates a layer matching the dialog parameters.
40+
*
41+
* If the \a initialPath argument is specified, then the dialog will default to the specified filename.
42+
*
3943
* \returns fileName on success, empty string use aborted, QString() if creation failed
44+
*
45+
* \deprecated in QGIS 3.4.5 - use execAndCreateLayer() instead.
4046
*/
41-
static QString runAndCreateLayer( QWidget *parent = nullptr, QString *enc = nullptr, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
47+
Q_DECL_DEPRECATED static QString runAndCreateLayer( QWidget *parent = nullptr, QString *enc = nullptr, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(),
48+
const QString &initialPath = QString() ) SIP_DEPRECATED;
4249

50+
/**
51+
* Runs the dialog and creates a layer matching the dialog parameters.
52+
*
53+
* If the \a initialPath argument is specified, then the dialog will default to the specified filename.
54+
*
55+
* Returns a filename if the dialog was accepted, or an empty string if the dialog was canceled.
56+
* If the dialog was accepted but an error occurred while creating the file, then the function will
57+
* return an empty string and \a errorMessage will contain the error message.
58+
*
59+
* If \a encoding is specified, it will be set to the encoding of the created file.
60+
*
61+
* \param errorMessage will be set to any error message encountered during layer creation
62+
* \param parent parent widget for dialog
63+
* \param initialPath initial file path to show in dialog
64+
* \param encoding if specified, will be set to file encoding of created layer
65+
* \param crs default layer CRS to show in dialog
66+
*
67+
* \returns Newly created file name, or an empty string if user canceled or an error occurred.
68+
*
69+
* \since QGIS 3.4.5
70+
*/
71+
static QString execAndCreateLayer( QString &errorMessage SIP_OUT, QWidget *parent = nullptr, const QString &initialPath = QString(), QString *encoding SIP_OUT = nullptr, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
72+
73+
/**
74+
* New dialog constructor.
75+
*/
4376
QgsNewVectorLayerDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
4477
~QgsNewVectorLayerDialog() override;
4578
//! Returns the selected geometry type
@@ -50,9 +83,23 @@ class GUI_EXPORT QgsNewVectorLayerDialog: public QDialog, private Ui::QgsNewVect
5083
QString selectedFileFormat() const;
5184
//! Returns the file format for storage
5285
QString selectedFileEncoding() const;
53-
//! Returns the name for the new layer
86+
87+
/**
88+
* Returns the name for the new layer
89+
*
90+
* \see setFilename()
91+
*/
5492
QString filename() const;
5593

94+
/**
95+
* Sets the initial file name to show in the dialog.
96+
*
97+
* \see filename()
98+
*
99+
* \since QGIS 3.4.5
100+
*/
101+
void setFilename( const QString &filename );
102+
56103
/**
57104
* Returns the selected CRS for the new layer.
58105
* \see setCrs()

src/plugins/geometry_checker/qgsgeometrycheckerresulttab.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,14 @@ bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString &file )
261261
{
262262
return false;
263263
}
264-
typedef bool ( *createEmptyDataSourceProc )( const QString &, const QString &, const QString &, QgsWkbTypes::Type, const QList< QPair<QString, QString> > &, const QgsCoordinateReferenceSystem & );
264+
typedef bool ( *createEmptyDataSourceProc )( const QString &, const QString &, const QString &, QgsWkbTypes::Type, const QList< QPair<QString, QString> > &, const QgsCoordinateReferenceSystem &, QString & );
265265
createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( ogrLib.resolve( "createEmptyDataSource" ) );
266266
if ( !createEmptyDataSource )
267267
{
268268
return false;
269269
}
270-
if ( !createEmptyDataSource( file, driver, "UTF-8", QgsWkbTypes::Point, attributes, QgsProject::instance()->crs() ) )
270+
QString createError;
271+
if ( !createEmptyDataSource( file, driver, "UTF-8", QgsWkbTypes::Point, attributes, QgsProject::instance()->crs(), createError ) )
271272
{
272273
return false;
273274
}

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,9 +3183,11 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
31833183
const QString &encoding,
31843184
QgsWkbTypes::Type vectortype,
31853185
const QList< QPair<QString, QString> > &attributes,
3186-
const QgsCoordinateReferenceSystem &srs = QgsCoordinateReferenceSystem() )
3186+
const QgsCoordinateReferenceSystem &srs,
3187+
QString &errorMessage )
31873188
{
31883189
QgsDebugMsg( QStringLiteral( "Creating empty vector layer with format: %1" ).arg( format ) );
3190+
errorMessage.clear();
31893191

31903192
QgsApplication::registerOgrDrivers();
31913193
OGRSFDriverH driver = OGRGetDriverByName( format.toLatin1() );
@@ -3200,7 +3202,8 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
32003202
{
32013203
if ( !uri.endsWith( QLatin1String( ".shp" ), Qt::CaseInsensitive ) )
32023204
{
3203-
QgsDebugMsg( QStringLiteral( "uri %1 doesn't end with .shp" ).arg( uri ) );
3205+
errorMessage = QObject::tr( "URI %1 doesn't end with .shp" ).arg( uri );
3206+
QgsDebugMsg( errorMessage );
32043207
return false;
32053208
}
32063209

@@ -3212,7 +3215,8 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
32123215
QString name = fldIt->first.left( 10 );
32133216
if ( fieldNames.contains( name ) )
32143217
{
3215-
QgsMessageLog::logMessage( QObject::tr( "Duplicate field (10 significant characters): %1" ).arg( name ), QObject::tr( "OGR" ) );
3218+
errorMessage = QObject::tr( "Duplicate field (10 significant characters): %1" ).arg( name );
3219+
QgsMessageLog::logMessage( errorMessage, QObject::tr( "OGR" ) );
32163220
return false;
32173221
}
32183222
fieldNames << name;
@@ -3229,7 +3233,8 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
32293233
dataSource.reset( OGR_Dr_CreateDataSource( driver, uri.toUtf8().constData(), nullptr ) );
32303234
if ( !dataSource )
32313235
{
3232-
QgsMessageLog::logMessage( QObject::tr( "Creating the data source %1 failed: %2" ).arg( uri, QString::fromUtf8( CPLGetLastErrorMsg() ) ), QObject::tr( "OGR" ) );
3236+
errorMessage = QObject::tr( "Creating the data source %1 failed: %2" ).arg( uri, QString::fromUtf8( CPLGetLastErrorMsg() ) );
3237+
QgsMessageLog::logMessage( errorMessage, QObject::tr( "OGR" ) );
32333238
return false;
32343239
}
32353240

@@ -3263,7 +3268,8 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
32633268
case QgsWkbTypes::GeometryCollectionZM:
32643269
case QgsWkbTypes::Unknown:
32653270
{
3266-
QgsMessageLog::logMessage( QObject::tr( "Unknown vector type of %1" ).arg( ( int )( vectortype ) ), QObject::tr( "OGR" ) );
3271+
errorMessage = QObject::tr( "Unknown vector type of %1" ).arg( static_cast< int >( vectortype ) );
3272+
QgsMessageLog::logMessage( errorMessage, QObject::tr( "OGR" ) );
32673273
return false;
32683274
}
32693275

@@ -3292,7 +3298,8 @@ QGISEXTERN bool createEmptyDataSource( const QString &uri,
32923298

32933299
if ( !layer )
32943300
{
3295-
QgsMessageLog::logMessage( QObject::tr( "Creation of OGR data source %1 failed: %2" ).arg( uri, QString::fromUtf8( CPLGetLastErrorMsg() ) ), QObject::tr( "OGR" ) );
3301+
errorMessage = QString::fromUtf8( CPLGetLastErrorMsg() );
3302+
QgsMessageLog::logMessage( errorMessage, QObject::tr( "OGR" ) );
32963303
return false;
32973304
}
32983305

0 commit comments

Comments
 (0)