QGIS API Documentation  2.99.0-Master (01468d0)
qgsrasterlayersaveasdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterlayersaveasdialog.cpp
3  ---------------------
4  begin : May 2012
5  copyright : (C) 2012 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsapplication.h"
16 #include "qgslogger.h"
17 #include "qgscoordinatetransform.h"
18 #include "qgsrasterlayer.h"
20 #include "qgsrasterdataprovider.h"
22 #include "qgsrasterrenderer.h"
23 #include "qgsrastertransparency.h"
25 #include "qgssettings.h"
26 
27 #include <gdal.h>
28 
29 #include <QFileDialog>
30 #include <QMessageBox>
31 
33  QgsRasterDataProvider *sourceProvider, const QgsRectangle &currentExtent,
34  const QgsCoordinateReferenceSystem &layerCrs, const QgsCoordinateReferenceSystem &currentCrs,
35  QWidget *parent, Qt::WindowFlags f )
36  : QDialog( parent, f )
37  , mRasterLayer( rasterLayer )
38  , mDataProvider( sourceProvider )
39  , mCurrentExtent( currentExtent )
40  , mLayerCrs( layerCrs )
41  , mCurrentCrs( currentCrs )
42  , mResolutionState( OriginalResolution )
43 {
44  setupUi( this );
45  mAddNoDataManuallyToolButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
46  mLoadTransparentNoDataToolButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
47  mRemoveSelectedNoDataToolButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyRemove.svg" ) ) );
48  mRemoveAllNoDataToolButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemove.svg" ) ) );
49 
50  mNoDataTableWidget->setColumnCount( 2 );
51  mNoDataTableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
52  mNoDataTableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "To" ) ) );
53 
54  on_mRawModeRadioButton_toggled( true );
55 
56  setValidators();
57 
58  toggleResolutionSize();
59 
60  //only one hardcoded format at the moment
61  QStringList myFormats;
62  myFormats << QStringLiteral( "GTiff" );
63  Q_FOREACH ( const QString &myFormat, myFormats )
64  {
65  mFormatComboBox->addItem( myFormat );
66  }
67 
68  //fill reasonable default values depending on the provider
69  if ( mDataProvider )
70  {
71  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size )
72  {
73  setOriginalResolution();
74  int xSize = mDataProvider->xSize();
75  int ySize = mDataProvider->ySize();
76  mMaximumSizeXLineEdit->setText( QString::number( xSize ) );
77  mMaximumSizeYLineEdit->setText( QString::number( ySize ) );
78  }
79  else //wms, sometimes wcs
80  {
81  mTileModeCheckBox->setChecked( true );
82  mMaximumSizeXLineEdit->setText( QString::number( 2000 ) );
83  mMaximumSizeYLineEdit->setText( QString::number( 2000 ) );
84  }
85 
86  // setup creation option widget
87  mCreateOptionsWidget->setProvider( mDataProvider->name() );
88  if ( mDataProvider->name() == QLatin1String( "gdal" ) )
89  {
90  mCreateOptionsWidget->setFormat( myFormats[0] );
91  }
92  mCreateOptionsWidget->setRasterLayer( mRasterLayer );
93  mCreateOptionsWidget->update();
94  }
95 
96  // Only do pyramids if dealing directly with GDAL.
97  if ( mDataProvider && mDataProvider->capabilities() & QgsRasterDataProvider::BuildPyramids )
98  {
99  // setup pyramids option widget
100  // mPyramidsOptionsWidget->createOptionsWidget()->setType( QgsRasterFormatSaveOptionsWidget::ProfileLineEdit );
101  mPyramidsOptionsWidget->createOptionsWidget()->setRasterLayer( mRasterLayer );
102 
103  // TODO enable "use existing", has no effect for now, because using Create() in gdal provider
104  // if ( ! mDataProvider->hasPyramids() )
105  // mPyramidsButtonGroup->button( QgsRaster::PyramidsCopyExisting )->setEnabled( false );
106  mPyramidsUseExistingCheckBox->setEnabled( false );
107  mPyramidsUseExistingCheckBox->setVisible( false );
108 
109  populatePyramidsLevels();
110  connect( mPyramidsOptionsWidget, &QgsRasterPyramidsOptionsWidget::overviewListChanged,
111  this, &QgsRasterLayerSaveAsDialog::populatePyramidsLevels );
112  }
113  else
114  {
115  mPyramidsGroupBox->setEnabled( false );
116  }
117 
118  // restore checked state for most groupboxes (default is to restore collapsed state)
119  // create options and pyramids will be preset, if user has selected defaults in the gdal options dlg
120  mCreateOptionsGroupBox->setSaveCheckedState( true );
121  //mTilesGroupBox->setSaveCheckedState( true );
122  // don't restore nodata, it needs user input
123  // pyramids are not necessarily built every time
124 
125  mTilesGroupBox->hide();
126 
127  mCrsSelector->setLayerCrs( mLayerCrs );
128  //default to layer CRS - see https://issues.qgis.org/issues/14209 for discussion
129  mCrsSelector->setCrs( mLayerCrs );
130 
131  connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged,
132  this, &QgsRasterLayerSaveAsDialog::crsChanged );
133 
134  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
135  if ( okButton )
136  {
137  okButton->setEnabled( false );
138  }
139 
140  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsRasterLayerSaveAsDialog::showHelp );
141 
142  mExtentGroupBox->setOutputCrs( outputCrs() );
143  mExtentGroupBox->setOriginalExtent( mDataProvider->extent(), mLayerCrs );
144  mExtentGroupBox->setCurrentExtent( mCurrentExtent, mCurrentCrs );
145  mExtentGroupBox->setOutputExtentFromOriginal();
146  connect( mExtentGroupBox, &QgsExtentGroupBox::extentChanged, this, &QgsRasterLayerSaveAsDialog::extentChanged );
147 
148  recalcResolutionSize();
149 }
150 
151 void QgsRasterLayerSaveAsDialog::setValidators()
152 {
153  mXResolutionLineEdit->setValidator( new QDoubleValidator( this ) );
154  mYResolutionLineEdit->setValidator( new QDoubleValidator( this ) );
155  mColumnsLineEdit->setValidator( new QIntValidator( this ) );
156  mRowsLineEdit->setValidator( new QIntValidator( this ) );
157  mMaximumSizeXLineEdit->setValidator( new QIntValidator( this ) );
158  mMaximumSizeYLineEdit->setValidator( new QIntValidator( this ) );
159 }
160 
161 void QgsRasterLayerSaveAsDialog::on_mBrowseButton_clicked()
162 {
163  QString fileName;
164 
165  QgsSettings settings;
166  QString dirName = mSaveAsLineEdit->text().isEmpty() ? settings.value( QStringLiteral( "UI/lastRasterFileDir" ), QDir::homePath() ).toString() : mSaveAsLineEdit->text();
167 
168  if ( mTileModeCheckBox->isChecked() )
169  {
170  Q_FOREVER
171  {
172  // TODO: would not it be better to select .vrt file instead of directory?
173  fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ), dirName );
174  //fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "VRT" ) + " (*.vrt *.VRT)" );
175 
176  if ( fileName.isEmpty() )
177  break; // canceled
178 
179  // Check if directory is empty
180  QDir dir( fileName );
181  QString baseName = QFileInfo( fileName ).baseName();
182  QStringList filters;
183  filters << QStringLiteral( "%1.*" ).arg( baseName );
184  QStringList files = dir.entryList( filters );
185  if ( files.isEmpty() )
186  break;
187 
188  if ( QMessageBox::warning( this, tr( "Warning" ),
189  tr( "The directory %1 contains files which will be overwritten: %2" ).arg( dir.absolutePath(), files.join( QStringLiteral( ", " ) ) ),
190  QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Ok )
191  break;
192 
193  fileName = QLatin1String( "" );
194  }
195  }
196  else
197  {
198  fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), dirName, tr( "GeoTIFF" ) + " (*.tif *.tiff *.TIF *.TIFF)" );
199 
200  // ensure the user never omits the extension from the file name
201  if ( !fileName.isEmpty() && !fileName.endsWith( QLatin1String( ".tif" ), Qt::CaseInsensitive ) && !fileName.endsWith( QLatin1String( ".tiff" ), Qt::CaseInsensitive ) )
202  {
203  fileName += QLatin1String( ".tif" );
204  }
205  }
206 
207  if ( !fileName.isEmpty() )
208  {
209  mSaveAsLineEdit->setText( fileName );
210  }
211 }
212 
213 void QgsRasterLayerSaveAsDialog::on_mSaveAsLineEdit_textChanged( const QString &text )
214 {
215  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
216  if ( !okButton )
217  {
218  return;
219  }
220 
221  okButton->setEnabled( QFileInfo( text ).absoluteDir().exists() );
222 }
223 
224 
225 void QgsRasterLayerSaveAsDialog::on_mFormatComboBox_currentIndexChanged( const QString &text )
226 {
227  //gdal-specific
228  if ( mDataProvider && mDataProvider->name() == QLatin1String( "gdal" ) )
229  {
230  mCreateOptionsWidget->setFormat( text );
231  mCreateOptionsWidget->update();
232  }
233 }
234 
236 {
237  return mColumnsLineEdit->text().toInt();
238 }
239 
241 {
242  return mRowsLineEdit->text().toInt();
243 }
244 
246 {
247  return mXResolutionLineEdit->text().toDouble();
248 }
249 
251 {
252  return mYResolutionLineEdit->text().toDouble();
253 }
254 
256 {
257  return mMaximumSizeXLineEdit->text().toInt();
258 }
259 
261 {
262  return mMaximumSizeYLineEdit->text().toInt();
263 }
264 
266 {
267  return mTileModeCheckBox->isChecked();
268 }
269 
271 {
272  return mAddToCanvas->isChecked();
273 }
274 
276 {
277  return mSaveAsLineEdit->text();
278 }
279 
281 {
282  return mFormatComboBox->currentText();
283 }
284 
286 {
287  return mCreateOptionsGroupBox->isChecked() ? mCreateOptionsWidget->options() : QStringList();
288 }
289 
291 {
292  return mExtentGroupBox->outputExtent();
293 }
294 
296 {
297  mFormatLabel->hide();
298  mFormatComboBox->hide();
299 }
300 
302 {
303  mSaveAsLabel->hide();
304  mSaveAsLineEdit->hide();
305  mBrowseButton->hide();
306  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
307  if ( okButton )
308  {
309  okButton->setEnabled( true );
310  }
311 }
312 
313 void QgsRasterLayerSaveAsDialog::toggleResolutionSize()
314 {
315  bool hasResolution = mDataProvider && mDataProvider->capabilities() & QgsRasterDataProvider::Size;
316 
317  bool on = mResolutionRadioButton->isChecked();
318  mXResolutionLineEdit->setEnabled( on );
319  mYResolutionLineEdit->setEnabled( on );
320  mOriginalResolutionPushButton->setEnabled( on && hasResolution );
321  mColumnsLineEdit->setEnabled( !on );
322  mRowsLineEdit->setEnabled( !on );
323  mOriginalSizePushButton->setEnabled( !on && hasResolution );
324 }
325 
326 void QgsRasterLayerSaveAsDialog::setOriginalResolution()
327 {
328  double xRes, yRes;
329 
330  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size )
331  {
332  xRes = mDataProvider->extent().width() / mDataProvider->xSize();
333  yRes = mDataProvider->extent().height() / mDataProvider->ySize();
334  }
335  else
336  {
337  // Init to something if no original resolution is available
338  xRes = yRes = mDataProvider->extent().width() / 100;
339  }
340  setResolution( xRes, yRes, mLayerCrs );
341  mResolutionState = OriginalResolution;
342  recalcSize();
343 }
344 
345 void QgsRasterLayerSaveAsDialog::setResolution( double xRes, double yRes, const QgsCoordinateReferenceSystem &srcCrs )
346 {
347  if ( srcCrs != outputCrs() )
348  {
349  // We reproject pixel rectangle from center of selected extent, of course, it gives
350  // bigger xRes,yRes than reprojected edges (envelope), it may also be that
351  // close to margins are higher resolutions (even very, too high)
352  // TODO: consider more precise resolution calculation
353 
354  QgsPointXY center = outputRectangle().center();
355  QgsCoordinateTransform ct( srcCrs, outputCrs() );
357 
358  QgsRectangle srcExtent( srsCenter.x() - xRes / 2, srsCenter.y() - yRes / 2, srsCenter.x() + xRes / 2, srsCenter.y() + yRes / 2 );
359 
360  QgsRectangle extent = ct.transform( srcExtent );
361  xRes = extent.width();
362  yRes = extent.height();
363  }
364  mXResolutionLineEdit->setText( QString::number( xRes ) );
365  mYResolutionLineEdit->setText( QString::number( yRes ) );
366 }
367 
368 void QgsRasterLayerSaveAsDialog::recalcSize()
369 {
370  QgsRectangle extent = outputRectangle();
371  int xSize = xResolution() != 0 ? static_cast<int>( std::round( extent.width() / xResolution() ) ) : 0;
372  int ySize = yResolution() != 0 ? static_cast<int>( std::round( extent.height() / yResolution() ) ) : 0;
373  mColumnsLineEdit->setText( QString::number( xSize ) );
374  mRowsLineEdit->setText( QString::number( ySize ) );
375  updateResolutionStateMsg();
376 }
377 
378 void QgsRasterLayerSaveAsDialog::setOriginalSize()
379 {
380  mColumnsLineEdit->setText( QString::number( mDataProvider->xSize() ) );
381  mRowsLineEdit->setText( QString::number( mDataProvider->ySize() ) );
382  recalcResolution();
383 }
384 
385 void QgsRasterLayerSaveAsDialog::recalcResolution()
386 {
387  QgsRectangle extent = outputRectangle();
388  double xRes = nColumns() != 0 ? extent.width() / nColumns() : 0;
389  double yRes = nRows() != 0 ? extent.height() / nRows() : 0;
390  mXResolutionLineEdit->setText( QString::number( xRes ) );
391  mYResolutionLineEdit->setText( QString::number( yRes ) );
392  updateResolutionStateMsg();
393 }
394 
395 void QgsRasterLayerSaveAsDialog::recalcResolutionSize()
396 {
397  if ( mResolutionRadioButton->isChecked() )
398  {
399  recalcSize();
400  }
401  else
402  {
403  mResolutionState = UserResolution;
404  recalcResolution();
405  }
406 }
407 
408 void QgsRasterLayerSaveAsDialog::updateResolutionStateMsg()
409 {
410  QString msg;
411  switch ( mResolutionState )
412  {
413  case OriginalResolution:
414  msg = tr( "layer" );
415  break;
416  case UserResolution:
417  msg = tr( "user defined" );
418  break;
419  default:
420  break;
421  }
422  msg = tr( "Resolution (current: %1)" ).arg( msg );
423  mResolutionGroupBox->setTitle( msg );
424 }
425 
426 void QgsRasterLayerSaveAsDialog::extentChanged()
427 {
428  // Whenever extent changes with fixed size, original resolution is lost
429  if ( mSizeRadioButton->isChecked() )
430  {
431  mResolutionState = UserResolution;
432  }
433  recalcResolutionSize();
434 }
435 
436 void QgsRasterLayerSaveAsDialog::crsChanged()
437 {
438  if ( outputCrs() != mPreviousCrs )
439  {
440  mExtentGroupBox->setOutputCrs( outputCrs() );
441 
442  // Reset resolution
443  if ( mResolutionRadioButton->isChecked() )
444  {
445  if ( mResolutionState == OriginalResolution )
446  {
447  setOriginalResolution();
448  }
449  else
450  {
451  // reset from present resolution and present crs
452  setResolution( xResolution(), yResolution(), mPreviousCrs );
453  }
454  }
455  else
456  {
457  // Size does not change, we just recalc resolution from new extent
458  recalcResolution();
459  }
460  }
461  mPreviousCrs = outputCrs();
462 }
463 
465 {
466  return mCrsSelector->crs();
467 }
468 
470 {
471  if ( mRenderedModeRadioButton->isChecked() ) return RenderedImageMode;
472  return RawDataMode;
473 }
474 
475 void QgsRasterLayerSaveAsDialog::on_mRawModeRadioButton_toggled( bool checked )
476 {
477  mNoDataGroupBox->setEnabled( checked && mDataProvider->bandCount() == 1 );
478 }
479 
480 void QgsRasterLayerSaveAsDialog::on_mAddNoDataManuallyToolButton_clicked()
481 {
482  addNoDataRow( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
483 }
484 
485 void QgsRasterLayerSaveAsDialog::on_mLoadTransparentNoDataToolButton_clicked()
486 {
487  if ( !mRasterLayer->renderer() ) return;
488  const QgsRasterTransparency *rasterTransparency = mRasterLayer->renderer()->rasterTransparency();
489  if ( !rasterTransparency ) return;
490 
491  Q_FOREACH ( const QgsRasterTransparency::TransparentSingleValuePixel &transparencyPixel, rasterTransparency->transparentSingleValuePixelList() )
492  {
493  if ( transparencyPixel.percentTransparent == 100 )
494  {
495  addNoDataRow( transparencyPixel.min, transparencyPixel.max );
496  if ( transparencyPixel.min != transparencyPixel.max )
497  {
498  setNoDataToEdited( mNoDataTableWidget->rowCount() - 1 );
499  }
500  }
501  }
502 }
503 
504 void QgsRasterLayerSaveAsDialog::on_mRemoveSelectedNoDataToolButton_clicked()
505 {
506  mNoDataTableWidget->removeRow( mNoDataTableWidget->currentRow() );
507 }
508 
509 void QgsRasterLayerSaveAsDialog::on_mRemoveAllNoDataToolButton_clicked()
510 {
511  while ( mNoDataTableWidget->rowCount() > 0 )
512  {
513  mNoDataTableWidget->removeRow( 0 );
514  }
515 }
516 
517 void QgsRasterLayerSaveAsDialog::addNoDataRow( double min, double max )
518 {
519  mNoDataTableWidget->insertRow( mNoDataTableWidget->rowCount() );
520  for ( int i = 0; i < 2; i++ )
521  {
522  double value = i == 0 ? min : max;
523  QLineEdit *lineEdit = new QLineEdit();
524  lineEdit->setFrame( false );
525  lineEdit->setContentsMargins( 1, 1, 1, 1 );
526  QString valueString;
527  switch ( mRasterLayer->dataProvider()->sourceDataType( 1 ) )
528  {
529  case Qgis::Float32:
530  case Qgis::Float64:
531  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
532  if ( !std::isnan( value ) )
533  {
534  valueString = QgsRasterBlock::printValue( value );
535  }
536  break;
537  default:
538  lineEdit->setValidator( new QIntValidator( nullptr ) );
539  if ( !std::isnan( value ) )
540  {
541  valueString = QString::number( static_cast<int>( value ) );
542  }
543  break;
544  }
545  lineEdit->setText( valueString );
546  mNoDataTableWidget->setCellWidget( mNoDataTableWidget->rowCount() - 1, i, lineEdit );
547 
548  adjustNoDataCellWidth( mNoDataTableWidget->rowCount() - 1, i );
549 
550  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerSaveAsDialog::noDataCellTextEdited );
551  }
552  mNoDataTableWidget->resizeColumnsToContents();
553  mNoDataTableWidget->resizeRowsToContents();
554 }
555 
556 void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString &text )
557 {
558  Q_UNUSED( text );
559 
560  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( sender() );
561  if ( !lineEdit ) return;
562  int row = -1;
563  int column = -1;
564  for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
565  {
566  for ( int c = 0 ; c < mNoDataTableWidget->columnCount(); c++ )
567  {
568  if ( mNoDataTableWidget->cellWidget( r, c ) == sender() )
569  {
570  row = r;
571  column = c;
572  break;
573  }
574  }
575  if ( row != -1 ) break;
576  }
577  QgsDebugMsg( QString( "row = %1 column =%2" ).arg( row ).arg( column ) );
578 
579  if ( column == 0 )
580  {
581  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, 1 ) );
582  if ( !toLineEdit ) return;
583  bool toChanged = mNoDataToEdited.value( row );
584  QgsDebugMsg( QString( "toChanged = %1" ).arg( toChanged ) );
585  if ( !toChanged )
586  {
587  toLineEdit->setText( lineEdit->text() );
588  }
589  }
590  else if ( column == 1 )
591  {
592  setNoDataToEdited( row );
593  }
594 }
595 
596 void QgsRasterLayerSaveAsDialog::on_mTileModeCheckBox_toggled( bool toggled )
597 {
598  if ( toggled )
599  {
600  // enable pyramids
601 
602  // Disabled (Radim), auto enabling of pyramids was making impression that
603  // we (programmers) know better what you (user) want to do,
604  // certainly auto expaning was bad experience
605 
606  //if ( ! mPyramidsGroupBox->isChecked() )
607  // mPyramidsGroupBox->setChecked( true );
608 
609  // Auto expanding mPyramidsGroupBox is bad - it auto crolls content of dialog
610  //if ( mPyramidsGroupBox->isCollapsed() )
611  // mPyramidsGroupBox->setCollapsed( false );
612  //mPyramidsOptionsWidget->checkAllLevels( true );
613 
614  // Show / hide tile options
615  mTilesGroupBox->show();
616  }
617  else
618  {
619  mTilesGroupBox->hide();
620  }
621 }
622 
623 void QgsRasterLayerSaveAsDialog::on_mPyramidsGroupBox_toggled( bool toggled )
624 {
625  Q_UNUSED( toggled );
626  populatePyramidsLevels();
627 }
628 
629 void QgsRasterLayerSaveAsDialog::populatePyramidsLevels()
630 {
631  QString text;
632 
633  if ( mPyramidsGroupBox->isChecked() )
634  {
635  QList<QgsRasterPyramid> myPyramidList;
636  // if use existing, get pyramids from actual layer
637  // but that's not available yet
638  if ( mPyramidsUseExistingCheckBox->isChecked() )
639  {
640  myPyramidList = mDataProvider->buildPyramidList();
641  }
642  else
643  {
644  if ( ! mPyramidsOptionsWidget->overviewList().isEmpty() )
645  myPyramidList = mDataProvider->buildPyramidList( mPyramidsOptionsWidget->overviewList() );
646  }
647  QList<QgsRasterPyramid>::iterator myRasterPyramidIterator;
648  for ( myRasterPyramidIterator = myPyramidList.begin();
649  myRasterPyramidIterator != myPyramidList.end();
650  ++myRasterPyramidIterator )
651  {
652  if ( ! mPyramidsUseExistingCheckBox->isChecked() || myRasterPyramidIterator->exists )
653  {
654  text += QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( "x" ) +
655  QString::number( myRasterPyramidIterator->yDim ) + ' ';
656  }
657  }
658  }
659 
660  mPyramidResolutionsLineEdit->setText( text.trimmed() );
661 }
662 
663 void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
664 {
665  if ( row >= mNoDataToEdited.size() )
666  {
667  mNoDataToEdited.resize( row + 1 );
668  }
669  mNoDataToEdited[row] = true;
670 }
671 
672 double QgsRasterLayerSaveAsDialog::noDataCellValue( int row, int column ) const
673 {
674  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
675  if ( !lineEdit || lineEdit->text().isEmpty() )
676  {
677  std::numeric_limits<double>::quiet_NaN();
678  }
679  return lineEdit->text().toDouble();
680 }
681 
682 void QgsRasterLayerSaveAsDialog::adjustNoDataCellWidth( int row, int column )
683 {
684  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
685  if ( !lineEdit ) return;
686 
687  int width = std::max( lineEdit->fontMetrics().width( lineEdit->text() ) + 10, 100 );
688  width = std::max( width, mNoDataTableWidget->columnWidth( column ) );
689 
690  lineEdit->setFixedWidth( width );
691 }
692 
694 {
695  QgsRasterRangeList noDataList;
696  if ( ! mNoDataGroupBox->isChecked() )
697  return noDataList;
698 
699  int rows = mNoDataTableWidget->rowCount();
700  noDataList.reserve( rows );
701  for ( int r = 0 ; r < rows; r++ )
702  {
703  QgsRasterRange noData( noDataCellValue( r, 0 ), noDataCellValue( r, 1 ) );
704  noDataList.append( noData );
705 
706  }
707  return noDataList;
708 }
709 
711 {
712  return mPyramidsGroupBox->isChecked() ? mPyramidsOptionsWidget->overviewList() : QList<int>();
713 }
714 
716 {
717  if ( ! mPyramidsGroupBox->isChecked() )
719  else if ( mPyramidsUseExistingCheckBox->isChecked() )
721  else
723 }
724 
725 bool QgsRasterLayerSaveAsDialog::validate() const
726 {
727  if ( mCreateOptionsGroupBox->isChecked() )
728  {
729  QString message = mCreateOptionsWidget->validateOptions( true, false );
730  if ( !message.isNull() )
731  return false;
732  }
733  if ( mPyramidsGroupBox->isChecked() )
734  {
735  QString message = mPyramidsOptionsWidget->createOptionsWidget()->validateOptions( true, false );
736  if ( !message.isNull() )
737  return false;
738  }
739  return true;
740 }
741 
742 void QgsRasterLayerSaveAsDialog::showHelp()
743 {
744  QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#save-layer-from-an-existing-file" ) );
745 }
virtual QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual int bandCount() const =0
Get number of bands.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
static QString printValue(double value)
Print double value with all necessary significant digits.
QgsRaster::RasterBuildPyramids buildPyramidsFlag() const
void extentChanged(const QgsRectangle &r)
Emitted when the widget&#39;s extent is changed.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
double y
Definition: qgspointxy.h:47
A class to represent a 2D point.
Definition: qgspointxy.h:42
virtual int ySize() const
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Raster values range container.
QgsCoordinateReferenceSystem outputCrs()
QgsRasterRenderer * renderer() const
Thirty two bit floating point (float)
Definition: qgis.h:82
const QgsRasterTransparency * rasterTransparency() const
virtual QString name() const =0
Return a provider name.
Sixty four bit floating point (double)
Definition: qgis.h:83
virtual Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
QgsRasterDataProvider * dataProvider() override
virtual QList< QgsRasterPyramid > buildPyramidList(QList< int > overviewList=QList< int >())
Accessor for the raster layers pyramid list.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:123
double x
Definition: qgspointxy.h:46
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Accessor for transparentSingleValuePixelList.
QgsRasterLayerSaveAsDialog(QgsRasterLayer *rasterLayer, QgsRasterDataProvider *sourceProvider, const QgsRectangle &currentExtent, const QgsCoordinateReferenceSystem &layerCrs, const QgsCoordinateReferenceSystem &currentCrs, QWidget *parent=nullptr, Qt::WindowFlags f=0)
Transform from destination to source CRS.
QList< QgsRasterRange > QgsRasterRangeList
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const
Transform the point from the source CRS to the destination CRS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
This class represents a coordinate reference system (CRS).
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:34
Class for doing transforms between two map coordinate systems.
RasterBuildPyramids
Definition: qgsraster.h:73
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
QgsPointXY center() const
Returns the center point of the rectangle.
Definition: qgsrectangle.h:151
virtual int xSize() const
Get raster size.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:130
Base class for raster data providers.