QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
qgsvectorlayersaveasdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectorlayersaveasdialog.h
3 Dialog to select destination, type and crs for ogr layers
4 -------------------
5 begin : Mon Mar 22 2010
6 copyright : (C) 2010 by Juergen E. Fischer
7 email : jef at norbit dot de
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18#include "qgslogger.h"
20#include "moc_qgsvectorlayersaveasdialog.cpp"
25#include "qgssettings.h"
26#include "qgsmapcanvas.h"
27#include "qgsgui.h"
28#include "qgsmaplayerutils.h"
29#include "qgshelp.h"
30#include <QMessageBox>
31#include <QFileDialog>
32#include <QTextCodec>
33#include <QSpinBox>
34#include <QRegularExpression>
35#include <limits>
36#include "gdal.h"
37#include "qgsdatums.h"
38#include "qgsiconutils.h"
39#include "qgsproviderregistry.h"
41
42QgsVectorLayerSaveAsDialog::QgsVectorLayerSaveAsDialog( long srsid, QWidget *parent, Qt::WindowFlags fl )
43 : QDialog( parent, fl )
44 , mSelectedCrs( QgsCoordinateReferenceSystem::fromSrsId( srsid ) )
45 , mActionOnExistingFile( QgsVectorFileWriter::CreateOrOverwriteFile )
46{
47 setup();
48}
49
51 : QDialog( parent, fl )
52 , mLayer( layer )
53 , mActionOnExistingFile( QgsVectorFileWriter::CreateOrOverwriteFile )
54 , mOptions( options )
55{
56 if ( layer )
57 {
58 mSelectedCrs = layer->crs();
59 mLayerExtent = layer->extent();
60 }
61 setup();
62
63 if ( layer )
64 {
65 mDefaultOutputLayerNameFromInputLayerName = QgsMapLayerUtils::launderLayerName( layer->name() );
66 leLayername->setDefaultValue( mDefaultOutputLayerNameFromInputLayerName );
67 leLayername->setClearMode( QgsFilterLineEdit::ClearToDefault );
68 if ( leLayername->isEnabled() )
69 leLayername->setText( mDefaultOutputLayerNameFromInputLayerName );
70 }
71
72 if ( !( mOptions & Option::Symbology ) )
73 {
74 mSymbologyExportLabel->hide();
75 mSymbologyExportComboBox->hide();
76 mScaleLabel->hide();
77 mScaleWidget->hide();
78 }
79
80 if ( !( mOptions & Option::DestinationCrs ) )
81 {
82 mCrsLabel->hide();
83 mCrsSelector->hide();
84 }
85 if ( !( mOptions & Option::Fields ) )
86 mAttributesSelection->hide();
87
88 if ( !( mOptions & Option::SelectedOnly ) )
89 mSelectedOnly->hide();
90
91 if ( !( mOptions & Option::AddToCanvas ) )
92 mAddToCanvas->hide();
93
94 if ( !( mOptions & Option::GeometryType ) )
95 mGeometryGroupBox->hide();
96
97 if ( !( mOptions & Option::Extent ) )
98 mExtentGroupBox->hide();
99
100 if ( !( mOptions & Option::Metadata ) )
101 {
102 mCheckPersistMetadata->setChecked( false );
103 mCheckPersistMetadata->hide();
104 }
105
106 mSelectedOnly->setEnabled( layer && layer->selectedFeatureCount() != 0 );
107 mButtonBox->button( QDialogButtonBox::Ok )->setDisabled( true );
108}
109
110void QgsVectorLayerSaveAsDialog::setup()
111{
112 setupUi( this );
114
115 connect( mFormatComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged );
116 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged );
117 connect( mSymbologyExportComboBox, &QComboBox::currentTextChanged, this, &QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged );
118 connect( mGeometryTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged );
119 connect( mSelectAllAttributes, &QPushButton::clicked, this, &QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked );
120 connect( mDeselectAllAttributes, &QPushButton::clicked, this, &QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked );
121 connect( mUseAliasesForExportedName, &QCheckBox::stateChanged, this, &QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged );
122 connect( mReplaceRawFieldValues, &QCheckBox::stateChanged, this, &QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged );
123 connect( mAttributeTable, &QTableWidget::itemChanged, this, &QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged );
124
125#ifdef Q_OS_WIN
126 mHelpButtonBox->setVisible( false );
127 mButtonBox->addButton( QDialogButtonBox::Help );
128 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerSaveAsDialog::showHelp );
129#else
130 connect( mHelpButtonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerSaveAsDialog::showHelp );
131#endif
132 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsVectorLayerSaveAsDialog::accept );
133 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsVectorLayerSaveAsDialog::reject );
134
135 const QList<QgsVectorFileWriter::DriverDetails> drivers = QgsVectorFileWriter::ogrDriverList();
136 mFormatComboBox->blockSignals( true );
137 for ( const QgsVectorFileWriter::DriverDetails &driver : drivers )
138 {
139 mFormatComboBox->addItem( driver.longName, driver.driverName );
140 }
141
142 QgsSettings settings;
143 QString format = settings.value( QStringLiteral( "UI/lastVectorFormat" ), "GPKG" ).toString();
144 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData( format ) );
145 mFormatComboBox->blockSignals( false );
146
147 const auto addGeomItem = [this]( Qgis::WkbType type ) {
148 mGeometryTypeComboBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), static_cast<quint32>( type ) );
149 };
150
151 //add geometry types to combobox
152 mGeometryTypeComboBox->addItem( tr( "Automatic" ), -1 );
153 addGeomItem( Qgis::WkbType::Point );
154 addGeomItem( Qgis::WkbType::LineString );
155 addGeomItem( Qgis::WkbType::Polygon );
156 mGeometryTypeComboBox->addItem( QgsWkbTypes::translatedDisplayString( Qgis::WkbType::GeometryCollection ), static_cast<quint32>( Qgis::WkbType::GeometryCollection ) );
157 addGeomItem( Qgis::WkbType::NoGeometry );
158 mGeometryTypeComboBox->setCurrentIndex( mGeometryTypeComboBox->findData( -1 ) );
159
160 mEncodingComboBox->addItems( QgsVectorDataProvider::availableEncodings() );
161
162 QString enc = settings.value( QStringLiteral( "UI/encoding" ), "System" ).toString();
163 int idx = mEncodingComboBox->findText( enc );
164 if ( idx < 0 )
165 {
166 mEncodingComboBox->insertItem( 0, enc );
167 idx = 0;
168 }
169
170 mCrsSelector->setCrs( mSelectedCrs );
171 mCrsSelector->setLayerCrs( mSelectedCrs );
172 mCrsSelector->setMessage( tr( "Select the coordinate reference system for the vector file. "
173 "The data points will be transformed from the layer coordinate reference system." ) );
174
175 mEncodingComboBox->setCurrentIndex( idx );
176 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
177
178 //symbology export combo box
179 mSymbologyExportComboBox->addItem( tr( "No Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::NoSymbology ) );
180 mSymbologyExportComboBox->addItem( tr( "Feature Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::PerFeature ) );
181 mSymbologyExportComboBox->addItem( tr( "Symbol Layer Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::PerSymbolLayer ) );
182 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
183
184 // extent group box
185 mExtentGroupBox->setOutputCrs( mSelectedCrs );
186 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
187 mExtentGroupBox->setOutputExtentFromOriginal();
188 mExtentGroupBox->setCheckable( true );
189 mExtentGroupBox->setChecked( false );
190 mExtentGroupBox->setCollapsed( true );
191
192 mFilename->setStorageMode( QgsFileWidget::SaveFile );
193 mFilename->setDialogTitle( tr( "Save Layer As" ) );
194 mFilename->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() );
195 mFilename->setConfirmOverwrite( false );
196 connect( mFilename, &QgsFileWidget::fileChanged, this, [=]( const QString &filePath ) {
197 QgsSettings settings;
198 QFileInfo tmplFileInfo( filePath );
199 settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() );
200
201 const QFileInfo fileInfo( filePath );
202 const QString suggestedLayerName = QgsMapLayerUtils::launderLayerName( fileInfo.completeBaseName() );
203 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
204 leLayername->setDefaultValue( suggestedLayerName );
205
206 // if no layer name set, then automatically match the output layer name to the file name
207 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
208 {
209 leLayername->setText( suggestedLayerName );
210 }
211 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
212 } );
213
214 try
215 {
216 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
217 if ( ensemble.isValid() )
218 {
219 mCrsSelector->setSourceEnsemble( ensemble.name() );
220 }
221 }
222 catch ( QgsNotSupportedException & )
223 {
224 }
225
226 mCrsSelector->setShowAccuracyWarnings( true );
227}
228
229QList<QPair<QLabel *, QWidget *>> QgsVectorLayerSaveAsDialog::createControls( const QMap<QString, QgsVectorFileWriter::Option *> &options )
230{
231 QList<QPair<QLabel *, QWidget *>> controls;
232 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
233
234 for ( it = options.constBegin(); it != options.constEnd(); ++it )
235 {
236 QgsVectorFileWriter::Option *option = it.value();
237 QWidget *control = nullptr;
238 switch ( option->type )
239 {
241 {
242 QgsVectorFileWriter::IntOption *opt = dynamic_cast<QgsVectorFileWriter::IntOption *>( option );
243 if ( opt )
244 {
245 QSpinBox *sb = new QSpinBox();
246 sb->setObjectName( it.key() );
247 sb->setMaximum( std::numeric_limits<int>::max() ); // the default is 99
248 sb->setValue( opt->defaultValue );
249 control = sb;
250 }
251 break;
252 }
253
255 {
256 QgsVectorFileWriter::SetOption *opt = dynamic_cast<QgsVectorFileWriter::SetOption *>( option );
257 if ( opt )
258 {
259 QComboBox *cb = new QComboBox();
260 cb->setObjectName( it.key() );
261 for ( const QString &val : std::as_const( opt->values ) )
262 {
263 cb->addItem( val, val );
264 }
265 if ( opt->allowNone )
266 cb->addItem( tr( "<Default>" ), QgsVariantUtils::createNullVariant( QMetaType::Type::QString ) );
267 int idx = cb->findText( opt->defaultValue );
268 if ( idx == -1 )
269 idx = cb->findData( QgsVariantUtils::createNullVariant( QMetaType::Type::QString ) );
270 cb->setCurrentIndex( idx );
271 control = cb;
272 }
273 break;
274 }
275
277 {
279 if ( opt )
280 {
281 QLineEdit *le = new QLineEdit( opt->defaultValue );
282 le->setObjectName( it.key() );
283 control = le;
284 }
285 break;
286 }
287
289 control = nullptr;
290 break;
291 }
292
293 if ( control )
294 {
295 QLabel *label = new QLabel( it.key() );
296
297 // Pack the tooltip in some html element, so it gets linebreaks.
298 label->setToolTip( QStringLiteral( "<p>%1</p>" ).arg( option->docString.toHtmlEscaped() ) );
299 control->setToolTip( QStringLiteral( "<p>%1</p>" ).arg( option->docString.toHtmlEscaped() ) );
300
301 controls << QPair<QLabel *, QWidget *>( label, control );
302 }
303 }
304
305 return controls;
306}
307
309{
310#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
311 if ( format() == QLatin1String( "OpenFileGDB" ) )
312 {
313 // The OpenFileGDB driver supports 64-bit integer fields starting with GDAL 3.9,
314 // if selecting the TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER option
315 bool targetAll = true;
316 for ( const QString &layerOption : layerOptions() )
317 {
318 if ( layerOption == QLatin1String( "TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER" ) )
319 {
320 targetAll = false;
321 }
322 }
323 if ( targetAll )
324 {
325 for ( int i = 0; i < mLayer->fields().size(); ++i )
326 {
327 QgsField fld = mLayer->fields().at( i );
328 if ( fld.type() == QMetaType::Type::LongLong )
329 {
330 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 )
331 {
332 return;
333 }
334 break;
335 }
336 }
337 }
338 }
339 else if ( format() == QLatin1String( "FileGDB" ) )
340 {
341 // The FileGDB driver based on the ESRI SDK doesn't support 64-bit integers
342 for ( int i = 0; i < mLayer->fields().size(); ++i )
343 {
344 QgsField fld = mLayer->fields().at( i );
345 if ( fld.type() == QMetaType::Type::LongLong )
346 {
347 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 )
348 {
349 return;
350 }
351 break;
352 }
353 }
354 }
355#endif
356
357 if ( QFile::exists( fileName() ) )
358 {
361 QMessageBox msgBox;
362 msgBox.setIcon( QMessageBox::Question );
363 msgBox.setWindowTitle( tr( "Save Vector Layer As" ) );
364 QPushButton *overwriteFileButton = msgBox.addButton( tr( "Overwrite File" ), QMessageBox::ActionRole );
365 QPushButton *overwriteLayerButton = msgBox.addButton( tr( "Overwrite Layer" ), QMessageBox::ActionRole );
366 QPushButton *appendToLayerButton = msgBox.addButton( tr( "Append to Layer" ), QMessageBox::ActionRole );
367 msgBox.setStandardButtons( QMessageBox::Cancel );
368 msgBox.setDefaultButton( QMessageBox::Cancel );
369 overwriteFileButton->hide();
370 overwriteLayerButton->hide();
371 appendToLayerButton->hide();
372 if ( layerExists )
373 {
375 {
376 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
377 overwriteFileButton->setVisible( true );
378 overwriteLayerButton->setVisible( true );
379 }
381 {
382 msgBox.setText( tr( "The file already exists. Do you want to overwrite it?" ) );
383 overwriteFileButton->setVisible( true );
384 }
386 {
387 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
388 appendToLayerButton->setVisible( true );
389 overwriteFileButton->setVisible( true );
390 overwriteLayerButton->setVisible( true );
391 }
392 else
393 {
394 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
395 appendToLayerButton->setVisible( true );
396 overwriteFileButton->setVisible( true );
397 }
398
399 int ret = msgBox.exec();
400 if ( ret == QMessageBox::Cancel )
401 return;
402 if ( msgBox.clickedButton() == overwriteFileButton )
403 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
404 else if ( msgBox.clickedButton() == overwriteLayerButton )
405 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
406 else if ( msgBox.clickedButton() == appendToLayerButton )
407 mActionOnExistingFile = QgsVectorFileWriter::AppendToLayerNoNewFields;
408 }
409 else // !layerExists
410 {
412 {
413 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
414 }
415 else
416 {
417 // should not reach here, layer does not exist and cannot add new layer
418 if ( QMessageBox::question( this, tr( "Save Vector Layer As" ), tr( "The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
419 {
420 return;
421 }
422 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
423 }
424 }
425 }
426
427 if ( mActionOnExistingFile == QgsVectorFileWriter::AppendToLayerNoNewFields )
428 {
430 {
431 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 )
432 {
433 mActionOnExistingFile = QgsVectorFileWriter::AppendToLayerAddFields;
434 }
435 }
436 }
437 else if ( mActionOnExistingFile == QgsVectorFileWriter::CreateOrOverwriteFile && QFile::exists( fileName() ) )
438 {
439 const QList<QgsProviderSublayerDetails> sublayers = QgsProviderRegistry::instance()->querySublayers( fileName() );
440 QStringList layerList;
441 layerList.reserve( sublayers.size() );
442 for ( const QgsProviderSublayerDetails &sublayer : sublayers )
443 {
444 layerList.append( sublayer.name() );
445 }
446 if ( layerList.length() > 1 )
447 {
448 layerList.sort( Qt::CaseInsensitive );
449 QMessageBox msgBox;
450 msgBox.setIcon( QMessageBox::Warning );
451 msgBox.setWindowTitle( tr( "Overwrite File" ) );
452 msgBox.setText( tr( "This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
453 msgBox.setDetailedText( tr( "The following layers will be permanently lost:\n\n%1" ).arg( layerList.join( "\n" ) ) );
454 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
455 if ( msgBox.exec() == QMessageBox::Cancel )
456 return;
457 }
458 }
459
460 QgsSettings settings;
461 settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( fileName() ).absolutePath() );
462 settings.setValue( QStringLiteral( "UI/lastVectorFormat" ), format() );
463 settings.setValue( QStringLiteral( "UI/encoding" ), encoding() );
464 QDialog::accept();
465}
466
467void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( int idx )
468{
469 Q_UNUSED( idx )
470
471 mFilename->setEnabled( true );
472 QString filter = QgsVectorFileWriter::filterForDriver( format() );
473 // A bit of hack to solve https://github.com/qgis/QGIS/issues/54566
474 // to be able to select an existing File Geodatabase, we add in the filter
475 // the "gdb" file that is found in all File Geodatabase .gdb directory
476 // to allow the user to select it. We need to detect this particular case
477 // in QgsFileWidget::openFileDialog() to remove this gdb file from the
478 // selected filename
479 if ( format() == QLatin1String( "OpenFileGDB" ) || format() == QLatin1String( "FileGDB" ) )
480 filter = QStringLiteral( "%1 (*.gdb *.GDB gdb)" ).arg( tr( "ESRI File Geodatabase" ) );
481 mFilename->setFilter( filter );
482
483 // if output filename already defined we need to replace old suffix
484 // to avoid double extensions like .gpkg.shp
485 if ( !mFilename->filePath().isEmpty() )
486 {
487 const thread_local QRegularExpression rx( "\\.(.*?)[\\s]" );
488 const QString ext = rx.match( filter ).captured( 1 );
489 if ( !ext.isEmpty() )
490 {
491 QFileInfo fi( mFilename->filePath() );
492 mFilename->setFilePath( QStringLiteral( "%1/%2.%3" ).arg( fi.path(), fi.baseName(), ext ) );
493 }
494 }
495
496 bool selectAllFields = true;
497
498 // Is it a format for which fields that have attached widgets of types
499 // ValueMap, ValueRelation, etc. should be by default exported with their displayed
500 // values
501 bool isFormatForFieldsAsDisplayedValues = false;
502
503 const QString sFormat( format() );
504 if ( sFormat == QLatin1String( "DXF" ) || sFormat == QLatin1String( "DGN" ) )
505 {
506 mAttributesSelection->setVisible( false );
507 selectAllFields = false;
508 }
509 else
510 {
511 if ( mOptions & Option::Fields )
512 {
513 mAttributesSelection->setVisible( true );
514 isFormatForFieldsAsDisplayedValues = ( sFormat == QLatin1String( "CSV" ) || sFormat == QLatin1String( "XLS" ) || sFormat == QLatin1String( "XLSX" ) || sFormat == QLatin1String( "ODS" ) );
515 }
516 }
517
518 // Show symbology options only for some formats
519 if ( QgsVectorFileWriter::supportsFeatureStyles( sFormat ) && ( mOptions & Option::Symbology ) )
520 {
521 mSymbologyExportLabel->setVisible( true );
522 mSymbologyExportComboBox->setVisible( true );
523 mScaleLabel->setVisible( true );
524 mScaleWidget->setVisible( true );
525 }
526 else
527 {
528 mSymbologyExportLabel->hide();
529 mSymbologyExportComboBox->hide();
530 mScaleLabel->hide();
531 mScaleWidget->hide();
532 }
533
534 leLayername->setEnabled( sFormat == QLatin1String( "KML" ) || sFormat == QLatin1String( "GPKG" ) || sFormat == QLatin1String( "XLSX" ) || sFormat == QLatin1String( "ODS" ) || sFormat == QLatin1String( "FileGDB" ) || sFormat == QLatin1String( "OpenFileGDB" ) || sFormat == QLatin1String( "SQLite" ) || sFormat == QLatin1String( "SpatiaLite" ) );
535
536 if ( sFormat == QLatin1String( "XLSX" ) )
537 leLayername->setMaxLength( 31 );
538 else if ( leLayername->isEnabled() )
539 leLayername->setMaxLength( 32767 ); // default length
540
541 if ( !leLayername->isEnabled() )
542 leLayername->setText( QString() );
543 else if ( leLayername->text().isEmpty() )
544 {
545 QString layerName = mDefaultOutputLayerNameFromInputLayerName;
546 if ( layerName.isEmpty() && !mFilename->filePath().isEmpty() )
547 {
548 layerName = QFileInfo( mFilename->filePath() ).baseName();
549 leLayername->setDefaultValue( layerName );
550 }
551 if ( layerName.isEmpty() )
552 layerName = tr( "new_layer" );
553 leLayername->setText( layerName );
554 }
555
556 if ( mLayer )
557 {
558 mAttributeTable->setRowCount( mLayer->fields().count() );
559
560 QStringList horizontalHeaders = QStringList() << tr( "Name" ) << tr( "Export name" ) << tr( "Type" ) << tr( "Replace with displayed values" );
561 mAttributeTable->setColumnCount( horizontalHeaders.size() );
562 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
563
564 bool foundFieldThatCanBeExportedAsDisplayedValue = false;
565 for ( int i = 0; i < mLayer->fields().size(); ++i )
566 {
567 const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mLayer, mLayer->fields()[i].name() );
568 if ( setup.type() != QLatin1String( "TextEdit" ) && QgsGui::editorWidgetRegistry()->factory( setup.type() ) )
569 {
570 foundFieldThatCanBeExportedAsDisplayedValue = true;
571 break;
572 }
573 }
574 mAttributeTable->setColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), !foundFieldThatCanBeExportedAsDisplayedValue );
575
576 bool checkReplaceRawFieldValues = selectAllFields && isFormatForFieldsAsDisplayedValues;
577 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
578 {
579 for ( int i = 0; i < mLayer->fields().size(); ++i )
580 {
581 QgsField fld = mLayer->fields().at( i );
582 Qt::ItemFlags flags = mLayer->providerType() != QLatin1String( "oracle" ) || !fld.typeName().contains( QLatin1String( "SDO_GEOMETRY" ) ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
583 QTableWidgetItem *item = nullptr;
584 item = new QTableWidgetItem( fld.name() );
585 item->setFlags( flags | Qt::ItemIsUserCheckable );
586 item->setCheckState( ( selectAllFields ) ? Qt::Checked : Qt::Unchecked );
587 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::Name ), item );
588
589 item = new QTableWidgetItem( fld.name() );
590 item->setFlags( flags | Qt::ItemIsEditable );
591 item->setData( Qt::UserRole, fld.displayName() );
592 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportName ), item );
593
594 item = new QTableWidgetItem( fld.typeName() );
595 item->setFlags( flags );
596 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::Type ), item );
597
598 if ( foundFieldThatCanBeExportedAsDisplayedValue )
599 {
600 const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mLayer, mLayer->fields()[i].name() );
601 QgsEditorWidgetFactory *factory = nullptr;
602 const QString widgetId( setup.type() );
603 if ( flags == Qt::ItemIsEnabled && widgetId != QLatin1String( "TextEdit" ) && ( factory = QgsGui::editorWidgetRegistry()->factory( widgetId ) ) )
604 {
605 item = new QTableWidgetItem( tr( "Use %1" ).arg( factory->name() ) );
606 item->setFlags( ( selectAllFields ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
607 const bool checkItem = ( selectAllFields && isFormatForFieldsAsDisplayedValues && ( widgetId == QLatin1String( "ValueMap" ) || widgetId == QLatin1String( "ValueRelation" ) || widgetId == QLatin1String( "CheckBox" ) || widgetId == QLatin1String( "RelationReference" ) ) );
608 checkReplaceRawFieldValues &= checkItem;
609 item->setCheckState( checkItem ? Qt::Checked : Qt::Unchecked );
610 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
611 }
612 else
613 {
614 item = new QTableWidgetItem();
615 item->setFlags( Qt::NoItemFlags );
616 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
617 }
618 }
619 }
620 }
621
622 whileBlocking( mReplaceRawFieldValues )->setChecked( checkReplaceRawFieldValues );
623 mReplaceRawFieldValues->setEnabled( selectAllFields );
624 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
625
626 mAttributeTable->resizeColumnsToContents();
627 }
628
629 QgsVectorFileWriter::MetaData driverMetaData;
630
631 while ( mDatasourceOptionsGroupBox->layout()->count() )
632 {
633 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
634 delete item->widget();
635 delete item;
636 }
637
638 while ( mLayerOptionsGroupBox->layout()->count() )
639 {
640 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
641 delete item->widget();
642 delete item;
643 }
644
645 typedef QPair<QLabel *, QWidget *> LabelControlPair;
646
647 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
648 {
649 if ( !driverMetaData.driverOptions.empty() )
650 {
651 mDatasourceOptionsGroupBox->setVisible( true );
652 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.driverOptions );
653
654 QFormLayout *datasourceLayout = dynamic_cast<QFormLayout *>( mDatasourceOptionsGroupBox->layout() );
655
656 const auto constControls = controls;
657 for ( LabelControlPair control : constControls )
658 {
659 datasourceLayout->addRow( control.first, control.second );
660 }
661 }
662 else
663 {
664 mDatasourceOptionsGroupBox->setVisible( false );
665 }
666
667 if ( !driverMetaData.layerOptions.empty() )
668 {
669 mLayerOptionsGroupBox->setVisible( true );
670 QList<QPair<QLabel *, QWidget *>> controls = createControls( driverMetaData.layerOptions );
671
672 QFormLayout *layerOptionsLayout = dynamic_cast<QFormLayout *>( mLayerOptionsGroupBox->layout() );
673
674 const auto constControls = controls;
675 for ( LabelControlPair control : constControls )
676 {
677 layerOptionsLayout->addRow( control.first, control.second );
678 }
679 }
680 else
681 {
682 mLayerOptionsGroupBox->setVisible( false );
683 }
684
685 if ( driverMetaData.compulsoryEncoding.isEmpty() )
686 {
687 mEncodingComboBox->setEnabled( true );
688 }
689 else
690 {
691 int idx = mEncodingComboBox->findText( driverMetaData.compulsoryEncoding );
692 if ( idx >= 0 )
693 {
694 mEncodingComboBox->setCurrentIndex( idx );
695 mEncodingComboBox->setDisabled( true );
696 }
697 else
698 {
699 mEncodingComboBox->setEnabled( true );
700 }
701 }
702 }
703 else
704 {
705 mEncodingComboBox->setEnabled( true );
706 }
707
708 GDALDriverH hDriver = GDALGetDriverByName( format().toUtf8().constData() );
709 if ( hDriver )
710 {
711 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN, nullptr );
712 if ( mAddToCanvas->isEnabled() && !canReopen )
713 {
714 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
715 mAddToCanvas->setChecked( false );
716 mAddToCanvas->setEnabled( false );
717 }
718 else if ( !mAddToCanvas->isEnabled() && canReopen )
719 {
720 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
721 mAddToCanvas->setEnabled( true );
722 }
723 }
724}
725
726void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged( int state )
727{
728 const QSignalBlocker signalBlocker( mAttributeTable );
729
730 switch ( state )
731 {
732 case Qt::Unchecked:
733 {
734 // Check for modified entries
735 bool modifiedEntries = false;
736 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
737 {
738 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text()
739 != mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
740 {
741 modifiedEntries = true;
742 break;
743 }
744 }
745
746 if ( modifiedEntries )
747 {
748 if ( QMessageBox::question( this, tr( "Modified names" ), tr( "Some names were modified and will be overridden. Do you want to continue?" ) )
749 == QMessageBox::No )
750 {
751 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
752 return;
753 }
754 }
755
756 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
757 {
758 mUseAliasesForExportedName->setTristate( false );
759 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->text() );
760 }
761 }
762 break;
763 case Qt::Checked:
764 {
765 // Check for modified entries
766 bool modifiedEntries = false;
767 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
768 {
769 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text()
770 != mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->text() )
771 modifiedEntries = true;
772 }
773
774 if ( modifiedEntries )
775 {
776 if ( QMessageBox::question( this, tr( "Modified names" ), tr( "Some names were modified and will be overridden. Do you want to continue?" ) )
777 == QMessageBox::No )
778 {
779 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
780 return;
781 }
782 }
783
784 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
785 {
786 mUseAliasesForExportedName->setTristate( false );
787 const QString alias = mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
788 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
789 }
790 }
791 break;
792 case Qt::PartiallyChecked:
793 // Do nothing
794 break;
795 }
796}
797
798void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged( int )
799{
800 if ( mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
801 return;
802
803 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
804 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
805
806 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
807 {
808 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
809 {
810 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 )
811 {
812 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
813 }
814 }
815 }
816 mReplaceRawFieldValues->setTristate( false );
817}
818
819void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
820{
821 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
822 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
823
824 int row = item->row();
825 int column = item->column();
826
827 switch ( static_cast<ColumnIndex>( column ) )
828 {
829 case ColumnIndex::Name:
830 {
831 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 ) )
832 return;
833
834 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
835 {
836 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
837 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
838 bool checkBoxEnabled = false;
839 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
840 {
841 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
842 {
843 checkBoxEnabled = true;
844 break;
845 }
846 }
847 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
848 if ( !checkBoxEnabled )
849 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
850 }
851 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
852 {
853 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
854 mReplaceRawFieldValues->setEnabled( true );
855 }
856 }
857 break;
858 case ColumnIndex::ExportName:
859 {
860 // Check empty export name
861 if ( item->text().isEmpty() )
862 {
863 QMessageBox::warning( this, tr( "Empty export name" ), tr( "Empty export name are not allowed." ) );
864 return;
865 }
866
867 // Rename eventually duplicated names
868 QStringList names = attributesExportNames();
869 while ( names.count( item->text() ) > 1 )
870 item->setText( QString( "%1_2" ).arg( item->text() ) );
871
872 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
873 }
874 break;
875 case ColumnIndex::Type:
876 // Nothing to do
877 break;
878 case ColumnIndex::ExportAsDisplayedValue:
879 {
880 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
881 {
882 bool allChecked = true;
883 bool allUnchecked = true;
884 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
885 {
886 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
887 {
888 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
889 allChecked = false;
890 else
891 allUnchecked = false;
892 }
893 }
894 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked
895 : Qt::Unchecked );
896 }
897 }
898 break;
899 }
900}
901
902void QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
903{
904 mSelectedCrs = crs;
905 mExtentGroupBox->setOutputCrs( mSelectedCrs );
906}
907
909{
910 return mFilename->filePath();
911}
912
914{
915 return leLayername->text();
916}
917
919{
920 return mEncodingComboBox->currentText();
921}
922
924{
925 return mFormatComboBox->currentData().toString();
926}
927
929{
930 return mSelectedCrs;
931}
932
934{
935 QStringList options;
936
937 QgsVectorFileWriter::MetaData driverMetaData;
938
939 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
940 {
941 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
942
943 for ( it = driverMetaData.driverOptions.constBegin(); it != driverMetaData.driverOptions.constEnd(); ++it )
944 {
945 switch ( it.value()->type )
946 {
948 {
950 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
951 if ( opt && sb && sb->value() != opt->defaultValue )
952 options << QStringLiteral( "%1=%2" ).arg( it.key() ).arg( sb->value() );
953 break;
954 }
955
957 {
959 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
960 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->defaultValue )
961 options << QStringLiteral( "%1=%2" ).arg( it.key(), cb->currentText() );
962 break;
963 }
964
966 {
968 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
969 if ( opt && le && le->text() != opt->defaultValue )
970 options << QStringLiteral( "%1=%2" ).arg( it.key(), le->text() );
971 break;
972 }
973
975 {
976 QgsVectorFileWriter::HiddenOption *opt = dynamic_cast<QgsVectorFileWriter::HiddenOption *>( it.value() );
977 if ( !opt->mValue.isEmpty() )
978 options << QStringLiteral( "%1=%2" ).arg( it.key(), opt->mValue );
979 break;
980 }
981 }
982 }
983 }
984
985 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
986 if ( !plainText.isEmpty() )
987 options += plainText.split( '\n' );
988
989 return options;
990}
991
993{
994 QStringList options;
995
996 QgsVectorFileWriter::MetaData driverMetaData;
997
998 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
999 {
1000 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1001
1002 for ( it = driverMetaData.layerOptions.constBegin(); it != driverMetaData.layerOptions.constEnd(); ++it )
1003 {
1004 switch ( it.value()->type )
1005 {
1007 {
1009 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1010 if ( opt && sb && sb->value() != opt->defaultValue )
1011 options << QStringLiteral( "%1=%2" ).arg( it.key() ).arg( sb->value() );
1012 break;
1013 }
1014
1016 {
1018 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1019 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->defaultValue )
1020 options << QStringLiteral( "%1=%2" ).arg( it.key(), cb->currentText() );
1021 break;
1022 }
1023
1025 {
1027 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1028 if ( opt && le && le->text() != opt->defaultValue )
1029 options << QStringLiteral( "%1=%2" ).arg( it.key(), le->text() );
1030 break;
1031 }
1032
1034 {
1035 QgsVectorFileWriter::HiddenOption *opt = dynamic_cast<QgsVectorFileWriter::HiddenOption *>( it.value() );
1036 if ( !opt->mValue.isEmpty() )
1037 options << QStringLiteral( "%1=%2" ).arg( it.key(), opt->mValue );
1038 break;
1039 }
1040 }
1041 }
1042 }
1043
1044 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1045 if ( !plainText.isEmpty() )
1046 options += plainText.split( '\n' );
1047
1048 return options;
1049}
1050
1052{
1053 QgsAttributeList attributes;
1054
1055 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1056 {
1057 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1058 {
1059 attributes.append( i );
1060 }
1061 }
1062
1063 return attributes;
1064}
1065
1067{
1068 QgsAttributeList attributes;
1069
1070 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1071 {
1072 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 )
1073 {
1074 attributes.append( i );
1075 }
1076 }
1077
1078 return attributes;
1079}
1080
1082{
1083 QStringList exportNames;
1084 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1085 exportNames.append( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text() );
1086
1087 return exportNames;
1088}
1089
1091{
1092 return mAddToCanvas->isChecked();
1093}
1094
1096{
1097 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1098 if ( mAddToCanvas->isEnabled() )
1099 mAddToCanvas->setChecked( enabled );
1100}
1101
1103{
1104 return mSymbologyExportComboBox->currentData().value<Qgis::FeatureSymbologyExport>();
1105}
1106
1108{
1109 return mScaleWidget->scale();
1110}
1111
1113{
1114 mMapCanvas = canvas;
1115 mScaleWidget->setMapCanvas( canvas );
1116 mScaleWidget->setShowCurrentScaleButton( true );
1117 mExtentGroupBox->setCurrentExtent( canvas->mapSettings().visibleExtent(), canvas->mapSettings().destinationCrs() );
1118}
1119
1121{
1122 return mExtentGroupBox->isChecked();
1123}
1124
1126{
1127 return mExtentGroupBox->outputExtent();
1128}
1129
1131{
1132 mSelectedOnly->setChecked( onlySelected );
1133}
1134
1136{
1137 return mSelectedOnly->isChecked();
1138}
1139
1141{
1142 return mCheckPersistMetadata->isChecked();
1143}
1144
1146{
1147 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1148 if ( currentIndexData == -1 )
1149 {
1150 //automatic
1152 }
1153
1154 return static_cast<Qgis::WkbType>( currentIndexData );
1155}
1156
1158{
1159 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1160 return currentIndexData == -1;
1161}
1162
1164{
1165 return mForceMultiCheckBox->isChecked();
1166}
1167
1169{
1170 mForceMultiCheckBox->setChecked( checked );
1171}
1172
1174{
1175 return mIncludeZCheckBox->isChecked();
1176}
1177
1182
1184{
1185 mIncludeZCheckBox->setChecked( checked );
1186}
1187
1188void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged( const QString &text )
1189{
1190 bool scaleEnabled = true;
1191 if ( text == tr( "No symbology" ) )
1192 {
1193 scaleEnabled = false;
1194 }
1195 mScaleWidget->setEnabled( scaleEnabled );
1196 mScaleLabel->setEnabled( scaleEnabled );
1197}
1198
1199void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged( int )
1200{
1201 Qgis::WkbType currentIndexData = static_cast<Qgis::WkbType>( mGeometryTypeComboBox->currentData().toInt() );
1202
1203 if ( mGeometryTypeComboBox->currentIndex() != -1 && currentIndexData != Qgis::WkbType::NoGeometry )
1204 {
1205 mForceMultiCheckBox->setEnabled( true );
1206 mIncludeZCheckBox->setEnabled( true );
1207 }
1208 else
1209 {
1210 mForceMultiCheckBox->setEnabled( false );
1211 mForceMultiCheckBox->setChecked( false );
1212 mIncludeZCheckBox->setEnabled( false );
1213 mIncludeZCheckBox->setChecked( false );
1214 }
1215}
1216
1217void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1218{
1219 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1220 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1221
1222 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1223 {
1224 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1225 {
1226 if ( !mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1227 {
1228 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1229 }
1230 mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1231 }
1232 }
1233 if ( !mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1234 {
1235 mReplaceRawFieldValues->setEnabled( true );
1236 }
1237}
1238
1239void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1240{
1241 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1242 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1243
1244 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1245 {
1246 mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1247 if ( !mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) && ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1248 {
1249 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1250 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1251 }
1252 }
1253 if ( !mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1254 {
1255 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1256 mReplaceRawFieldValues->setEnabled( false );
1257 }
1258}
1259
1260void QgsVectorLayerSaveAsDialog::showHelp()
1261{
1262 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer" ) );
1263}
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ LineString
LineString.
@ Polygon
Polygon.
@ NoGeometry
No geometry.
@ Unknown
Unknown.
@ GeometryCollection
GeometryCollection.
FeatureSymbologyExport
Options for exporting features considering their symbology.
Definition qgis.h:5200
@ 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.
This class represents a coordinate reference system (CRS).
QgsDatumEnsemble datumEnsemble() const
Attempts to retrieve datum ensemble details from the CRS.
Contains information about a datum ensemble.
Definition qgsdatums.h:95
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
Definition qgsdatums.h:102
QString name() const
Display name of datum ensemble.
Definition qgsdatums.h:107
Every attribute editor widget needs a factory, which inherits this class.
QString name() const
Returns The human readable identifier name of this widget type.
QgsEditorWidgetSetup findBest(const QgsVectorLayer *vl, const QString &fieldName) const
Find the best editor widget and its configuration for a given field.
Holder for the widget type and its configuration for a field.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QMetaType::Type type
Definition qgsfield.h:60
QString typeName() const
Gets the field type.
Definition qgsfield.cpp:161
QString name
Definition qgsfield.h:62
QString displayName() const
Returns the name to use when displaying this field.
Definition qgsfield.cpp:95
int count
Definition qgsfields.h:50
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
@ SaveFile
Select a single new or pre-existing file.
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
@ 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.
Definition qgsgui.cpp:95
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...
Definition qgsgui.cpp:210
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
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...
QString name
Definition qgsmaplayer.h:80
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:83
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.
Custom exception class which is raised when an operation is not supported.
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
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.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
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.
QgsVectorFileWriter::OptionType type
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.
@ 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 data sets.
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 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.
Definition qgis.h:5928
QList< int > QgsAttributeList
Definition qgsfield.h:27
const QgsCoordinateReferenceSystem & crs
Details of available driver formats.
QMap< QString, QgsVectorFileWriter::Option * > driverOptions
QMap< QString, QgsVectorFileWriter::Option * > layerOptions
QString compulsoryEncoding
Some formats require a compulsory encoding, typically UTF-8. If no compulsory encoding,...