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