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