QGIS API Documentation  3.12.1-București (121cc00ff0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsrasterlayerproperties.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterlayerproperties.cpp - description
3  -------------------
4  begin : 1/1/2004
5  copyright : (C) 2004 Tim Sutton
6  email : tim@linfiniti.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <limits>
19 #include <typeinfo>
20 
21 #include "qgsgui.h"
22 #include "qgsapplication.h"
25 #include "qgscontrastenhancement.h"
26 #include "qgscoordinatetransform.h"
29 #include "qgslogger.h"
30 #include "qgsmapcanvas.h"
32 #include "qgsmaptoolemitpoint.h"
33 #include "qgsmaptopixel.h"
34 #include "qgsmetadatawidget.h"
37 #include "qgsnative.h"
39 #include "qgsproject.h"
40 #include "qgsrasterbandstats.h"
41 #include "qgsrasterdataprovider.h"
44 #include "qgsrasterlayer.h"
46 #include "qgsrasterpyramid.h"
47 #include "qgsrasterrange.h"
48 #include "qgsrasterrenderer.h"
51 #include "qgsrastertransparency.h"
54 #include "qgshuesaturationfilter.h"
56 #include "qgssettings.h"
58 #include "qgsmaplayerlegend.h"
59 #include "qgsfileutils.h"
60 #include "qgswebview.h"
61 
62 #include <QDesktopServices>
63 #include <QTableWidgetItem>
64 #include <QHeaderView>
65 #include <QTextStream>
66 #include <QFile>
67 #include <QFileDialog>
68 #include <QMessageBox>
69 #include <QPainter>
70 #include <QLinearGradient>
71 #include <QPainterPath>
72 #include <QPolygonF>
73 #include <QColorDialog>
74 #include <QList>
75 #include <QMouseEvent>
76 #include <QVector>
77 #include <QUrl>
78 #include <QMenu>
79 #include <QScreen>
80 
81 QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags fl )
82  : QgsOptionsDialogBase( QStringLiteral( "RasterLayerProperties" ), parent, fl )
83  // Constant that signals property not used.
84  , TRSTRING_NOT_SET( tr( "Not Set" ) )
85  , mDefaultStandardDeviation( 0 )
86  , mDefaultRedBand( 0 )
87  , mDefaultGreenBand( 0 )
88  , mDefaultBlueBand( 0 )
89  , mRasterLayer( qobject_cast<QgsRasterLayer *>( lyr ) )
90  , mGradientHeight( 0.0 )
91  , mGradientWidth( 0.0 )
92  , mMapCanvas( canvas )
93  , mMetadataFilled( false )
94 {
95  mGrayMinimumMaximumEstimated = true;
96  mRGBMinimumMaximumEstimated = true;
97 
98  setupUi( this );
99  connect( mLayerOrigNameLineEd, &QLineEdit::textEdited, this, &QgsRasterLayerProperties::mLayerOrigNameLineEd_textEdited );
100  connect( buttonBuildPyramids, &QPushButton::clicked, this, &QgsRasterLayerProperties::buttonBuildPyramids_clicked );
101  connect( pbnAddValuesFromDisplay, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnAddValuesFromDisplay_clicked );
102  connect( pbnAddValuesManually, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnAddValuesManually_clicked );
103  connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsRasterLayerProperties::mCrsSelector_crsChanged );
104  connect( pbnDefaultValues, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnDefaultValues_clicked );
105  connect( pbnExportTransparentPixelValues, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnExportTransparentPixelValues_clicked );
106  connect( pbnImportTransparentPixelValues, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnImportTransparentPixelValues_clicked );
107  connect( pbnRemoveSelectedRow, &QToolButton::clicked, this, &QgsRasterLayerProperties::pbnRemoveSelectedRow_clicked );
108  connect( mRenderTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged );
109  connect( mResetColorRenderingBtn, &QToolButton::clicked, this, &QgsRasterLayerProperties::mResetColorRenderingBtn_clicked );
110  // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
111  // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
112  // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
113  initOptionsBase( false );
114  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsRasterLayerProperties::showHelp );
115 
116  mBtnStyle = new QPushButton( tr( "Style" ) );
117  QMenu *menuStyle = new QMenu( this );
118  menuStyle->addAction( tr( "Load Style…" ), this, &QgsRasterLayerProperties::loadStyle_clicked );
119  menuStyle->addAction( tr( "Save Style…" ), this, &QgsRasterLayerProperties::saveStyleAs_clicked );
120  menuStyle->addSeparator();
121  menuStyle->addAction( tr( "Save as Default" ), this, &QgsRasterLayerProperties::saveDefaultStyle_clicked );
122  menuStyle->addAction( tr( "Restore Default" ), this, &QgsRasterLayerProperties::loadDefaultStyle_clicked );
123  mBtnStyle->setMenu( menuStyle );
124  connect( menuStyle, &QMenu::aboutToShow, this, &QgsRasterLayerProperties::aboutToShowStyleMenu );
125  buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
126 
127  mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
128  QMenu *menuMetadata = new QMenu( this );
129  mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsRasterLayerProperties::loadMetadata );
130  mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsRasterLayerProperties::saveMetadataAs );
131  menuMetadata->addSeparator();
132  menuMetadata->addAction( tr( "Save as Default" ), this, &QgsRasterLayerProperties::saveDefaultMetadata );
133  menuMetadata->addAction( tr( "Restore Default" ), this, &QgsRasterLayerProperties::loadDefaultMetadata );
134  mBtnMetadata->setMenu( menuMetadata );
135  buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
136 
137  connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsRasterLayerProperties::syncToLayer );
138 
139  connect( this, &QDialog::accepted, this, &QgsRasterLayerProperties::apply );
140  connect( this, &QDialog::rejected, this, &QgsRasterLayerProperties::onCancel );
141 
142  connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsRasterLayerProperties::apply );
143 
144  // brightness/contrast controls
145  connect( mSliderBrightness, &QAbstractSlider::valueChanged, mBrightnessSpinBox, &QSpinBox::setValue );
146  connect( mBrightnessSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mSliderBrightness, &QAbstractSlider::setValue );
147 
148  connect( mSliderContrast, &QAbstractSlider::valueChanged, mContrastSpinBox, &QSpinBox::setValue );
149  connect( mContrastSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mSliderContrast, &QAbstractSlider::setValue );
150 
151  // Connect saturation slider and spin box
152  connect( sliderSaturation, &QAbstractSlider::valueChanged, spinBoxSaturation, &QSpinBox::setValue );
153  connect( spinBoxSaturation, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), sliderSaturation, &QAbstractSlider::setValue );
154 
155  // Connect colorize strength slider and spin box
156  connect( sliderColorizeStrength, &QAbstractSlider::valueChanged, spinColorizeStrength, &QSpinBox::setValue );
157  connect( spinColorizeStrength, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), sliderColorizeStrength, &QAbstractSlider::setValue );
158 
159  // enable or disable saturation slider and spin box depending on grayscale combo choice
160  connect( comboGrayscale, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterLayerProperties::toggleSaturationControls );
161 
162  // enable or disable colorize colorbutton with colorize checkbox
163  connect( mColorizeCheck, &QAbstractButton::toggled, this, &QgsRasterLayerProperties::toggleColorizeControls );
164 
165  // enable or disable Build Pyramids button depending on selection in pyramid list
166  connect( lbxPyramidResolutions, &QListWidget::itemSelectionChanged, this, &QgsRasterLayerProperties::toggleBuildPyramidsButton );
167 
168  connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );
169 
170  // set up the scale based layer visibility stuff....
171  mScaleRangeWidget->setMapCanvas( mMapCanvas );
172  chkUseScaleDependentRendering->setChecked( lyr->hasScaleBasedVisibility() );
173  mScaleRangeWidget->setScaleRange( lyr->minimumScale(), lyr->maximumScale() );
174 
175  leNoDataValue->setValidator( new QDoubleValidator( -std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), 1000, this ) );
176 
177  // build GUI components
178  QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
179  QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
180 
181  pbnAddValuesManually->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
182  pbnAddValuesFromDisplay->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionContextHelp.png" ) ) );
183  pbnRemoveSelectedRow->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyRemove.svg" ) ) );
184  pbnDefaultValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) );
185  pbnImportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
186  pbnExportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileSave.svg" ) ) );
187 
188  if ( mMapCanvas )
189  {
190  mPixelSelectorTool = qgis::make_unique<QgsMapToolEmitPoint>( canvas );
191  connect( mPixelSelectorTool.get(), &QgsMapToolEmitPoint::canvasClicked, this, &QgsRasterLayerProperties::pixelSelected );
192  connect( mPixelSelectorTool.get(), &QgsMapToolEmitPoint::deactivated, this, &QgsRasterLayerProperties::restoreWindowModality );
193  }
194  else
195  {
196  pbnAddValuesFromDisplay->setEnabled( false );
197  }
198 
199  if ( !mRasterLayer )
200  {
201  return;
202  }
203 
204  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
205 
206  // Only do pyramids if dealing directly with GDAL.
207  if ( provider && provider->capabilities() & QgsRasterDataProvider::BuildPyramids )
208  {
209  // initialize resampling methods
210  cboResamplingMethod->clear();
211 
212  const auto constProviderType = QgsRasterDataProvider::pyramidResamplingMethods( mRasterLayer->providerType() );
213  for ( QPair<QString, QString> method : constProviderType )
214  {
215  cboResamplingMethod->addItem( method.second, method.first );
216  }
217 
218  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
219  QString prefix = provider->name() + "/driverOptions/_pyramids/";
220  QgsSettings mySettings;
221  QString defaultMethod = mySettings.value( prefix + "resampling", "AVERAGE" ).toString();
222  int idx = cboResamplingMethod->findData( defaultMethod );
223  if ( idx >= 0 )
224  cboResamplingMethod->setCurrentIndex( idx );
225 
226 
227  // build pyramid list
228  QList< QgsRasterPyramid > myPyramidList = provider->buildPyramidList();
229  QList< QgsRasterPyramid >::iterator myRasterPyramidIterator;
230 
231  for ( myRasterPyramidIterator = myPyramidList.begin();
232  myRasterPyramidIterator != myPyramidList.end();
233  ++myRasterPyramidIterator )
234  {
235  if ( myRasterPyramidIterator->exists )
236  {
237  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
238  QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( " x " ) +
239  QString::number( myRasterPyramidIterator->yDim ) ) );
240  }
241  else
242  {
243  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
244  QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( " x " ) +
245  QString::number( myRasterPyramidIterator->yDim ) ) );
246  }
247  }
248  }
249  else
250  {
251  // disable Pyramids tab completely
252  mOptsPage_Pyramids->setEnabled( false );
253  }
254 
255  // We can calculate histogram for all data sources but estimated only if
256  // size is unknown - could also be enabled if well supported (estimated histogram
257  // and and let user know that it is estimated)
258  if ( !provider || !( provider->capabilities() & QgsRasterDataProvider::Size ) )
259  {
260  // disable Histogram tab completely
261  mOptsPage_Histogram->setEnabled( false );
262  }
263 
264  QVBoxLayout *layout = new QVBoxLayout( metadataFrame );
265  layout->setMargin( 0 );
266  mMetadataWidget = new QgsMetadataWidget( this, mRasterLayer );
267  mMetadataWidget->layout()->setContentsMargins( -1, 0, -1, 0 );
268  mMetadataWidget->setMapCanvas( mMapCanvas );
269  layout->addWidget( mMetadataWidget );
270  metadataFrame->setLayout( layout );
271 
272  QgsDebugMsg( "Setting crs to " + mRasterLayer->crs().toWkt( QgsCoordinateReferenceSystem::WKT2_2018 ) );
273  QgsDebugMsg( "Setting crs to " + mRasterLayer->crs().userFriendlyIdentifier() );
274  mCrsSelector->setCrs( mRasterLayer->crs() );
275 
276  // Set text for pyramid info box
277  QString pyramidFormat( QStringLiteral( "<h2>%1</h2><p>%2 %3 %4</p><b><font color='red'><p>%5</p><p>%6</p>" ) );
278  QString pyramidHeader = tr( "Description" );
279  QString pyramidSentence1 = tr( "Large resolution raster layers can slow navigation in QGIS." );
280  QString pyramidSentence2 = tr( "By creating lower resolution copies of the data (pyramids) performance can be considerably improved as QGIS selects the most suitable resolution to use depending on the level of zoom." );
281  QString pyramidSentence3 = tr( "You must have write access in the directory where the original data is stored to build pyramids." );
282  QString pyramidSentence4 = tr( "Please note that building internal pyramids may alter the original data file and once created they cannot be removed!" );
283  QString pyramidSentence5 = tr( "Please note that building internal pyramids could corrupt your image - always make a backup of your data first!" );
284 
285  tePyramidDescription->setHtml( pyramidFormat.arg( pyramidHeader,
286  pyramidSentence1,
287  pyramidSentence2,
288  pyramidSentence3,
289  pyramidSentence4,
290  pyramidSentence5 ) );
291 
292  //resampling
293  mResamplingGroupBox->setSaveCheckedState( true );
294  const QgsRasterRenderer *renderer = mRasterLayer->renderer();
295  mZoomedInResamplingComboBox->insertItem( 0, tr( "Nearest neighbour" ) );
296  mZoomedInResamplingComboBox->insertItem( 1, tr( "Bilinear" ) );
297  mZoomedInResamplingComboBox->insertItem( 2, tr( "Cubic" ) );
298  mZoomedOutResamplingComboBox->insertItem( 0, tr( "Nearest neighbour" ) );
299  mZoomedOutResamplingComboBox->insertItem( 1, tr( "Average" ) );
300 
301  const QgsRasterResampleFilter *resampleFilter = mRasterLayer->resampleFilter();
302  //set combo boxes to current resampling types
303  if ( resampleFilter )
304  {
305  const QgsRasterResampler *zoomedInResampler = resampleFilter->zoomedInResampler();
306  if ( zoomedInResampler )
307  {
308  if ( zoomedInResampler->type() == QLatin1String( "bilinear" ) )
309  {
310  mZoomedInResamplingComboBox->setCurrentIndex( 1 );
311  }
312  else if ( zoomedInResampler->type() == QLatin1String( "cubic" ) )
313  {
314  mZoomedInResamplingComboBox->setCurrentIndex( 2 );
315  }
316  }
317  else
318  {
319  mZoomedInResamplingComboBox->setCurrentIndex( 0 );
320  }
321 
322  const QgsRasterResampler *zoomedOutResampler = resampleFilter->zoomedOutResampler();
323  if ( zoomedOutResampler )
324  {
325  if ( zoomedOutResampler->type() == QLatin1String( "bilinear" ) ) //bilinear resampler does averaging when zooming out
326  {
327  mZoomedOutResamplingComboBox->setCurrentIndex( 1 );
328  }
329  }
330  else
331  {
332  mZoomedOutResamplingComboBox->setCurrentIndex( 0 );
333  }
334  mMaximumOversamplingSpinBox->setValue( resampleFilter->maxOversampling() );
335  }
336 
337  btnColorizeColor->setColorDialogTitle( tr( "Select Color" ) );
338  btnColorizeColor->setContext( QStringLiteral( "symbology" ) );
339 
340  // Hue and saturation color control
341  const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
342  //set hue and saturation controls to current values
343  if ( hueSaturationFilter )
344  {
345  sliderSaturation->setValue( hueSaturationFilter->saturation() );
346  comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
347 
348  // Set initial state of saturation controls based on grayscale mode choice
349  toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
350 
351  // Set initial state of colorize controls
352  mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
353  btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
354  toggleColorizeControls( hueSaturationFilter->colorizeOn() );
355  sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
356  }
357 
358  //blend mode
359  mBlendModeComboBox->setBlendMode( mRasterLayer->blendMode() );
360 
361  //transparency band
362  if ( provider )
363  {
364  cboxTransparencyBand->setShowNotSetOption( true, tr( "None" ) );
365  cboxTransparencyBand->setLayer( mRasterLayer );
366 
367 // Alpha band is set in sync()
368 #if 0
369  if ( renderer )
370  {
371  QgsDebugMsg( QStringLiteral( "alphaBand = %1" ).arg( renderer->alphaBand() ) );
372  if ( renderer->alphaBand() > 0 )
373  {
374  cboxTransparencyBand->setCurrentIndex( cboxTransparencyBand->findData( renderer->alphaBand() ) );
375  }
376  }
377 #endif
378  }
379 
380  // create histogram widget
381  mHistogramWidget = nullptr;
382  if ( mOptsPage_Histogram->isEnabled() )
383  {
384  mHistogramWidget = new QgsRasterHistogramWidget( mRasterLayer, mOptsPage_Histogram );
385  mHistogramStackedWidget->addWidget( mHistogramWidget );
386  }
387 
388  //insert renderer widgets into registry
394 
395  //fill available renderers into combo box
397  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
398  const auto constRenderersList = QgsApplication::rasterRendererRegistry()->renderersList();
399  for ( const QString &name : constRenderersList )
400  {
401  if ( QgsApplication::rasterRendererRegistry()->rendererData( name, entry ) )
402  {
403  if ( ( mRasterLayer->rasterType() != QgsRasterLayer::ColorLayer && entry.name != QLatin1String( "singlebandcolordata" ) ) ||
404  ( mRasterLayer->rasterType() == QgsRasterLayer::ColorLayer && entry.name == QLatin1String( "singlebandcolordata" ) ) )
405  {
406  mRenderTypeComboBox->addItem( entry.visibleName, entry.name );
407  }
408  }
409  }
410  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
411 
412  int widgetIndex = 0;
413  if ( renderer )
414  {
415  QString rendererType = renderer->type();
416  widgetIndex = mRenderTypeComboBox->findData( rendererType );
417  if ( widgetIndex != -1 )
418  {
419  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
420  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
421  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
422  }
423 
424  if ( rendererType == QLatin1String( "singlebandcolordata" ) && mRenderTypeComboBox->count() == 1 )
425  {
426  // no band rendering options for singlebandcolordata, so minimize group box
427  QSizePolicy sizep = mBandRenderingGrpBx->sizePolicy();
428  sizep.setVerticalStretch( 0 );
429  sizep.setVerticalPolicy( QSizePolicy::Maximum );
430  mBandRenderingGrpBx->setSizePolicy( sizep );
431  mBandRenderingGrpBx->updateGeometry();
432  }
433 
434  if ( mRasterLayer->providerType() != QStringLiteral( "wms" ) )
435  {
436  mWMSPrintGroupBox->hide();
437  mPublishDataSourceUrlCheckBox->hide();
438  mBackgroundLayerCheckBox->hide();
439  }
440  }
441 
442 #ifdef WITH_QTWEBKIT
443  // Setup information tab
444 
445 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
446  const int horizontalDpi = qApp->desktop()->screen()->logicalDpiX();
447 #else
448  const int horizontalDpi = logicalDpiX();
449 #endif
450 
451  // Adjust zoom: text is ok, but HTML seems rather big at least on Linux/KDE
452  if ( horizontalDpi > 96 )
453  {
454  mMetadataViewer->setZoomFactor( mMetadataViewer->zoomFactor() * 0.9 );
455  }
456  mMetadataViewer->page()->setLinkDelegationPolicy( QWebPage::LinkDelegationPolicy::DelegateAllLinks );
457  connect( mMetadataViewer->page(), &QWebPage::linkClicked, this, &QgsRasterLayerProperties::urlClicked );
458  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
459  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
460 
461 #endif
462 
463  mRenderTypeComboBox_currentIndexChanged( widgetIndex );
464 
465  // update based on lyr's current state
466  sync();
467 
468  QgsSettings settings;
469  // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
470  // this will be read by restoreOptionsBaseUi()
471  if ( !settings.contains( QStringLiteral( "/Windows/RasterLayerProperties/tab" ) ) )
472  {
473  settings.setValue( QStringLiteral( "Windows/RasterLayerProperties/tab" ),
474  mOptStackedWidget->indexOf( mOptsPage_Style ) );
475  }
476 
477  mResetColorRenderingBtn->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
478 
479  QString title = QString( tr( "Layer Properties - %1" ) ).arg( lyr->name() );
480 
481  if ( !mRasterLayer->styleManager()->isDefault( mRasterLayer->styleManager()->currentStyle() ) )
482  title += QStringLiteral( " (%1)" ).arg( mRasterLayer->styleManager()->currentStyle() );
483  restoreOptionsBaseUi( title );
484  optionsStackedWidget_CurrentChanged( mOptionsStackedWidget->currentIndex() );
485 }
486 
487 void QgsRasterLayerProperties::setupTransparencyTable( int nBands )
488 {
489  tableTransparency->clear();
490  tableTransparency->setColumnCount( 0 );
491  tableTransparency->setRowCount( 0 );
492  mTransparencyToEdited.clear();
493 
494  if ( nBands == 3 )
495  {
496  tableTransparency->setColumnCount( 4 );
497  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Red" ) ) );
498  tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Green" ) ) );
499  tableTransparency->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Blue" ) ) );
500  tableTransparency->setHorizontalHeaderItem( 3, new QTableWidgetItem( tr( "Percent Transparent" ) ) );
501  }
502  else //1 band
503  {
504  tableTransparency->setColumnCount( 3 );
505 // Is it important to distinguish the header? It becomes difficult with range.
506 #if 0
507  if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
508  QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
509  QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
510  QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
511  {
512  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Gray" ) ) );
513  }
514  else
515  {
516  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Indexed Value" ) ) );
517  }
518 #endif
519  tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
520  tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "To" ) ) );
521  tableTransparency->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Percent Transparent" ) ) );
522  }
523 
524  tableTransparency->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
525  tableTransparency->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
526 }
527 
528 void QgsRasterLayerProperties::populateTransparencyTable( QgsRasterRenderer *renderer )
529 {
530  if ( !mRasterLayer )
531  {
532  return;
533  }
534 
535  if ( !renderer )
536  {
537  return;
538  }
539 
540  int nBands = renderer->usesBands().size();
541  setupTransparencyTable( nBands );
542 
543  const QgsRasterTransparency *rasterTransparency = renderer->rasterTransparency();
544  if ( !rasterTransparency )
545  {
546  return;
547  }
548 
549  if ( nBands == 1 )
550  {
551  QList<QgsRasterTransparency::TransparentSingleValuePixel> pixelList = rasterTransparency->transparentSingleValuePixelList();
552  for ( int i = 0; i < pixelList.size(); ++i )
553  {
554  tableTransparency->insertRow( i );
555  setTransparencyCell( i, 0, pixelList[i].min );
556  setTransparencyCell( i, 1, pixelList[i].max );
557  setTransparencyCell( i, 2, pixelList[i].percentTransparent );
558  // break synchronization only if values differ
559  if ( pixelList[i].min != pixelList[i].max )
560  {
561  setTransparencyToEdited( i );
562  }
563  }
564  }
565  else if ( nBands == 3 )
566  {
567  QList<QgsRasterTransparency::TransparentThreeValuePixel> pixelList = rasterTransparency->transparentThreeValuePixelList();
568  for ( int i = 0; i < pixelList.size(); ++i )
569  {
570  tableTransparency->insertRow( i );
571  setTransparencyCell( i, 0, pixelList[i].red );
572  setTransparencyCell( i, 1, pixelList[i].green );
573  setTransparencyCell( i, 2, pixelList[i].blue );
574  setTransparencyCell( i, 3, pixelList[i].percentTransparent );
575  }
576  }
577 
578  tableTransparency->resizeColumnsToContents();
579  tableTransparency->resizeRowsToContents();
580 }
581 
582 void QgsRasterLayerProperties::setRendererWidget( const QString &rendererName )
583 {
584  QgsDebugMsg( "rendererName = " + rendererName );
585  QgsRasterRendererWidget *oldWidget = mRendererWidget;
586  QgsRasterRenderer *oldRenderer = mRasterLayer->renderer();
587 
588  int alphaBand = -1;
589  double opacity = 1;
590  QColor nodataColor;
591  if ( oldRenderer )
592  {
593  // Retain alpha band and opacity when switching renderer
594  alphaBand = oldRenderer->alphaBand();
595  opacity = oldRenderer->opacity();
596  nodataColor = oldRenderer->nodataColor();
597  }
598 
599  QgsRasterRendererRegistryEntry rendererEntry;
600  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererName, rendererEntry ) )
601  {
602  if ( rendererEntry.widgetCreateFunction ) //single band color data renderer e.g. has no widget
603  {
604  QgsDebugMsg( QStringLiteral( "renderer has widgetCreateFunction" ) );
605  // Current canvas extent (used to calc min/max) in layer CRS
606  QgsRectangle myExtent = mMapCanvas->mapSettings().outputExtentToLayerExtent( mRasterLayer, mMapCanvas->extent() );
607  if ( oldWidget && ( !oldRenderer || rendererName != oldRenderer->type() ) )
608  {
609  if ( rendererName == QLatin1String( "singlebandgray" ) )
610  {
611  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::SingleBandGray, mRasterLayer->dataProvider() ) );
612  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
613  }
614  else if ( rendererName == QLatin1String( "multibandcolor" ) )
615  {
616  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::MultiBandColor, mRasterLayer->dataProvider() ) );
617  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
618  }
619  }
620  mRasterLayer->renderer()->setAlphaBand( alphaBand );
621  mRasterLayer->renderer()->setOpacity( opacity );
622  mRasterLayer->renderer()->setNodataColor( nodataColor );
623  mRendererWidget = rendererEntry.widgetCreateFunction( mRasterLayer, myExtent );
624  mRendererWidget->setMapCanvas( mMapCanvas );
625  mRendererStackedWidget->addWidget( mRendererWidget );
626  if ( oldWidget )
627  {
628  //compare used bands in new and old renderer and reset transparency dialog if different
629  QgsRasterRenderer *oldRenderer = oldWidget->renderer();
630  QgsRasterRenderer *newRenderer = mRendererWidget->renderer();
631  QList<int> oldBands = oldRenderer->usesBands();
632  QList<int> newBands = newRenderer->usesBands();
633  if ( oldBands != newBands )
634  {
635  populateTransparencyTable( newRenderer );
636  }
637  delete oldRenderer;
638  delete newRenderer;
639  }
640  }
641  }
642 
643  const int widgetIndex = mRenderTypeComboBox->findData( rendererName );
644  if ( widgetIndex != -1 )
645  {
646  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
647  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
648  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
649  }
650 
651  if ( mRendererWidget != oldWidget )
652  delete oldWidget;
653 
654  if ( mHistogramWidget )
655  {
656  mHistogramWidget->setRendererWidget( rendererName, mRendererWidget );
657  }
658 }
659 
669 void QgsRasterLayerProperties::sync()
670 {
671  QgsSettings myQSettings;
672 
673  const QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
674  if ( !provider )
675  return;
676 
677  if ( provider->dataType( 1 ) == Qgis::ARGB32
678  || provider->dataType( 1 ) == Qgis::ARGB32_Premultiplied )
679  {
680  gboxNoDataValue->setEnabled( false );
681  gboxCustomTransparency->setEnabled( false );
682  mOptionsStackedWidget->setCurrentWidget( mOptsPage_Server );
683  }
684 
685  // TODO: Wouldn't it be better to just removeWidget() the tabs than delete them? [LS]
686  if ( !( provider->capabilities() & QgsRasterDataProvider::BuildPyramids ) )
687  {
688  if ( mOptsPage_Pyramids )
689  {
690  delete mOptsPage_Pyramids;
691  mOptsPage_Pyramids = nullptr;
692  }
693  }
694 
695  if ( !( provider->capabilities() & QgsRasterDataProvider::Size ) )
696  {
697  if ( mOptsPage_Histogram )
698  {
699  delete mOptsPage_Histogram;
700  mOptsPage_Histogram = nullptr;
701  delete mHistogramWidget;
702  mHistogramWidget = nullptr;
703  }
704  }
705 
706  QgsDebugMsg( QStringLiteral( "populate transparency tab" ) );
707 
708  /*
709  * Style tab (brightness and contrast)
710  */
711 
712  QgsBrightnessContrastFilter *brightnessFilter = mRasterLayer->brightnessFilter();
713  if ( brightnessFilter )
714  {
715  mSliderBrightness->setValue( brightnessFilter->brightness() );
716  mSliderContrast->setValue( brightnessFilter->contrast() );
717  }
718 
719  //set the transparency slider
720 
721  /*
722  * Transparent Pixel Tab
723  */
724 
725  //set the transparency slider
726  QgsRasterRenderer *renderer = mRasterLayer->renderer();
727  if ( renderer )
728  {
729  mOpacityWidget->setOpacity( renderer->opacity() );
730  cboxTransparencyBand->setBand( renderer->alphaBand() );
731  }
732 
733  //add current NoDataValue to NoDataValue line edit
734  // TODO: should be per band
735  // TODO: no data ranges
736  if ( provider->sourceHasNoDataValue( 1 ) )
737  {
738  lblSrcNoDataValue->setText( QgsRasterBlock::printValue( provider->sourceNoDataValue( 1 ) ) );
739  }
740  else
741  {
742  lblSrcNoDataValue->setText( tr( "not defined" ) );
743  }
744 
745  mSrcNoDataValueCheckBox->setChecked( provider->useSourceNoDataValue( 1 ) );
746 
747  bool enableSrcNoData = provider->sourceHasNoDataValue( 1 ) && !std::isnan( provider->sourceNoDataValue( 1 ) );
748 
749  mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
750  lblSrcNoDataValue->setEnabled( enableSrcNoData );
751 
752  QgsRasterRangeList noDataRangeList = provider->userNoDataValues( 1 );
753  QgsDebugMsg( QStringLiteral( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) );
754  if ( !noDataRangeList.isEmpty() )
755  {
756  leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) );
757  }
758  else
759  {
760  leNoDataValue->insert( QString() );
761  }
762 
763  mRefreshLayerCheckBox->setChecked( mRasterLayer->hasAutoRefreshEnabled() );
764  mRefreshLayerIntervalSpinBox->setEnabled( mRasterLayer->hasAutoRefreshEnabled() );
765  mRefreshLayerIntervalSpinBox->setValue( mRasterLayer->autoRefreshInterval() / 1000.0 );
766 
767  populateTransparencyTable( mRasterLayer->renderer() );
768 
769  QgsDebugMsg( QStringLiteral( "populate colormap tab" ) );
770  /*
771  * Transparent Pixel Tab
772  */
773 
774  QgsDebugMsg( QStringLiteral( "populate general tab" ) );
775  /*
776  * General Tab
777  */
778 
779  //these properties (layer name and label) are provided by the qgsmaplayer superclass
780  mLayerOrigNameLineEd->setText( mRasterLayer->name() );
781  leDisplayName->setText( mRasterLayer->name() );
782 
783  //get the thumbnail for the layer
784  QPixmap thumbnail = QPixmap::fromImage( mRasterLayer->previewAsImage( pixmapThumbnail->size() ) );
785  pixmapThumbnail->setPixmap( thumbnail );
786 
787  // TODO fix legend + palette pixmap
788 
789  //update the legend pixmap on this dialog
790 #if 0
791  pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
792  pixmapLegend->setScaledContents( true );
793  pixmapLegend->repaint();
794 
795  //set the palette pixmap
796  pixmapPalette->setPixmap( mRasterLayer->paletteAsPixmap( mRasterLayer->bandNumber( mRasterLayer->grayBandName() ) ) );
797  pixmapPalette->setScaledContents( true );
798  pixmapPalette->repaint();
799 #endif
800 
801  QgsDebugMsg( QStringLiteral( "populate metadata tab" ) );
802  /*
803  * Metadata Tab
804  */
805  //populate the metadata tab's text browser widget with gdal metadata info
806  updateInformationContent();
807 
808  // WMS Name as layer short name
809  mLayerShortNameLineEdit->setText( mRasterLayer->shortName() );
810  // WMS Name validator
811  QValidator *shortNameValidator = new QRegExpValidator( QgsApplication::shortNameRegExp(), this );
812  mLayerShortNameLineEdit->setValidator( shortNameValidator );
813 
814  //layer title and abstract
815  mLayerTitleLineEdit->setText( mRasterLayer->title() );
816  mLayerAbstractTextEdit->setPlainText( mRasterLayer->abstract() );
817  mLayerKeywordListLineEdit->setText( mRasterLayer->keywordList() );
818  mLayerDataUrlLineEdit->setText( mRasterLayer->dataUrl() );
819  mLayerDataUrlFormatComboBox->setCurrentIndex(
820  mLayerDataUrlFormatComboBox->findText(
821  mRasterLayer->dataUrlFormat()
822  )
823  );
824 
825  //layer attribution and metadataUrl
826  mLayerAttributionLineEdit->setText( mRasterLayer->attribution() );
827  mLayerAttributionUrlLineEdit->setText( mRasterLayer->attributionUrl() );
828  mLayerMetadataUrlLineEdit->setText( mRasterLayer->metadataUrl() );
829  mLayerMetadataUrlTypeComboBox->setCurrentIndex(
830  mLayerMetadataUrlTypeComboBox->findText(
831  mRasterLayer->metadataUrlType()
832  )
833  );
834  mLayerMetadataUrlFormatComboBox->setCurrentIndex(
835  mLayerMetadataUrlFormatComboBox->findText(
836  mRasterLayer->metadataUrlFormat()
837  )
838  );
839 
840  mLayerLegendUrlLineEdit->setText( mRasterLayer->legendUrl() );
841  mLayerLegendUrlFormatComboBox->setCurrentIndex( mLayerLegendUrlFormatComboBox->findText( mRasterLayer->legendUrlFormat() ) );
842 
843  //WMS print layer
844  QVariant wmsPrintLayer = mRasterLayer->customProperty( QStringLiteral( "WMSPrintLayer" ) );
845  if ( wmsPrintLayer.isValid() )
846  {
847  mWMSPrintLayerLineEdit->setText( wmsPrintLayer.toString() );
848  }
849 
850  QVariant wmsPublishDataSourceUrl = mRasterLayer->customProperty( QStringLiteral( "WMSPublishDataSourceUrl" ), false );
851  mPublishDataSourceUrlCheckBox->setChecked( wmsPublishDataSourceUrl.toBool() );
852 
853  QVariant wmsBackgroundLayer = mRasterLayer->customProperty( QStringLiteral( "WMSBackgroundLayer" ), false );
854  mBackgroundLayerCheckBox->setChecked( wmsBackgroundLayer.toBool() );
855 
856  /*
857  * Legend Tab
858  */
859  mLegendConfigEmbeddedWidget->setLayer( mRasterLayer );
860 
861 } // QgsRasterLayerProperties::sync()
862 
863 /*
864  *
865  * PUBLIC AND PRIVATE SLOTS
866  *
867  */
868 void QgsRasterLayerProperties::apply()
869 {
870 
871  // Do nothing on "bad" layers
872  if ( !mRasterLayer->isValid() )
873  return;
874 
875  /*
876  * Legend Tab
877  */
878  mLegendConfigEmbeddedWidget->applyToLayer();
879 
880  QgsDebugMsg( QStringLiteral( "apply processing symbology tab" ) );
881  /*
882  * Symbology Tab
883  */
884 
885  //set whether the layer histogram should be inverted
886  //mRasterLayer->setInvertHistogram( cboxInvertColorMap->isChecked() );
887 
888  mRasterLayer->brightnessFilter()->setBrightness( mSliderBrightness->value() );
889  mRasterLayer->brightnessFilter()->setContrast( mSliderContrast->value() );
890 
891  QgsDebugMsg( QStringLiteral( "processing transparency tab" ) );
892  /*
893  * Transparent Pixel Tab
894  */
895 
896  //set NoDataValue
897  QgsRasterRangeList myNoDataRangeList;
898  if ( "" != leNoDataValue->text() )
899  {
900  bool myDoubleOk = false;
901  double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk );
902  if ( myDoubleOk )
903  {
904  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
905  myNoDataRangeList << myNoDataRange;
906  }
907  }
908  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
909  {
910  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
911  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mSrcNoDataValueCheckBox->isChecked() );
912  }
913 
914  //set renderer from widget
915  QgsRasterRendererWidget *rendererWidget = dynamic_cast<QgsRasterRendererWidget *>( mRendererStackedWidget->currentWidget() );
916  if ( rendererWidget )
917  {
918  rendererWidget->doComputations();
919 
920  mRasterLayer->setRenderer( rendererWidget->renderer() );
921  }
922 
923  mMetadataWidget->acceptMetadata();
924  mMetadataFilled = false;
925 
926  //transparency settings
927  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
928  if ( rasterRenderer )
929  {
930  rasterRenderer->setAlphaBand( cboxTransparencyBand->currentBand() );
931 
932  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
933  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
934  if ( tableTransparency->columnCount() == 4 )
935  {
937  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
938  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
939  {
940  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
941  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
942  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
943  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
944  myTransparentThreeValuePixelList.append( myTransparentPixel );
945  }
946  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
947  }
948  else if ( tableTransparency->columnCount() == 3 )
949  {
951  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
952  for ( int myListRunner = 0; myListRunner < tableTransparency->rowCount(); myListRunner++ )
953  {
954  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
955  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
956  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
957 
958  myTransparentSingleValuePixelList.append( myTransparentPixel );
959  }
960  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
961  }
962 
963  rasterRenderer->setRasterTransparency( rasterTransparency );
964 
965  //set global transparency
966  rasterRenderer->setOpacity( mOpacityWidget->opacity() );
967  }
968 
969  QgsDebugMsg( QStringLiteral( "processing general tab" ) );
970  /*
971  * General Tab
972  */
973  mRasterLayer->setName( mLayerOrigNameLineEd->text() );
974 
975  // set up the scale based layer visibility stuff....
976  mRasterLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
977  mRasterLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
978  mRasterLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
979 
980  mRasterLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
981  mRasterLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
982 
983  //update the legend pixmap
984  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
985  // pixmapLegend->setScaledContents( true );
986  // pixmapLegend->repaint();
987 
988  QgsRasterResampleFilter *resampleFilter = mRasterLayer->resampleFilter();
989  if ( resampleFilter )
990  {
991  QgsRasterResampler *zoomedInResampler = nullptr;
992  QString zoomedInResamplingMethod = mZoomedInResamplingComboBox->currentText();
993  if ( zoomedInResamplingMethod == tr( "Bilinear" ) )
994  {
995  zoomedInResampler = new QgsBilinearRasterResampler();
996  }
997  else if ( zoomedInResamplingMethod == tr( "Cubic" ) )
998  {
999  zoomedInResampler = new QgsCubicRasterResampler();
1000  }
1001 
1002  resampleFilter->setZoomedInResampler( zoomedInResampler );
1003 
1004  //raster resampling
1005  QgsRasterResampler *zoomedOutResampler = nullptr;
1006  QString zoomedOutResamplingMethod = mZoomedOutResamplingComboBox->currentText();
1007  if ( zoomedOutResamplingMethod == tr( "Average" ) )
1008  {
1009  zoomedOutResampler = new QgsBilinearRasterResampler();
1010  }
1011 
1012  resampleFilter->setZoomedOutResampler( zoomedOutResampler );
1013 
1014  resampleFilter->setMaxOversampling( mMaximumOversamplingSpinBox->value() );
1015  }
1016 
1017  // Hue and saturation controls
1018  QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
1019  if ( hueSaturationFilter )
1020  {
1021  hueSaturationFilter->setSaturation( sliderSaturation->value() );
1022  hueSaturationFilter->setGrayscaleMode( ( QgsHueSaturationFilter::GrayscaleMode ) comboGrayscale->currentIndex() );
1023  hueSaturationFilter->setColorizeOn( mColorizeCheck->checkState() );
1024  hueSaturationFilter->setColorizeColor( btnColorizeColor->color() );
1025  hueSaturationFilter->setColorizeStrength( sliderColorizeStrength->value() );
1026  }
1027 
1028  //set the blend mode for the layer
1029  mRasterLayer->setBlendMode( mBlendModeComboBox->blendMode() );
1030 
1031  //get the thumbnail for the layer
1032  QPixmap thumbnail = QPixmap::fromImage( mRasterLayer->previewAsImage( pixmapThumbnail->size() ) );
1033  pixmapThumbnail->setPixmap( thumbnail );
1034 
1035  if ( mRasterLayer->shortName() != mLayerShortNameLineEdit->text() )
1036  mMetadataFilled = false;
1037  mRasterLayer->setShortName( mLayerShortNameLineEdit->text() );
1038 
1039  if ( mRasterLayer->title() != mLayerTitleLineEdit->text() )
1040  mMetadataFilled = false;
1041  mRasterLayer->setTitle( mLayerTitleLineEdit->text() );
1042 
1043  if ( mRasterLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
1044  mMetadataFilled = false;
1045  mRasterLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
1046 
1047  if ( mRasterLayer->keywordList() != mLayerKeywordListLineEdit->text() )
1048  mMetadataFilled = false;
1049  mRasterLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
1050 
1051  if ( mRasterLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
1052  mMetadataFilled = false;
1053  mRasterLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
1054 
1055  if ( mRasterLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
1056  mMetadataFilled = false;
1057  mRasterLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
1058 
1059  //layer attribution and metadataUrl
1060  if ( mRasterLayer->attribution() != mLayerAttributionLineEdit->text() )
1061  mMetadataFilled = false;
1062  mRasterLayer->setAttribution( mLayerAttributionLineEdit->text() );
1063 
1064  if ( mRasterLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
1065  mMetadataFilled = false;
1066  mRasterLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
1067 
1068  if ( mRasterLayer->metadataUrl() != mLayerMetadataUrlLineEdit->text() )
1069  mMetadataFilled = false;
1070  mRasterLayer->setMetadataUrl( mLayerMetadataUrlLineEdit->text() );
1071 
1072  if ( mRasterLayer->metadataUrlType() != mLayerMetadataUrlTypeComboBox->currentText() )
1073  mMetadataFilled = false;
1074  mRasterLayer->setMetadataUrlType( mLayerMetadataUrlTypeComboBox->currentText() );
1075 
1076  if ( mRasterLayer->metadataUrlFormat() != mLayerMetadataUrlFormatComboBox->currentText() )
1077  mMetadataFilled = false;
1078  mRasterLayer->setMetadataUrlFormat( mLayerMetadataUrlFormatComboBox->currentText() );
1079 
1080  if ( mRasterLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
1081  mMetadataFilled = false;
1082  mRasterLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
1083 
1084  if ( mRasterLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
1085  mMetadataFilled = false;
1086  mRasterLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
1087 
1088  if ( !mWMSPrintLayerLineEdit->text().isEmpty() )
1089  {
1090  mRasterLayer->setCustomProperty( QStringLiteral( "WMSPrintLayer" ), mWMSPrintLayerLineEdit->text() );
1091  }
1092 
1093  mRasterLayer->setCustomProperty( "WMSPublishDataSourceUrl", mPublishDataSourceUrlCheckBox->isChecked() );
1094  mRasterLayer->setCustomProperty( "WMSBackgroundLayer", mBackgroundLayerCheckBox->isChecked() );
1095 
1096  // Force a redraw of the legend
1097  mRasterLayer->setLegend( QgsMapLayerLegend::defaultRasterLegend( mRasterLayer ) );
1098 
1099  //make sure the layer is redrawn
1100  mRasterLayer->triggerRepaint();
1101 
1102  // notify the project we've made a change
1103  QgsProject::instance()->setDirty( true );
1104 }//apply
1105 
1106 void QgsRasterLayerProperties::mLayerOrigNameLineEd_textEdited( const QString &text )
1107 {
1108  leDisplayName->setText( mRasterLayer->formatLayerName( text ) );
1109 }
1110 
1111 void QgsRasterLayerProperties::buttonBuildPyramids_clicked()
1112 {
1113  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1114 
1115  std::unique_ptr< QgsRasterBlockFeedback > feedback( new QgsRasterBlockFeedback() );
1116 
1117  connect( feedback.get(), &QgsRasterBlockFeedback::progressChanged, mPyramidProgress, &QProgressBar::setValue );
1118  //
1119  // Go through the list marking any files that are selected in the listview
1120  // as true so that we can generate pyramids for them.
1121  //
1122  QList< QgsRasterPyramid> myPyramidList = provider->buildPyramidList();
1123  for ( int myCounterInt = 0; myCounterInt < lbxPyramidResolutions->count(); myCounterInt++ )
1124  {
1125  QListWidgetItem *myItem = lbxPyramidResolutions->item( myCounterInt );
1126  //mark to be pyramided
1127  myPyramidList[myCounterInt].build = myItem->isSelected() || myPyramidList[myCounterInt].exists;
1128  }
1129 
1130  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
1131  QString prefix = provider->name() + "/driverOptions/_pyramids/";
1132  QgsSettings mySettings;
1133  QString resamplingMethod( cboResamplingMethod->currentData().toString() );
1134  mySettings.setValue( prefix + "resampling", resamplingMethod );
1135 
1136  //
1137  // Ask raster layer to build the pyramids
1138  //
1139 
1140  // let the user know we're going to possibly be taking a while
1141  QApplication::setOverrideCursor( Qt::WaitCursor );
1142  QString res = provider->buildPyramids(
1143  myPyramidList,
1144  resamplingMethod,
1145  ( QgsRaster::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex(),
1146  QStringList(),
1147  feedback.get() );
1148  QApplication::restoreOverrideCursor();
1149  mPyramidProgress->setValue( 0 );
1150  buttonBuildPyramids->setEnabled( false );
1151  if ( !res.isNull() )
1152  {
1153  if ( res == QLatin1String( "CANCELED" ) )
1154  {
1155  // user canceled
1156  }
1157  else if ( res == QLatin1String( "ERROR_WRITE_ACCESS" ) )
1158  {
1159  QMessageBox::warning( this, tr( "Building Pyramids" ),
1160  tr( "Write access denied. Adjust the file permissions and try again." ) );
1161  }
1162  else if ( res == QLatin1String( "ERROR_WRITE_FORMAT" ) )
1163  {
1164  QMessageBox::warning( this, tr( "Building Pyramids" ),
1165  tr( "The file was not writable. Some formats do not "
1166  "support pyramid overviews. Consult the GDAL documentation if in doubt." ) );
1167  }
1168  else if ( res == QLatin1String( "FAILED_NOT_SUPPORTED" ) )
1169  {
1170  QMessageBox::warning( this, tr( "Building Pyramids" ),
1171  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1172  }
1173  else if ( res == QLatin1String( "ERROR_JPEG_COMPRESSION" ) )
1174  {
1175  QMessageBox::warning( this, tr( "Building Pyramids" ),
1176  tr( "Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." ) );
1177  }
1178  else if ( res == QLatin1String( "ERROR_VIRTUAL" ) )
1179  {
1180  QMessageBox::warning( this, tr( "Building Pyramids" ),
1181  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1182  }
1183 
1184  }
1185 
1186  //
1187  // repopulate the pyramids list
1188  //
1189  lbxPyramidResolutions->clear();
1190  // Need to rebuild list as some or all pyramids may have failed to build
1191  myPyramidList = provider->buildPyramidList();
1192  QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
1193  QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
1194 
1195  QList< QgsRasterPyramid >::iterator myRasterPyramidIterator;
1196  for ( myRasterPyramidIterator = myPyramidList.begin();
1197  myRasterPyramidIterator != myPyramidList.end();
1198  ++myRasterPyramidIterator )
1199  {
1200  if ( myRasterPyramidIterator->exists )
1201  {
1202  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
1203  QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( " x " ) +
1204  QString::number( myRasterPyramidIterator->yDim ) ) );
1205  }
1206  else
1207  {
1208  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
1209  QString::number( myRasterPyramidIterator->xDim ) + QStringLiteral( " x " ) +
1210  QString::number( myRasterPyramidIterator->yDim ) ) );
1211  }
1212  }
1213  //update the legend pixmap
1214  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
1215  // pixmapLegend->setScaledContents( true );
1216  // pixmapLegend->repaint();
1217 
1218  //populate the metadata tab's text browser widget with gdal metadata info
1219  updateInformationContent();
1220 }
1221 
1222 void QgsRasterLayerProperties::urlClicked( const QUrl &url )
1223 {
1224  QFileInfo file( url.toLocalFile() );
1225  if ( file.exists() && !file.isDir() )
1226  QgsGui::instance()->nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
1227  else
1228  QDesktopServices::openUrl( url );
1229 }
1230 
1231 void QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged( int index )
1232 {
1233  if ( index < 0 || mDisableRenderTypeComboBoxCurrentIndexChanged || ! mRasterLayer->renderer() )
1234  {
1235  return;
1236  }
1237 
1238  QString rendererName = mRenderTypeComboBox->itemData( index ).toString();
1239  setRendererWidget( rendererName );
1240 }
1241 
1242 void QgsRasterLayerProperties::pbnAddValuesFromDisplay_clicked()
1243 {
1244  if ( mMapCanvas && mPixelSelectorTool )
1245  {
1246  //Need to work around the modality of the dialog but can not just hide() it.
1247  // According to Qt5 docs, to change modality the dialog needs to be hidden
1248  // and shown again.
1249  hide();
1250  setModal( false );
1251 
1252  // Transfer focus to the canvas to use the selector tool
1253  mMapCanvas->window()->raise();
1254  mMapCanvas->window()->activateWindow();
1255  mMapCanvas->window()->setFocus();
1256  mMapCanvas->setMapTool( mPixelSelectorTool.get() );
1257 
1258  }
1259 }
1260 
1261 void QgsRasterLayerProperties::pbnAddValuesManually_clicked()
1262 {
1263  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1264  if ( !renderer )
1265  {
1266  return;
1267  }
1268 
1269  tableTransparency->insertRow( tableTransparency->rowCount() );
1270 
1271  int n = renderer->usesBands().size();
1272  if ( n == 1 ) n++;
1273 
1274  for ( int i = 0; i < n; i++ )
1275  {
1276  setTransparencyCell( tableTransparency->rowCount() - 1, i, std::numeric_limits<double>::quiet_NaN() );
1277  }
1278 
1279  setTransparencyCell( tableTransparency->rowCount() - 1, n, 100 );
1280 
1281  tableTransparency->resizeColumnsToContents();
1282  tableTransparency->resizeRowsToContents();
1283 }
1284 
1285 void QgsRasterLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
1286 {
1287  QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mMapCanvas, tr( "Select Transformation" ) );
1288  mRasterLayer->setCrs( crs );
1289  mMetadataWidget->crsChanged();
1290 }
1291 
1292 void QgsRasterLayerProperties::pbnDefaultValues_clicked()
1293 {
1294  if ( !mRendererWidget )
1295  {
1296  return;
1297  }
1298 
1299  QgsRasterRenderer *r = mRendererWidget->renderer();
1300  if ( !r )
1301  {
1302  return;
1303  }
1304 
1305  int nBands = r->usesBands().size();
1306  delete r; // really delete?
1307 
1308  setupTransparencyTable( nBands );
1309 
1310  tableTransparency->resizeColumnsToContents(); // works only with values
1311  tableTransparency->resizeRowsToContents();
1312 }
1313 
1314 void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double value )
1315 {
1316  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
1317  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1318  if ( !provider ) return;
1319 
1320  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1321  if ( !renderer ) return;
1322  int nBands = renderer->usesBands().size();
1323 
1324  QLineEdit *lineEdit = new QLineEdit();
1325  lineEdit->setFrame( false ); // frame looks bad in table
1326  // Without margins row selection is not displayed (important for delete row)
1327  lineEdit->setContentsMargins( 1, 1, 1, 1 );
1328 
1329  if ( column == tableTransparency->columnCount() - 1 )
1330  {
1331  // transparency
1332  // Who needs transparency as floating point?
1333  lineEdit->setValidator( new QIntValidator( nullptr ) );
1334  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
1335  }
1336  else
1337  {
1338  // value
1339  QString valueString;
1340  switch ( provider->sourceDataType( 1 ) )
1341  {
1342  case Qgis::Float32:
1343  case Qgis::Float64:
1344  lineEdit->setValidator( new QDoubleValidator( nullptr ) );
1345  if ( !std::isnan( value ) )
1346  {
1347  valueString = QgsRasterBlock::printValue( value );
1348  }
1349  break;
1350  default:
1351  lineEdit->setValidator( new QIntValidator( nullptr ) );
1352  if ( !std::isnan( value ) )
1353  {
1354  valueString = QString::number( static_cast<int>( value ) );
1355  }
1356  break;
1357  }
1358  lineEdit->setText( valueString );
1359  }
1360  tableTransparency->setCellWidget( row, column, lineEdit );
1361  adjustTransparencyCellWidth( row, column );
1362 
1363  if ( nBands == 1 && ( column == 0 || column == 1 ) )
1364  {
1365  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerProperties::transparencyCellTextEdited );
1366  }
1367  tableTransparency->resizeColumnsToContents();
1368 }
1369 
1370 void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, double value )
1371 {
1372  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
1373  if ( !lineEdit ) return;
1374  lineEdit->setText( QgsRasterBlock::printValue( value ) );
1375  lineEdit->adjustSize();
1376  adjustTransparencyCellWidth( row, column );
1377  tableTransparency->resizeColumnsToContents();
1378 }
1379 
1380 double QgsRasterLayerProperties::transparencyCellValue( int row, int column )
1381 {
1382  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
1383  if ( !lineEdit || lineEdit->text().isEmpty() )
1384  {
1385  std::numeric_limits<double>::quiet_NaN();
1386  }
1387  return lineEdit->text().toDouble();
1388 }
1389 
1390 void QgsRasterLayerProperties::adjustTransparencyCellWidth( int row, int column )
1391 {
1392  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, column ) );
1393  if ( !lineEdit ) return;
1394 
1395  int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
1396  width = std::max( width, tableTransparency->columnWidth( column ) );
1397 
1398  lineEdit->setFixedWidth( width );
1399 }
1400 
1401 void QgsRasterLayerProperties::pbnExportTransparentPixelValues_clicked()
1402 {
1403  QgsSettings myQSettings;
1404  QString myLastDir = myQSettings.value( QStringLiteral( "lastRasterFileFilterDir" ), QDir::homePath() ).toString();
1405  QString myFileName = QFileDialog::getSaveFileName( this, tr( "Save File" ), myLastDir, tr( "Textfile" ) + " (*.txt)" );
1406  if ( !myFileName.isEmpty() )
1407  {
1408  if ( !myFileName.endsWith( QLatin1String( ".txt" ), Qt::CaseInsensitive ) )
1409  {
1410  myFileName = myFileName + ".txt";
1411  }
1412 
1413  QFile myOutputFile( myFileName );
1414  if ( myOutputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
1415  {
1416  QTextStream myOutputStream( &myOutputFile );
1417  myOutputStream << "# " << tr( "QGIS Generated Transparent Pixel Value Export File" ) << '\n';
1418  if ( rasterIsMultiBandColor() )
1419  {
1420  myOutputStream << "#\n#\n# " << tr( "Red" ) << "\t" << tr( "Green" ) << "\t" << tr( "Blue" ) << "\t" << tr( "Percent Transparent" );
1421  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
1422  {
1423  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
1424  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
1425  << QString::number( transparencyCellValue( myTableRunner, 2 ) ) << "\t"
1426  << QString::number( transparencyCellValue( myTableRunner, 3 ) );
1427  }
1428  }
1429  else
1430  {
1431  myOutputStream << "#\n#\n# " << tr( "Value" ) << "\t" << tr( "Percent Transparent" );
1432 
1433  for ( int myTableRunner = 0; myTableRunner < tableTransparency->rowCount(); myTableRunner++ )
1434  {
1435  myOutputStream << '\n' << QString::number( transparencyCellValue( myTableRunner, 0 ) ) << "\t"
1436  << QString::number( transparencyCellValue( myTableRunner, 1 ) ) << "\t"
1437  << QString::number( transparencyCellValue( myTableRunner, 2 ) );
1438  }
1439  }
1440  }
1441  else
1442  {
1443  QMessageBox::warning( this, tr( "Export Transparent Pixels" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
1444  }
1445  }
1446 }
1447 
1448 void QgsRasterLayerProperties::transparencyCellTextEdited( const QString &text )
1449 {
1450  Q_UNUSED( text )
1451  QgsDebugMsg( QStringLiteral( "text = %1" ).arg( text ) );
1452  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1453  if ( !renderer )
1454  {
1455  return;
1456  }
1457  int nBands = renderer->usesBands().size();
1458  if ( nBands == 1 )
1459  {
1460  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
1461  if ( !lineEdit ) return;
1462  int row = -1;
1463  int column = -1;
1464  for ( int r = 0; r < tableTransparency->rowCount(); r++ )
1465  {
1466  for ( int c = 0; c < tableTransparency->columnCount(); c++ )
1467  {
1468  if ( tableTransparency->cellWidget( r, c ) == sender() )
1469  {
1470  row = r;
1471  column = c;
1472  break;
1473  }
1474  }
1475  if ( row != -1 ) break;
1476  }
1477  QgsDebugMsg( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ) );
1478 
1479  if ( column == 0 )
1480  {
1481  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( tableTransparency->cellWidget( row, 1 ) );
1482  if ( !toLineEdit ) return;
1483  bool toChanged = mTransparencyToEdited.value( row );
1484  QgsDebugMsg( QStringLiteral( "toChanged = %1" ).arg( toChanged ) );
1485  if ( !toChanged )
1486  {
1487  toLineEdit->setText( lineEdit->text() );
1488  }
1489  }
1490  else if ( column == 1 )
1491  {
1492  setTransparencyToEdited( row );
1493  }
1494  }
1495 }
1496 
1497 void QgsRasterLayerProperties::aboutToShowStyleMenu()
1498 {
1499  // this should be unified with QgsVectorLayerProperties::aboutToShowStyleMenu()
1500 
1501  QMenu *m = qobject_cast<QMenu *>( sender() );
1502  if ( !m )
1503  return;
1504 
1505  // first get rid of previously added style manager actions (they are dynamic)
1506  bool gotFirstSeparator = false;
1507  QList<QAction *> actions = m->actions();
1508  for ( int i = 0; i < actions.count(); ++i )
1509  {
1510  if ( actions[i]->isSeparator() )
1511  {
1512  if ( gotFirstSeparator )
1513  {
1514  // remove all actions after second separator (including it)
1515  while ( actions.count() != i )
1516  delete actions.takeAt( i );
1517  break;
1518  }
1519  else
1520  gotFirstSeparator = true;
1521  }
1522  }
1523 
1524  // re-add style manager actions!
1525  m->addSeparator();
1527 }
1528 
1529 void QgsRasterLayerProperties::syncToLayer()
1530 {
1531  QgsRasterRenderer *renderer = mRasterLayer->renderer();
1532  if ( renderer )
1533  {
1534  setRendererWidget( renderer->type() );
1535  }
1536  sync();
1537  mRasterLayer->triggerRepaint();
1538 }
1539 
1540 void QgsRasterLayerProperties::setTransparencyToEdited( int row )
1541 {
1542  if ( row >= mTransparencyToEdited.size() )
1543  {
1544  mTransparencyToEdited.resize( row + 1 );
1545  }
1546  mTransparencyToEdited[row] = true;
1547 }
1548 
1550 {
1552 
1553  bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1554  mBtnStyle->setVisible( ! isMetadataPanel );
1555  mBtnMetadata->setVisible( isMetadataPanel );
1556 
1557  if ( !mHistogramWidget )
1558  return;
1559 
1560  if ( index == mOptStackedWidget->indexOf( mOptsPage_Histogram ) )
1561  {
1562  mHistogramWidget->setActive( true );
1563  }
1564  else
1565  {
1566  mHistogramWidget->setActive( false );
1567  }
1568 
1569  if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) || !mMetadataFilled )
1570  {
1571  //set the metadata contents (which can be expensive)
1572  updateInformationContent();
1573  }
1574 }
1575 
1576 void QgsRasterLayerProperties::pbnImportTransparentPixelValues_clicked()
1577 {
1578  int myLineCounter = 0;
1579  bool myImportError = false;
1580  QString myBadLines;
1581  QgsSettings myQSettings;
1582  QString myLastDir = myQSettings.value( QStringLiteral( "lastRasterFileFilterDir" ), QDir::homePath() ).toString();
1583  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Open file" ), myLastDir, tr( "Textfile" ) + " (*.txt)" );
1584  QFile myInputFile( myFileName );
1585  if ( myInputFile.open( QFile::ReadOnly ) )
1586  {
1587  QTextStream myInputStream( &myInputFile );
1588  QString myInputLine;
1589  if ( rasterIsMultiBandColor() )
1590  {
1591  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
1592  {
1593  tableTransparency->removeRow( myTableRunner );
1594  }
1595 
1596  while ( !myInputStream.atEnd() )
1597  {
1598  myLineCounter++;
1599  myInputLine = myInputStream.readLine();
1600  if ( !myInputLine.isEmpty() )
1601  {
1602  if ( !myInputLine.simplified().startsWith( '#' ) )
1603  {
1604  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
1605  if ( myTokens.count() != 4 )
1606  {
1607  myImportError = true;
1608  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
1609  }
1610  else
1611  {
1612  tableTransparency->insertRow( tableTransparency->rowCount() );
1613  for ( int col = 0; col < 4; col++ )
1614  {
1615  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
1616  }
1617  }
1618  }
1619  }
1620  }
1621  }
1622  else
1623  {
1624  for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
1625  {
1626  tableTransparency->removeRow( myTableRunner );
1627  }
1628 
1629  while ( !myInputStream.atEnd() )
1630  {
1631  myLineCounter++;
1632  myInputLine = myInputStream.readLine();
1633  if ( !myInputLine.isEmpty() )
1634  {
1635  if ( !myInputLine.simplified().startsWith( '#' ) )
1636  {
1637  QStringList myTokens = myInputLine.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
1638  if ( myTokens.count() != 3 && myTokens.count() != 2 ) // 2 for QGIS < 1.9 compatibility
1639  {
1640  myImportError = true;
1641  myBadLines = myBadLines + QString::number( myLineCounter ) + ":\t[" + myInputLine + "]\n";
1642  }
1643  else
1644  {
1645  if ( myTokens.count() == 2 )
1646  {
1647  myTokens.insert( 1, myTokens[0] ); // add 'to' value, QGIS < 1.9 compatibility
1648  }
1649  tableTransparency->insertRow( tableTransparency->rowCount() );
1650  for ( int col = 0; col < 3; col++ )
1651  {
1652  setTransparencyCell( tableTransparency->rowCount() - 1, col, myTokens[col].toDouble() );
1653  }
1654  }
1655  }
1656  }
1657  }
1658  }
1659 
1660  if ( myImportError )
1661  {
1662  QMessageBox::warning( this, tr( "Import Transparent Pixels" ), tr( "The following lines contained errors\n\n%1" ).arg( myBadLines ) );
1663  }
1664  }
1665  else if ( !myFileName.isEmpty() )
1666  {
1667  QMessageBox::warning( this, tr( "Import Transparent Pixels" ), tr( "Read access denied. Adjust the file permissions and try again.\n\n" ) );
1668  }
1669  tableTransparency->resizeColumnsToContents();
1670  tableTransparency->resizeRowsToContents();
1671 }
1672 
1673 void QgsRasterLayerProperties::pbnRemoveSelectedRow_clicked()
1674 {
1675  if ( 0 < tableTransparency->rowCount() )
1676  {
1677  tableTransparency->removeRow( tableTransparency->currentRow() );
1678  }
1679 }
1680 
1681 void QgsRasterLayerProperties::pixelSelected( const QgsPointXY &canvasPoint, const Qt::MouseButton &btn )
1682 {
1683  Q_UNUSED( btn )
1684  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1685  if ( !renderer )
1686  {
1687  return;
1688  }
1689 
1690  //Get the pixel values and add a new entry to the transparency table
1691  if ( mMapCanvas && mPixelSelectorTool )
1692  {
1693  mMapCanvas->unsetMapTool( mPixelSelectorTool.get() );
1694 
1695  const QgsMapSettings &ms = mMapCanvas->mapSettings();
1696  QgsPointXY myPoint = ms.mapToLayerCoordinates( mRasterLayer, canvasPoint );
1697 
1698  QgsRectangle myExtent = ms.mapToLayerCoordinates( mRasterLayer, mMapCanvas->extent() );
1699  double mapUnitsPerPixel = mMapCanvas->mapUnitsPerPixel();
1700  int myWidth = mMapCanvas->extent().width() / mapUnitsPerPixel;
1701  int myHeight = mMapCanvas->extent().height() / mapUnitsPerPixel;
1702 
1703  QMap<int, QVariant> myPixelMap = mRasterLayer->dataProvider()->identify( myPoint, QgsRaster::IdentifyFormatValue, myExtent, myWidth, myHeight ).results();
1704 
1705  QList<int> bands = renderer->usesBands();
1706 
1707  QList<double> values;
1708  for ( int i = 0; i < bands.size(); ++i )
1709  {
1710  int bandNo = bands.value( i );
1711  if ( myPixelMap.count( bandNo ) == 1 )
1712  {
1713  if ( myPixelMap.value( bandNo ).isNull() )
1714  {
1715  return; // Don't add nodata, transparent anyway
1716  }
1717  double value = myPixelMap.value( bandNo ).toDouble();
1718  QgsDebugMsg( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ) );
1719  values.append( value );
1720  }
1721  }
1722  if ( bands.size() == 1 )
1723  {
1724  // Set 'to'
1725  values.insert( 1, values.value( 0 ) );
1726  }
1727  tableTransparency->insertRow( tableTransparency->rowCount() );
1728  for ( int i = 0; i < values.size(); i++ )
1729  {
1730  setTransparencyCell( tableTransparency->rowCount() - 1, i, values.value( i ) );
1731  }
1732  setTransparencyCell( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, 100 );
1733  }
1734  delete renderer;
1735 
1736  tableTransparency->resizeColumnsToContents();
1737  tableTransparency->resizeRowsToContents();
1738 }
1739 
1740 void QgsRasterLayerProperties::toggleSaturationControls( int grayscaleMode )
1741 {
1742  // Enable or disable saturation controls based on choice of grayscale mode
1743  if ( grayscaleMode == 0 )
1744  {
1745  sliderSaturation->setEnabled( true );
1746  spinBoxSaturation->setEnabled( true );
1747  }
1748  else
1749  {
1750  sliderSaturation->setEnabled( false );
1751  spinBoxSaturation->setEnabled( false );
1752  }
1753 }
1754 
1755 void QgsRasterLayerProperties::toggleColorizeControls( bool colorizeEnabled )
1756 {
1757  // Enable or disable colorize controls based on checkbox
1758  btnColorizeColor->setEnabled( colorizeEnabled );
1759  sliderColorizeStrength->setEnabled( colorizeEnabled );
1760  spinColorizeStrength->setEnabled( colorizeEnabled );
1761 }
1762 
1763 
1764 QLinearGradient QgsRasterLayerProperties::redGradient()
1765 {
1766  //define a gradient
1767  // TODO change this to actual polygon dims
1768  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1769  myGradient.setColorAt( 0.0, QColor( 242, 14, 25, 190 ) );
1770  myGradient.setColorAt( 0.5, QColor( 175, 29, 37, 190 ) );
1771  myGradient.setColorAt( 1.0, QColor( 114, 17, 22, 190 ) );
1772  return myGradient;
1773 }
1774 QLinearGradient QgsRasterLayerProperties::greenGradient()
1775 {
1776  //define a gradient
1777  // TODO change this to actual polygon dims
1778  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1779  myGradient.setColorAt( 0.0, QColor( 48, 168, 5, 190 ) );
1780  myGradient.setColorAt( 0.8, QColor( 36, 122, 4, 190 ) );
1781  myGradient.setColorAt( 1.0, QColor( 21, 71, 2, 190 ) );
1782  return myGradient;
1783 }
1784 QLinearGradient QgsRasterLayerProperties::blueGradient()
1785 {
1786  //define a gradient
1787  // TODO change this to actual polygon dims
1788  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1789  myGradient.setColorAt( 0.0, QColor( 30, 0, 106, 190 ) );
1790  myGradient.setColorAt( 0.2, QColor( 30, 72, 128, 190 ) );
1791  myGradient.setColorAt( 1.0, QColor( 30, 223, 196, 190 ) );
1792  return myGradient;
1793 }
1794 QLinearGradient QgsRasterLayerProperties::grayGradient()
1795 {
1796  //define a gradient
1797  // TODO change this to actual polygon dims
1798  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1799  myGradient.setColorAt( 0.0, QColor( 5, 5, 5, 190 ) );
1800  myGradient.setColorAt( 0.8, QColor( 122, 122, 122, 190 ) );
1801  myGradient.setColorAt( 1.0, QColor( 220, 220, 220, 190 ) );
1802  return myGradient;
1803 }
1804 QLinearGradient QgsRasterLayerProperties::highlightGradient()
1805 {
1806  //define another gradient for the highlight
1807  // TODO change this to actual polygon dims
1808  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1809  myGradient.setColorAt( 1.0, QColor( 255, 255, 255, 50 ) );
1810  myGradient.setColorAt( 0.5, QColor( 255, 255, 255, 100 ) );
1811  myGradient.setColorAt( 0.0, QColor( 255, 255, 255, 150 ) );
1812  return myGradient;
1813 }
1814 
1815 
1816 
1817 //
1818 //
1819 // Next four methods for saving and restoring qml style state
1820 //
1821 //
1822 void QgsRasterLayerProperties::loadDefaultStyle_clicked()
1823 {
1824  bool defaultLoadedFlag = false;
1825  QString myMessage = mRasterLayer->loadDefaultStyle( defaultLoadedFlag );
1826  //reset if the default style was loaded OK only
1827  if ( defaultLoadedFlag )
1828  {
1829  syncToLayer();
1830  }
1831  else
1832  {
1833  //otherwise let the user know what went wrong
1834  QMessageBox::information( this,
1835  tr( "Default Style" ),
1836  myMessage
1837  );
1838  }
1839 }
1840 
1841 void QgsRasterLayerProperties::saveDefaultStyle_clicked()
1842 {
1843 
1844  apply(); // make sure the style to save is up-to-date
1845 
1846  // a flag passed by reference
1847  bool defaultSavedFlag = false;
1848  // after calling this the above flag will be set true for success
1849  // or false if the save operation failed
1850  QString myMessage = mRasterLayer->saveDefaultStyle( defaultSavedFlag );
1851  if ( !defaultSavedFlag )
1852  {
1853  //let the user know what went wrong
1854  QMessageBox::information( this,
1855  tr( "Default Style" ),
1856  myMessage
1857  );
1858  }
1859 }
1860 
1861 
1862 void QgsRasterLayerProperties::loadStyle_clicked()
1863 {
1864  QgsSettings settings;
1865  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1866 
1867  QString fileName = QFileDialog::getOpenFileName(
1868  this,
1869  tr( "Load layer properties from style file" ),
1870  lastUsedDir,
1871  tr( "QGIS Layer Style File" ) + " (*.qml)" );
1872  if ( fileName.isEmpty() )
1873  return;
1874 
1875  // ensure the user never omits the extension from the file name
1876  if ( !fileName.endsWith( QLatin1String( ".qml" ), Qt::CaseInsensitive ) )
1877  fileName += QLatin1String( ".qml" );
1878 
1879  mOldStyle = mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() );
1880 
1881  bool defaultLoadedFlag = false;
1882  QString message = mRasterLayer->loadNamedStyle( fileName, defaultLoadedFlag );
1883  if ( defaultLoadedFlag )
1884  {
1885  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( fileName ).absolutePath() );
1886  syncToLayer();
1887  }
1888  else
1889  {
1890  QMessageBox::information( this, tr( "Save Style" ), message );
1891  }
1892 }
1893 
1894 
1895 void QgsRasterLayerProperties::saveStyleAs_clicked()
1896 {
1897  QgsSettings settings;
1898  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1899 
1900  QString outputFileName = QFileDialog::getSaveFileName(
1901  this,
1902  tr( "Save layer properties as style file" ),
1903  lastUsedDir,
1904  tr( "QGIS Layer Style File" ) + " (*.qml)" + ";;" + tr( "Styled Layer Descriptor" ) + " (*.sld)" );
1905  if ( outputFileName.isEmpty() )
1906  return;
1907 
1908  // set style type depending on extension
1909  StyleType type = StyleType::QML;
1910  if ( outputFileName.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
1911  type = StyleType::SLD;
1912  else
1913  // ensure the user never omits the extension from the file name
1914  outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "qml" ) );
1915 
1916  apply(); // make sure the style to save is up-to-date
1917 
1918  // then export style
1919  bool defaultLoadedFlag = false;
1920  QString message;
1921  switch ( type )
1922  {
1923  case QML:
1924  {
1925  message = mRasterLayer->saveNamedStyle( outputFileName, defaultLoadedFlag );
1926  break;
1927  }
1928  case SLD:
1929  {
1930  message = mRasterLayer->saveSldStyle( outputFileName, defaultLoadedFlag );
1931  break;
1932  }
1933  }
1934  if ( defaultLoadedFlag )
1935  {
1936  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( outputFileName ).absolutePath() );
1937  sync();
1938  }
1939  else
1940  QMessageBox::information( this, tr( "Save Style" ), message );
1941 }
1942 
1943 void QgsRasterLayerProperties::restoreWindowModality()
1944 {
1945  hide();
1946  setModal( true );
1947  show();
1948  raise();
1949  activateWindow();
1950 }
1951 
1952 //
1953 //
1954 // Next four methods for saving and restoring QMD metadata
1955 //
1956 //
1957 
1958 void QgsRasterLayerProperties::loadMetadata()
1959 {
1960  QgsSettings myQSettings; // where we keep last used filter in persistent state
1961  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1962 
1963  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
1964  tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1965  if ( myFileName.isNull() )
1966  {
1967  return;
1968  }
1969 
1970  QString myMessage;
1971  bool defaultLoadedFlag = false;
1972  myMessage = mRasterLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1973 
1974  //reset if the default style was loaded OK only
1975  if ( defaultLoadedFlag )
1976  {
1977  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1978  }
1979  else
1980  {
1981  //let the user know what went wrong
1982  QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1983  }
1984 
1985  QFileInfo myFI( myFileName );
1986  QString myPath = myFI.path();
1987  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1988 
1989  activateWindow(); // set focus back to properties dialog
1990 }
1991 
1992 void QgsRasterLayerProperties::saveMetadataAs()
1993 {
1994  QgsSettings myQSettings; // where we keep last used filter in persistent state
1995  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1996 
1997  QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1998  myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1999  if ( myOutputFileName.isNull() ) //dialog canceled
2000  {
2001  return;
2002  }
2003 
2004  mMetadataWidget->acceptMetadata();
2005 
2006  //ensure the user never omitted the extension from the file name
2007  if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
2008  {
2010  }
2011 
2012  bool defaultLoadedFlag = false;
2013  QString message = mRasterLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
2014  if ( defaultLoadedFlag )
2015  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
2016  else
2017  QMessageBox::information( this, tr( "Save Metadata" ), message );
2018 }
2019 
2020 void QgsRasterLayerProperties::saveDefaultMetadata()
2021 {
2022  mMetadataWidget->acceptMetadata();
2023 
2024  bool defaultSavedFlag = false;
2025  QString errorMsg = mRasterLayer->saveDefaultMetadata( defaultSavedFlag );
2026  if ( !defaultSavedFlag )
2027  {
2028  QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
2029  }
2030 }
2031 
2032 void QgsRasterLayerProperties::loadDefaultMetadata()
2033 {
2034  bool defaultLoadedFlag = false;
2035  QString myMessage = mRasterLayer->loadNamedMetadata( mRasterLayer->metadataUri(), defaultLoadedFlag );
2036  //reset if the default metadata was loaded OK only
2037  if ( defaultLoadedFlag )
2038  {
2039  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
2040  }
2041  else
2042  {
2043  QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
2044  }
2045 }
2046 
2047 
2048 void QgsRasterLayerProperties::toggleBuildPyramidsButton()
2049 {
2050  if ( lbxPyramidResolutions->selectedItems().empty() )
2051  {
2052  buttonBuildPyramids->setEnabled( false );
2053  }
2054  else
2055  {
2056  buttonBuildPyramids->setEnabled( true );
2057  }
2058 }
2059 
2060 void QgsRasterLayerProperties::mResetColorRenderingBtn_clicked()
2061 {
2062  mBlendModeComboBox->setBlendMode( QPainter::CompositionMode_SourceOver );
2063  mSliderBrightness->setValue( 0 );
2064  mSliderContrast->setValue( 0 );
2065  sliderSaturation->setValue( 0 );
2066  comboGrayscale->setCurrentIndex( ( int ) QgsHueSaturationFilter::GrayscaleOff );
2067  mColorizeCheck->setChecked( false );
2068  sliderColorizeStrength->setValue( 100 );
2069 }
2070 
2071 bool QgsRasterLayerProperties::rasterIsMultiBandColor()
2072 {
2073  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
2074 }
2075 
2076 void QgsRasterLayerProperties::updateInformationContent()
2077 {
2078  const QString myStyle = QgsApplication::reportStyleSheet( QgsApplication::StyleSheetType::WebBrowser );
2079  // Inject the stylesheet
2080  const QString html { mRasterLayer->htmlMetadata().replace( QStringLiteral( "<head>" ), QStringLiteral( R"raw(<head><style type="text/css">%1</style>)raw" ) ).arg( myStyle ) };
2081  mMetadataViewer->setHtml( html );
2082  mMetadataFilled = true;
2083 }
2084 
2085 void QgsRasterLayerProperties::onCancel()
2086 {
2087  if ( mOldStyle.xmlData() != mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() ).xmlData() )
2088  {
2089  // need to reset style to previous - style applied directly to the layer (not in apply())
2090  QString myMessage;
2091  QDomDocument doc( QStringLiteral( "qgis" ) );
2092  int errorLine, errorColumn;
2093  doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
2094  mRasterLayer->importNamedStyle( doc, myMessage );
2095  syncToLayer();
2096  }
2097 }
2098 
2099 void QgsRasterLayerProperties::showHelp()
2100 {
2101  QgsHelp::openHelp( QStringLiteral( "working_with_raster/raster_properties.html" ) );
2102 }
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:388
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:491
virtual int bandCount() const =0
Gets number of bands.
void setMetadataUrl(const QString &metaUrl)
Sets the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:399
int autoRefreshInterval
Definition: qgsmaplayer.h:84
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:350
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:79
static QString formatLayerName(const QString &name)
A convenience function to capitalize and format a layer name.
static QgsMapLayerStyleGuiUtils * instance()
returns a singleton instance of this class
Cubic Raster Resampler.
void setActive(bool activeFlag)
Activate the histogram widget.
void setRendererWidget(const QString &name, QgsRasterRendererWidget *rendererWidget=nullptr)
Sets the renderer widget (or just its name if there is no widget)
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
void setShortName(const QString &shortName)
Sets the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:258
static QString printValue(double value)
Print double value with all necessary significant digits.
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Sets the source nodata value usage.
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Sets the transparent three value pixel list, replacing the whole existing list.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
void canvasClicked(const QgsPointXY &point, Qt::MouseButton button)
signal emitted on canvas click
virtual QString saveNamedStyle(const QString &uri, bool &resultFlag, StyleCategories categories=AllStyleCategories)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
Interface for resampling rasters (e.g.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QgsHueSaturationFilter * hueSaturationFilter() const
Returns the raster&#39;s hue/saturation filter.
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
QString xmlData() const
Returns XML content of the style.
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS&#39;s underlying public inte...
Definition: qgsgui.cpp:68
void setMetadata(const QgsAbstractMetadataBase *metadata)
Sets the metadata to display in the widget.
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
QgsRasterRendererWidgetCreateFunc widgetCreateFunction
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setColorizeColor(const QColor &colorizeColor)
void setRenderer(QgsRasterRenderer *renderer)
Sets the raster&#39;s renderer.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Represents a raster layer.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the widget.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:332
A class to represent a 2D point.
Definition: qgspointxy.h:43
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:296
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer&#39;s CRS
void initOptionsBase(bool restoreUi=true, const QString &title=QString())
Set up the base ui connections for vertical tabs.
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
virtual QString type() const
virtual QString saveSldStyle(const QString &uri, bool &resultFlag) const
Saves the properties of this layer to an SLD format file.
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
void restoreOptionsBaseUi(const QString &title=QString())
Restore the base ui.
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...
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void setMetadataUrlType(const QString &metaUrlType)
Set the metadata type of the layer used by QGIS Server in GetCapabilities request MetadataUrlType ind...
Definition: qgsmaplayer.h:417
Raster values range container.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:85
Resample filter pipe for rasters.
QgsRasterRenderer * renderer() const
Returns the raster&#39;s renderer.
Thirty two bit floating point (float)
Definition: qgis.h:109
StyleType
enumeration for the different types of style
QString saveNamedMetadata(const QString &uri, bool &resultFlag)
Save the current metadata of this layer as a named metadata (either as a .qmd file on disk or as a re...
const QgsCoordinateReferenceSystem & crs
static QgsGui * instance()
Returns a pointer to the singleton instance.
Definition: qgsgui.cpp:62
bool isValid() const
Returns the status of the layer.
virtual QString buildPyramids(const QList< QgsRasterPyramid > &pyramidList, const QString &resamplingMethod="NEAREST", QgsRaster::RasterPyramidsFormat format=QgsRaster::PyramidsGTiff, const QStringList &configOptions=QStringList(), QgsRasterBlockFeedback *feedback=nullptr)
Create pyramid overviews.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsRasterLayerProperties(QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent=nullptr, Qt::WindowFlags=QgsGuiUtils::ModalDialogFlags)
Constructor.
QPixmap paletteAsPixmap(int bandNumber=1)
Returns a 100x100 pixmap of the color palette.
A wizard to edit metadata on a map layer.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:75
const QgsRasterTransparency * rasterTransparency() const
virtual QString name() const =0
Returns a provider name.
Sixty four bit floating point (double)
Definition: qgis.h:110
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
QgsBrightnessContrastFilter * brightnessFilter() const
Returns the raster&#39;s brightness/contrast filter.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
The QgsMapSettings class contains configuration for rendering of the map.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer&#39;s style manager.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition: qgis.h:116
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:971
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Creates new raster renderer widget.
QString metadataUrlFormat() const
Returns the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:444
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:304
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:272
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
virtual QString type() const =0
Gets a descriptive type identifier for this raster resampler.
virtual QList< QgsRasterPyramid > buildPyramidList(QList< int > overviewList=QList< int >())
Returns the raster layers pyramid list.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:312
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
virtual QString saveDefaultMetadata(bool &resultFlag)
Save the current metadata of this layer as the default metadata (either as a .qmd file on disk or as ...
QString legendUrl() const
Returns the URL for the layer&#39;s legend.
Definition: qgsmaplayer.h:966
static bool run(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr, const QString &windowTitle=QString())
Runs the dialog (if required) prompting for the desired transform to use from sourceCrs to destinatio...
LayerType rasterType()
Returns the raster layer type (which is a read only property).
A base dialog for options and properties dialogs that offers vertical tabs.
QgsMapLayerStyle style(const QString &name) const
Returns data of a stored style - accessed by its unique name.
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:57
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
double minimumScale() const
Returns the minimum map scale (i.e.
void setAlphaBand(int band)
double maximumScale() const
Returns the maximum map scale (i.e.
void setColorizeOn(bool colorizeOn)
void setName(const QString &name)
Set the display name of the layer.
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:341
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:976
void setLegendUrl(const QString &legendUrl)
Sets the URL for the layer&#39;s legend.
Definition: qgsmaplayer.h:961
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
void setMetadataUrlFormat(const QString &metaUrlFormat)
Sets the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:435
void acceptMetadata()
Saves the metadata to the layer.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:280
Full WKT2 string, conforming to ISO 19162:2018 / OGC 18-010, with all possible nodes and new keyword ...
QList< QgsRasterTransparency::TransparentSingleValuePixel > transparentSingleValuePixelList() const
Returns the transparent single value pixel list.
QMap< int, QVariant > results() const
Returns the identify results.
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Sets the transparent single value pixel list, replacing the whole existing list.
bool isDefault(const QString &styleName) const
Returns true if this is the default style.
static QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns a list of pyramid resampling method name and label pairs for given provider.
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Registry for raster renderer entries.
QString currentStyle() const
Returns name of the current style.
static QRegExp shortNameRegExp()
Returns the short name regular expression for line edit validator.
QImage previewAsImage(QSize size, const QColor &bgColor=Qt::white, QImage::Format format=QImage::Format_ARGB32_Premultiplied)
Draws a preview of the rasterlayer into a QImage.
void setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
virtual void doComputations()
Load programmatically with current values.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
virtual QString saveDefaultStyle(bool &resultFlag)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
QgsHueSaturationFilter::GrayscaleMode grayscaleMode() const
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
void deactivated()
signal emitted once the map tool is deactivated
void crsChanged()
If the CRS is updated.
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
void setZoomedInResampler(QgsRasterResampler *r)
Sets resampler for zoomed in scales. Takes ownership of the object.
QgsRasterResampleFilter * resampleFilter() const
Returns the raster&#39;s resample filter.
QList< QgsRasterRange > QgsRasterRangeList
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Factory method to create the renderer for this type.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:450
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
Brightness/contrast filter pipe for rasters.
Bilinear Raster Resampler.
const QgsRasterResampler * zoomedOutResampler() const
This class represents a coordinate reference system (CRS).
Color and saturation filter pipe for rasters.
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
void setZoomedOutResampler(QgsRasterResampler *r)
Sets resampler for zoomed out scales. Takes ownership of the object.
void optionsStackedWidget_CurrentChanged(int index) override
auto slot executed when the active page in the main widget stack is changed
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
Renderer for multiband images with the color components.
void setAttributionUrl(const QString &attribUrl)
Sets the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:379
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
QStackedWidget * mOptStackedWidget
QString metadataUrl() const
Returns the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:408
QString name
Definition: qgsmaplayer.h:83
void setAutoRefreshEnabled(bool enabled)
Sets whether auto refresh is enabled for the layer.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setColorizeStrength(int colorizeStrength)
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1...
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:361
virtual QString loadNamedMetadata(const QString &uri, bool &resultFlag)
Retrieve a named metadata for this layer if one exists (either as a .qmd file on disk or as a record ...
bool hasAutoRefreshEnabled() const
Returns true if auto refresh is enabled for the layer.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
QList< QgsRasterTransparency::TransparentThreeValuePixel > transparentThreeValuePixelList() const
Returns the transparent three value pixel list.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
void addStyleManagerActions(QMenu *m, QgsMapLayer *layer)
adds actions to the menu in accordance to the layer
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
virtual QgsRasterRenderer * renderer()=0
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer&#39;s CRS
void setRasterTransparency(QgsRasterTransparency *t)
RasterPyramidsFormat
Definition: qgsraster.h:81
Feedback object tailored for raster block reading.
virtual void optionsStackedWidget_CurrentChanged(int index)
Select relevant tab on current page change.
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:323
void insertWidgetFunction(const QString &rendererName, QgsRasterRendererWidgetCreateFunc func)
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application&#39;s raster renderer registry, used for managing raster layer renderers...
Raster renderer pipe that applies colors to a raster.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:288
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:86
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:370
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition: qgis.h:115
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QString metadataUrlType() const
Returns the metadata type of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:426
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
void setGrayscaleMode(QgsHueSaturationFilter::GrayscaleMode grayscaleMode)
void setSaturation(int saturation)
const QgsRasterResampler * zoomedInResampler() const
Base class for raster data providers.
virtual QString metadataUri() const
Retrieve the metadata URI for this layer (either as a .qmd file on disk or as a record in the users s...