33 #include <QPushButton> 36 #include <QMessageBox> 37 #include <QFileDialog> 41 #include <ogr_srs_api.h> 42 #include <gdal_version.h> 43 #include <cpl_error.h> 44 #include <cpl_string.h> 46 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,0,0) 47 #define SUPPORT_GEOMETRY_LESS 48 #define SUPPORT_CURVE_GEOMETRIES 49 #define SUPPORT_INTEGER64 50 #define SUPPORT_SPATIAL_INDEX 51 #define SUPPORT_IDENTIFIER_DESCRIPTION 52 #define SUPPORT_FIELD_WIDTH 57 , mOkButton( nullptr )
58 , mTableNameEdited( false )
59 , mLayerIdentifierEdited( false )
69 #ifdef SUPPORT_GEOMETRY_LESS 70 mGeometryTypeBox->addItem(
tr(
"Non spatial" ), wkbNone );
72 mGeometryTypeBox->addItem(
tr(
"Point" ), wkbPoint );
73 mGeometryTypeBox->addItem(
tr(
"Line" ), wkbLineString );
74 mGeometryTypeBox->addItem(
tr(
"Polygon" ), wkbPolygon );
75 mGeometryTypeBox->addItem(
tr(
"Multi point" ), wkbMultiPoint );
76 mGeometryTypeBox->addItem(
tr(
"Multi line" ), wkbMultiLineString );
77 mGeometryTypeBox->addItem(
tr(
"Multi polygon" ), wkbMultiPolygon );
78 #ifdef SUPPORT_CURVE_GEOMETRIES 81 mGeometryTypeBox->addItem(
tr(
"Circular string" ), wkbCircularString );
83 mGeometryTypeBox->addItem(
tr(
"Compound curve" ), wkbCompoundCurve );
84 mGeometryTypeBox->addItem(
tr(
"Curve polygon" ), wkbCurvePolygon );
85 mGeometryTypeBox->addItem(
tr(
"Multi curve" ), wkbMultiCurve );
86 mGeometryTypeBox->addItem(
tr(
"Multi surface" ), wkbMultiSurface );
89 #ifdef SUPPORT_GEOMETRY_LESS 90 mGeometryColumnEdit->setEnabled(
false );
91 mCheckBoxCreateSpatialIndex->setEnabled(
false );
92 mCrsSelector->setEnabled(
false );
95 mFieldTypeBox->addItem(
tr(
"Text data" ),
"text" );
96 mFieldTypeBox->addItem(
tr(
"Whole number (integer)" ),
"integer" );
97 #ifdef SUPPORT_INTEGER64 98 mFieldTypeBox->addItem(
tr(
"Whole number (integer 64 bit)" ),
"integer64" );
100 mFieldTypeBox->addItem(
tr(
"Decimal number (real)" ),
"real" );
101 mFieldTypeBox->addItem(
tr(
"Date" ),
"date" );
102 mFieldTypeBox->addItem(
tr(
"Date&time" ),
"datetime" );
104 mOkButton = buttonBox->button( QDialogButtonBox::Ok );
110 mCrsSelector->setCrs( defaultCrs );
112 connect( mFieldNameEdit, SIGNAL( textChanged(
const QString& ) ),
this, SLOT( fieldNameChanged(
QString ) ) );
113 connect( mAttributeView, SIGNAL( itemSelectionChanged() ),
this, SLOT( selectionChanged() ) );
114 connect( mTableNameEdit, SIGNAL( textChanged(
const QString& ) ),
this, SLOT( checkOk() ) );
115 connect( mDatabaseEdit, SIGNAL( textChanged(
const QString& ) ),
this, SLOT( checkOk() ) );
117 mAddAttributeButton->setEnabled(
false );
118 mRemoveAttributeButton->setEnabled(
false );
120 #ifndef SUPPORT_SPATIAL_INDEX 121 mCheckBoxCreateSpatialIndex->hide();
122 mCheckBoxCreateSpatialIndex->setChecked(
false );
124 mCheckBoxCreateSpatialIndex->setChecked(
true );
127 #ifndef SUPPORT_IDENTIFIER_DESCRIPTION 128 mLayerIdentifierLabel->hide();
129 mLayerIdentifierEdit->hide();
130 mLayerDescriptionLabel->hide();
131 mLayerDescriptionEdit->hide();
134 #ifndef SUPPORT_FIELD_WIDTH 135 mFieldLengthLabel->hide();
136 mFieldLengthEdit->hide();
146 void QgsNewGeoPackageLayerDialog::on_mFieldTypeBox_currentIndexChanged(
int )
148 QString myType = mFieldTypeBox->itemData( mFieldTypeBox->currentIndex(), Qt::UserRole ).toString();
149 mFieldLengthEdit->setEnabled( myType ==
"text" );
150 if ( myType !=
"text" )
151 mFieldLengthEdit->setText(
"" );
155 void QgsNewGeoPackageLayerDialog::on_mGeometryTypeBox_currentIndexChanged(
int )
157 OGRwkbGeometryType geomType =
static_cast<OGRwkbGeometryType
> 158 ( mGeometryTypeBox->itemData( mGeometryTypeBox->currentIndex(), Qt::UserRole ).toInt() );
159 bool isSpatial = geomType != wkbNone;
160 mGeometryColumnEdit->setEnabled( isSpatial );
161 mCheckBoxCreateSpatialIndex->setEnabled( isSpatial );
162 mCrsSelector->setEnabled( isSpatial );
165 void QgsNewGeoPackageLayerDialog::on_mSelectDatabaseButton_clicked()
169 tr(
"GeoPackage" ) +
" (*.gpkg)",
171 QFileDialog::DontConfirmOverwrite );
176 if ( !fileName.
endsWith(
".gpkg", Qt::CaseInsensitive ) )
181 mDatabaseEdit->setText( fileName );
184 void QgsNewGeoPackageLayerDialog::on_mDatabaseEdit_textChanged(
const QString& text )
186 if ( !text.
isEmpty() && !mTableNameEdited )
189 mTableNameEdit->setText( fileInfo.
baseName() );
193 void QgsNewGeoPackageLayerDialog::on_mTableNameEdit_textChanged(
const QString& text )
195 mTableNameEdited = !text.
isEmpty();
196 if ( !text.
isEmpty() && !mLayerIdentifierEdited )
198 mLayerIdentifierEdit->setText( text );
202 void QgsNewGeoPackageLayerDialog::on_mTableNameEdit_textEdited(
const QString& text )
205 mTableNameEdited = !text.
isEmpty();
208 void QgsNewGeoPackageLayerDialog::on_mLayerIdentifierEdit_textEdited(
const QString& text )
211 mLayerIdentifierEdited = !text.
isEmpty();
214 void QgsNewGeoPackageLayerDialog::checkOk()
216 bool ok = !mDatabaseEdit->text().isEmpty() &&
217 !mTableNameEdit->text().isEmpty();
221 void QgsNewGeoPackageLayerDialog::on_mAddAttributeButton_clicked()
223 if ( !mFieldNameEdit->text().isEmpty() )
225 QString myName = mFieldNameEdit->text();
226 if ( myName == mFeatureIdColumnEdit->text() )
228 QMessageBox::critical(
this,
tr(
"Invalid field name" ),
tr(
"The field cannot have the same name as the feature identifier" ) );
233 QString myType = mFieldTypeBox->itemData( mFieldTypeBox->currentIndex(), Qt::UserRole ).toString();
234 QString length = mFieldLengthEdit->text();
239 mFieldNameEdit->clear();
243 void QgsNewGeoPackageLayerDialog::on_mRemoveAttributeButton_clicked()
245 delete mAttributeView->currentItem();
250 void QgsNewGeoPackageLayerDialog::fieldNameChanged(
const QString&
name )
252 mAddAttributeButton->setDisabled( name.
isEmpty() || ! mAttributeView->findItems( name, Qt::MatchExactly ).isEmpty() );
255 void QgsNewGeoPackageLayerDialog::selectionChanged()
257 mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() );
260 void QgsNewGeoPackageLayerDialog::on_buttonBox_accepted()
266 void QgsNewGeoPackageLayerDialog::on_buttonBox_rejected()
271 bool QgsNewGeoPackageLayerDialog::apply()
273 QString fileName( mDatabaseEdit->text() );
274 bool createNewDb =
false;
278 msgBox.
setIcon( QMessageBox::Question );
280 msgBox.
setText(
tr(
"Do you want to overwrite the existing file with a new database or add a new layer to it?" ) );
285 bool overwrite =
false;
287 if (
property(
"hideDialogs" ).toBool() )
289 overwrite =
property(
"question_existing_db_answer_overwrite" ).
toBool();
291 cancel = !
property(
"question_existing_db_answer_add_new_layer" ).
toBool();
295 int ret = msgBox.
exec();
296 if ( ret == QMessageBox::Cancel )
316 OGRSFDriverH hGpkgDriver = OGRGetDriverByName(
"GPKG" );
319 if ( !
property(
"hideDialogs" ).toBool() )
321 tr(
"GeoPackage driver not found" ) );
325 OGRDataSourceH hDS =
nullptr;
328 hDS = OGR_Dr_CreateDataSource( hGpkgDriver, fileName.toUtf8().constData(), nullptr );
332 if ( !
property(
"hideDialogs" ).toBool() )
339 OGRSFDriverH hDriver =
nullptr;
340 hDS = OGROpen( fileName.toUtf8().constData(),
true, &hDriver );
344 if ( !
property(
"hideDialogs" ).toBool() )
348 if ( hDriver != hGpkgDriver )
350 QString msg(
tr(
"Opening of file succeeded, but this is not a GeoPackage database" ) );
351 if ( !
property(
"hideDialogs" ).toBool() )
353 OGR_DS_Destroy( hDS );
358 QString tableName( mTableNameEdit->text() );
360 bool overwriteTable =
false;
361 if ( OGR_DS_GetLayerByName( hDS, tableName.toUtf8().constData() ) !=
nullptr )
365 overwriteTable =
property(
"question_existing_layer_answer_overwrite" ).
toBool();
368 tr(
"A table with the same name already exists. Do you want to overwrite it?" ),
369 QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes )
371 overwriteTable =
true;
374 if ( !overwriteTable )
376 OGR_DS_Destroy( hDS );
381 QString layerIdentifier( mLayerIdentifierEdit->text() );
382 QString layerDescription( mLayerDescriptionEdit->text() );
384 OGRwkbGeometryType wkbType =
static_cast<OGRwkbGeometryType
> 385 ( mGeometryTypeBox->itemData( mGeometryTypeBox->currentIndex(), Qt::UserRole ).toInt() );
389 int crsId = mCrsSelector->crs().srsid();
390 if ( wkbType != wkbNone && crsId > 0 )
398 char **options =
nullptr;
400 if ( overwriteTable )
401 options = CSLSetNameValue( options,
"OVERWRITE",
"YES" );
402 if ( !layerIdentifier.isEmpty() )
403 options = CSLSetNameValue( options,
"IDENTIFIER", layerIdentifier.toUtf8().constData() );
404 if ( !layerDescription.isEmpty() )
405 options = CSLSetNameValue( options,
"DESCRIPTION", layerDescription.toUtf8().constData() );
407 QString featureId( mFeatureIdColumnEdit->text() );
408 if ( !featureId.isEmpty() )
409 options = CSLSetNameValue( options,
"FID", featureId.toUtf8().constData() );
411 QString geometryColumn( mGeometryColumnEdit->text() );
412 if ( wkbType != wkbNone && !geometryColumn.isEmpty() )
413 options = CSLSetNameValue( options,
"GEOMETRY_COLUMN", geometryColumn.toUtf8().constData() );
415 #ifdef SUPPORT_SPATIAL_INDEX 416 if ( wkbType != wkbNone )
417 options = CSLSetNameValue( options,
"SPATIAL_INDEX", mCheckBoxCreateSpatialIndex->isChecked() ?
"YES" :
"NO" );
420 OGRLayerH hLayer = OGR_DS_CreateLayer( hDS, tableName.toUtf8().constData(), hSRS, wkbType, options );
421 CSLDestroy( options );
422 if ( hSRS !=
nullptr )
424 if ( hLayer ==
nullptr )
427 if ( !
property(
"hideDialogs" ).toBool() )
429 OGR_DS_Destroy( hDS );
436 QString fieldName(( *it )->text( 0 ) );
437 QString fieldType(( *it )->text( 1 ) );
438 QString fieldWidth(( *it )->text( 2 ) );
440 OGRFieldType ogrType( OFTString );
441 if ( fieldType ==
"text" )
443 else if ( fieldType ==
"integer" )
444 ogrType = OFTInteger;
445 #ifdef SUPPORT_INTEGER64 446 else if ( fieldType ==
"integer64" )
447 ogrType = OFTInteger64;
449 else if ( fieldType ==
"real" )
451 else if ( fieldType ==
"date" )
453 else if ( fieldType ==
"datetime" )
454 ogrType = OFTDateTime;
456 int ogrWidth = fieldWidth.toInt();
458 OGRFieldDefnH fld = OGR_Fld_Create( fieldName.toUtf8().constData(), ogrType );
459 OGR_Fld_SetWidth( fld, ogrWidth );
461 if ( OGR_L_CreateField( hLayer, fld,
true ) != OGRERR_NONE )
463 if ( !
property(
"hideDialogs" ).toBool() )
466 tr(
"Creation of field %1 failed (OGR error: %2)" )
469 OGR_Fld_Destroy( fld );
470 OGR_DS_Destroy( hDS );
473 OGR_Fld_Destroy( fld );
481 OGR_L_ResetReading( hLayer );
482 if ( CPLGetLastErrorType() != CE_None )
485 if ( !
property(
"hideDialogs" ).toBool() )
487 OGR_DS_Destroy( hDS );
491 OGR_DS_Destroy( hDS );
493 QString uri(
QString(
"%1|layername=%2" ).arg( mDatabaseEdit->text(), tableName ) );
494 QString userVisiblelayerName( layerIdentifier.isEmpty() ? tableName : layerIdentifier );
496 if ( layer->isValid() )
QByteArray toByteArray() const
QgsCoordinateReferenceSystem crsByOgcWmsCrs(const QString &ogcCrs) const
Returns the CRS from a given OGC WMS-format Coordinate Reference System string.
void validate()
Perform some validation on this CRS.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
QString tr(const char *sourceText, const char *disambiguation, int n)
QgsCoordinateReferenceSystem crsBySrsId(long srsId) const
Returns the CRS from a specified QGIS SRS ID.
void setValue(const QString &key, const QVariant &value)
const char * name() const
QString fromUtf8(const char *str, int size)
QVariant property(const char *name) const
QList< QgsMapLayer * > addMapLayers(const QList< QgsMapLayer *> &theMapLayers, bool addToLegend=true, bool takeOwnership=true)
Add a list of layers to the map of loaded layers.
StandardButton question(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
void setWindowTitle(const QString &title)
void setText(const QString &text)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
QByteArray toLocal8Bit() const
QVariant value(const QString &key, const QVariant &defaultValue) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsNewGeoPackageLayerDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgisGui::ModalDialogFlags)
Constructor.
Class for storing a coordinate reference system (CRS)
QString toWkt() const
Returns a WKT representation of this CRS.
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
~QgsNewGeoPackageLayerDialog()
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
void * OGRSpatialReferenceH