QGIS API Documentation  2.99.0-Master (314842d)
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, SIGNAL( overviewListChanged() ),
111  this, SLOT( 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 http://hub.qgis.org/issues/14209 for discussion
129  mCrsSelector->setCrs( mLayerCrs );
130 
131  connect( mCrsSelector, SIGNAL( crsChanged( QgsCoordinateReferenceSystem ) ),
132  this, SLOT( crsChanged() ) );
133 
134  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
135  if ( okButton )
136  {
137  okButton->setEnabled( false );
138  }
139 
140  mExtentGroupBox->setOutputCrs( outputCrs() );
141  mExtentGroupBox->setOriginalExtent( mDataProvider->extent(), mLayerCrs );
142  mExtentGroupBox->setCurrentExtent( mCurrentExtent, mCurrentCrs );
143  mExtentGroupBox->setOutputExtentFromOriginal();
144  connect( mExtentGroupBox, SIGNAL( extentChanged( QgsRectangle ) ), this, SLOT( extentChanged() ) );
145 
146  recalcResolutionSize();
147 }
148 
149 void QgsRasterLayerSaveAsDialog::setValidators()
150 {
151  mXResolutionLineEdit->setValidator( new QDoubleValidator( this ) );
152  mYResolutionLineEdit->setValidator( new QDoubleValidator( this ) );
153  mColumnsLineEdit->setValidator( new QIntValidator( this ) );
154  mRowsLineEdit->setValidator( new QIntValidator( this ) );
155  mMaximumSizeXLineEdit->setValidator( new QIntValidator( this ) );
156  mMaximumSizeYLineEdit->setValidator( new QIntValidator( this ) );
157 }
158 
159 void QgsRasterLayerSaveAsDialog::on_mBrowseButton_clicked()
160 {
161  QString fileName;
162 
163  QgsSettings settings;
164  QString dirName = mSaveAsLineEdit->text().isEmpty() ? settings.value( QStringLiteral( "UI/lastRasterFileDir" ), QDir::homePath() ).toString() : mSaveAsLineEdit->text();
165 
166  if ( mTileModeCheckBox->isChecked() )
167  {
168  Q_FOREVER
169  {
170  // TODO: would not it be better to select .vrt file instead of directory?
171  fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ), dirName );
172  //fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "VRT" ) + " (*.vrt *.VRT)" );
173 
174  if ( fileName.isEmpty() )
175  break; // canceled
176 
177  // Check if directory is empty
178  QDir dir( fileName );
179  QString baseName = QFileInfo( fileName ).baseName();
180  QStringList filters;
181  filters << QStringLiteral( "%1.*" ).arg( baseName );
182  QStringList files = dir.entryList( filters );
183  if ( files.isEmpty() )
184  break;
185 
186  if ( QMessageBox::warning( this, tr( "Warning" ),
187  tr( "The directory %1 contains files which will be overwritten: %2" ).arg( dir.absolutePath(), files.join( QStringLiteral( ", " ) ) ),
188  QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Ok )
189  break;
190 
191  fileName = QLatin1String( "" );
192  }
193  }
194  else
195  {
196  fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), dirName, tr( "GeoTIFF" ) + " (*.tif *.tiff *.TIF *.TIFF)" );
197 
198  // ensure the user never omits the extension from the file name
199  if ( !fileName.isEmpty() && !fileName.endsWith( QLatin1String( ".tif" ), Qt::CaseInsensitive ) && !fileName.endsWith( QLatin1String( ".tiff" ), Qt::CaseInsensitive ) )
200  {
201  fileName += QLatin1String( ".tif" );
202  }
203  }
204 
205  if ( !fileName.isEmpty() )
206  {
207  mSaveAsLineEdit->setText( fileName );
208  }
209 }
210 
211 void QgsRasterLayerSaveAsDialog::on_mSaveAsLineEdit_textChanged( const QString &text )
212 {
213  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
214  if ( !okButton )
215  {
216  return;
217  }
218 
219  okButton->setEnabled( QFileInfo( text ).absoluteDir().exists() );
220 }
221 
222 
223 void QgsRasterLayerSaveAsDialog::on_mFormatComboBox_currentIndexChanged( const QString &text )
224 {
225  //gdal-specific
226  if ( mDataProvider && mDataProvider->name() == QLatin1String( "gdal" ) )
227  {
228  mCreateOptionsWidget->setFormat( text );
229  mCreateOptionsWidget->update();
230  }
231 }
232 
234 {
235  return mColumnsLineEdit->text().toInt();
236 }
237 
239 {
240  return mRowsLineEdit->text().toInt();
241 }
242 
244 {
245  return mXResolutionLineEdit->text().toDouble();
246 }
247 
249 {
250  return mYResolutionLineEdit->text().toDouble();
251 }
252 
254 {
255  return mMaximumSizeXLineEdit->text().toInt();
256 }
257 
259 {
260  return mMaximumSizeYLineEdit->text().toInt();
261 }
262 
264 {
265  return mTileModeCheckBox->isChecked();
266 }
267 
269 {
270  return mAddToCanvas->isChecked();
271 }
272 
274 {
275  return mSaveAsLineEdit->text();
276 }
277 
279 {
280  return mFormatComboBox->currentText();
281 }
282 
284 {
285  return mCreateOptionsGroupBox->isChecked() ? mCreateOptionsWidget->options() : QStringList();
286 }
287 
289 {
290  return mExtentGroupBox->outputExtent();
291 }
292 
294 {
295  mFormatLabel->hide();
296  mFormatComboBox->hide();
297 }
298 
300 {
301  mSaveAsLabel->hide();
302  mSaveAsLineEdit->hide();
303  mBrowseButton->hide();
304  QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok );
305  if ( okButton )
306  {
307  okButton->setEnabled( true );
308  }
309 }
310 
311 void QgsRasterLayerSaveAsDialog::toggleResolutionSize()
312 {
313  bool hasResolution = mDataProvider && mDataProvider->capabilities() & QgsRasterDataProvider::Size;
314 
315  bool on = mResolutionRadioButton->isChecked();
316  mXResolutionLineEdit->setEnabled( on );
317  mYResolutionLineEdit->setEnabled( on );
318  mOriginalResolutionPushButton->setEnabled( on && hasResolution );
319  mColumnsLineEdit->setEnabled( !on );
320  mRowsLineEdit->setEnabled( !on );
321  mOriginalSizePushButton->setEnabled( !on && hasResolution );
322 }
323 
324 void QgsRasterLayerSaveAsDialog::setOriginalResolution()
325 {
326  double xRes, yRes;
327 
328  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Size )
329  {
330  xRes = mDataProvider->extent().width() / mDataProvider->xSize();
331  yRes = mDataProvider->extent().height() / mDataProvider->ySize();
332  }
333  else
334  {
335  // Init to something if no original resolution is available
336  xRes = yRes = mDataProvider->extent().width() / 100;
337  }
338  setResolution( xRes, yRes, mLayerCrs );
339  mResolutionState = OriginalResolution;
340  recalcSize();
341 }
342 
343 void QgsRasterLayerSaveAsDialog::setResolution( double xRes, double yRes, const QgsCoordinateReferenceSystem &srcCrs )
344 {
345  if ( srcCrs != outputCrs() )
346  {
347  // We reproject pixel rectangle from center of selected extent, of course, it gives
348  // bigger xRes,yRes than reprojected edges (envelope), it may also be that
349  // close to margins are higher resolutions (even very, too high)
350  // TODO: consider more precise resolution calculation
351 
352  QgsPoint center = outputRectangle().center();
353  QgsCoordinateTransform ct( srcCrs, outputCrs() );
355 
356  QgsRectangle srcExtent( srsCenter.x() - xRes / 2, srsCenter.y() - yRes / 2, srsCenter.x() + xRes / 2, srsCenter.y() + yRes / 2 );
357 
358  QgsRectangle extent = ct.transform( srcExtent );
359  xRes = extent.width();
360  yRes = extent.height();
361  }
362  mXResolutionLineEdit->setText( QString::number( xRes ) );
363  mYResolutionLineEdit->setText( QString::number( yRes ) );
364 }
365 
366 void QgsRasterLayerSaveAsDialog::recalcSize()
367 {
368  QgsRectangle extent = outputRectangle();
369  int xSize = xResolution() != 0 ? static_cast<int>( qRound( extent.width() / xResolution() ) ) : 0;
370  int ySize = yResolution() != 0 ? static_cast<int>( qRound( extent.height() / yResolution() ) ) : 0;
371  mColumnsLineEdit->setText( QString::number( xSize ) );
372  mRowsLineEdit->setText( QString::number( ySize ) );
373  updateResolutionStateMsg();
374 }
375 
376 void QgsRasterLayerSaveAsDialog::setOriginalSize()
377 {
378  mColumnsLineEdit->setText( QString::number( mDataProvider->xSize() ) );
379  mRowsLineEdit->setText( QString::number( mDataProvider->ySize() ) );
380  recalcResolution();
381 }
382 
383 void QgsRasterLayerSaveAsDialog::recalcResolution()
384 {
385  QgsRectangle extent = outputRectangle();
386  double xRes = nColumns() != 0 ? extent.width() / nColumns() : 0;
387  double yRes = nRows() != 0 ? extent.height() / nRows() : 0;
388  mXResolutionLineEdit->setText( QString::number( xRes ) );
389  mYResolutionLineEdit->setText( QString::number( yRes ) );
390  updateResolutionStateMsg();
391 }
392 
393 void QgsRasterLayerSaveAsDialog::recalcResolutionSize()
394 {
395  if ( mResolutionRadioButton->isChecked() )
396  {
397  recalcSize();
398  }
399  else
400  {
401  mResolutionState = UserResolution;
402  recalcResolution();
403  }
404 }
405 
406 void QgsRasterLayerSaveAsDialog::updateResolutionStateMsg()
407 {
408  QString msg;
409  switch ( mResolutionState )
410  {
411  case OriginalResolution:
412  msg = tr( "layer" );
413  break;
414  case UserResolution:
415  msg = tr( "user defined" );
416  break;
417  default:
418  break;
419  }
420  msg = tr( "Resolution (current: %1)" ).arg( msg );
421  mResolutionGroupBox->setTitle( msg );
422 }
423 
424 void QgsRasterLayerSaveAsDialog::extentChanged()
425 {
426  // Whenever extent changes with fixed size, original resolution is lost
427  if ( mSizeRadioButton->isChecked() )
428  {
429  mResolutionState = UserResolution;
430  }
431  recalcResolutionSize();
432 }
433 
434 void QgsRasterLayerSaveAsDialog::crsChanged()
435 {
436  if ( outputCrs() != mPreviousCrs )
437  {
438  mExtentGroupBox->setOutputCrs( outputCrs() );
439  QgsExtentGroupBox::ExtentState state = mExtentGroupBox->extentState();
440 
441  // Reset extent
442  // We could reproject previous but that would add additional space also if
443  // it is was not necessary or at leas it could decrease accuracy
444  if ( state == QgsExtentGroupBox::OriginalExtent )
445  {
446  mExtentGroupBox->setOutputExtentFromOriginal();
447  }
448  else if ( state == QgsExtentGroupBox::CurrentExtent )
449  {
450  mExtentGroupBox->setOutputExtentFromCurrent();
451  }
452  else
453  {
454  mExtentGroupBox->setOutputExtentFromUser( mExtentGroupBox->outputExtent(), mPreviousCrs );
455  }
456 
457  // Reset resolution
458  if ( mResolutionRadioButton->isChecked() )
459  {
460  if ( mResolutionState == OriginalResolution )
461  {
462  setOriginalResolution();
463  }
464  else
465  {
466  // reset from present resolution and present crs
467  setResolution( xResolution(), yResolution(), mPreviousCrs );
468  }
469  }
470  else
471  {
472  // Size does not change, we just recalc resolution from new extent
473  recalcResolution();
474  }
475  }
476  mPreviousCrs = outputCrs();
477 }
478 
480 {
481  return mCrsSelector->crs();
482 }
483 
485 {
486  if ( mRenderedModeRadioButton->isChecked() ) return RenderedImageMode;
487  return RawDataMode;
488 }
489 
490 void QgsRasterLayerSaveAsDialog::on_mRawModeRadioButton_toggled( bool checked )
491 {
492  mNoDataGroupBox->setEnabled( checked && mDataProvider->bandCount() == 1 );
493 }
494 
495 void QgsRasterLayerSaveAsDialog::on_mAddNoDataManuallyToolButton_clicked()
496 {
497  addNoDataRow( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
498 }
499 
500 void QgsRasterLayerSaveAsDialog::on_mLoadTransparentNoDataToolButton_clicked()
501 {
502  if ( !mRasterLayer->renderer() ) return;
503  const QgsRasterTransparency *rasterTransparency = mRasterLayer->renderer()->rasterTransparency();
504  if ( !rasterTransparency ) return;
505 
506  Q_FOREACH ( const QgsRasterTransparency::TransparentSingleValuePixel &transparencyPixel, rasterTransparency->transparentSingleValuePixelList() )
507  {
508  if ( transparencyPixel.percentTransparent == 100 )
509  {
510  addNoDataRow( transparencyPixel.min, transparencyPixel.max );
511  if ( transparencyPixel.min != transparencyPixel.max )
512  {
513  setNoDataToEdited( mNoDataTableWidget->rowCount() - 1 );
514  }
515  }
516  }
517 }
518 
519 void QgsRasterLayerSaveAsDialog::on_mRemoveSelectedNoDataToolButton_clicked()
520 {
521  mNoDataTableWidget->removeRow( mNoDataTableWidget->currentRow() );
522 }
523 
524 void QgsRasterLayerSaveAsDialog::on_mRemoveAllNoDataToolButton_clicked()
525 {
526  while ( mNoDataTableWidget->rowCount() > 0 )
527  {
528  mNoDataTableWidget->removeRow( 0 );
529  }
530 }
531 
532 void QgsRasterLayerSaveAsDialog::addNoDataRow( double min, double max )
533 {
534  mNoDataTableWidget->insertRow( mNoDataTableWidget->rowCount() );
535  for ( int i = 0; i < 2; i++ )
536  {
537  double value = i == 0 ? min : max;
538  QLineEdit *lineEdit = new QLineEdit();
539  lineEdit->setFrame( false );
540  lineEdit->setContentsMargins( 1, 1, 1, 1 );
541  QString valueString;
542  switch ( mRasterLayer->dataProvider()->sourceDataType( 1 ) )
543  {
544  case Qgis::Float32:
545  case Qgis::Float64:
546  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
547  if ( !qIsNaN( value ) )
548  {
549  valueString = QgsRasterBlock::printValue( value );
550  }
551  break;
552  default:
553  lineEdit->setValidator( new QIntValidator( nullptr ) );
554  if ( !qIsNaN( value ) )
555  {
556  valueString = QString::number( static_cast<int>( value ) );
557  }
558  break;
559  }
560  lineEdit->setText( valueString );
561  mNoDataTableWidget->setCellWidget( mNoDataTableWidget->rowCount() - 1, i, lineEdit );
562 
563  adjustNoDataCellWidth( mNoDataTableWidget->rowCount() - 1, i );
564 
565  connect( lineEdit, SIGNAL( textEdited( const QString & ) ), this, SLOT( noDataCellTextEdited( const QString & ) ) );
566  }
567  mNoDataTableWidget->resizeColumnsToContents();
568  mNoDataTableWidget->resizeRowsToContents();
569 }
570 
571 void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString &text )
572 {
573  Q_UNUSED( text );
574 
575  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( sender() );
576  if ( !lineEdit ) return;
577  int row = -1;
578  int column = -1;
579  for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
580  {
581  for ( int c = 0 ; c < mNoDataTableWidget->columnCount(); c++ )
582  {
583  if ( mNoDataTableWidget->cellWidget( r, c ) == sender() )
584  {
585  row = r;
586  column = c;
587  break;
588  }
589  }
590  if ( row != -1 ) break;
591  }
592  QgsDebugMsg( QString( "row = %1 column =%2" ).arg( row ).arg( column ) );
593 
594  if ( column == 0 )
595  {
596  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, 1 ) );
597  if ( !toLineEdit ) return;
598  bool toChanged = mNoDataToEdited.value( row );
599  QgsDebugMsg( QString( "toChanged = %1" ).arg( toChanged ) );
600  if ( !toChanged )
601  {
602  toLineEdit->setText( lineEdit->text() );
603  }
604  }
605  else if ( column == 1 )
606  {
607  setNoDataToEdited( row );
608  }
609 }
610 
611 void QgsRasterLayerSaveAsDialog::on_mTileModeCheckBox_toggled( bool toggled )
612 {
613  if ( toggled )
614  {
615  // enable pyramids
616 
617  // Disabled (Radim), auto enabling of pyramids was making impression that
618  // we (programmers) know better what you (user) want to do,
619  // certainly auto expaning was bad experience
620 
621  //if ( ! mPyramidsGroupBox->isChecked() )
622  // mPyramidsGroupBox->setChecked( true );
623 
624  // Auto expanding mPyramidsGroupBox is bad - it auto crolls content of dialog
625  //if ( mPyramidsGroupBox->isCollapsed() )
626  // mPyramidsGroupBox->setCollapsed( false );
627  //mPyramidsOptionsWidget->checkAllLevels( true );
628 
629  // Show / hide tile options
630  mTilesGroupBox->show();
631  }
632  else
633  {
634  mTilesGroupBox->hide();
635  }
636 }
637 
638 void QgsRasterLayerSaveAsDialog::on_mPyramidsGroupBox_toggled( bool toggled )
639 {
640  Q_UNUSED( toggled );
641  populatePyramidsLevels();
642 }
643 
644 void QgsRasterLayerSaveAsDialog::populatePyramidsLevels()
645 {
646  QString text;
647 
648  if ( mPyramidsGroupBox->isChecked() )
649  {
650  QList<QgsRasterPyramid> myPyramidList;
651  // if use existing, get pyramids from actual layer
652  // but that's not available yet
653  if ( mPyramidsUseExistingCheckBox->isChecked() )
654  {
655  myPyramidList = mDataProvider->buildPyramidList();
656  }
657  else
658  {
659  if ( ! mPyramidsOptionsWidget->overviewList().isEmpty() )
660  myPyramidList = mDataProvider->buildPyramidList( mPyramidsOptionsWidget->overviewList() );
661  }
662  QList<QgsRasterPyramid>::iterator myRasterPyramidIterator;
663  for ( myRasterPyramidIterator = myPyramidList.begin();
664  myRasterPyramidIterator != myPyramidList.end();
665  ++myRasterPyramidIterator )
666  {
667  if ( ! mPyramidsUseExistingCheckBox->isChecked() || myRasterPyramidIterator->exists )
668  {
669  text += QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( "x" ) +
670  QString::number( myRasterPyramidIterator->yDim ) + ' ';
671  }
672  }
673  }
674 
675  mPyramidResolutionsLineEdit->setText( text.trimmed() );
676 }
677 
678 void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
679 {
680  if ( row >= mNoDataToEdited.size() )
681  {
682  mNoDataToEdited.resize( row + 1 );
683  }
684  mNoDataToEdited[row] = true;
685 }
686 
687 double QgsRasterLayerSaveAsDialog::noDataCellValue( int row, int column ) const
688 {
689  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
690  if ( !lineEdit || lineEdit->text().isEmpty() )
691  {
692  std::numeric_limits<double>::quiet_NaN();
693  }
694  return lineEdit->text().toDouble();
695 }
696 
697 void QgsRasterLayerSaveAsDialog::adjustNoDataCellWidth( int row, int column )
698 {
699  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
700  if ( !lineEdit ) return;
701 
702  int width = qMax( lineEdit->fontMetrics().width( lineEdit->text() ) + 10, 100 );
703  width = qMax( width, mNoDataTableWidget->columnWidth( column ) );
704 
705  lineEdit->setFixedWidth( width );
706 }
707 
709 {
710  QgsRasterRangeList noDataList;
711  if ( ! mNoDataGroupBox->isChecked() )
712  return noDataList;
713 
714  int rows = mNoDataTableWidget->rowCount();
715  noDataList.reserve( rows );
716  for ( int r = 0 ; r < rows; r++ )
717  {
718  QgsRasterRange noData( noDataCellValue( r, 0 ), noDataCellValue( r, 1 ) );
719  noDataList.append( noData );
720 
721  }
722  return noDataList;
723 }
724 
726 {
727  return mPyramidsGroupBox->isChecked() ? mPyramidsOptionsWidget->overviewList() : QList<int>();
728 }
729 
731 {
732  if ( ! mPyramidsGroupBox->isChecked() )
734  else if ( mPyramidsUseExistingCheckBox->isChecked() )
736  else
738 }
739 
740 bool QgsRasterLayerSaveAsDialog::validate() const
741 {
742  if ( mCreateOptionsGroupBox->isChecked() )
743  {
744  QString message = mCreateOptionsWidget->validateOptions( true, false );
745  if ( !message.isNull() )
746  return false;
747  }
748  if ( mPyramidsGroupBox->isChecked() )
749  {
750  QString message = mPyramidsOptionsWidget->createOptionsWidget()->validateOptions( true, false );
751  if ( !message.isNull() )
752  return false;
753  }
754  return true;
755 }
756 
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:36
double y
Definition: qgspoint.h:42
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:225
static QString printValue(double value)
Print double value with all necessary significant digits.
QgsRaster::RasterBuildPyramids buildPyramidsFlag() const
This class is a composition of two QSettings instances:
Definition: qgssettings.h:51
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
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:69
const QgsRasterTransparency * rasterTransparency() const
virtual QString name() const =0
Return a provider name.
Sixty four bit floating point (double)
Definition: qgis.h:70
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...
QgsPoint transform(const QgsPoint &point, TransformDirection direction=ForwardTransform) const
Transform the point from the source CRS to the destination CRS.
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
Width of the rectangle.
Definition: qgsrectangle.h:215
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:452
A class to represent a point.
Definition: qgspoint.h:37
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
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
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=Section::NoSection) const
Returns the value for setting key.
RasterBuildPyramids
Definition: qgsraster.h:89
QgsRasterDataProvider * dataProvider()
Returns the data provider.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
virtual int xSize() const
Get raster size.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:220
Base class for raster data providers.
double x
Definition: qgspoint.h:41