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