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(
"Select the coordinate reference system for the vector file. "
181 "The data points will be transformed from the layer coordinate reference system." ) );
183 mEncodingComboBox->setCurrentIndex( idx );
184 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
190 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
193 mExtentGroupBox->setOutputCrs( mSelectedCrs );
194 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
195 mExtentGroupBox->setOutputExtentFromOriginal();
196 mExtentGroupBox->setCheckable(
true );
197 mExtentGroupBox->setChecked(
false );
198 mExtentGroupBox->setCollapsed(
true );
201 mFilename->setDialogTitle( tr(
"Save Layer As" ) );
202 mFilename->setDefaultRoot( settings.
value( u
"UI/lastVectorFileFilterDir"_s, QDir::homePath() ).toString() );
203 mFilename->setConfirmOverwrite(
false );
205 QgsSettings settings;
206 QFileInfo tmplFileInfo( filePath );
207 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, tmplFileInfo.absolutePath() );
209 const QFileInfo fileInfo( filePath );
211 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
212 leLayername->setDefaultValue( suggestedLayerName );
215 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
217 leLayername->setText( suggestedLayerName );
219 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
224 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
227 mCrsSelector->setSourceEnsemble( ensemble.
name() );
230 catch ( QgsNotSupportedException & )
234 mCrsSelector->setShowAccuracyWarnings(
true );
237QList<QPair<QLabel *, QWidget *>> QgsVectorLayerSaveAsDialog::createControls(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
239 QList<QPair<QLabel *, QWidget *>> controls;
240 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
242 for ( it = options.constBegin(); it != options.constEnd(); ++it )
244 QgsVectorFileWriter::Option *option = it.value();
245 QWidget *control =
nullptr;
246 switch ( option->
type )
250 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
253 QSpinBox *sb =
new QSpinBox();
254 sb->setObjectName( it.key() );
255 sb->setMaximum( std::numeric_limits<int>::max() );
264 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
267 QComboBox *cb =
new QComboBox();
268 cb->setObjectName( it.key() );
269 for (
const QString &val : std::as_const( opt->
values ) )
271 cb->addItem( val, val );
278 cb->setCurrentIndex( idx );
286 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
290 le->setObjectName( it.key() );
303 QLabel *label =
new QLabel( it.key() );
306 label->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
307 control->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
309 controls << QPair<QLabel *, QWidget *>( label, control );
318#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
319 if (
format() ==
"OpenFileGDB"_L1 )
323 bool targetAll =
true;
326 if ( layerOption ==
"TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER"_L1 )
334 for (
int i = 0; i < attributesSelected.size(); ++i )
336 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
337 if ( fld.
type() == QMetaType::Type::LongLong )
339 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?" ) ) != QMessageBox::Yes )
348 else if (
format() ==
"FileGDB"_L1 )
352 for (
int i = 0; i < attributesSelected.size(); ++i )
354 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
355 if ( fld.
type() == QMetaType::Type::LongLong )
357 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"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 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?" ).arg( tr(
"ESRI File Geodatabase" ) ) ) != QMessageBox::Yes )
372 msgBox.setIcon( QMessageBox::Question );
373 msgBox.setWindowTitle( tr(
"Save Vector Layer As" ) );
374 QPushButton *overwriteFileButton = msgBox.addButton( tr(
"Overwrite File" ), QMessageBox::ActionRole );
375 QPushButton *overwriteLayerButton = msgBox.addButton( tr(
"Overwrite Layer" ), QMessageBox::ActionRole );
376 QPushButton *appendToLayerButton = msgBox.addButton( tr(
"Append to Layer" ), QMessageBox::ActionRole );
377 msgBox.setStandardButtons( QMessageBox::Cancel );
378 msgBox.setDefaultButton( QMessageBox::Cancel );
379 overwriteFileButton->hide();
380 overwriteLayerButton->hide();
381 appendToLayerButton->hide();
386 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
387 overwriteFileButton->setVisible(
true );
388 overwriteLayerButton->setVisible(
true );
392 msgBox.setText( tr(
"The file already exists. Do you want to overwrite it?" ) );
393 overwriteFileButton->setVisible(
true );
397 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
398 appendToLayerButton->setVisible(
true );
399 overwriteFileButton->setVisible(
true );
400 overwriteLayerButton->setVisible(
true );
404 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
405 appendToLayerButton->setVisible(
true );
406 overwriteFileButton->setVisible(
true );
409 int ret = msgBox.exec();
410 if ( ret == QMessageBox::Cancel )
412 if ( msgBox.clickedButton() == overwriteFileButton )
414 else if ( msgBox.clickedButton() == overwriteLayerButton )
416 else if ( msgBox.clickedButton() == appendToLayerButton )
428 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
441 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 )
450 QStringList layerList;
451 layerList.reserve( sublayers.size() );
454 layerList.append( sublayer.name() );
456 if ( layerList.length() > 1 )
458 layerList.sort( Qt::CaseInsensitive );
460 msgBox.setIcon( QMessageBox::Warning );
461 msgBox.setWindowTitle( tr(
"Overwrite File" ) );
462 msgBox.setText( tr(
"This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
463 msgBox.setDetailedText( tr(
"The following layers will be permanently lost:\n\n%1" ).arg( layerList.join(
"\n" ) ) );
464 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
465 if ( msgBox.exec() == QMessageBox::Cancel )
471 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo(
fileName() ).absolutePath() );
477void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged(
int idx )
481 mFilename->setEnabled(
true );
489 if (
format() ==
"OpenFileGDB"_L1 ||
format() ==
"FileGDB"_L1 )
490 filter = u
"%1 (*.gdb *.GDB gdb)"_s.arg( tr(
"ESRI File Geodatabase" ) );
491 mFilename->setFilter( filter );
495 if ( !mFilename->filePath().isEmpty() )
497 const thread_local QRegularExpression rx(
"\\.(.*?)[\\s]" );
498 const QString ext = rx.match( filter ).captured( 1 );
499 if ( !ext.isEmpty() )
501 QFileInfo fi( mFilename->filePath() );
502 mFilename->setFilePath( u
"%1/%2.%3"_s.arg( fi.path(), fi.baseName(), ext ) );
506 bool selectAllFields =
true;
511 bool isFormatForFieldsAsDisplayedValues =
false;
513 const QString sFormat(
format() );
514 if ( sFormat ==
"DXF"_L1 || sFormat ==
"DGN"_L1 )
516 mAttributesSelection->setVisible(
false );
517 selectAllFields =
false;
523 mAttributesSelection->setVisible(
true );
524 isFormatForFieldsAsDisplayedValues = ( sFormat ==
"CSV"_L1 || sFormat ==
"XLS"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 );
531 mSymbologyExportLabel->setVisible(
true );
532 mSymbologyExportComboBox->setVisible(
true );
533 mScaleLabel->setVisible(
true );
534 mScaleWidget->setVisible(
true );
538 mSymbologyExportLabel->hide();
539 mSymbologyExportComboBox->hide();
541 mScaleWidget->hide();
544 leLayername->setEnabled( sFormat ==
"KML"_L1 || sFormat ==
"GPKG"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 || sFormat ==
"FileGDB"_L1 || sFormat ==
"OpenFileGDB"_L1 || sFormat ==
"SQLite"_L1 || sFormat ==
"SpatiaLite"_L1 );
546 if ( sFormat ==
"XLSX"_L1 )
547 leLayername->setMaxLength( 31 );
548 else if ( leLayername->isEnabled() )
549 leLayername->setMaxLength( 32767 );
551 if ( !leLayername->isEnabled() )
552 leLayername->setText( QString() );
553 else if ( leLayername->text().isEmpty() )
555 QString
layerName = mDefaultOutputLayerNameFromInputLayerName;
556 if (
layerName.isEmpty() && !mFilename->filePath().isEmpty() )
558 layerName = QFileInfo( mFilename->filePath() ).baseName();
559 leLayername->setDefaultValue(
layerName );
569 const bool isPreviousFormatForFieldsAsDisplayedValues = ( mPreviousFormat ==
"CSV"_L1 || mPreviousFormat ==
"XLS"_L1 || mPreviousFormat ==
"XLSX"_L1 || mPreviousFormat ==
"ODS"_L1 );
570 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
572 QTableWidgetItem *nameItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) );
578 const QString fieldName = nameItem->text();
579 const bool exportField = ( nameItem->checkState() == Qt::Checked );
581 std::optional<bool> exportAsValue = std::nullopt;
582 if ( isPreviousFormatForFieldsAsDisplayedValues )
584 QTableWidgetItem *valueItem = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) );
585 if ( valueItem && ( valueItem->flags() & Qt::ItemIsUserCheckable ) )
587 exportAsValue = ( valueItem->checkState() == Qt::Checked );
592 exportAsValue = mFieldsState[fieldName].second;
595 mFieldsState[fieldName] = { exportField, exportAsValue };
598 mPreviousFormat = sFormat;
600 mAttributeTable->setRowCount( mLayer->fields().count() );
602 QStringList horizontalHeaders = QStringList() << tr(
"Name" ) << tr(
"Export name" ) << tr(
"Type" ) << tr(
"Replace with displayed values" );
603 mAttributeTable->setColumnCount(
static_cast<int>( horizontalHeaders.size() ) );
604 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
606 bool foundFieldThatCanBeExportedAsDisplayedValue =
false;
607 for (
int i = 0; i < mLayer->fields().size(); ++i )
612 foundFieldThatCanBeExportedAsDisplayedValue =
true;
616 mAttributeTable->setColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
618 bool allChecked =
true;
619 bool allUnchecked =
true;
620 bool anyEnabled =
false;
622 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
624 for (
int i = 0; i < mLayer->fields().size(); ++i )
626 QgsField fld = mLayer->fields().at( i );
627 Qt::ItemFlags flags = mLayer->providerType() !=
"oracle"_L1 || !fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
628 QTableWidgetItem *item =
nullptr;
629 const QString fieldName = fld.
name();
630 const bool exportField = mFieldsState.contains( fieldName ) ? mFieldsState[fieldName].first : selectAllFields;
631 item =
new QTableWidgetItem( fieldName );
632 item->setFlags( flags | Qt::ItemIsUserCheckable );
633 item->setCheckState( ( exportField ) ? Qt::Checked : Qt::Unchecked );
634 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Name ), item );
636 item =
new QTableWidgetItem( fieldName );
637 item->setFlags( flags | Qt::ItemIsEditable );
639 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportName ), item );
641 item =
new QTableWidgetItem( fld.
typeName() );
642 item->setFlags( flags );
643 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Type ), item );
645 if ( foundFieldThatCanBeExportedAsDisplayedValue )
648 QgsEditorWidgetFactory *factory =
nullptr;
649 const QString widgetId( setup.type() );
652 item =
new QTableWidgetItem( tr(
"Use %1" ).arg( factory->
name() ) );
654 if ( mFieldsState.contains( fieldName ) && mFieldsState[fieldName].second.has_value() )
656 exportAsValue = mFieldsState[fieldName].second.value();
660 exportAsValue = ( exportField && isFormatForFieldsAsDisplayedValues && ( widgetId ==
"ValueMap"_L1 || widgetId ==
"ValueRelation"_L1 || widgetId ==
"CheckBox"_L1 || widgetId ==
"RelationReference"_L1 ) );
662 item->setFlags( ( exportField ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
663 item->setCheckState( exportAsValue ? Qt::Checked : Qt::Unchecked );
664 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
671 allUnchecked =
false;
678 item =
new QTableWidgetItem();
679 item->setFlags( Qt::NoItemFlags );
680 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
686 Qt::CheckState replaceRawState;
687 if ( !anyEnabled || allUnchecked )
688 replaceRawState = Qt::Unchecked;
689 else if ( allChecked )
690 replaceRawState = Qt::Checked;
692 replaceRawState = Qt::PartiallyChecked;
694 whileBlocking( mReplaceRawFieldValues )->setCheckState( replaceRawState );
695 mReplaceRawFieldValues->setEnabled( selectAllFields && anyEnabled );
696 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
698 mAttributeTable->resizeColumnsToContents();
701 QgsVectorFileWriter::MetaData driverMetaData;
703 while ( mDatasourceOptionsGroupBox->layout()->count() )
705 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
706 delete item->widget();
710 while ( mLayerOptionsGroupBox->layout()->count() )
712 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
713 delete item->widget();
717 typedef QPair<QLabel *, QWidget *> LabelControlPair;
723 mDatasourceOptionsGroupBox->setVisible(
true );
724 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
driverOptions );
726 QFormLayout *datasourceLayout =
dynamic_cast<QFormLayout *
>( mDatasourceOptionsGroupBox->layout() );
728 const auto constControls = controls;
729 for ( LabelControlPair control : constControls )
731 datasourceLayout->addRow( control.first, control.second );
736 mDatasourceOptionsGroupBox->setVisible(
false );
741 mLayerOptionsGroupBox->setVisible(
true );
742 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
layerOptions );
744 QFormLayout *layerOptionsLayout =
dynamic_cast<QFormLayout *
>( mLayerOptionsGroupBox->layout() );
746 const auto constControls = controls;
747 for ( LabelControlPair control : constControls )
749 layerOptionsLayout->addRow( control.first, control.second );
754 mLayerOptionsGroupBox->setVisible(
false );
759 mEncodingComboBox->setEnabled(
true );
766 mEncodingComboBox->setCurrentIndex( idx );
767 mEncodingComboBox->setDisabled(
true );
771 mEncodingComboBox->setEnabled(
true );
777 mEncodingComboBox->setEnabled(
true );
780 GDALDriverH hDriver = GDALGetDriverByName(
format().toUtf8().constData() );
783 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN,
nullptr );
784 if ( mAddToCanvas->isEnabled() && !canReopen )
786 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
787 mAddToCanvas->setChecked(
false );
788 mAddToCanvas->setEnabled(
false );
790 else if ( !mAddToCanvas->isEnabled() && canReopen )
792 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
793 mAddToCanvas->setEnabled(
true );
798void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged(
int state )
800 const QSignalBlocker signalBlocker( mAttributeTable );
807 bool modifiedEntries =
false;
808 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
810 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text()
811 != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
813 modifiedEntries =
true;
818 if ( modifiedEntries )
820 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) )
823 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
828 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
830 mUseAliasesForExportedName->setTristate(
false );
831 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() );
838 bool modifiedEntries =
false;
839 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
841 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text()
842 != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() )
843 modifiedEntries =
true;
846 if ( modifiedEntries )
848 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) )
851 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
856 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
858 mUseAliasesForExportedName->setTristate(
false );
859 const QString alias = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
860 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
864 case Qt::PartiallyChecked:
870void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged(
int )
872 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
875 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
876 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
878 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
880 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
882 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
884 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
888 mReplaceRawFieldValues->setTristate(
false );
891void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
893 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
894 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
896 int row = item->row();
897 int column = item->column();
899 switch (
static_cast<ColumnIndex
>( column ) )
901 case ColumnIndex::Name:
903 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) || !mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) || !( mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
906 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
908 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
909 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
910 bool checkBoxEnabled =
false;
911 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
913 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
915 checkBoxEnabled =
true;
919 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
920 if ( !checkBoxEnabled )
921 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
923 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
925 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
926 mReplaceRawFieldValues->setEnabled(
true );
930 case ColumnIndex::ExportName:
933 if ( item->text().isEmpty() )
935 QMessageBox::warning(
this, tr(
"Empty export name" ), tr(
"Empty export name are not allowed." ) );
941 while ( names.count( item->text() ) > 1 )
942 item->setText( QString(
"%1_2" ).arg( item->text() ) );
944 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
947 case ColumnIndex::Type:
950 case ColumnIndex::ExportAsDisplayedValue:
952 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
954 bool allChecked =
true;
955 bool allUnchecked =
true;
956 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
958 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
960 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
963 allUnchecked =
false;
966 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked
977 mExtentGroupBox->setOutputCrs( mSelectedCrs );
982 return mFilename->filePath();
987 return leLayername->text();
992 return mEncodingComboBox->currentText();
997 return mFormatComboBox->currentData().toString();
1002 return mSelectedCrs;
1007 QStringList options;
1013 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1017 switch ( it.value()->type )
1022 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1024 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1031 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
1032 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1033 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1040 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1042 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1049 if ( opt && !opt->
mValue.isEmpty() )
1050 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1057 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
1058 if ( !plainText.isEmpty() )
1059 options += plainText.split(
'\n' );
1066 QStringList options;
1072 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1076 switch ( it.value()->type )
1081 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1083 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1090 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1091 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1092 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1099 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1101 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1108 if ( !opt->
mValue.isEmpty() )
1109 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1116 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1117 if ( !plainText.isEmpty() )
1118 options += plainText.split(
'\n' );
1127 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1129 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1131 attributes.append( i );
1142 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1144 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked && !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Checked )
1146 attributes.append( i );
1155 QStringList exportNames;
1156 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1157 exportNames.append( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() );
1164 return mAddToCanvas->isChecked();
1169 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1170 if ( mAddToCanvas->isEnabled() )
1171 mAddToCanvas->setChecked( enabled );
1181 return mScaleWidget->scale();
1186 mMapCanvas = canvas;
1187 mScaleWidget->setMapCanvas( canvas );
1188 mScaleWidget->setShowCurrentScaleButton(
true );
1194 return mExtentGroupBox->isChecked();
1199 return mExtentGroupBox->outputExtent();
1209 return mSelectedOnly->isChecked();
1214 return mCheckPersistMetadata->isChecked();
1219 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1220 if ( currentIndexData == -1 )
1231 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1232 return currentIndexData == -1;
1237 return mForceMultiCheckBox->isChecked();
1242 mForceMultiCheckBox->setChecked( checked );
1247 return mIncludeZCheckBox->isChecked();
1252 return mActionOnExistingFile;
1257 mIncludeZCheckBox->setChecked( checked );
1260void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged(
const QString &text )
1262 bool scaleEnabled =
true;
1263 if ( text == tr(
"No symbology" ) )
1265 scaleEnabled =
false;
1267 mScaleWidget->setEnabled( scaleEnabled );
1268 mScaleLabel->setEnabled( scaleEnabled );
1271void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged(
int )
1273 const int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1276 mForceMultiCheckBox->setEnabled(
true );
1277 mIncludeZCheckBox->setEnabled(
true );
1283 mForceMultiCheckBox->setEnabled(
false );
1284 mForceMultiCheckBox->setChecked(
false );
1288 mForceMultiCheckBox->setEnabled(
true );
1290 mIncludeZCheckBox->setEnabled(
false );
1291 mIncludeZCheckBox->setChecked(
false );
1295void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1297 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1298 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1300 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1302 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1304 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1306 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1308 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1311 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1313 mReplaceRawFieldValues->setEnabled(
true );
1317void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1319 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1320 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1322 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1324 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1325 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1327 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1328 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1331 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1333 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1334 mReplaceRawFieldValues->setEnabled(
false );
1338void QgsVectorLayerSaveAsDialog::showHelp()
1340 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.