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() );
267 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
270 QComboBox *cb =
new QComboBox();
271 cb->setObjectName( it.key() );
272 for (
const QString &val : std::as_const( opt->
values ) )
274 cb->addItem( val, val );
281 cb->setCurrentIndex( idx );
289 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
293 le->setObjectName( it.key() );
306 QLabel *label =
new QLabel( it.key() );
309 label->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
310 control->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
312 controls << QPair<QLabel *, QWidget *>( label, control );
321#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
322 if (
format() ==
"OpenFileGDB"_L1 )
326 bool targetAll =
true;
329 if ( layerOption ==
"TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER"_L1 )
337 for (
int i = 0; i < attributesSelected.size(); ++i )
339 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
340 if ( fld.
type() == QMetaType::Type::LongLong )
342 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?" ) )
343 != QMessageBox::Yes )
352 else if (
format() ==
"FileGDB"_L1 )
356 for (
int i = 0; i < attributesSelected.size(); ++i )
358 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
359 if ( fld.
type() == QMetaType::Type::LongLong )
361 if ( QMessageBox::question(
363 tr(
"Save Vector Layer As" ),
365 "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 "
366 "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?"
368 .arg( tr(
"ESRI File Geodatabase" ) )
370 != QMessageBox::Yes )
385 msgBox.setIcon( QMessageBox::Question );
386 msgBox.setWindowTitle( tr(
"Save Vector Layer As" ) );
387 QPushButton *overwriteFileButton = msgBox.addButton( tr(
"Overwrite File" ), QMessageBox::ActionRole );
388 QPushButton *overwriteLayerButton = msgBox.addButton( tr(
"Overwrite Layer" ), QMessageBox::ActionRole );
389 QPushButton *appendToLayerButton = msgBox.addButton( tr(
"Append to Layer" ), QMessageBox::ActionRole );
390 msgBox.setStandardButtons( QMessageBox::Cancel );
391 msgBox.setDefaultButton( QMessageBox::Cancel );
392 overwriteFileButton->hide();
393 overwriteLayerButton->hide();
394 appendToLayerButton->hide();
399 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
400 overwriteFileButton->setVisible(
true );
401 overwriteLayerButton->setVisible(
true );
405 msgBox.setText( tr(
"The file already exists. Do you want to overwrite it?" ) );
406 overwriteFileButton->setVisible(
true );
410 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
411 appendToLayerButton->setVisible(
true );
412 overwriteFileButton->setVisible(
true );
413 overwriteLayerButton->setVisible(
true );
417 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
418 appendToLayerButton->setVisible(
true );
419 overwriteFileButton->setVisible(
true );
422 int ret = msgBox.exec();
423 if ( ret == QMessageBox::Cancel )
425 if ( msgBox.clickedButton() == overwriteFileButton )
427 else if ( msgBox.clickedButton() == overwriteLayerButton )
429 else if ( msgBox.clickedButton() == appendToLayerButton )
441 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
454 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 )
463 QStringList layerList;
464 layerList.reserve( sublayers.size() );
467 layerList.append( sublayer.name() );
469 if ( layerList.length() > 1 )
471 layerList.sort( Qt::CaseInsensitive );
473 msgBox.setIcon( QMessageBox::Warning );
474 msgBox.setWindowTitle( tr(
"Overwrite File" ) );
475 msgBox.setText( tr(
"This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
476 msgBox.setDetailedText( tr(
"The following layers will be permanently lost:\n\n%1" ).arg( layerList.join(
"\n" ) ) );
477 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
478 if ( msgBox.exec() == QMessageBox::Cancel )
484 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo(
fileName() ).absolutePath() );
490void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged(
int idx )
494 mFilename->setEnabled(
true );
502 if (
format() ==
"OpenFileGDB"_L1 ||
format() ==
"FileGDB"_L1 )
503 filter = u
"%1 (*.gdb *.GDB gdb)"_s.arg( tr(
"ESRI File Geodatabase" ) );
504 mFilename->setFilter( filter );
508 if ( !mFilename->filePath().isEmpty() )
510 const thread_local QRegularExpression rx(
"\\.(.*?)[\\s]" );
511 const QString ext = rx.match( filter ).captured( 1 );
512 if ( !ext.isEmpty() )
514 QFileInfo fi( mFilename->filePath() );
515 mFilename->setFilePath( u
"%1/%2.%3"_s.arg( fi.path(), fi.baseName(), ext ) );
519 bool selectAllFields =
true;
524 bool isFormatForFieldsAsDisplayedValues =
false;
526 const QString sFormat(
format() );
527 if ( sFormat ==
"DXF"_L1 || sFormat ==
"DGN"_L1 )
529 mAttributesSelection->setVisible(
false );
530 selectAllFields =
false;
536 mAttributesSelection->setVisible(
true );
537 isFormatForFieldsAsDisplayedValues = ( sFormat ==
"CSV"_L1 || sFormat ==
"XLS"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 );
544 mSymbologyExportLabel->setVisible(
true );
545 mSymbologyExportComboBox->setVisible(
true );
546 mScaleLabel->setVisible(
true );
547 mScaleWidget->setVisible(
true );
551 mSymbologyExportLabel->hide();
552 mSymbologyExportComboBox->hide();
554 mScaleWidget->hide();
557 leLayername->setEnabled(
558 sFormat ==
"KML"_L1 || sFormat ==
"GPKG"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 || sFormat ==
"FileGDB"_L1 || sFormat ==
"OpenFileGDB"_L1 || sFormat ==
"SQLite"_L1 || sFormat ==
"SpatiaLite"_L1
561 if ( sFormat ==
"XLSX"_L1 )
562 leLayername->setMaxLength( 31 );
563 else if ( leLayername->isEnabled() )
564 leLayername->setMaxLength( 32767 );
566 if ( !leLayername->isEnabled() )
567 leLayername->setText( QString() );
568 else if ( leLayername->text().isEmpty() )
570 QString
layerName = mDefaultOutputLayerNameFromInputLayerName;
571 if (
layerName.isEmpty() && !mFilename->filePath().isEmpty() )
573 layerName = QFileInfo( mFilename->filePath() ).baseName();
574 leLayername->setDefaultValue(
layerName );
584 const bool isPreviousFormatForFieldsAsDisplayedValues = ( mPreviousFormat ==
"CSV"_L1 || mPreviousFormat ==
"XLS"_L1 || mPreviousFormat ==
"XLSX"_L1 || mPreviousFormat ==
"ODS"_L1 );
585 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
587 QTableWidgetItem *nameItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) );
593 const QString fieldName = nameItem->text();
594 const bool exportField = ( nameItem->checkState() == Qt::Checked );
596 std::optional<bool> exportAsValue = std::nullopt;
597 if ( isPreviousFormatForFieldsAsDisplayedValues )
599 QTableWidgetItem *valueItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) );
600 if ( valueItem && ( valueItem->flags() & Qt::ItemIsUserCheckable ) )
602 exportAsValue = ( valueItem->checkState() == Qt::Checked );
607 exportAsValue = mFieldsState[fieldName].second;
610 mFieldsState[fieldName] = { exportField, exportAsValue };
613 mPreviousFormat = sFormat;
615 mAttributeTable->setRowCount( mLayer->fields().count() );
617 QStringList horizontalHeaders = QStringList() << tr(
"Name" ) << tr(
"Export name" ) << tr(
"Type" ) << tr(
"Replace with displayed values" );
618 mAttributeTable->setColumnCount(
static_cast<int>( horizontalHeaders.size() ) );
619 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
621 bool foundFieldThatCanBeExportedAsDisplayedValue =
false;
622 for (
int i = 0; i < mLayer->fields().size(); ++i )
627 foundFieldThatCanBeExportedAsDisplayedValue =
true;
631 mAttributeTable->setColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
633 bool allChecked =
true;
634 bool allUnchecked =
true;
635 bool anyEnabled =
false;
637 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
639 for (
int i = 0; i < mLayer->fields().size(); ++i )
641 QgsField fld = mLayer->fields().at( i );
642 Qt::ItemFlags flags = mLayer->providerType() !=
"oracle"_L1 || !fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
643 QTableWidgetItem *item =
nullptr;
644 const QString fieldName = fld.
name();
645 const bool exportField = mFieldsState.contains( fieldName ) ? mFieldsState[fieldName].first : selectAllFields;
646 item =
new QTableWidgetItem( fieldName );
647 item->setFlags( flags | Qt::ItemIsUserCheckable );
648 item->setCheckState( ( exportField ) ? Qt::Checked : Qt::Unchecked );
649 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Name ), item );
651 item =
new QTableWidgetItem( fieldName );
652 item->setFlags( flags | Qt::ItemIsEditable );
654 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportName ), item );
656 item =
new QTableWidgetItem( fld.
typeName() );
657 item->setFlags( flags );
658 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Type ), item );
660 if ( foundFieldThatCanBeExportedAsDisplayedValue )
663 QgsEditorWidgetFactory *factory =
nullptr;
664 const QString widgetId( setup.type() );
667 item =
new QTableWidgetItem( tr(
"Use %1" ).arg( factory->
name() ) );
669 if ( mFieldsState.contains( fieldName ) && mFieldsState[fieldName].second.has_value() )
671 exportAsValue = mFieldsState[fieldName].second.value();
676 = ( exportField && isFormatForFieldsAsDisplayedValues && ( widgetId ==
"ValueMap"_L1 || widgetId ==
"ValueRelation"_L1 || widgetId ==
"CheckBox"_L1 || widgetId ==
"RelationReference"_L1 ) );
678 item->setFlags( ( exportField ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
679 item->setCheckState( exportAsValue ? Qt::Checked : Qt::Unchecked );
680 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
687 allUnchecked =
false;
694 item =
new QTableWidgetItem();
695 item->setFlags( Qt::NoItemFlags );
696 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
702 Qt::CheckState replaceRawState;
703 if ( !anyEnabled || allUnchecked )
704 replaceRawState = Qt::Unchecked;
705 else if ( allChecked )
706 replaceRawState = Qt::Checked;
708 replaceRawState = Qt::PartiallyChecked;
710 whileBlocking( mReplaceRawFieldValues )->setCheckState( replaceRawState );
711 mReplaceRawFieldValues->setEnabled( selectAllFields && anyEnabled );
712 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
714 mAttributeTable->resizeColumnsToContents();
717 QgsVectorFileWriter::MetaData driverMetaData;
719 while ( mDatasourceOptionsGroupBox->layout()->count() )
721 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
722 delete item->widget();
726 while ( mLayerOptionsGroupBox->layout()->count() )
728 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
729 delete item->widget();
733 typedef QPair<QLabel *, QWidget *> LabelControlPair;
739 mDatasourceOptionsGroupBox->setVisible(
true );
740 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
driverOptions );
742 QFormLayout *datasourceLayout =
dynamic_cast<QFormLayout *
>( mDatasourceOptionsGroupBox->layout() );
744 const auto constControls = controls;
745 for ( LabelControlPair control : constControls )
747 datasourceLayout->addRow( control.first, control.second );
752 mDatasourceOptionsGroupBox->setVisible(
false );
757 mLayerOptionsGroupBox->setVisible(
true );
758 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
layerOptions );
760 QFormLayout *layerOptionsLayout =
dynamic_cast<QFormLayout *
>( mLayerOptionsGroupBox->layout() );
762 const auto constControls = controls;
763 for ( LabelControlPair control : constControls )
765 layerOptionsLayout->addRow( control.first, control.second );
769 if ( sFormat ==
"GeoJSON"_L1 )
771 if ( QComboBox *cmbRfc7946 = mLayerOptionsGroupBox->findChild<QComboBox *>(
"RFC7946"_L1 ) )
773 connect( cmbRfc7946, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::setCrsForFormat );
779 mLayerOptionsGroupBox->setVisible(
false );
784 mEncodingComboBox->setEnabled(
true );
791 mEncodingComboBox->setCurrentIndex( idx );
792 mEncodingComboBox->setDisabled(
true );
796 mEncodingComboBox->setEnabled(
true );
802 mEncodingComboBox->setEnabled(
true );
805 GDALDriverH hDriver = GDALGetDriverByName(
format().toUtf8().constData() );
808 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN,
nullptr );
809 if ( mAddToCanvas->isEnabled() && !canReopen )
811 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
812 mAddToCanvas->setChecked(
false );
813 mAddToCanvas->setEnabled(
false );
815 else if ( !mAddToCanvas->isEnabled() && canReopen )
817 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
818 mAddToCanvas->setEnabled(
true );
826void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged(
int state )
828 const QSignalBlocker signalBlocker( mAttributeTable );
835 bool modifiedEntries =
false;
836 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
838 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
840 modifiedEntries =
true;
845 if ( modifiedEntries )
847 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
849 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
854 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
856 mUseAliasesForExportedName->setTristate(
false );
857 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() );
864 bool modifiedEntries =
false;
865 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
867 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() )
868 modifiedEntries =
true;
871 if ( modifiedEntries )
873 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
875 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
880 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
882 mUseAliasesForExportedName->setTristate(
false );
883 const QString alias = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
884 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
888 case Qt::PartiallyChecked:
894void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged(
int )
896 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
899 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
900 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
902 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
904 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
906 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
907 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
908 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
910 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
914 mReplaceRawFieldValues->setTristate(
false );
917void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
919 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
920 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
922 int row = item->row();
923 int column = item->column();
925 switch (
static_cast<ColumnIndex
>( column ) )
927 case ColumnIndex::Name:
929 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
930 || !mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
931 || !( mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
934 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
936 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
937 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
938 bool checkBoxEnabled =
false;
939 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
941 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
942 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
944 checkBoxEnabled =
true;
948 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
949 if ( !checkBoxEnabled )
950 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
952 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
954 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
955 mReplaceRawFieldValues->setEnabled(
true );
959 case ColumnIndex::ExportName:
962 if ( item->text().isEmpty() )
964 QMessageBox::warning(
this, tr(
"Empty export name" ), tr(
"Empty export name are not allowed." ) );
970 while ( names.count( item->text() ) > 1 )
971 item->setText( QString(
"%1_2" ).arg( item->text() ) );
973 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
976 case ColumnIndex::Type:
979 case ColumnIndex::ExportAsDisplayedValue:
981 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
983 bool allChecked =
true;
984 bool allUnchecked =
true;
985 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
987 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
988 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
990 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
993 allUnchecked =
false;
996 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked : Qt::Unchecked );
1005 if ( mCrsDefinedByFormat )
1013 mUserDefinedCrs =
crs;
1014 mExtentGroupBox->setOutputCrs( mSelectedCrs );
1019 return mFilename->filePath();
1024 return leLayername->text();
1029 return mEncodingComboBox->currentText();
1034 return mFormatComboBox->currentData().toString();
1039 return mSelectedCrs;
1044 QStringList options;
1050 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1054 switch ( it.value()->type )
1059 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1061 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1068 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
1069 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1070 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1077 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1079 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1086 if ( opt && !opt->
mValue.isEmpty() )
1087 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1094 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
1095 if ( !plainText.isEmpty() )
1096 options += plainText.split(
'\n' );
1103 QStringList options;
1109 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1113 switch ( it.value()->type )
1118 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1120 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1127 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1128 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1129 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1136 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1138 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1145 if ( !opt->
mValue.isEmpty() )
1146 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1153 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1154 if ( !plainText.isEmpty() )
1155 options += plainText.split(
'\n' );
1164 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1166 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1168 attributes.append( i );
1179 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1181 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
1182 && !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1183 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Checked )
1185 attributes.append( i );
1194 QStringList exportNames;
1195 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1196 exportNames.append( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() );
1203 return mAddToCanvas->isChecked();
1208 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1209 if ( mAddToCanvas->isEnabled() )
1210 mAddToCanvas->setChecked( enabled );
1220 return mScaleWidget->scale();
1225 mMapCanvas = canvas;
1226 mScaleWidget->setMapCanvas( canvas );
1227 mScaleWidget->setShowCurrentScaleButton(
true );
1233 return mExtentGroupBox->isChecked();
1238 return mExtentGroupBox->outputExtent();
1248 return mSelectedOnly->isChecked();
1253 return mCheckPersistMetadata->isChecked();
1258 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1259 if ( currentIndexData == -1 )
1270 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1271 return currentIndexData == -1;
1276 return mForceMultiCheckBox->isChecked();
1281 mForceMultiCheckBox->setChecked( checked );
1286 return mIncludeZCheckBox->isChecked();
1291 return mActionOnExistingFile;
1296 mIncludeZCheckBox->setChecked( checked );
1299void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged(
const QString &text )
1301 bool scaleEnabled =
true;
1302 if ( text == tr(
"No symbology" ) )
1304 scaleEnabled =
false;
1306 mScaleWidget->setEnabled( scaleEnabled );
1307 mScaleLabel->setEnabled( scaleEnabled );
1310void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged(
int )
1312 const int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1315 mForceMultiCheckBox->setEnabled(
true );
1316 mIncludeZCheckBox->setEnabled(
true );
1322 mForceMultiCheckBox->setEnabled(
false );
1323 mForceMultiCheckBox->setChecked(
false );
1327 mForceMultiCheckBox->setEnabled(
true );
1329 mIncludeZCheckBox->setEnabled(
false );
1330 mIncludeZCheckBox->setChecked(
false );
1334void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1336 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1337 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1339 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1341 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1343 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1344 && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1346 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1348 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1351 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1353 mReplaceRawFieldValues->setEnabled(
true );
1357void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1359 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1360 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1362 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1364 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1365 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1366 && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1368 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1369 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1372 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1374 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1375 mReplaceRawFieldValues->setEnabled(
false );
1379void QgsVectorLayerSaveAsDialog::showHelp()
1381 QgsHelp::openHelp( u
"managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer"_s );
1384void QgsVectorLayerSaveAsDialog::setCrsForFormat()
1386 const QString outputFormat =
format();
1388 bool force4326 = ( outputFormat ==
"KML"_L1 || outputFormat ==
"LIBKML"_L1 || outputFormat ==
"GPX"_L1 );
1391 if ( outputFormat ==
"GeoJSON"_L1 )
1393 QComboBox *cmb = mLayerOptionsGroupBox->findChild<QComboBox *>( u
"RFC7946"_s );
1394 if ( cmb && cmb->currentText() ==
"YES"_L1 )
1400 if ( force4326 && !mCrsDefinedByFormat )
1402 mUserDefinedCrs = mCrsSelector->crs();
1403 mCrsDefinedByFormat =
true;
1404 mCrsSelector->setEnabled(
false );
1405 mSelectedCrs = QgsCoordinateReferenceSystem( u
"EPSG:4326"_s );
1407 mExtentGroupBox->setOutputCrs( mSelectedCrs );
1409 else if ( !force4326 && mCrsDefinedByFormat )
1411 mCrsDefinedByFormat =
false;
1412 mCrsSelector->setEnabled(
true );
1413 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.