QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsnewgeopackagelayerdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsnewgeopackagelayerdialog.cpp
3 
4  -------------------
5  begin : April 2016
6  copyright : (C) 2016 by Even Rouault
7  email : even.rouault at spatialys.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 
21 
22 #include "qgis.h"
23 #include "qgsapplication.h"
24 #include "qgsproviderregistry.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsproject.h"
29 #include "qgslogger.h"
30 #include "qgssettings.h"
31 #include "qgshelp.h"
32 #include "qgsogrutils.h"
33 #include "qgsgui.h"
35 
36 #include <QPushButton>
37 #include <QLineEdit>
38 #include <QMessageBox>
39 #include <QFileDialog>
40 #include <QCompleter>
41 
42 #include <ogr_api.h>
43 #include <ogr_srs_api.h>
44 #include <gdal_version.h>
45 #include <cpl_error.h>
46 #include <cpl_string.h>
47 
48 #define DEFAULT_OGR_FID_COLUMN_TITLE "fid" // default value from OGR
49 
50 QgsNewGeoPackageLayerDialog::QgsNewGeoPackageLayerDialog( QWidget *parent, Qt::WindowFlags fl )
51  : QDialog( parent, fl )
52 {
53  setupUi( this );
55 
56  connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewGeoPackageLayerDialog::mAddAttributeButton_clicked );
57  connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewGeoPackageLayerDialog::mRemoveAttributeButton_clicked );
58  connect( mFieldTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewGeoPackageLayerDialog::mFieldTypeBox_currentIndexChanged );
59  connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewGeoPackageLayerDialog::mGeometryTypeBox_currentIndexChanged );
60  connect( mTableNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::mTableNameEdit_textChanged );
61  connect( mTableNameEdit, &QLineEdit::textEdited, this, &QgsNewGeoPackageLayerDialog::mTableNameEdit_textEdited );
62  connect( mLayerIdentifierEdit, &QLineEdit::textEdited, this, &QgsNewGeoPackageLayerDialog::mLayerIdentifierEdit_textEdited );
63  connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsNewGeoPackageLayerDialog::buttonBox_accepted );
64  connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsNewGeoPackageLayerDialog::buttonBox_rejected );
65  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsNewGeoPackageLayerDialog::showHelp );
66 
67  mAddAttributeButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewAttribute.svg" ) ) );
68  mRemoveAttributeButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteAttribute.svg" ) ) );
69 
70  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) ), tr( "No Geometry" ), wkbNone );
71  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "Point" ), wkbPoint );
72  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "Line" ), wkbLineString );
73  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "Polygon" ), wkbPolygon );
74  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) ), tr( "MultiPoint" ), wkbMultiPoint );
75  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiLine" ), wkbMultiLineString );
76  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiPolygon" ), wkbMultiPolygon );
77 
78 #if 0
79  // QGIS always create CompoundCurve and there's no real interest of having just CircularString. CompoundCurve are more useful
80  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "CircularString" ), wkbCircularString );
81 #endif
82  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "CompoundCurve" ), wkbCompoundCurve );
83  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "CurvePolygon" ), wkbCurvePolygon );
84  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) ), tr( "MultiCurve" ), wkbMultiCurve );
85  mGeometryTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) ), tr( "MultiSurface" ), wkbMultiSurface );
86  mGeometryTypeBox->setCurrentIndex( -1 );
87 
88  mGeometryWithZCheckBox->setEnabled( false );
89  mGeometryWithMCheckBox->setEnabled( false );
90  mGeometryColumnEdit->setEnabled( false );
91  mGeometryColumnEdit->setText( QStringLiteral( "geometry" ) );
92  mFeatureIdColumnEdit->setPlaceholderText( QStringLiteral( DEFAULT_OGR_FID_COLUMN_TITLE ) );
93  mCheckBoxCreateSpatialIndex->setEnabled( false );
94  mCrsSelector->setEnabled( false );
95 
96  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) ), tr( "Text Data" ), "text" );
97  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole Number (integer)" ), "integer" );
98  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole Number (integer 64 bit)" ), "integer64" );
99  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal Number (real)" ), "real" );
100  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) ), tr( "Date" ), "date" );
101  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) ), tr( "Date and Time" ), "datetime" );
102  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) ), tr( "Boolean" ), "bool" );
103  mFieldTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) ), tr( "Binary (BLOB)" ), "binary" );
104 
105  mOkButton = buttonBox->button( QDialogButtonBox::Ok );
106  mOkButton->setEnabled( false );
107 
108  connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::fieldNameChanged );
109  connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewGeoPackageLayerDialog::selectionChanged );
110  connect( mTableNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::checkOk );
111  connect( mGeometryTypeBox, static_cast<void( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewGeoPackageLayerDialog::checkOk );
112 
113  mAddAttributeButton->setEnabled( false );
114  mRemoveAttributeButton->setEnabled( false );
115 
116  mCheckBoxCreateSpatialIndex->setChecked( true );
117 
118  QgsSettings settings;
119  mDatabase->setStorageMode( QgsFileWidget::SaveFile );
120  mDatabase->setFilter( tr( "GeoPackage" ) + " (*.gpkg)" );
121  mDatabase->setDialogTitle( tr( "Select Existing or Create a New GeoPackage Database Fileā€¦" ) );
122  mDatabase->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() );
123  mDatabase->setConfirmOverwrite( false );
124  connect( mDatabase, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath )
125  {
126  QgsSettings settings;
127  QFileInfo tmplFileInfo( filePath );
128  settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() );
129  if ( !filePath.isEmpty() && !mTableNameEdited )
130  {
131  QFileInfo fileInfo( filePath );
132  mTableNameEdit->setText( fileInfo.baseName() );
133  }
134  checkOk();
135  } );
136 
137  QgsProviderConnectionModel *ogrProviderModel = new QgsProviderConnectionModel( QStringLiteral( "ogr" ), this );
138 
139  QCompleter *completer = new QCompleter( this );
140  completer->setModel( ogrProviderModel );
141  completer->setCompletionRole( QgsProviderConnectionModel::RoleUri );
142  completer->setCompletionMode( QCompleter::PopupCompletion );
143  completer->setFilterMode( Qt::MatchContains );
144  mDatabase->lineEdit()->setCompleter( completer );
145 }
146 
148 {
149  mCrsSelector->setCrs( crs );
150 }
151 
153 {
154  mDatabase->setReadOnly( true );
155 }
156 
157 void QgsNewGeoPackageLayerDialog::mFieldTypeBox_currentIndexChanged( int )
158 {
159  QString myType = mFieldTypeBox->currentData( Qt::UserRole ).toString();
160  mFieldLengthEdit->setEnabled( myType == QLatin1String( "text" ) );
161  if ( myType != QLatin1String( "text" ) )
162  mFieldLengthEdit->clear();
163 }
164 
165 
166 void QgsNewGeoPackageLayerDialog::mGeometryTypeBox_currentIndexChanged( int )
167 {
168  OGRwkbGeometryType geomType = static_cast<OGRwkbGeometryType>
169  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
170  bool isSpatial = geomType != wkbNone;
171  mGeometryWithZCheckBox->setEnabled( isSpatial );
172  mGeometryWithMCheckBox->setEnabled( isSpatial );
173  mGeometryColumnEdit->setEnabled( isSpatial );
174  mCheckBoxCreateSpatialIndex->setEnabled( isSpatial );
175  mCrsSelector->setEnabled( isSpatial );
176 }
177 
178 void QgsNewGeoPackageLayerDialog::mTableNameEdit_textChanged( const QString &text )
179 {
180  mTableNameEdited = !text.isEmpty();
181  if ( !text.isEmpty() && !mLayerIdentifierEdited )
182  {
183  mLayerIdentifierEdit->setText( text );
184  }
185 }
186 
187 void QgsNewGeoPackageLayerDialog::mTableNameEdit_textEdited( const QString &text )
188 {
189  // Remember if the user explicitly defined a name
190  mTableNameEdited = !text.isEmpty();
191 }
192 
193 void QgsNewGeoPackageLayerDialog::mLayerIdentifierEdit_textEdited( const QString &text )
194 {
195  // Remember if the user explicitly defined a name
196  mLayerIdentifierEdited = !text.isEmpty();
197 }
198 
199 void QgsNewGeoPackageLayerDialog::checkOk()
200 {
201  bool ok = !mDatabase->filePath().isEmpty() &&
202  !mTableNameEdit->text().isEmpty() &&
203  mGeometryTypeBox->currentIndex() != -1;
204 
205  mOkButton->setEnabled( ok );
206 }
207 
208 void QgsNewGeoPackageLayerDialog::mAddAttributeButton_clicked()
209 {
210  if ( !mFieldNameEdit->text().isEmpty() )
211  {
212  QString myName = mFieldNameEdit->text();
213  const QString featureId = mFeatureIdColumnEdit->text().isEmpty() ? QStringLiteral( DEFAULT_OGR_FID_COLUMN_TITLE ) : mFeatureIdColumnEdit->text();
214  if ( myName.compare( featureId, Qt::CaseInsensitive ) == 0 )
215  {
216  QMessageBox::critical( this, tr( "Add Field" ), tr( "The field cannot have the same name as the feature identifier." ) );
217  return;
218  }
219 
220  //use userrole to avoid translated type string
221  QString myType = mFieldTypeBox->currentData( Qt::UserRole ).toString();
222  QString length = mFieldLengthEdit->text();
223  mAttributeView->addTopLevelItem( new QTreeWidgetItem( QStringList() << myName << myType << length ) );
224 
225  checkOk();
226 
227  mFieldNameEdit->clear();
228  }
229 }
230 
231 void QgsNewGeoPackageLayerDialog::mRemoveAttributeButton_clicked()
232 {
233  delete mAttributeView->currentItem();
234 
235  checkOk();
236 }
237 
238 void QgsNewGeoPackageLayerDialog::fieldNameChanged( const QString &name )
239 {
240  mAddAttributeButton->setDisabled( name.isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
241 }
242 
243 void QgsNewGeoPackageLayerDialog::selectionChanged()
244 {
245  mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
246 }
247 
248 void QgsNewGeoPackageLayerDialog::buttonBox_accepted()
249 {
250  if ( apply() )
251  accept();
252 }
253 
254 void QgsNewGeoPackageLayerDialog::buttonBox_rejected()
255 {
256  reject();
257 }
258 
259 bool QgsNewGeoPackageLayerDialog::apply()
260 {
261  QString fileName( mDatabase->filePath() );
262  if ( !fileName.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) )
263  fileName += QLatin1String( ".gpkg" );
264 
265  bool createNewDb = false;
266 
267  if ( QFile( fileName ).exists( fileName ) )
268  {
269  bool overwrite = false;
270 
271  switch ( mBehavior )
272  {
273  case Prompt:
274  {
275  QMessageBox msgBox;
276  msgBox.setIcon( QMessageBox::Question );
277  msgBox.setWindowTitle( tr( "New GeoPackage Layer" ) );
278  msgBox.setText( tr( "The File already exists. Do you want to overwrite the existing file with a new database or add a new layer to it?" ) );
279  QPushButton *overwriteButton = msgBox.addButton( tr( "Overwrite" ), QMessageBox::ActionRole );
280  QPushButton *addNewLayerButton = msgBox.addButton( tr( "Add New Layer" ), QMessageBox::ActionRole );
281  msgBox.setStandardButtons( QMessageBox::Cancel );
282  msgBox.setDefaultButton( addNewLayerButton );
283  bool cancel = false;
284  if ( property( "hideDialogs" ).toBool() )
285  {
286  overwrite = property( "question_existing_db_answer_overwrite" ).toBool();
287  if ( !overwrite )
288  cancel = !property( "question_existing_db_answer_add_new_layer" ).toBool();
289  }
290  else
291  {
292  int ret = msgBox.exec();
293  if ( ret == QMessageBox::Cancel )
294  cancel = true;
295  if ( msgBox.clickedButton() == overwriteButton )
296  overwrite = true;
297  }
298  if ( cancel )
299  {
300  return false;
301  }
302  break;
303  }
304 
305  case Overwrite:
306  overwrite = true;
307  break;
308 
309  case AddNewLayer:
310  overwrite = false;
311  break;
312  }
313 
314  if ( overwrite )
315  {
316  QFile( fileName ).remove();
317  createNewDb = true;
318  }
319  }
320  else
321  {
322  createNewDb = true;
323  }
324 
325  OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" );
326  if ( !hGpkgDriver )
327  {
328  if ( !property( "hideDialogs" ).toBool() )
329  QMessageBox::critical( this, tr( "New GeoPackage Layer" ),
330  tr( "Layer creation failed. GeoPackage driver not found." ) );
331  return false;
332  }
333 
335  if ( createNewDb )
336  {
337  hDS.reset( OGR_Dr_CreateDataSource( hGpkgDriver, fileName.toUtf8().constData(), nullptr ) );
338  if ( !hDS )
339  {
340  QString msg( tr( "Creation of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
341  if ( !property( "hideDialogs" ).toBool() )
342  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), msg );
343  return false;
344  }
345  }
346  else
347  {
348  OGRSFDriverH hDriver = nullptr;
349  hDS.reset( OGROpen( fileName.toUtf8().constData(), true, &hDriver ) );
350  if ( !hDS )
351  {
352  QString msg( tr( "Opening of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
353  if ( !property( "hideDialogs" ).toBool() )
354  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), msg );
355  return false;
356  }
357  if ( hDriver != hGpkgDriver )
358  {
359  QString msg( tr( "Opening of file succeeded, but this is not a GeoPackage database." ) );
360  if ( !property( "hideDialogs" ).toBool() )
361  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), msg );
362  return false;
363  }
364  }
365 
366  QString tableName( mTableNameEdit->text() );
367 
368  bool overwriteTable = false;
369  if ( OGR_DS_GetLayerByName( hDS.get(), tableName.toUtf8().constData() ) )
370  {
371  if ( property( "hideDialogs" ).toBool() )
372  {
373  overwriteTable = property( "question_existing_layer_answer_overwrite" ).toBool();
374  }
375  else if ( QMessageBox::question( this, tr( "New GeoPackage Layer" ),
376  tr( "A table with the same name already exists. Do you want to overwrite it?" ),
377  QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes )
378  {
379  overwriteTable = true;
380  }
381 
382  if ( !overwriteTable )
383  {
384  return false;
385  }
386  }
387 
388  QString layerIdentifier( mLayerIdentifierEdit->text() );
389  QString layerDescription( mLayerDescriptionEdit->text() );
390 
391  OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>
392  ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() );
393 
394  // z-coordinate & m-value.
395  if ( mGeometryWithZCheckBox->isChecked() )
396  wkbType = OGR_GT_SetZ( wkbType );
397 
398  if ( mGeometryWithMCheckBox->isChecked() )
399  wkbType = OGR_GT_SetM( wkbType );
400 
401  OGRSpatialReferenceH hSRS = nullptr;
402  // consider spatial reference system of the layer
403  QgsCoordinateReferenceSystem srs = mCrsSelector->crs();
404  if ( wkbType != wkbNone && srs.isValid() )
405  {
407  hSRS = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() );
408  }
409 
410  // Set options
411  char **options = nullptr;
412 
413  if ( overwriteTable )
414  options = CSLSetNameValue( options, "OVERWRITE", "YES" );
415  if ( !layerIdentifier.isEmpty() )
416  options = CSLSetNameValue( options, "IDENTIFIER", layerIdentifier.toUtf8().constData() );
417  if ( !layerDescription.isEmpty() )
418  options = CSLSetNameValue( options, "DESCRIPTION", layerDescription.toUtf8().constData() );
419 
420  QString featureId( mFeatureIdColumnEdit->text() );
421  if ( !featureId.isEmpty() )
422  options = CSLSetNameValue( options, "FID", featureId.toUtf8().constData() );
423 
424  QString geometryColumn( mGeometryColumnEdit->text() );
425  if ( wkbType != wkbNone && !geometryColumn.isEmpty() )
426  options = CSLSetNameValue( options, "GEOMETRY_COLUMN", geometryColumn.toUtf8().constData() );
427 
428  if ( wkbType != wkbNone )
429  options = CSLSetNameValue( options, "SPATIAL_INDEX", mCheckBoxCreateSpatialIndex->isChecked() ? "YES" : "NO" );
430 
431  OGRLayerH hLayer = OGR_DS_CreateLayer( hDS.get(), tableName.toUtf8().constData(), hSRS, wkbType, options );
432  CSLDestroy( options );
433  if ( hSRS )
434  OSRRelease( hSRS );
435  if ( !hLayer )
436  {
437  QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
438  if ( !property( "hideDialogs" ).toBool() )
439  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), msg );
440  return false;
441  }
442 
443  QTreeWidgetItemIterator it( mAttributeView );
444  while ( *it )
445  {
446  QString fieldName( ( *it )->text( 0 ) );
447  QString fieldType( ( *it )->text( 1 ) );
448  QString fieldWidth( ( *it )->text( 2 ) );
449 
450  bool isBool = false;
451  OGRFieldType ogrType( OFTString );
452  if ( fieldType == QLatin1String( "text" ) )
453  ogrType = OFTString;
454  else if ( fieldType == QLatin1String( "integer" ) )
455  ogrType = OFTInteger;
456  else if ( fieldType == QLatin1String( "integer64" ) )
457  ogrType = OFTInteger64;
458  else if ( fieldType == QLatin1String( "real" ) )
459  ogrType = OFTReal;
460  else if ( fieldType == QLatin1String( "date" ) )
461  ogrType = OFTDate;
462  else if ( fieldType == QLatin1String( "datetime" ) )
463  ogrType = OFTDateTime;
464  else if ( fieldType == QLatin1String( "bool" ) )
465  {
466  ogrType = OFTInteger;
467  isBool = true;
468  }
469  else if ( fieldType == QLatin1String( "binary" ) )
470  ogrType = OFTBinary;
471 
472  int ogrWidth = fieldWidth.toInt();
473 
474  gdal::ogr_field_def_unique_ptr fld( OGR_Fld_Create( fieldName.toUtf8().constData(), ogrType ) );
475  if ( ogrType != OFTBinary )
476  OGR_Fld_SetWidth( fld.get(), ogrWidth );
477  if ( isBool )
478  OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
479 
480  if ( OGR_L_CreateField( hLayer, fld.get(), true ) != OGRERR_NONE )
481  {
482  if ( !property( "hideDialogs" ).toBool() )
483  {
484  QMessageBox::critical( this, tr( "New GeoPackage Layer" ),
485  tr( "Creation of field %1 failed (OGR error: %2)" )
486  .arg( fieldName, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
487  }
488  return false;
489  }
490 
491  ++it;
492  }
493 
494  // In GDAL >= 2.0, the driver implements a deferred creation strategy, so
495  // issue a command that will force table creation
496  CPLErrorReset();
497  OGR_L_ResetReading( hLayer );
498  if ( CPLGetLastErrorType() != CE_None )
499  {
500  QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
501  if ( !property( "hideDialogs" ).toBool() )
502  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), msg );
503  return false;
504  }
505  hDS.reset();
506 
507  QString uri( QStringLiteral( "%1|layername=%2" ).arg( fileName, tableName ) );
508  QString userVisiblelayerName( layerIdentifier.isEmpty() ? tableName : layerIdentifier );
510  std::unique_ptr< QgsVectorLayer > layer = qgis::make_unique< QgsVectorLayer >( uri, userVisiblelayerName, QStringLiteral( "ogr" ), layerOptions );
511  if ( layer->isValid() )
512  {
513  if ( mAddToProject )
514  {
515  // register this layer with the central layers registry
516  QList<QgsMapLayer *> myList;
517  myList << layer.release();
518  //addMapLayers returns a list of all successfully added layers
519  //so we compare that to our original list.
520  if ( myList == QgsProject::instance()->addMapLayers( myList ) )
521  return true;
522  }
523  else
524  {
525  return true;
526  }
527  }
528  else
529  {
530  if ( !property( "hideDialogs" ).toBool() )
531  QMessageBox::critical( this, tr( "New GeoPackage Layer" ), tr( "%1 is an invalid layer and cannot be loaded." ).arg( tableName ) );
532  }
533 
534  return false;
535 }
536 
538 {
539  mBehavior = behavior;
540 }
541 
543 {
544  mAddToProject = addToProject;
545 }
546 
547 void QgsNewGeoPackageLayerDialog::showHelp()
548 {
549  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-a-new-geopackage-layer" ) );
550 }
DEFAULT_OGR_FID_COLUMN_TITLE
#define DEFAULT_OGR_FID_COLUMN_TITLE
Definition: qgsnewgeopackagelayerdialog.cpp:48
QgsFileWidget::fileChanged
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsNewGeoPackageLayerDialog::AddNewLayer
@ AddNewLayer
Keep existing contents and add new layer.
Definition: qgsnewgeopackagelayerdialog.h:67
QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
Definition: qgscoordinatereferencesystem.h:680
qgsgui.h
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
gdal::ogr_datasource_unique_ptr
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
Definition: qgsogrutils.h:114
gdal::ogr_field_def_unique_ptr
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
Definition: qgsogrutils.h:124
QgsNewGeoPackageLayerDialog::OverwriteBehavior
OverwriteBehavior
Behavior to use when an existing geopackage already exists.
Definition: qgsnewgeopackagelayerdialog.h:50
QgsProject::transformContext
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:99
qgis.h
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsNewGeoPackageLayerDialog::lockDatabasePath
void lockDatabasePath()
Sets the database path widgets to a locked and read-only mode.
Definition: qgsnewgeopackagelayerdialog.cpp:152
qgsogrutils.h
QgsSettings
Definition: qgssettings.h:61
qgsproviderconnectionmodel.h
QgsFileWidget::SaveFile
@ SaveFile
Select a single new or pre-existing file.
Definition: qgsfilewidget.h:69
qgsapplication.h
OGRSpatialReferenceH
void * OGRSpatialReferenceH
Definition: qgscoordinatereferencesystem.h:60
qgsprojectionselectiondialog.h
QgsGui::enableAutoGeometryRestore
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:133
QgsProviderConnectionModel::RoleUri
@ RoleUri
Connection URI string.
Definition: qgsproviderconnectionmodel.h:48
QgsNewGeoPackageLayerDialog::QgsNewGeoPackageLayerDialog
QgsNewGeoPackageLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Constructor.
Definition: qgsnewgeopackagelayerdialog.cpp:50
qgsproviderregistry.h
QgsCoordinateReferenceSystem::toWkt
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Definition: qgscoordinatereferencesystem.cpp:1931
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:902
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
QgsCoordinateReferenceSystem
Definition: qgscoordinatereferencesystem.h:206
QgsNewGeoPackageLayerDialog::Overwrite
@ Overwrite
Overwrite whole geopackage.
Definition: qgsnewgeopackagelayerdialog.h:66
qgsvectorlayer.h
QgsVectorLayer::LayerOptions
Setting options for loading vector layers.
Definition: qgsvectorlayer.h:423
QgsHelp::openHelp
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
qgsnewgeopackagelayerdialog.h
qgssettings.h
QgsNewGeoPackageLayerDialog::setAddToProject
void setAddToProject(bool addToProject)
Sets whether a newly created layer should automatically be added to the current project.
Definition: qgsnewgeopackagelayerdialog.cpp:542
QgsProviderConnectionModel
A model containing registered connection names for a specific data provider.
Definition: qgsproviderconnectionmodel.h:38
qgslogger.h
QgsNewGeoPackageLayerDialog::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs value for the new layer in the dialog.
Definition: qgsnewgeopackagelayerdialog.cpp:147
qgscoordinatereferencesystem.h
qgshelp.h
qgsproject.h
QgsNewGeoPackageLayerDialog::Prompt
@ Prompt
Prompt user for action.
Definition: qgsnewgeopackagelayerdialog.h:65
QgsNewGeoPackageLayerDialog::setOverwriteBehavior
void setOverwriteBehavior(OverwriteBehavior behavior)
Sets the behavior to use when a path to an existing geopackage file is used.
Definition: qgsnewgeopackagelayerdialog.cpp:537