40#include <QRegularExpression>
45#include "moc_qgsvectorlayersaveasdialog.cpp"
47using namespace Qt::StringLiterals;
50 : QDialog( parent, fl )
58 : QDialog( parent, fl )
65 mSelectedCrs = layer->
crs();
66 mLayerExtent = layer->
extent();
73 leLayername->setDefaultValue( mDefaultOutputLayerNameFromInputLayerName );
75 if ( leLayername->isEnabled() )
76 leLayername->setText( mDefaultOutputLayerNameFromInputLayerName );
81 mSymbologyExportLabel->hide();
82 mSymbologyExportComboBox->hide();
93 mAttributesSelection->hide();
96 mSelectedOnly->hide();
102 mGeometryGroupBox->hide();
105 mExtentGroupBox->hide();
109 mCheckPersistMetadata->setChecked(
false );
110 mCheckPersistMetadata->hide();
114 mButtonBox->button( QDialogButtonBox::Ok )->setDisabled(
true );
117void QgsVectorLayerSaveAsDialog::setup()
122 connect( mFormatComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged );
124 connect( mSymbologyExportComboBox, &QComboBox::currentTextChanged,
this, &QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged );
125 connect( mGeometryTypeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged );
126 connect( mSelectAllAttributes, &QPushButton::clicked,
this, &QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked );
127 connect( mDeselectAllAttributes, &QPushButton::clicked,
this, &QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked );
128 connect( mUseAliasesForExportedName, &QCheckBox::stateChanged,
this, &QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged );
129 connect( mReplaceRawFieldValues, &QCheckBox::stateChanged,
this, &QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged );
130 connect( mAttributeTable, &QTableWidget::itemChanged,
this, &QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged );
133 mHelpButtonBox->setVisible(
false );
134 mButtonBox->addButton( QDialogButtonBox::Help );
135 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsVectorLayerSaveAsDialog::showHelp );
137 connect( mHelpButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsVectorLayerSaveAsDialog::showHelp );
140 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QgsVectorLayerSaveAsDialog::reject );
143 mFormatComboBox->blockSignals(
true );
146 mFormatComboBox->addItem( driver.longName, driver.driverName );
149 QgsSettings settings;
150 QString
format = settings.
value( u
"UI/lastVectorFormat"_s,
"GPKG" ).toString();
151 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData(
format ) );
152 mFormatComboBox->blockSignals(
false );
159 mGeometryTypeComboBox->addItem( tr(
"Automatic" ), -1 );
165 mGeometryTypeComboBox->setCurrentIndex( mGeometryTypeComboBox->findData( -1 ) );
169 QString enc = settings.
value( u
"UI/encoding"_s,
"System" ).toString();
170 int idx = mEncodingComboBox->findText( enc );
173 mEncodingComboBox->insertItem( 0, enc );
177 mCrsSelector->setCrs( mSelectedCrs );
178 mCrsSelector->setLayerCrs( mSelectedCrs );
179 mCrsSelector->setMessage( tr(
"Select the coordinate reference system for the vector file. "
180 "The data points will be transformed from the layer coordinate reference system." ) );
182 mEncodingComboBox->setCurrentIndex( idx );
183 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
189 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
192 mExtentGroupBox->setOutputCrs( mSelectedCrs );
193 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
194 mExtentGroupBox->setOutputExtentFromOriginal();
195 mExtentGroupBox->setCheckable(
true );
196 mExtentGroupBox->setChecked(
false );
197 mExtentGroupBox->setCollapsed(
true );
200 mFilename->setDialogTitle( tr(
"Save Layer As" ) );
201 mFilename->setDefaultRoot( settings.
value( u
"UI/lastVectorFileFilterDir"_s, QDir::homePath() ).toString() );
202 mFilename->setConfirmOverwrite(
false );
204 QgsSettings settings;
205 QFileInfo tmplFileInfo( filePath );
206 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, tmplFileInfo.absolutePath() );
208 const QFileInfo fileInfo( filePath );
210 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
211 leLayername->setDefaultValue( suggestedLayerName );
214 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
216 leLayername->setText( suggestedLayerName );
218 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
223 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
226 mCrsSelector->setSourceEnsemble( ensemble.
name() );
229 catch ( QgsNotSupportedException & )
233 mCrsSelector->setShowAccuracyWarnings(
true );
236QList<QPair<QLabel *, QWidget *>> QgsVectorLayerSaveAsDialog::createControls(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
238 QList<QPair<QLabel *, QWidget *>> controls;
239 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
241 for ( it = options.constBegin(); it != options.constEnd(); ++it )
243 QgsVectorFileWriter::Option *option = it.value();
244 QWidget *control =
nullptr;
245 switch ( option->
type )
249 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
252 QSpinBox *sb =
new QSpinBox();
253 sb->setObjectName( it.key() );
254 sb->setMaximum( std::numeric_limits<int>::max() );
263 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
266 QComboBox *cb =
new QComboBox();
267 cb->setObjectName( it.key() );
268 for (
const QString &val : std::as_const( opt->
values ) )
270 cb->addItem( val, val );
277 cb->setCurrentIndex( idx );
285 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
289 le->setObjectName( it.key() );
302 QLabel *label =
new QLabel( it.key() );
305 label->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
306 control->setToolTip( u
"<p>%1</p>"_s.arg( option->
docString.toHtmlEscaped() ) );
308 controls << QPair<QLabel *, QWidget *>( label, control );
317#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
318 if (
format() ==
"OpenFileGDB"_L1 )
322 bool targetAll =
true;
325 if ( layerOption ==
"TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER"_L1 )
333 for (
int i = 0; i < attributesSelected.size(); ++i )
335 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
336 if ( fld.
type() == QMetaType::Type::LongLong )
338 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 )
347 else if (
format() ==
"FileGDB"_L1 )
351 for (
int i = 0; i < attributesSelected.size(); ++i )
353 QgsField fld = mLayer->fields().at( attributesSelected.at( i ) );
354 if ( fld.
type() == QMetaType::Type::LongLong )
356 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 )
371 msgBox.setIcon( QMessageBox::Question );
372 msgBox.setWindowTitle( tr(
"Save Vector Layer As" ) );
373 QPushButton *overwriteFileButton = msgBox.addButton( tr(
"Overwrite File" ), QMessageBox::ActionRole );
374 QPushButton *overwriteLayerButton = msgBox.addButton( tr(
"Overwrite Layer" ), QMessageBox::ActionRole );
375 QPushButton *appendToLayerButton = msgBox.addButton( tr(
"Append to Layer" ), QMessageBox::ActionRole );
376 msgBox.setStandardButtons( QMessageBox::Cancel );
377 msgBox.setDefaultButton( QMessageBox::Cancel );
378 overwriteFileButton->hide();
379 overwriteLayerButton->hide();
380 appendToLayerButton->hide();
385 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
386 overwriteFileButton->setVisible(
true );
387 overwriteLayerButton->setVisible(
true );
391 msgBox.setText( tr(
"The file already exists. Do you want to overwrite it?" ) );
392 overwriteFileButton->setVisible(
true );
396 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
397 appendToLayerButton->setVisible(
true );
398 overwriteFileButton->setVisible(
true );
399 overwriteLayerButton->setVisible(
true );
403 msgBox.setText( tr(
"The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
404 appendToLayerButton->setVisible(
true );
405 overwriteFileButton->setVisible(
true );
408 int ret = msgBox.exec();
409 if ( ret == QMessageBox::Cancel )
411 if ( msgBox.clickedButton() == overwriteFileButton )
413 else if ( msgBox.clickedButton() == overwriteLayerButton )
415 else if ( msgBox.clickedButton() == appendToLayerButton )
427 if ( QMessageBox::question(
this, tr(
"Save Vector Layer As" ), tr(
"The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
440 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 )
449 QStringList layerList;
450 layerList.reserve( sublayers.size() );
453 layerList.append( sublayer.name() );
455 if ( layerList.length() > 1 )
457 layerList.sort( Qt::CaseInsensitive );
459 msgBox.setIcon( QMessageBox::Warning );
460 msgBox.setWindowTitle( tr(
"Overwrite File" ) );
461 msgBox.setText( tr(
"This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
462 msgBox.setDetailedText( tr(
"The following layers will be permanently lost:\n\n%1" ).arg( layerList.join(
"\n" ) ) );
463 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
464 if ( msgBox.exec() == QMessageBox::Cancel )
470 settings.
setValue( u
"UI/lastVectorFileFilterDir"_s, QFileInfo(
fileName() ).absolutePath() );
476void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged(
int idx )
480 mFilename->setEnabled(
true );
488 if (
format() ==
"OpenFileGDB"_L1 ||
format() ==
"FileGDB"_L1 )
489 filter = u
"%1 (*.gdb *.GDB gdb)"_s.arg( tr(
"ESRI File Geodatabase" ) );
490 mFilename->setFilter( filter );
494 if ( !mFilename->filePath().isEmpty() )
496 const thread_local QRegularExpression rx(
"\\.(.*?)[\\s]" );
497 const QString ext = rx.match( filter ).captured( 1 );
498 if ( !ext.isEmpty() )
500 QFileInfo fi( mFilename->filePath() );
501 mFilename->setFilePath( u
"%1/%2.%3"_s.arg( fi.path(), fi.baseName(), ext ) );
505 bool selectAllFields =
true;
510 bool isFormatForFieldsAsDisplayedValues =
false;
512 const QString sFormat(
format() );
513 if ( sFormat ==
"DXF"_L1 || sFormat ==
"DGN"_L1 )
515 mAttributesSelection->setVisible(
false );
516 selectAllFields =
false;
522 mAttributesSelection->setVisible(
true );
523 isFormatForFieldsAsDisplayedValues = ( sFormat ==
"CSV"_L1 || sFormat ==
"XLS"_L1 || sFormat ==
"XLSX"_L1 || sFormat ==
"ODS"_L1 );
530 mSymbologyExportLabel->setVisible(
true );
531 mSymbologyExportComboBox->setVisible(
true );
532 mScaleLabel->setVisible(
true );
533 mScaleWidget->setVisible(
true );
537 mSymbologyExportLabel->hide();
538 mSymbologyExportComboBox->hide();
540 mScaleWidget->hide();
543 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 );
545 if ( sFormat ==
"XLSX"_L1 )
546 leLayername->setMaxLength( 31 );
547 else if ( leLayername->isEnabled() )
548 leLayername->setMaxLength( 32767 );
550 if ( !leLayername->isEnabled() )
551 leLayername->setText( QString() );
552 else if ( leLayername->text().isEmpty() )
554 QString
layerName = mDefaultOutputLayerNameFromInputLayerName;
555 if (
layerName.isEmpty() && !mFilename->filePath().isEmpty() )
557 layerName = QFileInfo( mFilename->filePath() ).baseName();
558 leLayername->setDefaultValue(
layerName );
567 mAttributeTable->setRowCount( mLayer->fields().count() );
569 QStringList horizontalHeaders = QStringList() << tr(
"Name" ) << tr(
"Export name" ) << tr(
"Type" ) << tr(
"Replace with displayed values" );
570 mAttributeTable->setColumnCount( horizontalHeaders.size() );
571 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
573 bool foundFieldThatCanBeExportedAsDisplayedValue =
false;
574 for (
int i = 0; i < mLayer->fields().size(); ++i )
579 foundFieldThatCanBeExportedAsDisplayedValue =
true;
583 mAttributeTable->setColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
585 bool checkReplaceRawFieldValues = selectAllFields && isFormatForFieldsAsDisplayedValues;
586 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
588 for (
int i = 0; i < mLayer->fields().size(); ++i )
590 QgsField fld = mLayer->fields().at( i );
591 Qt::ItemFlags flags = mLayer->providerType() !=
"oracle"_L1 || !fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
592 QTableWidgetItem *item =
nullptr;
593 item =
new QTableWidgetItem( fld.
name() );
594 item->setFlags( flags | Qt::ItemIsUserCheckable );
595 item->setCheckState( ( selectAllFields ) ? Qt::Checked : Qt::Unchecked );
596 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Name ), item );
598 item =
new QTableWidgetItem( fld.
name() );
599 item->setFlags( flags | Qt::ItemIsEditable );
601 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportName ), item );
603 item =
new QTableWidgetItem( fld.
typeName() );
604 item->setFlags( flags );
605 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::Type ), item );
607 if ( foundFieldThatCanBeExportedAsDisplayedValue )
610 QgsEditorWidgetFactory *factory =
nullptr;
611 const QString widgetId( setup.type() );
614 item =
new QTableWidgetItem( tr(
"Use %1" ).arg( factory->
name() ) );
615 item->setFlags( ( selectAllFields ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
616 const bool checkItem = ( selectAllFields && isFormatForFieldsAsDisplayedValues && ( widgetId ==
"ValueMap"_L1 || widgetId ==
"ValueRelation"_L1 || widgetId ==
"CheckBox"_L1 || widgetId ==
"RelationReference"_L1 ) );
617 checkReplaceRawFieldValues &= checkItem;
618 item->setCheckState( checkItem ? Qt::Checked : Qt::Unchecked );
619 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
623 item =
new QTableWidgetItem();
624 item->setFlags( Qt::NoItemFlags );
625 mAttributeTable->setItem( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
631 whileBlocking( mReplaceRawFieldValues )->setChecked( checkReplaceRawFieldValues );
632 mReplaceRawFieldValues->setEnabled( selectAllFields );
633 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
635 mAttributeTable->resizeColumnsToContents();
638 QgsVectorFileWriter::MetaData driverMetaData;
640 while ( mDatasourceOptionsGroupBox->layout()->count() )
642 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
643 delete item->widget();
647 while ( mLayerOptionsGroupBox->layout()->count() )
649 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
650 delete item->widget();
654 typedef QPair<QLabel *, QWidget *> LabelControlPair;
660 mDatasourceOptionsGroupBox->setVisible(
true );
661 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
driverOptions );
663 QFormLayout *datasourceLayout =
dynamic_cast<QFormLayout *
>( mDatasourceOptionsGroupBox->layout() );
665 const auto constControls = controls;
666 for ( LabelControlPair control : constControls )
668 datasourceLayout->addRow( control.first, control.second );
673 mDatasourceOptionsGroupBox->setVisible(
false );
678 mLayerOptionsGroupBox->setVisible(
true );
679 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.
layerOptions );
681 QFormLayout *layerOptionsLayout =
dynamic_cast<QFormLayout *
>( mLayerOptionsGroupBox->layout() );
683 const auto constControls = controls;
684 for ( LabelControlPair control : constControls )
686 layerOptionsLayout->addRow( control.first, control.second );
691 mLayerOptionsGroupBox->setVisible(
false );
696 mEncodingComboBox->setEnabled(
true );
703 mEncodingComboBox->setCurrentIndex( idx );
704 mEncodingComboBox->setDisabled(
true );
708 mEncodingComboBox->setEnabled(
true );
714 mEncodingComboBox->setEnabled(
true );
717 GDALDriverH hDriver = GDALGetDriverByName(
format().toUtf8().constData() );
720 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN,
nullptr );
721 if ( mAddToCanvas->isEnabled() && !canReopen )
723 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
724 mAddToCanvas->setChecked(
false );
725 mAddToCanvas->setEnabled(
false );
727 else if ( !mAddToCanvas->isEnabled() && canReopen )
729 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
730 mAddToCanvas->setEnabled(
true );
735void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged(
int state )
737 const QSignalBlocker signalBlocker( mAttributeTable );
744 bool modifiedEntries =
false;
745 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
747 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text()
748 != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
750 modifiedEntries =
true;
755 if ( modifiedEntries )
757 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) )
760 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
765 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
767 mUseAliasesForExportedName->setTristate(
false );
768 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() );
775 bool modifiedEntries =
false;
776 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
778 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text()
779 != mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->text() )
780 modifiedEntries =
true;
783 if ( modifiedEntries )
785 if ( QMessageBox::question(
this, tr(
"Modified names" ), tr(
"Some names were modified and will be overridden. Do you want to continue?" ) )
788 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
793 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
795 mUseAliasesForExportedName->setTristate(
false );
796 const QString alias = mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
797 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
801 case Qt::PartiallyChecked:
807void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged(
int )
809 if ( mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
812 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
813 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
815 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
817 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
819 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 )
821 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
825 mReplaceRawFieldValues->setTristate(
false );
828void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
830 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
831 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
833 int row = item->row();
834 int column = item->column();
836 switch (
static_cast<ColumnIndex
>( column ) )
838 case ColumnIndex::Name:
840 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 ) )
843 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
845 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
846 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
847 bool checkBoxEnabled =
false;
848 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
850 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
852 checkBoxEnabled =
true;
856 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
857 if ( !checkBoxEnabled )
858 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
860 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
862 mAttributeTable->item( row,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
863 mReplaceRawFieldValues->setEnabled(
true );
867 case ColumnIndex::ExportName:
870 if ( item->text().isEmpty() )
872 QMessageBox::warning(
this, tr(
"Empty export name" ), tr(
"Empty export name are not allowed." ) );
878 while ( names.count( item->text() ) > 1 )
879 item->setText( QString(
"%1_2" ).arg( item->text() ) );
881 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
884 case ColumnIndex::Type:
887 case ColumnIndex::ExportAsDisplayedValue:
889 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
891 bool allChecked =
true;
892 bool allUnchecked =
true;
893 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
895 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
897 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
900 allUnchecked =
false;
903 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked
914 mExtentGroupBox->setOutputCrs( mSelectedCrs );
919 return mFilename->filePath();
924 return leLayername->text();
929 return mEncodingComboBox->currentText();
934 return mFormatComboBox->currentData().toString();
950 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
954 switch ( it.value()->type )
959 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
961 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
968 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
969 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
970 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
977 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
979 options << u
"%1=%2"_s.arg( it.key(), le->text() );
986 if ( opt && !opt->
mValue.isEmpty() )
987 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
994 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
995 if ( !plainText.isEmpty() )
996 options += plainText.split(
'\n' );
1003 QStringList options;
1009 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1013 switch ( it.value()->type )
1018 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1020 options << u
"%1=%2"_s.arg( it.key() ).arg( sb->value() );
1027 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1028 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->
defaultValue )
1029 options << u
"%1=%2"_s.arg( it.key(), cb->currentText() );
1036 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1038 options << u
"%1=%2"_s.arg( it.key(), le->text() );
1045 if ( !opt->
mValue.isEmpty() )
1046 options << u
"%1=%2"_s.arg( it.key(), opt->
mValue );
1053 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1054 if ( !plainText.isEmpty() )
1055 options += plainText.split(
'\n' );
1064 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1066 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1068 attributes.append( i );
1079 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1081 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 )
1083 attributes.append( i );
1092 QStringList exportNames;
1093 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1094 exportNames.append( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportName ) )->text() );
1101 return mAddToCanvas->isChecked();
1106 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1107 if ( mAddToCanvas->isEnabled() )
1108 mAddToCanvas->setChecked( enabled );
1118 return mScaleWidget->scale();
1123 mMapCanvas = canvas;
1124 mScaleWidget->setMapCanvas( canvas );
1125 mScaleWidget->setShowCurrentScaleButton(
true );
1131 return mExtentGroupBox->isChecked();
1136 return mExtentGroupBox->outputExtent();
1146 return mSelectedOnly->isChecked();
1151 return mCheckPersistMetadata->isChecked();
1156 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1157 if ( currentIndexData == -1 )
1168 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1169 return currentIndexData == -1;
1174 return mForceMultiCheckBox->isChecked();
1179 mForceMultiCheckBox->setChecked( checked );
1184 return mIncludeZCheckBox->isChecked();
1189 return mActionOnExistingFile;
1194 mIncludeZCheckBox->setChecked( checked );
1197void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged(
const QString &text )
1199 bool scaleEnabled =
true;
1200 if ( text == tr(
"No symbology" ) )
1202 scaleEnabled =
false;
1204 mScaleWidget->setEnabled( scaleEnabled );
1205 mScaleLabel->setEnabled( scaleEnabled );
1208void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged(
int )
1210 const int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1213 mForceMultiCheckBox->setEnabled(
true );
1214 mIncludeZCheckBox->setEnabled(
true );
1220 mForceMultiCheckBox->setEnabled(
false );
1221 mForceMultiCheckBox->setChecked(
false );
1225 mForceMultiCheckBox->setEnabled(
true );
1227 mIncludeZCheckBox->setEnabled(
false );
1228 mIncludeZCheckBox->setChecked(
false );
1232void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1234 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1235 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1237 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1239 if ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1241 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1243 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1245 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1248 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1250 mReplaceRawFieldValues->setEnabled(
true );
1254void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1256 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1257 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1259 for (
int i = 0; i < mAttributeTable->rowCount(); i++ )
1261 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1262 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1264 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1265 mAttributeTable->item( i,
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1268 if ( !mAttributeTable->isColumnHidden(
static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1270 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1271 mReplaceRawFieldValues->setEnabled(
false );
1275void QgsVectorLayerSaveAsDialog::showHelp()
1277 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.