QGIS API Documentation  2.99.0-Master (dcec6bb)
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  mExtentGroupBox->setOutputCrs( outputCrs() );
141  mExtentGroupBox->setOriginalExtent( mDataProvider->extent(), mLayerCrs );
142  mExtentGroupBox->setCurrentExtent( mCurrentExtent, mCurrentCrs );
143  mExtentGroupBox->setOutputExtentFromOriginal();
144  connect( mExtentGroupBox, &QgsExtentGroupBox::extentChanged, this, &QgsRasterLayerSaveAsDialog::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  QgsPointXY 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 
440  // Reset resolution
441  if ( mResolutionRadioButton->isChecked() )
442  {
443  if ( mResolutionState == OriginalResolution )
444  {
445  setOriginalResolution();
446  }
447  else
448  {
449  // reset from present resolution and present crs
450  setResolution( xResolution(), yResolution(), mPreviousCrs );
451  }
452  }
453  else
454  {
455  // Size does not change, we just recalc resolution from new extent
456  recalcResolution();
457  }
458  }
459  mPreviousCrs = outputCrs();
460 }
461 
463 {
464  return mCrsSelector->crs();
465 }
466 
468 {
469  if ( mRenderedModeRadioButton->isChecked() ) return RenderedImageMode;
470  return RawDataMode;
471 }
472 
473 void QgsRasterLayerSaveAsDialog::on_mRawModeRadioButton_toggled( bool checked )
474 {
475  mNoDataGroupBox->setEnabled( checked && mDataProvider->bandCount() == 1 );
476 }
477 
478 void QgsRasterLayerSaveAsDialog::on_mAddNoDataManuallyToolButton_clicked()
479 {
480  addNoDataRow( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
481 }
482 
483 void QgsRasterLayerSaveAsDialog::on_mLoadTransparentNoDataToolButton_clicked()
484 {
485  if ( !mRasterLayer->renderer() ) return;
486  const QgsRasterTransparency *rasterTransparency = mRasterLayer->renderer()->rasterTransparency();
487  if ( !rasterTransparency ) return;
488 
489  Q_FOREACH ( const QgsRasterTransparency::TransparentSingleValuePixel &transparencyPixel, rasterTransparency->transparentSingleValuePixelList() )
490  {
491  if ( transparencyPixel.percentTransparent == 100 )
492  {
493  addNoDataRow( transparencyPixel.min, transparencyPixel.max );
494  if ( transparencyPixel.min != transparencyPixel.max )
495  {
496  setNoDataToEdited( mNoDataTableWidget->rowCount() - 1 );
497  }
498  }
499  }
500 }
501 
502 void QgsRasterLayerSaveAsDialog::on_mRemoveSelectedNoDataToolButton_clicked()
503 {
504  mNoDataTableWidget->removeRow( mNoDataTableWidget->currentRow() );
505 }
506 
507 void QgsRasterLayerSaveAsDialog::on_mRemoveAllNoDataToolButton_clicked()
508 {
509  while ( mNoDataTableWidget->rowCount() > 0 )
510  {
511  mNoDataTableWidget->removeRow( 0 );
512  }
513 }
514 
515 void QgsRasterLayerSaveAsDialog::addNoDataRow( double min, double max )
516 {
517  mNoDataTableWidget->insertRow( mNoDataTableWidget->rowCount() );
518  for ( int i = 0; i < 2; i++ )
519  {
520  double value = i == 0 ? min : max;
521  QLineEdit *lineEdit = new QLineEdit();
522  lineEdit->setFrame( false );
523  lineEdit->setContentsMargins( 1, 1, 1, 1 );
524  QString valueString;
525  switch ( mRasterLayer->dataProvider()->sourceDataType( 1 ) )
526  {
527  case Qgis::Float32:
528  case Qgis::Float64:
529  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
530  if ( !qIsNaN( value ) )
531  {
532  valueString = QgsRasterBlock::printValue( value );
533  }
534  break;
535  default:
536  lineEdit->setValidator( new QIntValidator( nullptr ) );
537  if ( !qIsNaN( value ) )
538  {
539  valueString = QString::number( static_cast<int>( value ) );
540  }
541  break;
542  }
543  lineEdit->setText( valueString );
544  mNoDataTableWidget->setCellWidget( mNoDataTableWidget->rowCount() - 1, i, lineEdit );
545 
546  adjustNoDataCellWidth( mNoDataTableWidget->rowCount() - 1, i );
547 
548  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerSaveAsDialog::noDataCellTextEdited );
549  }
550  mNoDataTableWidget->resizeColumnsToContents();
551  mNoDataTableWidget->resizeRowsToContents();
552 }
553 
554 void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString &text )
555 {
556  Q_UNUSED( text );
557 
558  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( sender() );
559  if ( !lineEdit ) return;
560  int row = -1;
561  int column = -1;
562  for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
563  {
564  for ( int c = 0 ; c < mNoDataTableWidget->columnCount(); c++ )
565  {
566  if ( mNoDataTableWidget->cellWidget( r, c ) == sender() )
567  {
568  row = r;
569  column = c;
570  break;
571  }
572  }
573  if ( row != -1 ) break;
574  }
575  QgsDebugMsg( QString( "row = %1 column =%2" ).arg( row ).arg( column ) );
576 
577  if ( column == 0 )
578  {
579  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, 1 ) );
580  if ( !toLineEdit ) return;
581  bool toChanged = mNoDataToEdited.value( row );
582  QgsDebugMsg( QString( "toChanged = %1" ).arg( toChanged ) );
583  if ( !toChanged )
584  {
585  toLineEdit->setText( lineEdit->text() );
586  }
587  }
588  else if ( column == 1 )
589  {
590  setNoDataToEdited( row );
591  }
592 }
593 
594 void QgsRasterLayerSaveAsDialog::on_mTileModeCheckBox_toggled( bool toggled )
595 {
596  if ( toggled )
597  {
598  // enable pyramids
599 
600  // Disabled (Radim), auto enabling of pyramids was making impression that
601  // we (programmers) know better what you (user) want to do,
602  // certainly auto expaning was bad experience
603 
604  //if ( ! mPyramidsGroupBox->isChecked() )
605  // mPyramidsGroupBox->setChecked( true );
606 
607  // Auto expanding mPyramidsGroupBox is bad - it auto crolls content of dialog
608  //if ( mPyramidsGroupBox->isCollapsed() )
609  // mPyramidsGroupBox->setCollapsed( false );
610  //mPyramidsOptionsWidget->checkAllLevels( true );
611 
612  // Show / hide tile options
613  mTilesGroupBox->show();
614  }
615  else
616  {
617  mTilesGroupBox->hide();
618  }
619 }
620 
621 void QgsRasterLayerSaveAsDialog::on_mPyramidsGroupBox_toggled( bool toggled )
622 {
623  Q_UNUSED( toggled );
624  populatePyramidsLevels();
625 }
626 
627 void QgsRasterLayerSaveAsDialog::populatePyramidsLevels()
628 {
629  QString text;
630 
631  if ( mPyramidsGroupBox->isChecked() )
632  {
633  QList<QgsRasterPyramid> myPyramidList;
634  // if use existing, get pyramids from actual layer
635  // but that's not available yet
636  if ( mPyramidsUseExistingCheckBox->isChecked() )
637  {
638  myPyramidList = mDataProvider->buildPyramidList();
639  }
640  else
641  {
642  if ( ! mPyramidsOptionsWidget->overviewList().isEmpty() )
643  myPyramidList = mDataProvider->buildPyramidList( mPyramidsOptionsWidget->overviewList() );
644  }
645  QList<QgsRasterPyramid>::iterator myRasterPyramidIterator;
646  for ( myRasterPyramidIterator = myPyramidList.begin();
647  myRasterPyramidIterator != myPyramidList.end();
648  ++myRasterPyramidIterator )
649  {
650  if ( ! mPyramidsUseExistingCheckBox->isChecked() || myRasterPyramidIterator->exists )
651  {
652  text += QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( "x" ) +
653  QString::number( myRasterPyramidIterator->yDim ) + ' ';
654  }
655  }
656  }
657 
658  mPyramidResolutionsLineEdit->setText( text.trimmed() );
659 }
660 
661 void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
662 {
663  if ( row >= mNoDataToEdited.size() )
664  {
665  mNoDataToEdited.resize( row + 1 );
666  }
667  mNoDataToEdited[row] = true;
668 }
669 
670 double QgsRasterLayerSaveAsDialog::noDataCellValue( int row, int column ) const
671 {
672  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
673  if ( !lineEdit || lineEdit->text().isEmpty() )
674  {
675  std::numeric_limits<double>::quiet_NaN();
676  }
677  return lineEdit->text().toDouble();
678 }
679 
680 void QgsRasterLayerSaveAsDialog::adjustNoDataCellWidth( int row, int column )
681 {
682  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
683  if ( !lineEdit ) return;
684 
685  int width = qMax( lineEdit->fontMetrics().width( lineEdit->text() ) + 10, 100 );
686  width = qMax( width, mNoDataTableWidget->columnWidth( column ) );
687 
688  lineEdit->setFixedWidth( width );
689 }
690 
692 {
693  QgsRasterRangeList noDataList;
694  if ( ! mNoDataGroupBox->isChecked() )
695  return noDataList;
696 
697  int rows = mNoDataTableWidget->rowCount();
698  noDataList.reserve( rows );
699  for ( int r = 0 ; r < rows; r++ )
700  {
701  QgsRasterRange noData( noDataCellValue( r, 0 ), noDataCellValue( r, 1 ) );
702  noDataList.append( noData );
703 
704  }
705  return noDataList;
706 }
707 
709 {
710  return mPyramidsGroupBox->isChecked() ? mPyramidsOptionsWidget->overviewList() : QList<int>();
711 }
712 
714 {
715  if ( ! mPyramidsGroupBox->isChecked() )
717  else if ( mPyramidsUseExistingCheckBox->isChecked() )
719  else
721 }
722 
723 bool QgsRasterLayerSaveAsDialog::validate() const
724 {
725  if ( mCreateOptionsGroupBox->isChecked() )
726  {
727  QString message = mCreateOptionsWidget->validateOptions( true, false );
728  if ( !message.isNull() )
729  return false;
730  }
731  if ( mPyramidsGroupBox->isChecked() )
732  {
733  QString message = mPyramidsOptionsWidget->createOptionsWidget()->validateOptions( true, false );
734  if ( !message.isNull() )
735  return false;
736  }
737  return true;
738 }
739 
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:118
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
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
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).
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:146
virtual int xSize() const
Get raster size.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
Base class for raster data providers.