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