QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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 {
149 mGeometryTypeComboBox->addItem( QgsIconUtils::iconForWkbType( type ), QgsWkbTypes::translatedDisplayString( type ), static_cast< quint32>( type ) );
150 };
151
152 //add geometry types to combobox
153 mGeometryTypeComboBox->addItem( tr( "Automatic" ), -1 );
154 addGeomItem( Qgis::WkbType::Point );
155 addGeomItem( Qgis::WkbType::LineString );
156 addGeomItem( Qgis::WkbType::Polygon );
157 mGeometryTypeComboBox->addItem( QgsWkbTypes::translatedDisplayString( Qgis::WkbType::GeometryCollection ), static_cast< quint32>( Qgis::WkbType::GeometryCollection ) );
158 addGeomItem( Qgis::WkbType::NoGeometry );
159 mGeometryTypeComboBox->setCurrentIndex( mGeometryTypeComboBox->findData( -1 ) );
160
161 mEncodingComboBox->addItems( QgsVectorDataProvider::availableEncodings() );
162
163 QString enc = settings.value( QStringLiteral( "UI/encoding" ), "System" ).toString();
164 int idx = mEncodingComboBox->findText( enc );
165 if ( idx < 0 )
166 {
167 mEncodingComboBox->insertItem( 0, enc );
168 idx = 0;
169 }
170
171 mCrsSelector->setCrs( mSelectedCrs );
172 mCrsSelector->setLayerCrs( mSelectedCrs );
173 mCrsSelector->setMessage( tr( "Select the coordinate reference system for the vector file. "
174 "The data points will be transformed from the layer coordinate reference system." ) );
175
176 mEncodingComboBox->setCurrentIndex( idx );
177 mFormatComboBox_currentIndexChanged( mFormatComboBox->currentIndex() );
178
179 //symbology export combo box
180 mSymbologyExportComboBox->addItem( tr( "No Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::NoSymbology ) );
181 mSymbologyExportComboBox->addItem( tr( "Feature Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::PerFeature ) );
182 mSymbologyExportComboBox->addItem( tr( "Symbol Layer Symbology" ), QVariant::fromValue( Qgis::FeatureSymbologyExport::PerSymbolLayer ) );
183 mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );
184
185 // extent group box
186 mExtentGroupBox->setOutputCrs( mSelectedCrs );
187 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
188 mExtentGroupBox->setOutputExtentFromOriginal();
189 mExtentGroupBox->setCheckable( true );
190 mExtentGroupBox->setChecked( false );
191 mExtentGroupBox->setCollapsed( true );
192
193 mFilename->setStorageMode( QgsFileWidget::SaveFile );
194 mFilename->setDialogTitle( tr( "Save Layer As" ) );
195 mFilename->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() );
196 mFilename->setConfirmOverwrite( false );
197 connect( mFilename, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath )
198 {
199 QgsSettings settings;
200 QFileInfo tmplFileInfo( filePath );
201 settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() );
202
203 const QFileInfo fileInfo( filePath );
204 const QString suggestedLayerName = QgsMapLayerUtils::launderLayerName( fileInfo.completeBaseName() );
205 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
206 leLayername->setDefaultValue( suggestedLayerName );
207
208 // if no layer name set, then automatically match the output layer name to the file name
209 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
210 {
211 leLayername->setText( suggestedLayerName );
212 }
213 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
214 } );
215
216 try
217 {
218 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
219 if ( ensemble.isValid() )
220 {
221 mCrsSelector->setSourceEnsemble( ensemble.name() );
222 }
223 }
224 catch ( QgsNotSupportedException & )
225 {
226 }
227
228 mCrsSelector->setShowAccuracyWarnings( true );
229}
230
231QList<QPair<QLabel *, QWidget *> > QgsVectorLayerSaveAsDialog::createControls( const QMap<QString, QgsVectorFileWriter::Option *> &options )
232{
233 QList<QPair<QLabel *, QWidget *> > controls;
234 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
235
236 for ( it = options.constBegin(); it != options.constEnd(); ++it )
237 {
238 QgsVectorFileWriter::Option *option = it.value();
239 QWidget *control = nullptr;
240 switch ( option->type )
241 {
243 {
244 QgsVectorFileWriter::IntOption *opt = dynamic_cast<QgsVectorFileWriter::IntOption *>( option );
245 if ( opt )
246 {
247 QSpinBox *sb = new QSpinBox();
248 sb->setObjectName( it.key() );
249 sb->setMaximum( std::numeric_limits<int>::max() ); // the default is 99
250 sb->setValue( opt->defaultValue );
251 control = sb;
252 }
253 break;
254 }
255
257 {
258 QgsVectorFileWriter::SetOption *opt = dynamic_cast<QgsVectorFileWriter::SetOption *>( option );
259 if ( opt )
260 {
261 QComboBox *cb = new QComboBox();
262 cb->setObjectName( it.key() );
263 for ( const QString &val : std::as_const( opt->values ) )
264 {
265 cb->addItem( val, val );
266 }
267 if ( opt->allowNone )
268 cb->addItem( tr( "<Default>" ), QgsVariantUtils::createNullVariant( QMetaType::Type::QString ) );
269 int idx = cb->findText( opt->defaultValue );
270 if ( idx == -1 )
271 idx = cb->findData( QgsVariantUtils::createNullVariant( QMetaType::Type::QString ) );
272 cb->setCurrentIndex( idx );
273 control = cb;
274 }
275 break;
276 }
277
279 {
281 if ( opt )
282 {
283 QLineEdit *le = new QLineEdit( opt->defaultValue );
284 le->setObjectName( it.key() );
285 control = le;
286 }
287 break;
288 }
289
291 control = nullptr;
292 break;
293 }
294
295 if ( control )
296 {
297 QLabel *label = new QLabel( it.key() );
298
299 // Pack the tooltip in some html element, so it gets linebreaks.
300 label->setToolTip( QStringLiteral( "<p>%1</p>" ).arg( option->docString.toHtmlEscaped() ) );
301 control->setToolTip( QStringLiteral( "<p>%1</p>" ).arg( option->docString.toHtmlEscaped() ) );
302
303 controls << QPair<QLabel *, QWidget *>( label, control );
304 }
305 }
306
307 return controls;
308}
309
311{
312#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0)
313 if ( format() == QLatin1String( "OpenFileGDB" ) )
314 {
315 // The OpenFileGDB driver supports 64-bit integer fields starting with GDAL 3.9,
316 // if selecting the TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER option
317 bool targetAll = true;
318 for ( const QString &layerOption : layerOptions() )
319 {
320 if ( layerOption == QLatin1String( "TARGET_ARCGIS_VERSION=ARCGIS_PRO_3_2_OR_LATER" ) )
321 {
322 targetAll = false;
323 }
324 }
325 if ( targetAll )
326 {
327 for ( int i = 0; i < mLayer->fields().size(); ++i )
328 {
329 QgsField fld = mLayer->fields().at( i );
330 if ( fld.type() == QMetaType::Type::LongLong )
331 {
332 if ( QMessageBox::question( this,
333 tr( "Save Vector Layer As" ),
334 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 )
335 {
336 return;
337 }
338 break;
339 }
340 }
341 }
342 }
343 else if ( format() == QLatin1String( "FileGDB" ) )
344 {
345 // The FileGDB driver based on the ESRI SDK doesn't support 64-bit integers
346 for ( int i = 0; i < mLayer->fields().size(); ++i )
347 {
348 QgsField fld = mLayer->fields().at( i );
349 if ( fld.type() == QMetaType::Type::LongLong )
350 {
351 if ( QMessageBox::question( this,
352 tr( "Save Vector Layer As" ),
353 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 )
354 {
355 return;
356 }
357 break;
358 }
359 }
360 }
361#endif
362
363 if ( QFile::exists( fileName() ) )
364 {
368 layerName() );
369 QMessageBox msgBox;
370 msgBox.setIcon( QMessageBox::Question );
371 msgBox.setWindowTitle( tr( "Save Vector Layer As" ) );
372 QPushButton *overwriteFileButton = msgBox.addButton( tr( "Overwrite File" ), QMessageBox::ActionRole );
373 QPushButton *overwriteLayerButton = msgBox.addButton( tr( "Overwrite Layer" ), QMessageBox::ActionRole );
374 QPushButton *appendToLayerButton = msgBox.addButton( tr( "Append to Layer" ), QMessageBox::ActionRole );
375 msgBox.setStandardButtons( QMessageBox::Cancel );
376 msgBox.setDefaultButton( QMessageBox::Cancel );
377 overwriteFileButton->hide();
378 overwriteLayerButton->hide();
379 appendToLayerButton->hide();
380 if ( layerExists )
381 {
385 {
386 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
387 overwriteFileButton->setVisible( true );
388 overwriteLayerButton->setVisible( true );
389 }
391 {
392 msgBox.setText( tr( "The file already exists. Do you want to overwrite it?" ) );
393 overwriteFileButton->setVisible( true );
394 }
395 else if ( ( caps & QgsVectorFileWriter::CanDeleteLayer ) &&
397 {
398 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
399 appendToLayerButton->setVisible( true );
400 overwriteFileButton->setVisible( true );
401 overwriteLayerButton->setVisible( true );
402 }
403 else
404 {
405 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
406 appendToLayerButton->setVisible( true );
407 overwriteFileButton->setVisible( true );
408 }
409
410 int ret = msgBox.exec();
411 if ( ret == QMessageBox::Cancel )
412 return;
413 if ( msgBox.clickedButton() == overwriteFileButton )
414 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
415 else if ( msgBox.clickedButton() == overwriteLayerButton )
416 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
417 else if ( msgBox.clickedButton() == appendToLayerButton )
418 mActionOnExistingFile = QgsVectorFileWriter::AppendToLayerNoNewFields;
419 }
420 else // !layerExists
421 {
423 {
424 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
425 }
426 else
427 {
428 // should not reach here, layer does not exist and cannot add new layer
429 if ( QMessageBox::question( this,
430 tr( "Save Vector Layer As" ),
431 tr( "The file already exists. Do you want to overwrite it?" ) ) != QMessageBox::Yes )
432 {
433 return;
434 }
435 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
436 }
437 }
438 }
439
440 if ( mActionOnExistingFile == QgsVectorFileWriter::AppendToLayerNoNewFields )
441 {
443 {
444 if ( QMessageBox::question( this,
445 tr( "Save Vector Layer As" ),
446 tr( "The existing layer has additional fields. Do you want to add the missing fields to the layer?" ) ) == QMessageBox::Yes )
447 {
448 mActionOnExistingFile = QgsVectorFileWriter::AppendToLayerAddFields;
449 }
450 }
451 }
452 else if ( mActionOnExistingFile == QgsVectorFileWriter::CreateOrOverwriteFile && QFile::exists( fileName() ) )
453 {
454 const QList<QgsProviderSublayerDetails> sublayers = QgsProviderRegistry::instance()->querySublayers( fileName() );
455 QStringList layerList;
456 layerList.reserve( sublayers.size() );
457 for ( const QgsProviderSublayerDetails &sublayer : sublayers )
458 {
459 layerList.append( sublayer.name() );
460 }
461 if ( layerList.length() > 1 )
462 {
463 layerList.sort( Qt::CaseInsensitive );
464 QMessageBox msgBox;
465 msgBox.setIcon( QMessageBox::Warning );
466 msgBox.setWindowTitle( tr( "Overwrite File" ) );
467 msgBox.setText( tr( "This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
468 msgBox.setDetailedText( tr( "The following layers will be permanently lost:\n\n%1" ).arg( layerList.join( "\n" ) ) );
469 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
470 if ( msgBox.exec() == QMessageBox::Cancel )
471 return;
472 }
473 }
474
475 QgsSettings settings;
476 settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( fileName() ).absolutePath() );
477 settings.setValue( QStringLiteral( "UI/lastVectorFormat" ), format() );
478 settings.setValue( QStringLiteral( "UI/encoding" ), encoding() );
479 QDialog::accept();
480}
481
482void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( int idx )
483{
484 Q_UNUSED( idx )
485
486 mFilename->setEnabled( true );
487 QString filter = QgsVectorFileWriter::filterForDriver( format() );
488 // A bit of hack to solve https://github.com/qgis/QGIS/issues/54566
489 // to be able to select an existing File Geodatabase, we add in the filter
490 // the "gdb" file that is found in all File Geodatabase .gdb directory
491 // to allow the user to select it. We need to detect this particular case
492 // in QgsFileWidget::openFileDialog() to remove this gdb file from the
493 // selected filename
494 if ( format() == QLatin1String( "OpenFileGDB" ) || format() == QLatin1String( "FileGDB" ) )
495 filter = QStringLiteral( "%1 (*.gdb *.GDB gdb)" ).arg( tr( "ESRI File Geodatabase" ) );
496 mFilename->setFilter( filter );
497
498 // if output filename already defined we need to replace old suffix
499 // to avoid double extensions like .gpkg.shp
500 if ( !mFilename->filePath().isEmpty() )
501 {
502 const thread_local QRegularExpression rx( "\\.(.*?)[\\s]" );
503 const QString ext = rx.match( filter ).captured( 1 );
504 if ( !ext.isEmpty() )
505 {
506 QFileInfo fi( mFilename->filePath() );
507 mFilename->setFilePath( QStringLiteral( "%1/%2.%3" ).arg( fi.path(), fi.baseName(), ext ) );
508 }
509 }
510
511 bool selectAllFields = true;
512
513 // Is it a format for which fields that have attached widgets of types
514 // ValueMap, ValueRelation, etc. should be by default exported with their displayed
515 // values
516 bool isFormatForFieldsAsDisplayedValues = false;
517
518 const QString sFormat( format() );
519 if ( sFormat == QLatin1String( "DXF" ) || sFormat == QLatin1String( "DGN" ) )
520 {
521 mAttributesSelection->setVisible( false );
522 selectAllFields = false;
523 }
524 else
525 {
526 if ( mOptions & Option::Fields )
527 {
528 mAttributesSelection->setVisible( true );
529 isFormatForFieldsAsDisplayedValues = ( sFormat == QLatin1String( "CSV" ) ||
530 sFormat == QLatin1String( "XLS" ) ||
531 sFormat == QLatin1String( "XLSX" ) ||
532 sFormat == QLatin1String( "ODS" ) );
533 }
534 }
535
536 // Show symbology options only for some formats
537 if ( QgsVectorFileWriter::supportsFeatureStyles( sFormat ) && ( mOptions & Option::Symbology ) )
538 {
539 mSymbologyExportLabel->setVisible( true );
540 mSymbologyExportComboBox->setVisible( true );
541 mScaleLabel->setVisible( true );
542 mScaleWidget->setVisible( true );
543 }
544 else
545 {
546 mSymbologyExportLabel->hide();
547 mSymbologyExportComboBox->hide();
548 mScaleLabel->hide();
549 mScaleWidget->hide();
550 }
551
552 leLayername->setEnabled( sFormat == QLatin1String( "KML" ) ||
553 sFormat == QLatin1String( "GPKG" ) ||
554 sFormat == QLatin1String( "XLSX" ) ||
555 sFormat == QLatin1String( "ODS" ) ||
556 sFormat == QLatin1String( "FileGDB" ) ||
557 sFormat == QLatin1String( "OpenFileGDB" ) ||
558 sFormat == QLatin1String( "SQLite" ) ||
559 sFormat == QLatin1String( "SpatiaLite" ) );
560
561 if ( sFormat == QLatin1String( "XLSX" ) )
562 leLayername->setMaxLength( 31 );
563 else if ( leLayername->isEnabled() )
564 leLayername->setMaxLength( 32767 ); // default length
565
566 if ( !leLayername->isEnabled() )
567 leLayername->setText( QString() );
568 else if ( leLayername->text().isEmpty() )
569 {
570 QString layerName = mDefaultOutputLayerNameFromInputLayerName;
571 if ( layerName.isEmpty() && !mFilename->filePath().isEmpty() )
572 {
573 layerName = QFileInfo( mFilename->filePath() ).baseName();
574 leLayername->setDefaultValue( layerName );
575 }
576 if ( layerName.isEmpty() )
577 layerName = tr( "new_layer" );
578 leLayername->setText( layerName );
579 }
580
581 if ( mLayer )
582 {
583 mAttributeTable->setRowCount( mLayer->fields().count() );
584
585 QStringList horizontalHeaders = QStringList() << tr( "Name" ) << tr( "Export name" ) << tr( "Type" ) << tr( "Replace with displayed values" );
586 mAttributeTable->setColumnCount( horizontalHeaders.size() );
587 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
588
589 bool foundFieldThatCanBeExportedAsDisplayedValue = false;
590 for ( int i = 0; i < mLayer->fields().size(); ++i )
591 {
592 const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mLayer, mLayer->fields()[i].name() );
593 if ( setup.type() != QLatin1String( "TextEdit" ) &&
594 QgsGui::editorWidgetRegistry()->factory( setup.type() ) )
595 {
596 foundFieldThatCanBeExportedAsDisplayedValue = true;
597 break;
598 }
599 }
600 mAttributeTable->setColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ),
601 ! foundFieldThatCanBeExportedAsDisplayedValue );
602
603 bool checkReplaceRawFieldValues = selectAllFields && isFormatForFieldsAsDisplayedValues;
604 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
605 {
606 for ( int i = 0; i < mLayer->fields().size(); ++i )
607 {
608 QgsField fld = mLayer->fields().at( i );
609 Qt::ItemFlags flags = mLayer->providerType() != QLatin1String( "oracle" ) || !fld.typeName().contains( QLatin1String( "SDO_GEOMETRY" ) ) ? Qt::ItemIsEnabled : Qt::NoItemFlags;
610 QTableWidgetItem *item = nullptr;
611 item = new QTableWidgetItem( fld.name() );
612 item->setFlags( flags | Qt::ItemIsUserCheckable );
613 item->setCheckState( ( selectAllFields ) ? Qt::Checked : Qt::Unchecked );
614 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::Name ), item );
615
616 item = new QTableWidgetItem( fld.name() );
617 item->setFlags( flags | Qt::ItemIsEditable );
618 item->setData( Qt::UserRole, fld.displayName() );
619 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportName ), item );
620
621 item = new QTableWidgetItem( fld.typeName() );
622 item->setFlags( flags );
623 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::Type ), item );
624
625 if ( foundFieldThatCanBeExportedAsDisplayedValue )
626 {
627 const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mLayer, mLayer->fields()[i].name() );
628 QgsEditorWidgetFactory *factory = nullptr;
629 const QString widgetId( setup.type() );
630 if ( flags == Qt::ItemIsEnabled &&
631 widgetId != QLatin1String( "TextEdit" ) &&
632 ( factory = QgsGui::editorWidgetRegistry()->factory( widgetId ) ) )
633 {
634 item = new QTableWidgetItem( tr( "Use %1" ).arg( factory->name() ) );
635 item->setFlags( ( selectAllFields ) ? ( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) : Qt::ItemIsUserCheckable );
636 const bool checkItem = ( selectAllFields && isFormatForFieldsAsDisplayedValues &&
637 ( widgetId == QLatin1String( "ValueMap" ) ||
638 widgetId == QLatin1String( "ValueRelation" ) ||
639 widgetId == QLatin1String( "CheckBox" ) ||
640 widgetId == QLatin1String( "RelationReference" ) ) );
641 checkReplaceRawFieldValues &= checkItem;
642 item->setCheckState( checkItem ?
643 Qt::Checked : Qt::Unchecked );
644 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
645 }
646 else
647 {
648 item = new QTableWidgetItem();
649 item->setFlags( Qt::NoItemFlags );
650 mAttributeTable->setItem( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ), item );
651 }
652 }
653 }
654 }
655
656 whileBlocking( mReplaceRawFieldValues )->setChecked( checkReplaceRawFieldValues );
657 mReplaceRawFieldValues->setEnabled( selectAllFields );
658 mReplaceRawFieldValues->setVisible( foundFieldThatCanBeExportedAsDisplayedValue );
659
660 mAttributeTable->resizeColumnsToContents();
661 }
662
663 QgsVectorFileWriter::MetaData driverMetaData;
664
665 while ( mDatasourceOptionsGroupBox->layout()->count() )
666 {
667 QLayoutItem *item = mDatasourceOptionsGroupBox->layout()->takeAt( 0 );
668 delete item->widget();
669 delete item;
670 }
671
672 while ( mLayerOptionsGroupBox->layout()->count() )
673 {
674 QLayoutItem *item = mLayerOptionsGroupBox->layout()->takeAt( 0 );
675 delete item->widget();
676 delete item;
677 }
678
679 typedef QPair<QLabel *, QWidget *> LabelControlPair;
680
681 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
682 {
683 if ( !driverMetaData.driverOptions.empty() )
684 {
685 mDatasourceOptionsGroupBox->setVisible( true );
686 QList<QPair<QLabel *, QWidget *> > controls = createControls( driverMetaData.driverOptions );
687
688 QFormLayout *datasourceLayout = dynamic_cast<QFormLayout *>( mDatasourceOptionsGroupBox->layout() );
689
690 const auto constControls = controls;
691 for ( LabelControlPair control : constControls )
692 {
693 datasourceLayout->addRow( control.first, control.second );
694 }
695 }
696 else
697 {
698 mDatasourceOptionsGroupBox->setVisible( false );
699 }
700
701 if ( !driverMetaData.layerOptions.empty() )
702 {
703 mLayerOptionsGroupBox->setVisible( true );
704 QList<QPair<QLabel *, QWidget *> > controls = createControls( driverMetaData.layerOptions );
705
706 QFormLayout *layerOptionsLayout = dynamic_cast<QFormLayout *>( mLayerOptionsGroupBox->layout() );
707
708 const auto constControls = controls;
709 for ( LabelControlPair control : constControls )
710 {
711 layerOptionsLayout->addRow( control.first, control.second );
712 }
713 }
714 else
715 {
716 mLayerOptionsGroupBox->setVisible( false );
717 }
718
719 if ( driverMetaData.compulsoryEncoding.isEmpty() )
720 {
721 mEncodingComboBox->setEnabled( true );
722 }
723 else
724 {
725 int idx = mEncodingComboBox->findText( driverMetaData.compulsoryEncoding );
726 if ( idx >= 0 )
727 {
728 mEncodingComboBox->setCurrentIndex( idx );
729 mEncodingComboBox->setDisabled( true );
730 }
731 else
732 {
733 mEncodingComboBox->setEnabled( true );
734 }
735 }
736
737 }
738 else
739 {
740 mEncodingComboBox->setEnabled( true );
741 }
742
743 GDALDriverH hDriver = GDALGetDriverByName( format().toUtf8().constData() );
744 if ( hDriver )
745 {
746 const bool canReopen = GDALGetMetadataItem( hDriver, GDAL_DCAP_OPEN, nullptr );
747 if ( mAddToCanvas->isEnabled() && !canReopen )
748 {
749 mAddToCanvasStateOnOpenCompatibleDriver = mAddToCanvas->isChecked();
750 mAddToCanvas->setChecked( false );
751 mAddToCanvas->setEnabled( false );
752 }
753 else if ( !mAddToCanvas->isEnabled() && canReopen )
754 {
755 mAddToCanvas->setChecked( mAddToCanvasStateOnOpenCompatibleDriver );
756 mAddToCanvas->setEnabled( true );
757 }
758 }
759}
760
761void QgsVectorLayerSaveAsDialog::mUseAliasesForExportedName_stateChanged( int state )
762{
763 const QSignalBlocker signalBlocker( mAttributeTable );
764
765 switch ( state )
766 {
767 case Qt::Unchecked:
768 {
769 // Check for modified entries
770 bool modifiedEntries = false;
771 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
772 {
773 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text()
774 != mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString() )
775 {
776 modifiedEntries = true;
777 break;
778 }
779 }
780
781 if ( modifiedEntries )
782 {
783 if ( QMessageBox::question( this,
784 tr( "Modified names" ),
785 tr( "Some names were modified and will be overridden. Do you want to continue?" ) )
786 == QMessageBox::No )
787 {
788 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
789 return;
790 }
791 }
792
793 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
794 {
795 mUseAliasesForExportedName->setTristate( false );
796 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->setText( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->text() );
797 }
798 }
799 break;
800 case Qt::Checked:
801 {
802 // Check for modified entries
803 bool modifiedEntries = false;
804 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
805 {
806 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text()
807 != mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->text() )
808 modifiedEntries = true;
809 }
810
811 if ( modifiedEntries )
812 {
813 if ( QMessageBox::question( this,
814 tr( "Modified names" ),
815 tr( "Some names were modified and will be overridden. Do you want to continue?" ) )
816 == QMessageBox::No )
817 {
818 whileBlocking( mUseAliasesForExportedName )->setCheckState( Qt::PartiallyChecked );
819 return;
820 }
821 }
822
823 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
824 {
825 mUseAliasesForExportedName->setTristate( false );
826 const QString alias = mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->data( Qt::UserRole ).toString();
827 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->setText( alias );
828 }
829 }
830 break;
831 case Qt::PartiallyChecked:
832 // Do nothing
833 break;
834 }
835}
836
837void QgsVectorLayerSaveAsDialog::mReplaceRawFieldValues_stateChanged( int )
838{
839 if ( mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
840 return;
841
842 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
843 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
844
845 if ( mReplaceRawFieldValues->checkState() != Qt::PartiallyChecked )
846 {
847 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
848 {
849 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked &&
850 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
851 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
852 {
853 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( mReplaceRawFieldValues->checkState() );
854 }
855 }
856 }
857 mReplaceRawFieldValues->setTristate( false );
858}
859
860void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem *item )
861{
862 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
863 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
864
865 int row = item->row();
866 int column = item->column();
867
868 switch ( static_cast<ColumnIndex>( column ) )
869 {
870 case ColumnIndex::Name:
871 {
872 if ( mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) ||
873 ! mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) ||
874 !( mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
875 return;
876
877 if ( mAttributeTable->item( row, column )->checkState() == Qt::Unchecked )
878 {
879 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
880 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
881 bool checkBoxEnabled = false;
882 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
883 {
884 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
885 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
886 {
887 checkBoxEnabled = true;
888 break;
889 }
890 }
891 mReplaceRawFieldValues->setEnabled( checkBoxEnabled );
892 if ( !checkBoxEnabled )
893 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
894 }
895 else if ( mAttributeTable->item( row, column )->checkState() == Qt::Checked )
896 {
897 mAttributeTable->item( row, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
898 mReplaceRawFieldValues->setEnabled( true );
899 }
900 }
901 break;
902 case ColumnIndex::ExportName:
903 {
904 // Check empty export name
905 if ( item->text().isEmpty() )
906 {
907 QMessageBox::warning( this,
908 tr( "Empty export name" ),
909 tr( "Empty export name are not allowed." ) );
910 return;
911 }
912
913 // Rename eventually duplicated names
914 QStringList names = attributesExportNames();
915 while ( names.count( item->text() ) > 1 )
916 item->setText( QString( "%1_2" ).arg( item->text() ) );
917
918 mUseAliasesForExportedName->setCheckState( Qt::PartiallyChecked );
919 }
920 break;
921 case ColumnIndex::Type:
922 // Nothing to do
923 break;
924 case ColumnIndex::ExportAsDisplayedValue:
925 {
926 if ( mAttributeTable->item( row, column )->flags() & Qt::ItemIsUserCheckable )
927 {
928 bool allChecked = true;
929 bool allUnchecked = true;
930 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
931 {
932 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
933 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsEnabled )
934 {
935 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Unchecked )
936 allChecked = false;
937 else
938 allUnchecked = false;
939 }
940 }
941 mReplaceRawFieldValues->setCheckState( ( !allChecked && !allUnchecked ) ? Qt::PartiallyChecked : ( allChecked ) ? Qt::Checked : Qt::Unchecked );
942 }
943 }
944 break;
945 }
946}
947
948void QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
949{
950 mSelectedCrs = crs;
951 mExtentGroupBox->setOutputCrs( mSelectedCrs );
952}
953
955{
956 return mFilename->filePath();
957}
958
960{
961 return leLayername->text();
962}
963
965{
966 return mEncodingComboBox->currentText();
967}
968
970{
971 return mFormatComboBox->currentData().toString();
972}
973
975{
976 return mSelectedCrs;
977}
978
980{
981 QStringList options;
982
983 QgsVectorFileWriter::MetaData driverMetaData;
984
985 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
986 {
987 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
988
989 for ( it = driverMetaData.driverOptions.constBegin(); it != driverMetaData.driverOptions.constEnd(); ++it )
990 {
991 switch ( it.value()->type )
992 {
994 {
996 QSpinBox *sb = mDatasourceOptionsGroupBox->findChild<QSpinBox *>( it.key() );
997 if ( opt && sb && sb->value() != opt->defaultValue )
998 options << QStringLiteral( "%1=%2" ).arg( it.key() ).arg( sb->value() );
999 break;
1000 }
1001
1003 {
1005 QComboBox *cb = mDatasourceOptionsGroupBox->findChild<QComboBox *>( it.key() );
1006 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->defaultValue )
1007 options << QStringLiteral( "%1=%2" ).arg( it.key(), cb->currentText() );
1008 break;
1009 }
1010
1012 {
1014 QLineEdit *le = mDatasourceOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1015 if ( opt && le && le->text() != opt->defaultValue )
1016 options << QStringLiteral( "%1=%2" ).arg( it.key(), le->text() );
1017 break;
1018 }
1019
1021 {
1023 dynamic_cast<QgsVectorFileWriter::HiddenOption *>( it.value() );
1024 if ( !opt->mValue.isEmpty() )
1025 options << QStringLiteral( "%1=%2" ).arg( it.key(), opt->mValue );
1026 break;
1027 }
1028 }
1029 }
1030 }
1031
1032 QString plainText = mOgrDatasourceOptions->toPlainText().trimmed();
1033 if ( !plainText.isEmpty() )
1034 options += plainText.split( '\n' );
1035
1036 return options;
1037}
1038
1040{
1041 QStringList options;
1042
1043 QgsVectorFileWriter::MetaData driverMetaData;
1044
1045 if ( QgsVectorFileWriter::driverMetadata( format(), driverMetaData ) )
1046 {
1047 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
1048
1049 for ( it = driverMetaData.layerOptions.constBegin(); it != driverMetaData.layerOptions.constEnd(); ++it )
1050 {
1051 switch ( it.value()->type )
1052 {
1054 {
1056 QSpinBox *sb = mLayerOptionsGroupBox->findChild<QSpinBox *>( it.key() );
1057 if ( opt && sb && sb->value() != opt->defaultValue )
1058 options << QStringLiteral( "%1=%2" ).arg( it.key() ).arg( sb->value() );
1059 break;
1060 }
1061
1063 {
1065 QComboBox *cb = mLayerOptionsGroupBox->findChild<QComboBox *>( it.key() );
1066 if ( opt && cb && cb->itemData( cb->currentIndex() ) != opt->defaultValue )
1067 options << QStringLiteral( "%1=%2" ).arg( it.key(), cb->currentText() );
1068 break;
1069 }
1070
1072 {
1074 QLineEdit *le = mLayerOptionsGroupBox->findChild<QLineEdit *>( it.key() );
1075 if ( opt && le && le->text() != opt->defaultValue )
1076 options << QStringLiteral( "%1=%2" ).arg( it.key(), le->text() );
1077 break;
1078 }
1079
1081 {
1083 dynamic_cast<QgsVectorFileWriter::HiddenOption *>( it.value() );
1084 if ( !opt->mValue.isEmpty() )
1085 options << QStringLiteral( "%1=%2" ).arg( it.key(), opt->mValue );
1086 break;
1087 }
1088 }
1089 }
1090 }
1091
1092 QString plainText = mOgrLayerOptions->toPlainText().trimmed();
1093 if ( !plainText.isEmpty() )
1094 options += plainText.split( '\n' );
1095
1096 return options;
1097}
1098
1100{
1101 QgsAttributeList attributes;
1102
1103 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1104 {
1105 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked )
1106 {
1107 attributes.append( i );
1108 }
1109 }
1110
1111 return attributes;
1112}
1113
1115{
1116 QgsAttributeList attributes;
1117
1118 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1119 {
1120 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->checkState() == Qt::Checked &&
1121 ! mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
1122 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->checkState() == Qt::Checked )
1123 {
1124 attributes.append( i );
1125 }
1126 }
1127
1128 return attributes;
1129}
1130
1132{
1133 QStringList exportNames;
1134 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1135 exportNames.append( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportName ) )->text() );
1136
1137 return exportNames;
1138}
1139
1141{
1142 return mAddToCanvas->isChecked();
1143}
1144
1146{
1147 mAddToCanvasStateOnOpenCompatibleDriver = enabled;
1148 if ( mAddToCanvas->isEnabled() )
1149 mAddToCanvas->setChecked( enabled );
1150}
1151
1153{
1154 return mSymbologyExportComboBox->currentData().value< Qgis::FeatureSymbologyExport >();
1155}
1156
1158{
1159 return mScaleWidget->scale();
1160}
1161
1163{
1164 mMapCanvas = canvas;
1165 mScaleWidget->setMapCanvas( canvas );
1166 mScaleWidget->setShowCurrentScaleButton( true );
1167 mExtentGroupBox->setCurrentExtent( canvas->mapSettings().visibleExtent(), canvas->mapSettings().destinationCrs() );
1168}
1169
1171{
1172 return mExtentGroupBox->isChecked();
1173}
1174
1176{
1177 return mExtentGroupBox->outputExtent();
1178}
1179
1181{
1182 mSelectedOnly->setChecked( onlySelected );
1183}
1184
1186{
1187 return mSelectedOnly->isChecked();
1188}
1189
1191{
1192 return mCheckPersistMetadata->isChecked();
1193}
1194
1196{
1197 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1198 if ( currentIndexData == -1 )
1199 {
1200 //automatic
1202 }
1203
1204 return static_cast< Qgis::WkbType >( currentIndexData );
1205}
1206
1208{
1209 int currentIndexData = mGeometryTypeComboBox->currentData().toInt();
1210 return currentIndexData == -1;
1211}
1212
1214{
1215 return mForceMultiCheckBox->isChecked();
1216}
1217
1219{
1220 mForceMultiCheckBox->setChecked( checked );
1221}
1222
1224{
1225 return mIncludeZCheckBox->isChecked();
1226}
1227
1232
1234{
1235 mIncludeZCheckBox->setChecked( checked );
1236}
1237
1238void QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged( const QString &text )
1239{
1240 bool scaleEnabled = true;
1241 if ( text == tr( "No symbology" ) )
1242 {
1243 scaleEnabled = false;
1244 }
1245 mScaleWidget->setEnabled( scaleEnabled );
1246 mScaleLabel->setEnabled( scaleEnabled );
1247}
1248
1249void QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged( int )
1250{
1251 Qgis::WkbType currentIndexData = static_cast< Qgis::WkbType >( mGeometryTypeComboBox->currentData().toInt() );
1252
1253 if ( mGeometryTypeComboBox->currentIndex() != -1 && currentIndexData != Qgis::WkbType::NoGeometry )
1254 {
1255 mForceMultiCheckBox->setEnabled( true );
1256 mIncludeZCheckBox->setEnabled( true );
1257 }
1258 else
1259 {
1260 mForceMultiCheckBox->setEnabled( false );
1261 mForceMultiCheckBox->setChecked( false );
1262 mIncludeZCheckBox->setEnabled( false );
1263 mIncludeZCheckBox->setChecked( false );
1264 }
1265}
1266
1267void QgsVectorLayerSaveAsDialog::mSelectAllAttributes_clicked()
1268{
1269 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1270 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1271
1272 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1273 {
1274 if ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->flags() & Qt::ItemIsEnabled )
1275 {
1276 if ( ! mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
1277 ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1278 {
1279 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
1280 }
1281 mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Checked );
1282 }
1283 }
1284 if ( ! mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1285 {
1286 mReplaceRawFieldValues->setEnabled( true );
1287 }
1288}
1289
1290void QgsVectorLayerSaveAsDialog::mDeselectAllAttributes_clicked()
1291{
1292 const QSignalBlocker signalBlockerAttributeTable( mAttributeTable );
1293 const QSignalBlocker signalBlockerReplaceRawFieldValues( mReplaceRawFieldValues );
1294
1295 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
1296 {
1297 mAttributeTable->item( i, static_cast<int>( ColumnIndex::Name ) )->setCheckState( Qt::Unchecked );
1298 if ( ! mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) &&
1299 ( mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->flags() & Qt::ItemIsUserCheckable ) )
1300 {
1301 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setFlags( Qt::ItemIsUserCheckable );
1302 mAttributeTable->item( i, static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) )->setCheckState( Qt::Unchecked );
1303 }
1304 }
1305 if ( ! mAttributeTable->isColumnHidden( static_cast<int>( ColumnIndex::ExportAsDisplayedValue ) ) )
1306 {
1307 mReplaceRawFieldValues->setCheckState( Qt::Unchecked );
1308 mReplaceRawFieldValues->setEnabled( false );
1309 }
1310}
1311
1312void QgsVectorLayerSaveAsDialog::showHelp()
1313{
1314 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer" ) );
1315}
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:5155
@ 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:94
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:209
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:5862
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,...