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