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."
185 mEncodingComboBox->setCurrentIndex( idx );
186 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
192 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
195 mExtentGroupBox->setOutputCrs( mSelectedCrs );
196 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
197 mExtentGroupBox->setOutputExtentFromOriginal();
198 mExtentGroupBox->setCheckable(
true );
199 mExtentGroupBox->setChecked(
false );
200 mExtentGroupBox->setCollapsed(
true );
203 mFilename->setDialogTitle( tr(
"Save Layer As" ) );
204 mFilename->setDefaultRoot( settings.
value( u
"UI/lastVectorFileFilterDir"_s, QDir::homePath() ).toString() );
205 mFilename->setConfirmOverwrite(
false );
207 QgsSettings settings;
208 QFileInfo tmplFileInfo( filePath );
209 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, tmplFileInfo.absolutePath() );
211 const QFileInfo fileInfo( filePath );
213 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
214 leLayername->setDefaultValue( suggestedLayerName );
217 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
219 leLayername->setText( suggestedLayerName );
221 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
226 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
229 mCrsSelector->setSourceEnsemble( ensemble.
name() );
232 catch ( QgsNotSupportedException & )
235 mCrsSelector->setShowAccuracyWarnings(
true );
238QList<QPair<QLabel *, QWidget *>> QgsVectorLayerSaveAsDialog::createControls(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
240 QList<QPair<QLabel *, QWidget *>> controls;
241 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
243 for ( it = options.constBegin(); it != options.constEnd(); ++it )
245 QgsVectorFileWriter::Option *option = it.value();
246 QWidget *control =
nullptr;
247 switch ( option->
type )
251 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
254 QSpinBox *sb =
new QSpinBox();
255 sb->setObjectName( it.key() );
256 sb->setMaximum( std::numeric_limits<int>::max() );
265 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
268 QComboBox *cb =
new QComboBox();
269 cb->setObjectName( it.key() );
270 for (
const QString &val : std::as_const( opt->
values ) )
272 cb->addItem( val, val );
279 cb->setCurrentIndex( idx );
287 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
291 le->setObjectName( it.key() );
304 QLabel *label =
new QLabel( it.key() );
307 label->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
308 control->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
310 controls << QPair<QLabel *, QWidget *>( label, control );
319#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
320 if (
format() ==
"OpenFileGDB"_L1 )
324 bool targetAll =
true;
327 if ( layerOption ==
"TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER"_L1 )
335 for (
int i = 0; i < attributesSelected.size(); ++i )
337 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
338 if ( fld.
type() == QMetaType::Type::LongLong )
340 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?" ) )
341 != QMessageBox::Yes )
350 else if (
format() ==
"FileGDB"_L1 )
354 for (
int i = 0; i < attributesSelected.size(); ++i )
356 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
357 if ( fld.
type() == QMetaType::Type::LongLong )
359 if ( QMessageBox::question(
361 tr(
"Save Vector Layer As" ),
363 "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 "
364 "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?"
366 .arg( tr(
"ESRI File Geodatabase" ) )
368 != QMessageBox::Yes )
383 msgBox.setIcon( QMessageBox::Question );
384 msgBox.setWindowTitle( tr(
"Save Vector Layer As" ) );
385 QPushButton *overwriteFileButton = msgBox.addButton( tr(
"Overwrite File" ), QMessageBox::ActionRole );
386 QPushButton *overwriteLayerButton = msgBox.addButton( tr(
"Overwrite Layer" ), QMessageBox::ActionRole );
387 QPushButton *appendToLayerButton = msgBox.addButton( tr(
"Append to Layer" ), QMessageBox::ActionRole );
388 msgBox.setStandardButtons( QMessageBox::Cancel );
389 msgBox.setDefaultButton( QMessageBox::Cancel );
390 overwriteFileButton->hide();
391 overwriteLayerButton->hide();
392 appendToLayerButton->hide();
397 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
398 overwriteFileButton->setVisible(
true );
399 overwriteLayerButton->setVisible(
true );
403 msgBox.setText( tr(
"The file already exists. Do you want to overwrite it?" ) );
404 overwriteFileButton->setVisible(
true );
408 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
409 appendToLayerButton->setVisible(
true );
410 overwriteFileButton->setVisible(
true );
411 overwriteLayerButton->setVisible(
true );
415 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
416 appendToLayerButton->setVisible(
true );
417 overwriteFileButton->setVisible(
true );
420 int ret = msgBox.exec();
421 if ( ret == QMessageBox::Cancel )
423 if ( msgBox.clickedButton() == overwriteFileButton )
425 else if ( msgBox.clickedButton() == overwriteLayerButton )
427 else if ( msgBox.clickedButton() == appendToLayerButton )
439 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
452 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 )
461 QStringList layerList;
462 layerList.reserve( sublayers.size() );
465 layerList.append( sublayer.name() );
467 if ( layerList.length() > 1 )
469 layerList.sort( Qt::CaseInsensitive );
471 msgBox.setIcon( QMessageBox::Warning );
472 msgBox.setWindowTitle( tr(
"Overwrite File" ) );
473 msgBox.setText( tr(
"This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
474 msgBox.setDetailedText( tr(
"The following layers will be permanently lost:\n\n%1" ).arg( layerList.join(
"\n" ) ) );
475 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
476 if ( msgBox.exec() == QMessageBox::Cancel )
482 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo(
fileName() ).absolutePath() );
488void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged(
int idx )
492 mFilename->setEnabled(
true );
500 if (
format() ==
"OpenFileGDB"_L1 ||
format() ==
"FileGDB"_L1 )
501 filter = u
"%1 (*.gdb *.GDB gdb)"_s.arg( tr(
"ESRI File Geodatabase" ) );
502 mFilename->setFilter( filter );
506 if ( !mFilename->filePath().isEmpty() )
508 const thread_local QRegularExpression rx(
"\\.(.*?)[\\s]" );
509 const QString ext = rx.match( filter ).captured( 1 );
510 if ( !ext.isEmpty() )
512 QFileInfo fi( mFilename->filePath() );
513 mFilename->setFilePath( u
"%1/%2.%3"_s.arg( fi.path(), fi.baseName(), ext ) );
517 bool selectAllFields =
true;
522 bool isFormatForFieldsAsDisplayedValues =
false;
524 const QString sFormat(
format() );
525 if ( sFormat ==
"DXF"_L1 || sFormat ==
"DGN"_L1 )
527 mAttributesSelection->setVisible(
false );
528 selectAllFields =
false;
534 mAttributesSelection->setVisible(
true );
535 isFormatForFieldsAsDisplayedValues = ( sFormat ==
"CSV"_L1 || sFormat ==
"XLS"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 );
542 mSymbologyExportLabel->setVisible(
true );
543 mSymbologyExportComboBox->setVisible(
true );
544 mScaleLabel->setVisible(
true );
545 mScaleWidget->setVisible(
true );
549 mSymbologyExportLabel->hide();
550 mSymbologyExportComboBox->hide();
552 mScaleWidget->hide();
555 leLayername->setEnabled(
556 sFormat ==
"KML"_L1 || sFormat ==
"GPKG"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 || sFormat ==
"FileGDB"_L1 || sFormat ==
"OpenFileGDB"_L1 || sFormat ==
"SQLite"_L1 || sFormat ==
"SpatiaLite"_L1
559 if ( sFormat ==
"XLSX"_L1 )
560 leLayername->setMaxLength( 31 );
561 else if ( leLayername->isEnabled() )
562 leLayername->setMaxLength( 32767 );
564 if ( !leLayername->isEnabled() )
565 leLayername->setText( QString() );
566 else if ( leLayername->text().isEmpty() )
568 QString
layerName = mDefaultOutputLayerNameFromInputLayerName;
569 if (
layerName.isEmpty() && !mFilename->filePath().isEmpty() )
571 layerName = QFileInfo( mFilename->filePath() ).baseName();
572 leLayername->setDefaultValue(
layerName );
582 const bool isPreviousFormatForFieldsAsDisplayedValues = ( mPreviousFormat ==
"CSV"_L1 || mPreviousFormat ==
"XLS"_L1 || mPreviousFormat ==
"XLSX"_L1 || mPreviousFormat ==
"ODS"_L1 );
583 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
585 QTableWidgetItem *nameItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) );
591 const QString fieldName = nameItem->text();
592 const bool exportField = ( nameItem->checkState() == Qt::Checked );
594 std::optional<bool> exportAsValue = std::nullopt;
595 if ( isPreviousFormatForFieldsAsDisplayedValues )
597 QTableWidgetItem *valueItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) );
598 if ( valueItem && ( valueItem->flags() & Qt::ItemIsUserCheckable ) )
600 exportAsValue = ( valueItem->checkState() == Qt::Checked );
605 exportAsValue = mFieldsState[fieldName].second;
608 mFieldsState[fieldName] = { exportField, exportAsValue };
611 mPreviousFormat = sFormat;
613 mAttributeTable->setRowCount( mLayer->fields().count() );
615 QStringList horizontalHeaders = QStringList() << tr(
"Name" ) << tr(
"Export name" ) << tr(
"Type" ) << tr(
"Replace with displayed values" );
616 mAttributeTable->setColumnCount(
static_cast<int>( horizontalHeaders.size() ) );
617 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
619 bool foundFieldThatCanBeExportedAsDisplayedValue =
false;
620 for (
int i = 0; i < mLayer->fields().size(); ++i )
625 foundFieldThatCanBeExportedAsDisplayedValue =
true;
629 mAttributeTable->setColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
631 bool allChecked =
true;
632 bool allUnchecked =
true;
633 bool anyEnabled =
false;
635 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
637 for (
int i = 0; i < mLayer->fields().size(); ++i )
639 QgsField fld = mLayer->fields().at( i );
640 Qt::ItemFlags flags = mLayer->providerType() !=
"oracle"_L1 || !fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
641 QTableWidgetItem *item =
nullptr;
642 const QString fieldName = fld.
name();
643 const bool exportField = mFieldsState.contains( fieldName ) ? mFieldsState[fieldName].first : selectAllFields;
644 item =
new QTableWidgetItem( fieldName );
645 item->setFlags( flags | Qt::ItemIsUserCheckable );
646 item->setCheckState( ( exportField ) ? Qt::Checked : Qt::Unchecked );
647 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Name ), item );
649 item =
new QTableWidgetItem( fieldName );
650 item->setFlags( flags | Qt::ItemIsEditable );
652 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportName ), item );
654 item =
new QTableWidgetItem( fld.
typeName() );
655 item->setFlags( flags );
656 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Type ), item );
658 if ( foundFieldThatCanBeExportedAsDisplayedValue )
661 QgsEditorWidgetFactory *factory =
nullptr;
662 const QString widgetId( setup.type() );
665 item =
new QTableWidgetItem( tr(
"Use %1" ).arg( factory->
name() ) );
667 if ( mFieldsState.contains( fieldName ) && mFieldsState[fieldName].second.has_value() )
669 exportAsValue = mFieldsState[fieldName].second.value();
674 = ( exportField && isFormatForFieldsAsDisplayedValues && ( widgetId ==
"ValueMap"_L1 || widgetId ==
"ValueRelation"_L1 || widgetId ==
"CheckBox"_L1 || widgetId ==
"RelationReference"_L1 ) );
676 item->setFlags( ( exportField ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
677 item->setCheckState( exportAsValue ? Qt::Checked : Qt::Unchecked );
678 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
685 allUnchecked =
false;
692 item =
new QTableWidgetItem();
693 item->setFlags( Qt::NoItemFlags );
694 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
700 Qt::CheckState replaceRawState;
701 if ( !anyEnabled || allUnchecked )
702 replaceRawState = Qt::Unchecked;
703 else if ( allChecked )
704 replaceRawState = Qt::Checked;
706 replaceRawState = Qt::PartiallyChecked;
708 whileBlocking( mReplaceRawFieldValues )->setCheckState( replaceRawState );
709 mReplaceRawFieldValues->setEnabled( selectAllFields && anyEnabled );
710 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
712 mAttributeTable->resizeColumnsToContents();
715 QgsVectorFileWriter::MetaData driverMetaData;
717 while ( mDatasourceOptionsGroupBox->layout()->count() )
719 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
720 delete item->widget();
724 while ( mLayerOptionsGroupBox->layout()->count() )
726 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
727 delete item->widget();
731 typedef QPair<QLabel *, QWidget *> LabelControlPair;
737 mDatasourceOptionsGroupBox->setVisible(
true );
738 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
driverOptions );
740 QFormLayout *datasourceLayout =
dynamic_cast<QFormLayout *
>( mDatasourceOptionsGroupBox->layout() );
742 const auto constControls = controls;
743 for ( LabelControlPair control : constControls )
745 datasourceLayout->addRow( control.first, control.second );
750 mDatasourceOptionsGroupBox->setVisible(
false );
755 mLayerOptionsGroupBox->setVisible(
true );
756 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
layerOptions );
758 QFormLayout *layerOptionsLayout =
dynamic_cast<QFormLayout *
>( mLayerOptionsGroupBox->layout() );
760 const auto constControls = controls;
761 for ( LabelControlPair control : constControls )
763 layerOptionsLayout->addRow( control.first, control.second );
768 mLayerOptionsGroupBox->setVisible(
false );
773 mEncodingComboBox->setEnabled(
true );
780 mEncodingComboBox->setCurrentIndex( idx );
781 mEncodingComboBox->setDisabled(
true );
785 mEncodingComboBox->setEnabled(
true );
791 mEncodingComboBox->setEnabled(
true );
794 GDALDriverH hDriver = GDALGetDriverByName(
format().toUtf8().constData() );
797 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN,
nullptr );
798 if ( mAddToCanvas->isEnabled() && !canReopen )
800 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
801 mAddToCanvas->setChecked(
false );
802 mAddToCanvas->setEnabled(
false );
804 else if ( !mAddToCanvas->isEnabled() && canReopen )
806 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
807 mAddToCanvas->setEnabled(
true );
812void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged(
int state )
814 const QSignalBlocker signalBlocker( mAttributeTable );
821 bool modifiedEntries =
false;
822 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
824 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
826 modifiedEntries =
true;
831 if ( modifiedEntries )
833 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
835 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
840 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
842 mUseAliasesForExportedName->setTristate(
false );
843 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() );
850 bool modifiedEntries =
false;
851 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
853 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() )
854 modifiedEntries =
true;
857 if ( modifiedEntries )
859 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) ) == QMessageBox::No )
861 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
866 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
868 mUseAliasesForExportedName->setTristate(
false );
869 const QString alias = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
870 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
874 case Qt::PartiallyChecked:
880void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged(
int )
882 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
885 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
886 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
888 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
890 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
892 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
893 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
894 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
896 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
900 mReplaceRawFieldValues->setTristate(
false );
903void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
905 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
906 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
908 int row = item->row();
909 int column = item->column();
911 switch (
static_cast<ColumnIndex
>( column ) )
913 case ColumnIndex::Name:
915 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
916 || !mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
917 || !( mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
920 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
922 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
923 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
924 bool checkBoxEnabled =
false;
925 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
927 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
928 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
930 checkBoxEnabled =
true;
934 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
935 if ( !checkBoxEnabled )
936 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
938 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
940 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
941 mReplaceRawFieldValues->setEnabled(
true );
945 case ColumnIndex::ExportName:
948 if ( item->text().isEmpty() )
950 QMessageBox::warning(
this, tr(
"Empty export name" ), tr(
"Empty export name are not allowed." ) );
956 while ( names.count( item->text() ) > 1 )
957 item->setText( QString(
"%1_2" ).arg( item->text() ) );
959 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
962 case ColumnIndex::Type:
965 case ColumnIndex::ExportAsDisplayedValue:
967 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
969 bool allChecked =
true;
970 bool allUnchecked =
true;
971 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
973 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
974 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
976 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
979 allUnchecked =
false;
982 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked : Qt::Unchecked );
992 mExtentGroupBox->setOutputCrs( mSelectedCrs );
997 return mFilename->filePath();
1002 return leLayername->text();
1007 return mEncodingComboBox->currentText();
1012 return mFormatComboBox->currentData().toString();
1017 return mSelectedCrs;
1022 QStringList options;
1028 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1032 switch ( it.value()->type )
1037 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1039 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1046 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
1047 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1048 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1055 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1057 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1064 if ( opt && !opt->
mValue.isEmpty() )
1065 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1072 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
1073 if ( !plainText.isEmpty() )
1074 options += plainText.split(
'\n' );
1081 QStringList options;
1087 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1091 switch ( it.value()->type )
1096 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1098 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1105 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1106 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1107 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1114 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1116 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1123 if ( !opt->
mValue.isEmpty() )
1124 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1131 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1132 if ( !plainText.isEmpty() )
1133 options += plainText.split(
'\n' );
1142 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1144 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1146 attributes.append( i );
1157 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1159 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked
1160 && !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1161 && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Checked )
1163 attributes.append( i );
1172 QStringList exportNames;
1173 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1174 exportNames.append( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() );
1181 return mAddToCanvas->isChecked();
1186 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1187 if ( mAddToCanvas->isEnabled() )
1188 mAddToCanvas->setChecked( enabled );
1198 return mScaleWidget->scale();
1203 mMapCanvas = canvas;
1204 mScaleWidget->setMapCanvas( canvas );
1205 mScaleWidget->setShowCurrentScaleButton(
true );
1211 return mExtentGroupBox->isChecked();
1216 return mExtentGroupBox->outputExtent();
1226 return mSelectedOnly->isChecked();
1231 return mCheckPersistMetadata->isChecked();
1236 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1237 if ( currentIndexData == -1 )
1248 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1249 return currentIndexData == -1;
1254 return mForceMultiCheckBox->isChecked();
1259 mForceMultiCheckBox->setChecked( checked );
1264 return mIncludeZCheckBox->isChecked();
1269 return mActionOnExistingFile;
1274 mIncludeZCheckBox->setChecked( checked );
1277void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged(
const QString &text )
1279 bool scaleEnabled =
true;
1280 if ( text == tr(
"No symbology" ) )
1282 scaleEnabled =
false;
1284 mScaleWidget->setEnabled( scaleEnabled );
1285 mScaleLabel->setEnabled( scaleEnabled );
1288void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged(
int )
1290 const int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1293 mForceMultiCheckBox->setEnabled(
true );
1294 mIncludeZCheckBox->setEnabled(
true );
1300 mForceMultiCheckBox->setEnabled(
false );
1301 mForceMultiCheckBox->setChecked(
false );
1305 mForceMultiCheckBox->setEnabled(
true );
1307 mIncludeZCheckBox->setEnabled(
false );
1308 mIncludeZCheckBox->setChecked(
false );
1312void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1314 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1315 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1317 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1319 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1321 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )
1322 && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1324 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1326 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1329 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1331 mReplaceRawFieldValues->setEnabled(
true );
1335void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1337 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1338 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1340 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1342 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
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 );
1347 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1350 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1352 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1353 mReplaceRawFieldValues->setEnabled(
false );
1357void QgsVectorLayerSaveAsDialog::showHelp()
1359 QgsHelp::openHelp( u
"managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer"_s );
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.