QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgspointcloudlayersaveasdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudlayersaveasdialog.h
3 Dialog to select destination, type and crs to save as pointcloud layers
4 -------------------
5 begin : July 2022
6 copyright : (C) 2022 by Stefanos Natsis
7 email : uclaros at gmail dot com
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
19#include <QMessageBox>
20#include <QRegularExpression>
21
23#include "moc_qgspointcloudlayersaveasdialog.cpp"
24#include "qgsgui.h"
25#include "qgsmapcanvas.h"
26#include "qgsdatums.h"
27#include "qgsproviderregistry.h"
29#include "qgspointcloudlayer.h"
30#include "qgsmaplayerutils.h"
31#include "qgsvectorlayer.h"
32
34 : QDialog( parent, fl )
35 , mLayer( layer )
36 , mActionOnExistingFile( QgsVectorFileWriter::CreateOrOverwriteFile )
37{
38 if ( layer )
39 {
40 mSelectedCrs = layer->crs();
41 mLayerExtent = layer->extent();
42 }
43 setup();
44}
45
46void QgsPointCloudLayerSaveAsDialog::setup()
47{
48 setupUi( this );
50
51 connect( mFormatComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPointCloudLayerSaveAsDialog::mFormatComboBox_currentIndexChanged );
52 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsPointCloudLayerSaveAsDialog::mCrsSelector_crsChanged );
53 connect( mSelectAllAttributes, &QPushButton::clicked, this, &QgsPointCloudLayerSaveAsDialog::mSelectAllAttributes_clicked );
54 connect( mDeselectAllAttributes, &QPushButton::clicked, this, &QgsPointCloudLayerSaveAsDialog::mDeselectAllAttributes_clicked );
55 connect( mFilterGeometryLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsPointCloudLayerSaveAsDialog::mFilterGeometryLayerChanged );
56 connect( mFilterGeometryGroupBox, &QgsCollapsibleGroupBox::toggled, this, &QgsPointCloudLayerSaveAsDialog::mFilterGeometryGroupBoxCheckToggled );
57 connect( mMinimumZSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudLayerSaveAsDialog::mMinimumZSpinBoxValueChanged );
58 connect( mMaximumZSpinBox, static_cast<void ( QgsDoubleSpinBox::* )( double )>( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudLayerSaveAsDialog::mMaximumZSpinBoxValueChanged );
59
60#ifdef Q_OS_WIN
61 mHelpButtonBox->setVisible( false );
62 mButtonBox->addButton( QDialogButtonBox::Help );
63 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsPointCloudLayerSaveAsDialog::showHelp );
64#else
65 connect( mHelpButtonBox, &QDialogButtonBox::helpRequested, this, &QgsPointCloudLayerSaveAsDialog::showHelp );
66#endif
67 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsPointCloudLayerSaveAsDialog::accept );
68 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsPointCloudLayerSaveAsDialog::reject );
69
70 mFormatComboBox->blockSignals( true );
71 const QList<QgsPointCloudLayerExporter::ExportFormat> supportedFormats = QgsPointCloudLayerExporter::supportedFormats();
72 for ( const auto &format : supportedFormats )
73 mFormatComboBox->addItem( getTranslatedNameForFormat( format ), static_cast<int>( format ) );
74
75 QgsSettings settings;
76 const int defaultFormat = settings.value( QStringLiteral( "UI/lastPointCloudFormat" ), 0 ).toInt();
77 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData( defaultFormat ) );
78 mFormatComboBox->blockSignals( false );
79 mFormatComboBox_currentIndexChanged( 0 );
80
81 mCrsSelector->setCrs( mSelectedCrs );
82 mCrsSelector->setLayerCrs( mSelectedCrs );
83 mCrsSelector->setMessage( tr( "Select the coordinate reference system for the vector file. "
84 "The data points will be transformed from the layer coordinate reference system." ) );
85
86
87 // attributes
88 if ( mLayer )
89 {
90 const auto attributes = mLayer->attributes();
91 QStringList availableAttributes;
92 for ( int i = 0; i < attributes.count(); ++i )
93 {
94 const QString attribute = attributes.at( i ).name();
95 if ( attribute.compare( QLatin1String( "X" ), Qt::CaseInsensitive ) && attribute.compare( QLatin1String( "Y" ), Qt::CaseInsensitive ) && attribute.compare( QLatin1String( "Z" ), Qt::CaseInsensitive ) )
96 {
97 availableAttributes.append( attribute );
98 }
99 }
100
101 mAttributeTable->setRowCount( availableAttributes.count() );
102 QStringList horizontalHeaders = QStringList() << tr( "Attribute" );
103 mAttributeTable->setColumnCount( horizontalHeaders.size() );
104 mAttributeTable->setHorizontalHeaderLabels( horizontalHeaders );
105
106 for ( int i = 0; i < availableAttributes.count(); ++i )
107 {
108 QTableWidgetItem *item = new QTableWidgetItem( availableAttributes.at( i ) );
109 item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
110 item->setCheckState( Qt::Checked );
111 mAttributeTable->setItem( i, 0, item );
112 }
113 mAttributeTable->resizeColumnsToContents();
114 }
115
116 // extent group box
117 mExtentGroupBox->setOutputCrs( mSelectedCrs );
118 mExtentGroupBox->setOriginalExtent( mLayerExtent, mSelectedCrs );
119 mExtentGroupBox->setOutputExtentFromOriginal();
120 mExtentGroupBox->setCheckable( true );
121 mExtentGroupBox->setChecked( false );
122 mExtentGroupBox->setCollapsed( true );
123
124 // polygon layer filter group box
125 mFilterGeometryLayerComboBox->setFilters( Qgis::LayerFilter::PolygonLayer );
126
127 // ZRange group box
128 mMinimumZSpinBox->setRange( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max() );
129 mMaximumZSpinBox->setRange( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max() );
130 if ( mLayer )
131 {
132 mMinimumZSpinBox->setValue( mLayer->statistics().minimum( QStringLiteral( "Z" ) ) );
133 mMinimumZSpinBox->setClearValue( mMinimumZSpinBox->value() );
134 mMaximumZSpinBox->setValue( mLayer->statistics().maximum( QStringLiteral( "Z" ) ) );
135 mMaximumZSpinBox->setClearValue( mMaximumZSpinBox->value() );
136 }
137
138 // points limit group box
139 mPointsLimitSpinBox->setMinimum( 1 );
140 mPointsLimitSpinBox->setMaximum( std::numeric_limits<int>::max() );
141 mPointsLimitSpinBox->setValue( 1e6 );
142 mPointsLimitSpinBox->setClearValue( 1e6 );
143
144 mFilename->setStorageMode( QgsFileWidget::SaveFile );
145 mFilename->setDialogTitle( tr( "Save Layer As" ) );
146 mFilename->setDefaultRoot( settings.value( QStringLiteral( "UI/lastPointCloudFileFilterDir" ), QDir::homePath() ).toString() );
147 mFilename->setConfirmOverwrite( false );
148 connect( mFilename, &QgsFileWidget::fileChanged, this, [=]( const QString &filePath ) {
149 QgsSettings settings;
150 if ( !filePath.isEmpty() )
151 mLastUsedFilename = filePath;
152
153 const QFileInfo fileInfo( filePath );
154 settings.setValue( QStringLiteral( "UI/lastPointCloudFileFilterDir" ), fileInfo.absolutePath() );
155 const QString suggestedLayerName = QgsMapLayerUtils::launderLayerName( fileInfo.completeBaseName() );
156 if ( mDefaultOutputLayerNameFromInputLayerName.isEmpty() )
157 {
158 leLayername->setDefaultValue( suggestedLayerName );
159 }
160
161 // if no layer name set, then automatically match the output layer name to the file name
162 if ( leLayername->text().isEmpty() && !filePath.isEmpty() && leLayername->isEnabled() )
163 {
164 leLayername->setText( suggestedLayerName );
165 }
166 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !filePath.isEmpty() );
167 } );
168
169 try
170 {
171 const QgsDatumEnsemble ensemble = mSelectedCrs.datumEnsemble();
172 if ( ensemble.isValid() )
173 {
174 mCrsSelector->setSourceEnsemble( ensemble.name() );
175 }
176 }
177 catch ( QgsNotSupportedException & )
178 {
179 }
180
181 mCrsSelector->setShowAccuracyWarnings( true );
182
183 mAddToCanvas->setEnabled( exportFormat() != QgsPointCloudLayerExporter::ExportFormat::Memory );
184
185 if ( mLayer )
186 {
187 mDefaultOutputLayerNameFromInputLayerName = QgsMapLayerUtils::launderLayerName( mLayer->name() );
188 leLayername->setDefaultValue( mDefaultOutputLayerNameFromInputLayerName );
189 leLayername->setClearMode( QgsFilterLineEdit::ClearToDefault );
190 if ( leLayername->isEnabled() )
191 leLayername->setText( mDefaultOutputLayerNameFromInputLayerName );
192 }
193
194 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( exportFormat() == QgsPointCloudLayerExporter::ExportFormat::Memory || !mFilename->filePath().isEmpty() );
195}
196
197void QgsPointCloudLayerSaveAsDialog::accept()
198{
199 if ( QFile::exists( filename() ) )
200 {
203 QMessageBox msgBox;
204 msgBox.setIcon( QMessageBox::Question );
205 msgBox.setWindowTitle( tr( "Save Point Cloud Layer As" ) );
206 QPushButton *overwriteFileButton = msgBox.addButton( tr( "Overwrite File" ), QMessageBox::ActionRole );
207 QPushButton *overwriteLayerButton = msgBox.addButton( tr( "Overwrite Layer" ), QMessageBox::ActionRole );
208 QPushButton *appendToLayerButton = msgBox.addButton( tr( "Append to Layer" ), QMessageBox::ActionRole );
209 msgBox.setStandardButtons( QMessageBox::Cancel );
210 msgBox.setDefaultButton( QMessageBox::Cancel );
211 overwriteFileButton->hide();
212 overwriteLayerButton->hide();
213 appendToLayerButton->hide();
214 if ( layerExists )
215 {
217 {
218 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or overwrite the layer?" ) );
219 overwriteFileButton->setVisible( true );
220 overwriteLayerButton->setVisible( true );
221 }
223 {
224 msgBox.setText( tr( "The file already exists. Do you want to overwrite it?" ) );
225 overwriteFileButton->setVisible( true );
226 }
228 {
229 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file, overwrite the layer or append features to the layer?" ) );
230 appendToLayerButton->setVisible( true );
231 overwriteFileButton->setVisible( true );
232 overwriteLayerButton->setVisible( true );
233 }
234 else
235 {
236 msgBox.setText( tr( "The layer already exists. Do you want to overwrite the whole file or append features to the layer?" ) );
237 appendToLayerButton->setVisible( true );
238 overwriteFileButton->setVisible( true );
239 }
240
241 int ret = msgBox.exec();
242 if ( ret == QMessageBox::Cancel )
243 return;
244 if ( msgBox.clickedButton() == overwriteFileButton )
245 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
246 else if ( msgBox.clickedButton() == overwriteLayerButton )
247 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
248 else if ( msgBox.clickedButton() == appendToLayerButton )
249 mActionOnExistingFile = QgsVectorFileWriter::AppendToLayerNoNewFields;
250 }
251 else // !layerExists
252 {
254 {
255 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
256 }
257 else
258 {
259 // should not reach here, layer does not exist and cannot add new layer
260 if ( QMessageBox::question( this, tr( "Save Point Cloud Layer As" ), tr( "The file already exists. Do you want to overwrite it?" ) ) == QMessageBox::NoButton )
261 {
262 return;
263 }
264 mActionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteFile;
265 }
266 }
267 }
268 else if ( mActionOnExistingFile == QgsVectorFileWriter::CreateOrOverwriteFile && QFile::exists( filename() ) )
269 {
270 const QList<QgsProviderSublayerDetails> sublayers = QgsProviderRegistry::instance()->querySublayers( filename() );
271 QStringList layerList;
272 layerList.reserve( sublayers.size() );
273 for ( const QgsProviderSublayerDetails &sublayer : sublayers )
274 {
275 layerList.append( sublayer.name() );
276 }
277 if ( layerList.length() > 1 )
278 {
279 layerList.sort( Qt::CaseInsensitive );
280 QMessageBox msgBox;
281 msgBox.setIcon( QMessageBox::Warning );
282 msgBox.setWindowTitle( tr( "Overwrite File" ) );
283 msgBox.setText( tr( "This file contains %1 layers that will be lost!\n" ).arg( QLocale().toString( layerList.length() ) ) );
284 msgBox.setDetailedText( tr( "The following layers will be permanently lost:\n\n%1" ).arg( layerList.join( "\n" ) ) );
285 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel );
286 if ( msgBox.exec() == QMessageBox::Cancel )
287 return;
288 }
289 }
290
291 QgsSettings settings;
292 settings.setValue( QStringLiteral( "UI/lastPointCloudFileFilterDir" ), QFileInfo( filename() ).absolutePath() );
293 settings.setValue( QStringLiteral( "UI/lastPointCloudFormat" ), static_cast<int>( exportFormat() ) );
294 QDialog::accept();
295}
296
297void QgsPointCloudLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( int idx )
298{
299 Q_UNUSED( idx )
300
302
303 switch ( format )
304 {
309 mAttributesSelection->setEnabled( true );
310 break;
311
314 mAttributesSelection->setEnabled( false );
315 break;
316 }
317
318 switch ( format )
319 {
322 leLayername->setEnabled( true );
323 break;
324
329 leLayername->setEnabled( false );
330 break;
331 }
332
333 switch ( format )
334 {
336 mWasAddToCanvasForced = !mAddToCanvas->isChecked();
337 mAddToCanvas->setEnabled( false );
338 mAddToCanvas->setChecked( true );
339 mFilename->setEnabled( false );
340 break;
341
347 mAddToCanvas->setEnabled( true );
348 if ( mWasAddToCanvasForced )
349 {
350 mAddToCanvas->setChecked( !mAddToCanvas->isChecked() );
351 mWasAddToCanvasForced = false;
352 }
353 mFilename->setEnabled( true );
354 break;
355 }
356
357 if ( mFilename->isEnabled() )
358 {
359 mFilename->setFilter( getFilterForFormat( format ) );
360
361 // if output filename already defined we need to replace old suffix
362 // to avoid double extensions like .gpkg.shp
363 if ( !mLastUsedFilename.isEmpty() )
364 {
365 const thread_local QRegularExpression rx( "\\.(.*?)[\\s]" );
366 QString ext;
367 ext = rx.match( getFilterForFormat( format ) ).captured( 1 );
368 if ( !ext.isEmpty() )
369 {
370 QFileInfo fi( mLastUsedFilename );
371 mFilename->setFilePath( QStringLiteral( "%1/%2.%3" ).arg( fi.path(), fi.baseName(), ext ) );
372 }
373 }
374 }
375
376 if ( !mFilename->isEnabled() )
377 mFilename->setFilePath( QString() );
378
379 if ( !leLayername->isEnabled() )
380 {
381 leLayername->setText( QString() );
382 }
383 else if ( leLayername->text().isEmpty() )
384 {
385 QString layerName = mDefaultOutputLayerNameFromInputLayerName;
386 if ( layerName.isEmpty() && !mFilename->filePath().isEmpty() )
387 {
388 layerName = QFileInfo( mFilename->filePath() ).baseName();
389 leLayername->setDefaultValue( layerName );
390 }
391 if ( layerName.isEmpty() )
392 {
393 layerName = tr( "new_layer" );
394 }
395 leLayername->setText( layerName );
396 }
397
398 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( format == QgsPointCloudLayerExporter::ExportFormat::Memory || !mFilename->filePath().isEmpty() );
399}
400
401void QgsPointCloudLayerSaveAsDialog::mFilterGeometryGroupBoxCheckToggled( bool checked )
402{
403 if ( checked )
404 mFilterGeometryLayerChanged( mFilterGeometryLayerComboBox->currentLayer() );
405}
406
407void QgsPointCloudLayerSaveAsDialog::mFilterGeometryLayerChanged( QgsMapLayer *layer )
408{
409 QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( layer );
410 mSelectedFeaturesCheckBox->setChecked( false );
411 mSelectedFeaturesCheckBox->setEnabled( hasFilterLayer() && vlayer && vlayer->selectedFeatureCount() );
412}
413
414void QgsPointCloudLayerSaveAsDialog::mMinimumZSpinBoxValueChanged( const double value )
415{
416 mMaximumZSpinBox->setMinimum( value );
417}
418
419void QgsPointCloudLayerSaveAsDialog::mMaximumZSpinBoxValueChanged( const double value )
420{
421 mMinimumZSpinBox->setMaximum( value );
422}
423
424void QgsPointCloudLayerSaveAsDialog::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
425{
426 mSelectedCrs = crs;
427 mExtentGroupBox->setOutputCrs( mSelectedCrs );
428}
429
431{
432 return mFilename->filePath();
433}
434
436{
437 return leLayername->text();
438}
439
441{
442 return static_cast<QgsPointCloudLayerExporter::ExportFormat>( mFormatComboBox->currentData().toInt() );
443}
444
449
451{
452 QStringList attributes;
453
454 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
455 {
456 if ( mAttributeTable->item( i, 0 )->checkState() == Qt::Checked )
457 {
458 attributes.append( mAttributeTable->item( i, 0 )->text() );
459 }
460 }
461
462 return attributes;
463}
464
466{
467 return mAddToCanvas->isChecked();
468}
469
471{
472 mAddToCanvas->setChecked( enabled );
473}
474
476{
477 mMapCanvas = canvas;
478 mExtentGroupBox->setCurrentExtent( canvas->mapSettings().visibleExtent(), canvas->mapSettings().destinationCrs() );
479}
480
482{
483 return mExtentGroupBox->isChecked();
484}
485
487{
488 return mExtentGroupBox->outputExtent();
489}
490
492{
493 return mFilterGeometryGroupBox->isChecked() && mFilterGeometryLayerComboBox->count() > 0;
494}
495
497{
498 return mFilterGeometryLayerComboBox->currentLayer();
499}
500
502{
503 return hasFilterLayer() && mSelectedFeaturesCheckBox->isChecked();
504}
505
507{
508 return mAttributesSelection->isChecked() && mAttributesSelection->isEnabled();
509}
510
512{
513 return mZRangeGroupBox->isChecked();
514}
515
517{
518 return QgsDoubleRange( mMinimumZSpinBox->value(), mMaximumZSpinBox->value() );
519}
520
522{
523 return mPointsLimitGroupBox->isChecked();
524}
525
527{
528 return mPointsLimitSpinBox->value();
529}
530
535
536void QgsPointCloudLayerSaveAsDialog::mSelectAllAttributes_clicked()
537{
538 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
539 {
540 mAttributeTable->item( i, 0 )->setCheckState( Qt::Checked );
541 }
542}
543
544void QgsPointCloudLayerSaveAsDialog::mDeselectAllAttributes_clicked()
545{
546 {
547 for ( int i = 0; i < mAttributeTable->rowCount(); i++ )
548 {
549 mAttributeTable->item( i, 0 )->setCheckState( Qt::Unchecked );
550 }
551 }
552}
553
554void QgsPointCloudLayerSaveAsDialog::showHelp()
555{
556 QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#creating-new-layers-from-an-existing-layer" ) );
557}
558
559QString QgsPointCloudLayerSaveAsDialog::getFilterForFormat( QgsPointCloudLayerExporter::ExportFormat format )
560{
561 switch ( format )
562 {
564 return QStringLiteral( "LAZ point cloud (*.laz *.LAZ);;LAS point cloud (*.las *.LAS)" );
566 return QStringLiteral( "GeoPackage (*.gpkg *.GPKG)" );
568 return QStringLiteral( "AutoCAD DXF (*.dxf *.dxf)" );
570 return QStringLiteral( "ESRI Shapefile (*.shp *.SHP)" );
572 return QStringLiteral( "Comma separated values (*.csv *.CSV)" );
574 break;
575 }
576 return QString();
577}
578
579QString QgsPointCloudLayerSaveAsDialog::getTranslatedNameForFormat( QgsPointCloudLayerExporter::ExportFormat format )
580{
581 switch ( format )
582 {
584 return tr( "Temporary Scratch Layer" );
586 return tr( "GeoPackage" );
588 return tr( "AutoCAD DXF" );
590 return tr( "ESRI Shapefile" );
592 return tr( "LAS/LAZ point cloud" );
594 return tr( "Comma separated values" );
595 }
596 return QString();
597}
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
QgsRange which stores a range of double values.
Definition qgsrange.h:231
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
@ 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 void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:210
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
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.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
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...
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:83
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Custom exception class which is raised when an operation is not supported.
const QgsPointCloudAttribute & at(int index) const
Returns the attribute at the specified index.
QString name() const
Returns name of the attribute.
ExportFormat
Supported export formats for point clouds.
static QList< ExportFormat > supportedFormats()
Gets a list of the supported export formats.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas to associate with the dialog.
QgsPointCloudLayerSaveAsDialog(QgsPointCloudLayer *layer, QWidget *parent=nullptr, Qt::WindowFlags fl=Qt::WindowFlags())
Construct a new QgsPointCloudLayerSaveAsDialog.
QString filename() const
Returns the target filename.
bool hasPointsLimit() const
Determines if limiting the number of exported points is enabled.
bool hasFilterLayer() const
Determines if points will be spatially filtered by a layer's features.
QgsRectangle filterExtent() const
Determines the extent to be exported.
bool hasZRange() const
Determines if filtering by Z values is activated.
QgsCoordinateReferenceSystem crsObject() const
Returns the CRS chosen for export.
bool hasAttributes() const
Determines if attributes will be exported as fields.
QgsDoubleRange zRange() const
Determines the Z range of points to be exported.
QgsPointCloudLayerExporter::ExportFormat exportFormat() const
The format in which the export should be written.
bool hasFilterExtent() const
Determines if filtering the export by an extent is activated.
int pointsLimit() const
Determines the limit to the total number of points.
bool filterLayerSelectedOnly() const
Determines if only the selected features from the filterLayer will be used for spatial filtering.
QString layername() const
Returns the target layer name.
void setAddToCanvas(bool checked)
Sets whether the "add to canvas" checkbox should be checked.
bool addToCanvas() const
Returns true if the "add to canvas" checkbox is checked.
QgsMapLayer * filterLayer() const
Returns the layer responsible for spatially filtering points.
QStringList attributes() const
Returns a list of attributes which are selected for saving.
QgsVectorFileWriter::ActionOnExistingFile creationActionOnExistingFile() const
Returns creation action.
Represents a map layer supporting display of point clouds.
QgsRectangle extent() const override
Returns the extent of the layer.
const QgsPointCloudStatistics statistics() const
Returns the object containing statistics.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes available from the layer.
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...
double minimum(const QString &attribute) const
Returns the minimum value for the attribute attribute If no matching statistic is available then NaN ...
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
QList< QgsProviderSublayerDetails > querySublayers(const QString &uri, Qgis::SublayerQueryFlags flags=Qgis::SublayerQueryFlags(), QgsFeedback *feedback=nullptr) const
Queries the specified uri and returns a list of any valid sublayers found in the dataset which can be...
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Contains details about a sub layer available from a dataset.
A rectangle specified with double values.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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.
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.
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.
Represents a vector layer which manages a vector based data sets.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
const QgsCoordinateReferenceSystem & crs