41#include <QRegularExpression>
46#include "moc_qgsvectorlayersaveasdialog.cpp"
48using namespace Qt::StringLiterals;
51 : QDialog( parent, fl )
59 : QDialog( parent, fl )
66 mSelectedCrs = layer->
crs();
67 mLayerExtent = layer->
extent();
74 leLayername->setDefaultValue( mDefaultOutputLayerNameFromInputLayerName );
76 if ( leLayername->isEnabled() )
77 leLayername->setText( mDefaultOutputLayerNameFromInputLayerName );
82 mSymbologyExportLabel->hide();
83 mSymbologyExportComboBox->hide();
94 mAttributesSelection->hide();
97 mSelectedOnly->hide();
100 mAddToCanvas->hide();
103 mGeometryGroupBox->hide();
106 mExtentGroupBox->hide();
110 mCheckPersistMetadata->setChecked(
false );
111 mCheckPersistMetadata->hide();
115 mButtonBox->button( QDialogButtonBox::Ok )->setDisabled(
true );
118void QgsVectorLayerSaveAsDialog::setup()
123 connect( mFormatComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged );
125 connect( mSymbologyExportComboBox, &QComboBox::currentTextChanged,
this, &QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged );
126 connect( mGeometryTypeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged );
127 connect( mSelectAllAttributes, &QPushButton::clicked,
this, &QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked );
128 connect( mDeselectAllAttributes, &QPushButton::clicked,
this, &QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked );
129 connect( mUseAliasesForExportedName, &QCheckBox::stateChanged,
this, &QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged );
130 connect( mReplaceRawFieldValues, &QCheckBox::stateChanged,
this, &QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged );
131 connect( mAttributeTable, &QTableWidget::itemChanged,
this, &QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged );
134 mHelpButtonBox->setVisible(
false );
135 mButtonBox->addButton( QDialogButtonBox::Help );
136 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsVectorLayerSaveAsDialog::showHelp );
138 connect( mHelpButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsVectorLayerSaveAsDialog::showHelp );
141 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QgsVectorLayerSaveAsDialog::reject );
144 mFormatComboBox->blockSignals(
true );
147 mFormatComboBox->addItem( driver.longName, driver.driverName );
150 QgsSettings settings;
151 QString
format = settings.
value( u
"UI/lastVectorFormat"_s,
"GPKG" ).toString();
152 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData(
format ) );
153 mFormatComboBox->blockSignals(
false );
160 mGeometryTypeComboBox->addItem( tr(
"Automatic" ), -1 );
166 mGeometryTypeComboBox->setCurrentIndex( mGeometryTypeComboBox->findData( -1 ) );
170 QString enc = settings.
value( u
"UI/encoding"_s,
"System" ).toString();
171 int idx = mEncodingComboBox->findText( enc );
174 mEncodingComboBox->insertItem( 0, enc );
178 mCrsSelector->setCrs( mSelectedCrs );
179 mCrsSelector->setLayerCrs( mSelectedCrs );
180 mCrsSelector->setMessage( tr(
181 "Select the coordinate reference system for the vector file. "
182 "The data points will be transformed from the layer coordinate reference system."
184 mUserDefinedCrs = mSelectedCrs;
186 mEncodingComboBox->setCurrentIndex( idx );
187 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
193 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
196 mExtentGroupBox->setOutputCrs( mSelectedCrs );
197 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
198 mExtentGroupBox->setOutputExtentFromOriginal();
199 mExtentGroupBox->setCheckable(
true );
200 mExtentGroupBox->setChecked(
false );
201 mExtentGroupBox->setCollapsed(
true );
204 mFilename->setDialogTitle( tr(
"Save Layer As" ) );
205 mFilename->setDefaultRoot( settings.
value( u
"UI/lastVectorFileFilterDir"_s, QDir::homePath() ).toString() );
206 mFilename->setConfirmOverwrite(
false );
208 QgsSettings settings;
209 QFileInfo tmplFileInfo( filePath );
210 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, tmplFileInfo.absolutePath() );
212 const QFileInfo fileInfo( filePath );
214 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
215 leLayername->setDefaultValue( suggestedLayerName );
218 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
220 leLayername->setText( suggestedLayerName );
222 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
227 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
230 mCrsSelector->setSourceEnsemble( ensemble.
name() );
233 catch ( QgsNotSupportedException & )
236 mCrsSelector->setShowAccuracyWarnings(
true );
239QList<QPair<QLabel *, QWidget *>> QgsVectorLayerSaveAsDialog::createControls(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
241 QList<QPair<QLabel *, QWidget *>> controls;
242 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
244 for ( it = options.constBegin(); it != options.constEnd(); ++it )
246 QgsVectorFileWriter::Option *option = it.value();
247 QWidget *control =
nullptr;
248 switch ( option->
type )
252 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
255 QSpinBox *sb =
new QSpinBox();
256 sb->setObjectName( it.key() );
257 sb->setMaximum( std::numeric_limits<int>::max() );
266 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
269 QComboBox *cb =
new QComboBox();
270 cb->setObjectName( it.key() );
271 for (
const QString &val : std::as_const( opt->
values ) )
273 cb->addItem( val, val );
280 cb->setCurrentIndex( idx );
288 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
292 le->setObjectName( it.key() );
305 QLabel *label =
new QLabel( it.key() );
308 label->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
309 control->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
311 controls << QPair<QLabel *, QWidget *>( label, control );
320#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
321 if (
format() ==
"OpenFileGDB"_L1 )
325 bool targetAll =
true;
328 if ( layerOption ==
"TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER"_L1 )
336 for (
int i = 0; i < attributesSelected.size(); ++i )
338 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
339 if ( fld.
type() == QMetaType::Type::LongLong )
341 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The layer contains at least one 64-bit integer field, which, with the current settings, can only be exported as a Real field. It could be exported as a 64-bit integer field if the TARGET_ARCGIS_VERSION layer option is set to ARCGIS_PRO_3_2_OR_LATER. Do you want to continue and export it as a Real field?" ) )
342 != QMessageBox::Yes )
351 else if (
format() ==
"FileGDB"_L1 )
355 for (
int i = 0; i < attributesSelected.size(); ++i )
357 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
358 if ( fld.
type() == QMetaType::Type::LongLong )
360 if ( QMessageBox::question(
362 tr(
"Save Vector Layer As" ),
364 "The layer contains at least one 64-bit integer field, which cannot be exported as such when using this output driver. 64-bit integer fields could be supported by selecting the %1 "
365 "format and setting its TARGET_ARCGIS_VERSION layer option to ARCGIS_PRO_3_2_OR_LATER. Do you want to continue and export it as a Real field?"
367 .arg( tr(
"ESRI File Geodatabase" ) )
369 != QMessageBox::Yes )
384 msgBox.setIcon( QMessageBox::Question );
385 msgBox.setWindowTitle( tr(
"Save Vector Layer As" ) );
386 QPushButton *overwriteFileButton = msgBox.addButton( tr(
"Overwrite File" ), QMessageBox::ActionRole );
387 QPushButton *overwriteLayerButton = msgBox.addButton( tr(
"Overwrite Layer" ), QMessageBox::ActionRole );
388 QPushButton *appendToLayerButton = msgBox.addButton( tr(
"Append to Layer" ), QMessageBox::ActionRole );
389 msgBox.setStandardButtons( QMessageBox::Cancel );
390 msgBox.setDefaultButton( QMessageBox::Cancel );
391 overwriteFileButton->hide();
392 overwriteLayerButton->hide();
393 appendToLayerButton->hide();
398 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
399 overwriteFileButton->setVisible(
true );
400 overwriteLayerButton->setVisible(
true );
404 msgBox.setText( tr(
"The file already exists. Do you want to overwrite it?" ) );
405 overwriteFileButton->setVisible(
true );
409 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
410 appendToLayerButton->setVisible(
true );
411 overwriteFileButton->setVisible(
true );
412 overwriteLayerButton->setVisible(
true );
416 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
417 appendToLayerButton->setVisible(
true );
418 overwriteFileButton->setVisible(
true );
421 int ret = msgBox.exec();
422 if ( ret == QMessageBox::Cancel )
424 if ( msgBox.clickedButton() == overwriteFileButton )
426 else if ( msgBox.clickedButton() == overwriteLayerButton )
428 else if ( msgBox.clickedButton() == appendToLayerButton )
440 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
453 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The existing layer has additional fields. Do you want to add the missing fields to the layer?" ) ) == QMessageBox::Yes )
462 QStringList layerList;
463 layerList.reserve( sublayers.size() );
466 layerList.append( sublayer.name() );
468 if ( layerList.length() > 1 )
470 layerList.sort( Qt::CaseInsensitive );
472 msgBox.setIcon( QMessageBox::Warning );
473 msgBox.setWindowTitle( tr(
"Overwrite File" ) );
474 msgBox.setText( tr(
"This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
475 msgBox.setDetailedText( tr(
"The following layers will be permanently lost:\n\n%1" ).arg( layerList.join(
"\n" ) ) );
476 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
477 if ( msgBox.exec() == QMessageBox::Cancel )
483 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo(
fileName() ).absolutePath() );
489void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged(
int idx )
493 mFilename->setEnabled(
true );
501 if (
format() ==
"OpenFileGDB"_L1 ||
format() ==
"FileGDB"_L1 )
502 filter = u
"%1 (*.gdb *.GDB gdb)"_s.arg( tr(
"ESRI File Geodatabase" ) );
503 mFilename->setFilter( filter );
507 if ( !mFilename->filePath().isEmpty() )
509 const thread_local QRegularExpression rx(
"\\.(.*?)[\\s]" );
510 const QString ext = rx.match( filter ).captured( 1 );
511 if ( !ext.isEmpty() )
513 QFileInfo fi( mFilename->filePath() );
514 mFilename->setFilePath( u
"%1/%2.%3"_s.arg( fi.path(), fi.baseName(), ext ) );
518 bool selectAllFields =
true;
523 bool isFormatForFieldsAsDisplayedValues =
false;
525 const QString sFormat(
format() );
526 if ( sFormat ==
"DXF"_L1 || sFormat ==
"DGN"_L1 )
528 mAttributesSelection->setVisible(
false );
529 selectAllFields =
false;
535 mAttributesSelection->setVisible(
true );
536 isFormatForFieldsAsDisplayedValues = ( sFormat ==
"CSV"_L1 || sFormat ==
"XLS"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 );
543 mSymbologyExportLabel->setVisible(
true );
544 mSymbologyExportComboBox->setVisible(
true );
545 mScaleLabel->setVisible(
true );
546 mScaleWidget->setVisible(
true );
550 mSymbologyExportLabel->hide();
551 mSymbologyExportComboBox->hide();
553 mScaleWidget->hide();
556 leLayername->setEnabled(
557 sFormat ==
"KML"_L1 || sFormat ==
"GPKG"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 || sFormat ==
"FileGDB"_L1 || sFormat ==
"OpenFileGDB"_L1 || sFormat ==
"SQLite"_L1 || sFormat ==
"SpatiaLite"_L1
560 if ( sFormat ==
"XLSX"_L1 )
561 leLayername->setMaxLength( 31 );
562 else if ( leLayername->isEnabled() )
563 leLayername->setMaxLength( 32767 );
565 if ( !leLayername->isEnabled() )
566 leLayername->setText( QString() );
567 else if ( leLayername->text().isEmpty() )
569 QString
layerName = mDefaultOutputLayerNameFromInputLayerName;
570 if (
layerName.isEmpty() && !mFilename->filePath().isEmpty() )
572 layerName = QFileInfo( mFilename->filePath() ).baseName();
573 leLayername->setDefaultValue(
layerName );
583 const bool isPreviousFormatForFieldsAsDisplayedValues = ( mPreviousFormat ==
"CSV"_L1 || mPreviousFormat ==
"XLS"_L1 || mPreviousFormat ==
"XLSX"_L1 || mPreviousFormat ==
"ODS"_L1 );
584 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
586 QTableWidgetItem *nameItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) );
592 const QString fieldName = nameItem->text();
593 const bool exportField = ( nameItem->checkState() == Qt::Checked );
595 std::optional<bool> exportAsValue = std::nullopt;
596 if ( isPreviousFormatForFieldsAsDisplayedValues )
598 QTableWidgetItem *valueItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) );
599 if ( valueItem && ( valueItem->flags() & Qt::ItemIsUserCheckable ) )
601 exportAsValue = ( valueItem->checkState() == Qt::Checked );
606 exportAsValue = mFieldsState[fieldName].second;
609 mFieldsState[fieldName] = { exportField, exportAsValue };
612 mPreviousFormat = sFormat;
614 mAttributeTable->setRowCount( mLayer->fields().count() );
616 QStringList horizontalHeaders = QStringList() << tr(
"Name" ) << tr(
"Export name" ) << tr(
"Type" ) << tr(
"Replace with displayed values" );
617 mAttributeTable->setColumnCount(
static_cast<int>( horizontalHeaders.size() ) );
618 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
620 bool foundFieldThatCanBeExportedAsDisplayedValue =
false;
621 for (
int i = 0; i < mLayer->fields().size(); ++i )
626 foundFieldThatCanBeExportedAsDisplayedValue =
true;
630 mAttributeTable->setColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
632 bool allChecked =
true;
633 bool allUnchecked =
true;
634 bool anyEnabled =
false;
636 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
638 for (
int i = 0; i < mLayer->fields().size(); ++i )
640 QgsField fld = mLayer->fields().at( i );
641 Qt::ItemFlags flags = mLayer->providerType() !=
"oracle"_L1 || !fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
642 QTableWidgetItem *item =
nullptr;
643 const QString fieldName = fld.
name();
644 const bool exportField = mFieldsState.contains( fieldName ) ? mFieldsState[fieldName].first : selectAllFields;
645 item =
new QTableWidgetItem( fieldName );
646 item->setFlags( flags | Qt::ItemIsUserCheckable );
647 item->setCheckState( ( exportField ) ? Qt::Checked : Qt::Unchecked );
648 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Name ), item );
650 item =
new QTableWidgetItem( fieldName );
651 item->setFlags( flags | Qt::ItemIsEditable );
653 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportName ), item );
655 item =
new QTableWidgetItem( fld.
typeName() );
656 item->setFlags( flags );
657 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Type ), item );
659 if ( foundFieldThatCanBeExportedAsDisplayedValue )
662 QgsEditorWidgetFactory *factory =
nullptr;
663 const QString widgetId( setup.type() );
666 item =
new QTableWidgetItem( tr(
"Use %1" ).arg( factory->
name() ) );
668 if ( mFieldsState.contains( fieldName ) && mFieldsState[fieldName].second.has_value() )
670 exportAsValue = mFieldsState[fieldName].second.value();
675 = ( exportField && isFormatForFieldsAsDisplayedValues && ( widgetId ==
"ValueMap"_L1 || widgetId ==
"ValueRelation"_L1 || widgetId ==
"CheckBox"_L1 || widgetId ==
"RelationReference"_L1 ) );
677 item->setFlags( ( exportField ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
678 item->setCheckState( exportAsValue ? Qt::Checked : Qt::Unchecked );
679 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
686 allUnchecked =
false;
693 item =
new QTableWidgetItem();
694 item->setFlags( Qt::NoItemFlags );
695 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
701 Qt::CheckState replaceRawState;
702 if ( !anyEnabled || allUnchecked )
703 replaceRawState = Qt::Unchecked;
704 else if ( allChecked )
705 replaceRawState = Qt::Checked;
707 replaceRawState = Qt::PartiallyChecked;
709 whileBlocking( mReplaceRawFieldValues )->setCheckState( replaceRawState );
710 mReplaceRawFieldValues->setEnabled( selectAllFields && anyEnabled );
711 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
713 mAttributeTable->resizeColumnsToContents();
716 QgsVectorFileWriter::MetaData driverMetaData;
718 while ( mDatasourceOptionsGroupBox->layout()->count() )
720 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
721 delete item->widget();
725 while ( mLayerOptionsGroupBox->layout()->count() )
727 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
728 delete item->widget();
732 typedef QPair<QLabel *, QWidget *> LabelControlPair;
738 mDatasourceOptionsGroupBox->setVisible(
true );
739 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
driverOptions );
741 QFormLayout *datasourceLayout =
dynamic_cast<QFormLayout *
>( mDatasourceOptionsGroupBox->layout() );
743 const auto constControls = controls;
744 for ( LabelControlPair control : constControls )
746 datasourceLayout->addRow( control.first, control.second );
751 mDatasourceOptionsGroupBox->setVisible(
false );
756 mLayerOptionsGroupBox->setVisible(
true );
757 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
layerOptions );
759 QFormLayout *layerOptionsLayout =
dynamic_cast<QFormLayout *
>( mLayerOptionsGroupBox->layout() );
761 const auto constControls = controls;
762 for ( LabelControlPair control : constControls )
764 layerOptionsLayout->addRow( control.first, control.second );
768 if ( sFormat ==
"GeoJSON"_L1 )
770 if ( QComboBox *cmbRfc7946 = mLayerOptionsGroupBox->findChild<QComboBox *>(
"RFC7946"_L1 ) )
772 connect( cmbRfc7946, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::setCrsForFormat );
778 mLayerOptionsGroupBox->setVisible(
false );
783 mEncodingComboBox->setEnabled(
true );
790 mEncodingComboBox->setCurrentIndex( idx );
791 mEncodingComboBox->setDisabled(
true );
795 mEncodingComboBox->setEnabled(
true );
801 mEncodingComboBox->setEnabled(
true );
804 GDALDriverH hDriver = GDALGetDriverByName(
format().toUtf8().constData() );
807 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN,
nullptr );
808 if ( mAddToCanvas->isEnabled() && !canReopen )
810 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
811 mAddToCanvas->setChecked(
false );
812 mAddToCanvas->setEnabled(
false );
814 else if ( !mAddToCanvas->isEnabled() && canReopen )
816 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
817 mAddToCanvas->setEnabled(
true );
825void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged(
int state )
827 const QSignalBlocker signalBlocker( mAttributeTable );
834 bool modifiedEntries =
false;
835 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
837 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
839 modifiedEntries =
true;
844 if ( modifiedEntries )
846 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
848 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
853 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
855 mUseAliasesForExportedName->setTristate(
false );
856 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() );
863 bool modifiedEntries =
false;
864 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
866 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() )
867 modifiedEntries =
true;
870 if ( modifiedEntries )
872 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
874 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
879 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
881 mUseAliasesForExportedName->setTristate(
false );
882 const QString alias = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
883 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
887 case Qt::PartiallyChecked:
893void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged(
int )
895 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
898 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
899 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
901 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
903 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
905 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
906 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
907 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
909 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
913 mReplaceRawFieldValues->setTristate(
false );
916void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
918 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
919 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
921 int row = item->row();
922 int column = item->column();
924 switch (
static_cast<ColumnIndex
>( column ) )
926 case ColumnIndex::Name:
928 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
929 || !mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
930 || !( mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
933 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
935 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
936 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
937 bool checkBoxEnabled =
false;
938 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
940 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
941 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
943 checkBoxEnabled =
true;
947 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
948 if ( !checkBoxEnabled )
949 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
951 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
953 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
954 mReplaceRawFieldValues->setEnabled(
true );
958 case ColumnIndex::ExportName:
961 if ( item->text().isEmpty() )
963 QMessageBox::warning(
this, tr(
"Empty export name" ), tr(
"Empty export name are not allowed." ) );
969 while ( names.count( item->text() ) > 1 )
970 item->setText( QString(
"%1_2" ).arg( item->text() ) );
972 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
975 case ColumnIndex::Type:
978 case ColumnIndex::ExportAsDisplayedValue:
980 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
982 bool allChecked =
true;
983 bool allUnchecked =
true;
984 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
986 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
987 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
989 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
992 allUnchecked =
false;
995 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked : Qt::Unchecked );
1004 if ( mCrsDefinedByFormat )
1012 mUserDefinedCrs =
crs;
1013 mExtentGroupBox->setOutputCrs( mSelectedCrs );
1018 return mFilename->filePath();
1023 return leLayername->text();
1028 return mEncodingComboBox->currentText();
1033 return mFormatComboBox->currentData().toString();
1038 return mSelectedCrs;
1043 QStringList options;
1049 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1053 switch ( it.value()->type )
1058 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1060 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1067 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
1068 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1069 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1076 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1078 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1085 if ( opt && !opt->
mValue.isEmpty() )
1086 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1093 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
1094 if ( !plainText.isEmpty() )
1095 options += plainText.split(
'\n' );
1102 QStringList options;
1108 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1112 switch ( it.value()->type )
1117 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1119 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1126 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1127 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1128 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1135 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1137 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1144 if ( !opt->
mValue.isEmpty() )
1145 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1152 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1153 if ( !plainText.isEmpty() )
1154 options += plainText.split(
'\n' );
1163 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1165 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1167 attributes.append( i );
1178 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1180 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
1181 && !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1182 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Checked )
1184 attributes.append( i );
1193 QStringList exportNames;
1194 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1195 exportNames.append( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() );
1202 return mAddToCanvas->isChecked();
1207 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1208 if ( mAddToCanvas->isEnabled() )
1209 mAddToCanvas->setChecked( enabled );
1219 return mScaleWidget->scale();
1224 mMapCanvas = canvas;
1225 mScaleWidget->setMapCanvas( canvas );
1226 mScaleWidget->setShowCurrentScaleButton(
true );
1232 return mExtentGroupBox->isChecked();
1237 return mExtentGroupBox->outputExtent();
1247 return mSelectedOnly->isChecked();
1252 return mCheckPersistMetadata->isChecked();
1257 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1258 if ( currentIndexData == -1 )
1269 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1270 return currentIndexData == -1;
1275 return mForceMultiCheckBox->isChecked();
1280 mForceMultiCheckBox->setChecked( checked );
1285 return mIncludeZCheckBox->isChecked();
1290 return mActionOnExistingFile;
1295 mIncludeZCheckBox->setChecked( checked );
1298void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged(
const QString &text )
1300 bool scaleEnabled =
true;
1301 if ( text == tr(
"No symbology" ) )
1303 scaleEnabled =
false;
1305 mScaleWidget->setEnabled( scaleEnabled );
1306 mScaleLabel->setEnabled( scaleEnabled );
1309void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged(
int )
1311 const int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1314 mForceMultiCheckBox->setEnabled(
true );
1315 mIncludeZCheckBox->setEnabled(
true );
1321 mForceMultiCheckBox->setEnabled(
false );
1322 mForceMultiCheckBox->setChecked(
false );
1326 mForceMultiCheckBox->setEnabled(
true );
1328 mIncludeZCheckBox->setEnabled(
false );
1329 mIncludeZCheckBox->setChecked(
false );
1333void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1335 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1336 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1338 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1340 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1342 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1343 && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1345 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1347 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1350 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1352 mReplaceRawFieldValues->setEnabled(
true );
1356void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1358 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1359 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1361 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1363 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1364 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1365 && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1367 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1368 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1371 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1373 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1374 mReplaceRawFieldValues->setEnabled(
false );
1378void QgsVectorLayerSaveAsDialog::showHelp()
1380 QgsHelp::openHelp( u
"managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer"_s );
1383void QgsVectorLayerSaveAsDialog::setCrsForFormat()
1385 const QString outputFormat =
format();
1387 bool force4326 = ( outputFormat ==
"KML"_L1 || outputFormat ==
"LIBKML"_L1 || outputFormat ==
"GPX"_L1 );
1390 if ( outputFormat ==
"GeoJSON"_L1 )
1392 QComboBox *cmb = mLayerOptionsGroupBox->findChild<QComboBox *>( u
"RFC7946"_s );
1393 if ( cmb && cmb->currentText() ==
"YES"_L1 )
1399 if ( force4326 && !mCrsDefinedByFormat )
1401 mUserDefinedCrs = mCrsSelector->crs();
1402 mCrsDefinedByFormat =
true;
1403 mCrsSelector->setEnabled(
false );
1404 mSelectedCrs = QgsCoordinateReferenceSystem( u
"EPSG:4326"_s );
1406 mExtentGroupBox->setOutputCrs( mSelectedCrs );
1408 else if ( !force4326 && mCrsDefinedByFormat )
1410 mCrsDefinedByFormat =
false;
1411 mCrsSelector->setEnabled(
true );
1412 mCrsSelector->setCrs( mUserDefinedCrs );
WkbType
The WKB type describes the number of dimensions a geometry has.
@ GeometryCollection
GeometryCollection.
FeatureSymbologyExport
Options for exporting features considering their symbology.
@ PerFeature
Keeps the number of features and export symbology per feature.
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels).
@ NoSymbology
Export only data.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
QString name() const
Display name of datum ensemble.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
QString displayName() const
Returns the name to use when displaying this field.
@ ClearToDefault
Reset value to default value (see defaultValue() ).
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
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...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
static QIcon iconForWkbType(Qgis::WkbType type)
Returns the icon for a vector layer whose geometry type is provided.
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
static QString launderLayerName(const QString &name)
Launders a layer's name, converting it into a format which is general suitable for file names or data...
QgsCoordinateReferenceSystem crs
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QList< QgsProviderSublayerDetails > querySublayers(const QString &uri, Qgis::SublayerQueryFlags flags=Qgis::SublayerQueryFlags(), QgsFeedback *feedback=nullptr) const
Queries the specified uri and returns a list of any valid sublayers found in the dataset which can be...
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Contains details about a sub layer available from a dataset.
A rectangle specified with double values.
Stores settings for use within QGIS.
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 QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
static QStringList availableEncodings()
Returns a list of available encodings.
A hidden option for file writing for a particular output format.
An available option for configuring file writing for a particular output format, presenting an intege...
QgsVectorFileWriter::OptionType type
An available option for configuring file writing for a particular output format, presenting a choice ...
An available option for configuring file writing for a particular output format, presenting a freefor...
A convenience class for writing vector layers to disk based formats (e.g.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
QFlags< EditionCapability > EditionCapabilities
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
ActionOnExistingFile
Enumeration to describe how to handle existing files.
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
bool onlySelected() const
Returns whether only selected features will be saved.
bool forceMulti() const
Returns true if force multi geometry type is checked.
QgsAttributeList selectedAttributes() const
Returns a list of attributes which are selected for saving.
QgsRectangle filterExtent() const
Determines the extent to be exported.
QString format() const
Returns the selected format in which the export should be written.
QStringList datasourceOptions() const
Returns a list of additional data source options which are passed to OGR.
bool persistMetadata() const
Returns true if the persist metadata (copy source metadata to destination layer) option is checked.
QString encoding() const
Returns the selected encoding for the target file.
void setIncludeZ(bool checked)
Sets whether the include z dimension checkbox should be checked.
QStringList attributesExportNames() const
Returns a list of export names for attributes.
QString fileName() const
Returns the target filename.
void setOnlySelected(bool onlySelected)
Sets whether only selected features will be saved.
QString layerName() const
Returns the target layer name.
bool automaticGeometryType() const
Returns true if geometry type is set to automatic.
Q_DECL_DEPRECATED QgsVectorLayerSaveAsDialog(long srsid, QWidget *parent=nullptr, Qt::WindowFlags fl=Qt::WindowFlags())
Construct a new QgsVectorLayerSaveAsDialog.
bool includeZ() const
Returns true if include z dimension is checked.
@ Symbology
Show symbology options.
@ DestinationCrs
Show destination CRS (reprojection) option.
@ AddToCanvas
Show add to map option.
@ Fields
Show field customization group.
@ Extent
Show extent group.
@ SelectedOnly
Show selected features only option.
@ GeometryType
Show geometry group.
@ Metadata
Show metadata options.
QgsCoordinateReferenceSystem crs() const
Returns the CRS chosen for export.
QStringList layerOptions() const
Returns a list of additional layer options which are passed to OGR.
void setForceMulti(bool checked)
Sets whether the force multi geometry checkbox should be checked.
QFlags< Option > Options
Available dialog options.
bool addToCanvas() const
Returns true if the "add to canvas" checkbox is checked.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas to associate with the dialog.
Qgis::WkbType geometryType() const
Returns the selected flat geometry type for the export.
QgsVectorFileWriter::ActionOnExistingFile creationActionOnExistingFile() const
Returns the creation action.
QgsAttributeList attributesAsDisplayedValues() const
Returns selected attributes that must be exported with their displayed values instead of their raw va...
double scale() const
Returns the specified map scale.
bool hasFilterExtent() const
Determines if filtering the export by an extent is activated.
Qgis::FeatureSymbologyExport symbologyExport() const
Returns type of symbology export.
void setAddToCanvas(bool checked)
Sets whether the "add to canvas" checkbox should be checked.
Represents a vector layer which manages a vector based dataset.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
QgsRectangle extent() const final
Returns the extent of the layer.
static Q_INVOKABLE QString translatedDisplayString(Qgis::WkbType type)
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QList< int > QgsAttributeList
Details of available driver formats.