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