QGIS API Documentation  3.21.0-Master (5b68dc587e)
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 : [email protected]
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"
24 #include "qgscontrastenhancement.h"
25 #include "qgscoordinatetransform.h"
27 #include "qgslogger.h"
28 #include "qgsmapcanvas.h"
30 #include "qgsmaptoolemitpoint.h"
31 #include "qgsmaptopixel.h"
32 #include "qgsmetadatawidget.h"
36 #include "qgsnative.h"
40 #include "qgsproject.h"
41 #include "qgsrasterbandstats.h"
43 #include "qgsrasterdataprovider.h"
47 #include "qgsrasterlayer.h"
49 #include "qgsrasterpyramid.h"
50 #include "qgsrasterrange.h"
51 #include "qgsrasterrenderer.h"
53 #include "qgsrastertransparency.h"
56 #include "qgshuesaturationfilter.h"
58 #include "qgssettings.h"
60 #include "qgsmaplayerlegend.h"
61 #include "qgsfileutils.h"
62 #include "qgswebview.h"
63 #include "qgsvectorlayer.h"
64 #include "qgsprovidermetadata.h"
65 #include "qgsproviderregistry.h"
67 #include "qgsdoublevalidator.h"
69 
71 #include "qgsprojecttimesettings.h"
73 
74 #include <QDesktopServices>
75 #include <QTableWidgetItem>
76 #include <QHeaderView>
77 #include <QTextStream>
78 #include <QFile>
79 #include <QFileDialog>
80 #include <QMessageBox>
81 #include <QPainter>
82 #include <QLinearGradient>
83 #include <QPainterPath>
84 #include <QPolygonF>
85 #include <QColorDialog>
86 #include <QList>
87 #include <QMouseEvent>
88 #include <QVector>
89 #include <QUrl>
90 #include <QMenu>
91 #include <QScreen>
92 #include <QRegularExpressionValidator>
93 #include <QRegularExpression>
94 
95 QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags fl )
96  : QgsOptionsDialogBase( QStringLiteral( "RasterLayerProperties" ), parent, fl )
97  // Constant that signals property not used.
98  , TRSTRING_NOT_SET( tr( "Not Set" ) )
99  , mDefaultStandardDeviation( 0 )
100  , mDefaultRedBand( 0 )
101  , mDefaultGreenBand( 0 )
102  , mDefaultBlueBand( 0 )
103  , mRasterLayer( qobject_cast<QgsRasterLayer *>( lyr ) )
104  , mGradientHeight( 0.0 )
105  , mGradientWidth( 0.0 )
106  , mMapCanvas( canvas )
107  , mMetadataFilled( false )
108 {
109  mGrayMinimumMaximumEstimated = true;
110  mRGBMinimumMaximumEstimated = true;
111 
112  setupUi( this );
113 
114  mMetadataViewer = new QgsWebView( this );
115  mOptsPage_Information->layout()->addWidget( mMetadataViewer );
116 
117  mRasterTransparencyWidget = new QgsRasterTransparencyWidget( mRasterLayer, canvas, this );
118 
119  transparencyScrollArea->setWidget( mRasterTransparencyWidget );
120 
121  connect( buttonBuildPyramids, &QPushButton::clicked, this, &QgsRasterLayerProperties::buttonBuildPyramids_clicked );
122  connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsRasterLayerProperties::mCrsSelector_crsChanged );
123  connect( mRenderTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged );
124  connect( mResetColorRenderingBtn, &QToolButton::clicked, this, &QgsRasterLayerProperties::mResetColorRenderingBtn_clicked );
125  connect( buttonRemoveMetadataUrl, &QPushButton::clicked, this, &QgsRasterLayerProperties::removeSelectedMetadataUrl );
126  connect( buttonAddMetadataUrl, &QPushButton::clicked, this, &QgsRasterLayerProperties::addMetadataUrl );
127  // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
128  // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
129  // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
130  initOptionsBase( false );
131  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsRasterLayerProperties::showHelp );
132 
133  mSourceGroupBox->hide();
134 
135  mBtnStyle = new QPushButton( tr( "Style" ) );
136  QMenu *menuStyle = new QMenu( this );
137  menuStyle->addAction( tr( "Load Style…" ), this, &QgsRasterLayerProperties::loadStyle_clicked );
138  menuStyle->addAction( tr( "Save Style…" ), this, &QgsRasterLayerProperties::saveStyleAs_clicked );
139  menuStyle->addSeparator();
140  menuStyle->addAction( tr( "Save as Default" ), this, &QgsRasterLayerProperties::saveDefaultStyle_clicked );
141  menuStyle->addAction( tr( "Restore Default" ), this, &QgsRasterLayerProperties::loadDefaultStyle_clicked );
142  mBtnStyle->setMenu( menuStyle );
143  connect( menuStyle, &QMenu::aboutToShow, this, &QgsRasterLayerProperties::aboutToShowStyleMenu );
144  buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
145 
146  mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
147  QMenu *menuMetadata = new QMenu( this );
148  mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsRasterLayerProperties::loadMetadata );
149  mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsRasterLayerProperties::saveMetadataAs );
150  menuMetadata->addSeparator();
151  menuMetadata->addAction( tr( "Save as Default" ), this, &QgsRasterLayerProperties::saveDefaultMetadata );
152  menuMetadata->addAction( tr( "Restore Default" ), this, &QgsRasterLayerProperties::loadDefaultMetadata );
153  mBtnMetadata->setMenu( menuMetadata );
154  buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
155 
156  connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsRasterLayerProperties::syncToLayer );
157 
158  connect( this, &QDialog::accepted, this, &QgsRasterLayerProperties::apply );
159  connect( this, &QDialog::rejected, this, &QgsRasterLayerProperties::onCancel );
160 
161  connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsRasterLayerProperties::apply );
162 
163  // brightness/contrast controls
164  connect( mSliderBrightness, &QAbstractSlider::valueChanged, mBrightnessSpinBox, &QSpinBox::setValue );
165  connect( mBrightnessSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mSliderBrightness, &QAbstractSlider::setValue );
166  mBrightnessSpinBox->setClearValue( 0 );
167 
168  connect( mSliderContrast, &QAbstractSlider::valueChanged, mContrastSpinBox, &QSpinBox::setValue );
169  connect( mContrastSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), mSliderContrast, &QAbstractSlider::setValue );
170  mContrastSpinBox->setClearValue( 0 );
171 
172  // gamma correction controls
173  connect( mSliderGamma, &QAbstractSlider::valueChanged, this, &QgsRasterLayerProperties::updateGammaSpinBox );
174  connect( mGammaSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsRasterLayerProperties::updateGammaSlider );
175  mGammaSpinBox->setClearValue( 1.0 );
176 
177  // Connect saturation slider and spin box
178  connect( sliderSaturation, &QAbstractSlider::valueChanged, spinBoxSaturation, &QSpinBox::setValue );
179  connect( spinBoxSaturation, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), sliderSaturation, &QAbstractSlider::setValue );
180  spinBoxSaturation->setClearValue( 0 );
181 
182  // Connect colorize strength slider and spin box
183  connect( sliderColorizeStrength, &QAbstractSlider::valueChanged, spinColorizeStrength, &QSpinBox::setValue );
184  connect( spinColorizeStrength, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), sliderColorizeStrength, &QAbstractSlider::setValue );
185  spinColorizeStrength->setClearValue( 100 );
186 
187  // enable or disable saturation slider and spin box depending on grayscale combo choice
188  connect( comboGrayscale, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsRasterLayerProperties::toggleSaturationControls );
189 
190  // enable or disable colorize colorbutton with colorize checkbox
191  connect( mColorizeCheck, &QAbstractButton::toggled, this, &QgsRasterLayerProperties::toggleColorizeControls );
192 
193  // enable or disable Build Pyramids button depending on selection in pyramid list
194  connect( lbxPyramidResolutions, &QListWidget::itemSelectionChanged, this, &QgsRasterLayerProperties::toggleBuildPyramidsButton );
195 
196  connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );
197 
198  // set up the scale based layer visibility stuff....
199  mScaleRangeWidget->setMapCanvas( mMapCanvas );
200  chkUseScaleDependentRendering->setChecked( lyr->hasScaleBasedVisibility() );
201  mScaleRangeWidget->setScaleRange( lyr->minimumScale(), lyr->maximumScale() );
202 
203  // Setup the layer metadata URL
204  tableViewMetadataUrl->setSelectionMode( QAbstractItemView::SingleSelection );
205  tableViewMetadataUrl->setSelectionBehavior( QAbstractItemView::SelectRows );
206  tableViewMetadataUrl->horizontalHeader()->setStretchLastSection( true );
207  tableViewMetadataUrl->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
208 
209  mMetadataUrlModel = new QStandardItemModel( tableViewMetadataUrl );
210  mMetadataUrlModel->clear();
211  mMetadataUrlModel->setColumnCount( 3 );
212  QStringList metadataUrlHeaders;
213  metadataUrlHeaders << tr( "URL" ) << tr( "Type" ) << tr( "Format" );
214  mMetadataUrlModel->setHorizontalHeaderLabels( metadataUrlHeaders );
215  tableViewMetadataUrl->setModel( mMetadataUrlModel );
216  tableViewMetadataUrl->setItemDelegate( new MetadataUrlItemDelegate( this ) );
217 
218  // build GUI components
219  QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
220  QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
221 
222  mRasterTransparencyWidget->pbnAddValuesManually->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
223  mRasterTransparencyWidget->pbnAddValuesFromDisplay->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionContextHelp.png" ) ) );
224  mRasterTransparencyWidget->pbnRemoveSelectedRow->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyRemove.svg" ) ) );
225  mRasterTransparencyWidget->pbnDefaultValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) );
226  mRasterTransparencyWidget->pbnImportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
227  mRasterTransparencyWidget->pbnExportTransparentPixelValues->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileSave.svg" ) ) );
228 
229 
230  if ( !mRasterLayer )
231  {
232  return;
233  }
234 
235  // Handles window modality raising canvas
236  if ( mMapCanvas && mRasterTransparencyWidget->pixelSelectorTool() )
237  {
238 
239  connect( mRasterTransparencyWidget->pixelSelectorTool(), &QgsMapToolEmitPoint::deactivated, this, [ = ]
240  {
241  hide();
242  setModal( true );
243  show();
244  raise();
245  activateWindow();
246  } );
247 
248  connect( mRasterTransparencyWidget->pbnAddValuesFromDisplay, &QPushButton::clicked, this, [ = ]
249  {
250  hide();
251  setModal( false );
252 
253  // Transfer focus to the canvas to use the selector tool
254  mMapCanvas->window()->raise();
255  mMapCanvas->window()->activateWindow();
256  mMapCanvas->window()->setFocus();
257  } );
258  }
259 
263  if ( mMapCanvas )
264  mContext << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() );
265  mContext << QgsExpressionContextUtils::layerScope( mRasterLayer );
266 
267  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
268 
269  // Only do pyramids if dealing directly with GDAL.
270  if ( provider && provider->capabilities() & QgsRasterDataProvider::BuildPyramids )
271  {
272  // initialize resampling methods
273  cboResamplingMethod->clear();
274 
275  const auto constProviderType = QgsRasterDataProvider::pyramidResamplingMethods( mRasterLayer->providerType() );
276  for ( const QPair<QString, QString> &method : std::as_const( constProviderType ) )
277  {
278  cboResamplingMethod->addItem( method.second, method.first );
279  }
280 
281  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
282  QString prefix = provider->name() + "/driverOptions/_pyramids/";
283  QgsSettings mySettings;
284  QString defaultMethod = mySettings.value( prefix + "resampling", "AVERAGE" ).toString();
285  int idx = cboResamplingMethod->findData( defaultMethod );
286  if ( idx >= 0 )
287  cboResamplingMethod->setCurrentIndex( idx );
288 
289 
290  // build pyramid list
291  const QList< QgsRasterPyramid > myPyramidList = provider->buildPyramidList();
292 
293  for ( const QgsRasterPyramid &pyramid : myPyramidList )
294  {
295  if ( pyramid.getExists() )
296  {
297  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
298  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
299  QString::number( pyramid.getYDim() ) ) );
300  }
301  else
302  {
303  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
304  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
305  QString::number( pyramid.getYDim() ) ) );
306  }
307  }
308  }
309  else
310  {
311  // disable Pyramids tab completely
312  mOptsPage_Pyramids->setEnabled( false );
313  }
314 
315  // We can calculate histogram for all data sources but estimated only if
316  // size is unknown - could also be enabled if well supported (estimated histogram
317  // and let user know that it is estimated)
318  if ( !provider || !( provider->capabilities() & QgsRasterDataProvider::Size ) )
319  {
320  // disable Histogram tab completely
321  mOptsPage_Histogram->setEnabled( false );
322  }
323 
324  QVBoxLayout *layout = new QVBoxLayout( metadataFrame );
325  layout->setContentsMargins( 0, 0, 0, 0 );
326  mMetadataWidget = new QgsMetadataWidget( this, mRasterLayer );
327  mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
328  mMetadataWidget->setMapCanvas( mMapCanvas );
329  layout->addWidget( mMetadataWidget );
330  metadataFrame->setLayout( layout );
331 
332  QVBoxLayout *temporalLayout = new QVBoxLayout( temporalFrame );
333  temporalLayout->setContentsMargins( 0, 0, 0, 0 );
334  mTemporalWidget = new QgsRasterLayerTemporalPropertiesWidget( this, mRasterLayer );
335  temporalLayout->addWidget( mTemporalWidget );
336 
337  QgsDebugMsgLevel( "Setting crs to " + mRasterLayer->crs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ), 2 );
338  QgsDebugMsgLevel( "Setting crs to " + mRasterLayer->crs().userFriendlyIdentifier(), 2 );
339  mCrsSelector->setCrs( mRasterLayer->crs() );
340 
341  // Set text for pyramid info box
342  QString pyramidFormat( QStringLiteral( "<h2>%1</h2><p>%2 %3 %4</p><b><font color='red'><p>%5</p><p>%6</p>" ) );
343  QString pyramidHeader = tr( "Description" );
344  QString pyramidSentence1 = tr( "Large resolution raster layers can slow navigation in QGIS." );
345  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." );
346  QString pyramidSentence3 = tr( "You must have write access in the directory where the original data is stored to build pyramids." );
347  QString pyramidSentence4 = tr( "Please note that building internal pyramids may alter the original data file and once created they cannot be removed!" );
348  QString pyramidSentence5 = tr( "Please note that building internal pyramids could corrupt your image - always make a backup of your data first!" );
349 
350  tePyramidDescription->setHtml( pyramidFormat.arg( pyramidHeader,
351  pyramidSentence1,
352  pyramidSentence2,
353  pyramidSentence3,
354  pyramidSentence4,
355  pyramidSentence5 ) );
356 
357  //resampling
358  mResamplingGroupBox->setSaveCheckedState( true );
359  mResamplingUtils.initWidgets( mRasterLayer, mZoomedInResamplingComboBox, mZoomedOutResamplingComboBox, mMaximumOversamplingSpinBox, mCbEarlyResampling );
360  mResamplingUtils.refreshWidgetsFromLayer();
361 
362  const QgsRasterRenderer *renderer = mRasterLayer->renderer();
363 
364  btnColorizeColor->setColorDialogTitle( tr( "Select Color" ) );
365  btnColorizeColor->setContext( QStringLiteral( "symbology" ) );
366 
367  // Hue and saturation color control
368  const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
369  //set hue and saturation controls to current values
370  if ( hueSaturationFilter )
371  {
372  sliderSaturation->setValue( hueSaturationFilter->saturation() );
373  comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
374 
375  // Set initial state of saturation controls based on grayscale mode choice
376  toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
377 
378  // Set initial state of colorize controls
379  mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
380  btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
381  toggleColorizeControls( hueSaturationFilter->colorizeOn() );
382  sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
383  mInvertColorsCheck->setChecked( hueSaturationFilter->invertColors() );
384  }
385 
386  //blend mode
387  mBlendModeComboBox->setBlendMode( mRasterLayer->blendMode() );
388 
389  //transparency band
390  if ( provider )
391  {
392  mRasterTransparencyWidget->cboxTransparencyBand->setShowNotSetOption( true, tr( "None" ) );
393  mRasterTransparencyWidget->cboxTransparencyBand->setLayer( mRasterLayer );
394 
395 // Alpha band is set in sync()
396 #if 0
397  if ( renderer )
398  {
399  QgsDebugMsg( QStringLiteral( "alphaBand = %1" ).arg( renderer->alphaBand() ) );
400  if ( renderer->alphaBand() > 0 )
401  {
402  cboxTransparencyBand->setCurrentIndex( cboxTransparencyBand->findData( renderer->alphaBand() ) );
403  }
404  }
405 #endif
406  }
407 
408  // create histogram widget
409  mHistogramWidget = nullptr;
410  if ( mOptsPage_Histogram->isEnabled() )
411  {
412  mHistogramWidget = new QgsRasterHistogramWidget( mRasterLayer, mOptsPage_Histogram );
413  mHistogramStackedWidget->addWidget( mHistogramWidget );
414  }
415 
416  //insert renderer widgets into registry
423 
424  //fill available renderers into combo box
426  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
427  const auto constRenderersList = QgsApplication::rasterRendererRegistry()->renderersList();
428  for ( const QString &name : constRenderersList )
429  {
430  if ( QgsApplication::rasterRendererRegistry()->rendererData( name, entry ) )
431  {
432  if ( ( mRasterLayer->rasterType() != QgsRasterLayer::ColorLayer && entry.name != QLatin1String( "singlebandcolordata" ) ) ||
433  ( mRasterLayer->rasterType() == QgsRasterLayer::ColorLayer && entry.name == QLatin1String( "singlebandcolordata" ) ) )
434  {
435  mRenderTypeComboBox->addItem( entry.visibleName, entry.name );
436  }
437  }
438  }
439  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
440 
441  int widgetIndex = 0;
442  if ( renderer )
443  {
444  QString rendererType = renderer->type();
445  widgetIndex = mRenderTypeComboBox->findData( rendererType );
446  if ( widgetIndex != -1 )
447  {
448  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
449  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
450  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
451  }
452 
453  if ( rendererType == QLatin1String( "singlebandcolordata" ) && mRenderTypeComboBox->count() == 1 )
454  {
455  // no band rendering options for singlebandcolordata, so minimize group box
456  QSizePolicy sizep = mBandRenderingGrpBx->sizePolicy();
457  sizep.setVerticalStretch( 0 );
458  sizep.setVerticalPolicy( QSizePolicy::Maximum );
459  mBandRenderingGrpBx->setSizePolicy( sizep );
460  mBandRenderingGrpBx->updateGeometry();
461  }
462 
463  if ( mRasterLayer->providerType() != QLatin1String( "wms" ) )
464  {
465  mWMSPrintGroupBox->hide();
466  mPublishDataSourceUrlCheckBox->hide();
467  mBackgroundLayerCheckBox->hide();
468  }
469  }
470 
471 #ifdef WITH_QTWEBKIT
472  // Setup information tab
473 
474  const int horizontalDpi = logicalDpiX();
475 
476  // Adjust zoom: text is ok, but HTML seems rather big at least on Linux/KDE
477  if ( horizontalDpi > 96 )
478  {
479  mMetadataViewer->setZoomFactor( mMetadataViewer->zoomFactor() * 0.9 );
480  }
481  mMetadataViewer->page()->setLinkDelegationPolicy( QWebPage::LinkDelegationPolicy::DelegateAllLinks );
482  connect( mMetadataViewer->page(), &QWebPage::linkClicked, this, &QgsRasterLayerProperties::urlClicked );
483  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
484  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
485 
486 #endif
487 
488  initializeDataDefinedButton( mRasterTransparencyWidget->mOpacityDDBtn, QgsRasterPipe::RendererOpacity );
489 
490  mRenderTypeComboBox_currentIndexChanged( widgetIndex );
491 
492  // update based on lyr's current state
493  sync();
494 
495  QgsSettings settings;
496  // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
497  // this will be read by restoreOptionsBaseUi()
498  if ( !settings.contains( QStringLiteral( "/Windows/RasterLayerProperties/tab" ) ) )
499  {
500  settings.setValue( QStringLiteral( "Windows/RasterLayerProperties/tab" ),
501  mOptStackedWidget->indexOf( mOptsPage_Style ) );
502  }
503 
504  mResetColorRenderingBtn->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
505 
506  QString title = tr( "Layer Properties — %1" ).arg( lyr->name() );
507 
508  if ( !mRasterLayer->styleManager()->isDefault( mRasterLayer->styleManager()->currentStyle() ) )
509  title += QStringLiteral( " (%1)" ).arg( mRasterLayer->styleManager()->currentStyle() );
510  restoreOptionsBaseUi( title );
511  optionsStackedWidget_CurrentChanged( mOptionsStackedWidget->currentIndex() );
512 
513  //Add help page references
514  mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#information-properties" ) );
515  mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#source-properties" ) );
516  mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#symbology-properties" ) );
517  mOptsPage_Transparency->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#transparency-properties" ) );
518 
519  if ( mOptsPage_Histogram )
520  mOptsPage_Histogram->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#histogram-properties" ) );
521 
522  mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#rendering-properties" ) );
523 
524  if ( mOptsPage_Pyramids )
525  mOptsPage_Pyramids->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#pyramids-properties" ) );
526 
527  mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#metadata-properties" ) );
528  mOptsPage_Legend->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#legend-properties" ) );
529  mOptsPage_Server->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#server-properties" ) );
530 }
531 
533 {
534  if ( !factory->supportsLayer( mRasterLayer ) || !factory->supportLayerPropertiesDialog() )
535  {
536  return;
537  }
538 
539  QgsMapLayerConfigWidget *page = factory->createWidget( mRasterLayer, nullptr, false, this );
540  switch ( factory->parentPage() )
541  {
543  {
544  mLayerPropertiesPages << page;
545 
546  const QString beforePage = factory->layerPropertiesPagePositionHint();
547  if ( beforePage.isEmpty() )
548  addPage( factory->title(), factory->title(), factory->icon(), page );
549  else
550  insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage );
551  break;
552  }
553 
555  mTemporalWidget->addWidget( page );
556  break;
557  }
558 }
559 
561 {
562  return mContext;
563 }
564 
565 void QgsRasterLayerProperties::setRendererWidget( const QString &rendererName )
566 {
567  QgsDebugMsgLevel( "rendererName = " + rendererName, 3 );
568  QgsRasterRendererWidget *oldWidget = mRendererWidget;
569  QgsRasterRenderer *oldRenderer = mRasterLayer->renderer();
570 
571  int alphaBand = -1;
572  double opacity = 1;
573  QColor nodataColor;
574  if ( oldRenderer )
575  {
576  // Retain alpha band and opacity when switching renderer
577  alphaBand = oldRenderer->alphaBand();
578  opacity = oldRenderer->opacity();
579  nodataColor = oldRenderer->nodataColor();
580  }
581 
582  QgsRasterRendererRegistryEntry rendererEntry;
583  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererName, rendererEntry ) )
584  {
585  if ( rendererEntry.widgetCreateFunction ) //single band color data renderer e.g. has no widget
586  {
587  QgsDebugMsgLevel( QStringLiteral( "renderer has widgetCreateFunction" ), 3 );
588  // Current canvas extent (used to calc min/max) in layer CRS
589  QgsRectangle myExtent = mMapCanvas->mapSettings().outputExtentToLayerExtent( mRasterLayer, mMapCanvas->extent() );
590  if ( oldWidget && ( !oldRenderer || rendererName != oldRenderer->type() ) )
591  {
592  if ( rendererName == QLatin1String( "singlebandgray" ) )
593  {
594  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::SingleBandGray, mRasterLayer->dataProvider() ) );
595  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
596  }
597  else if ( rendererName == QLatin1String( "multibandcolor" ) )
598  {
599  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::MultiBandColor, mRasterLayer->dataProvider() ) );
600  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
601  }
602  }
603  mRasterLayer->renderer()->setAlphaBand( alphaBand );
604  mRasterLayer->renderer()->setOpacity( opacity );
605  mRasterLayer->renderer()->setNodataColor( nodataColor );
606  mRendererWidget = rendererEntry.widgetCreateFunction( mRasterLayer, myExtent );
607  mRendererWidget->setMapCanvas( mMapCanvas );
608  mRendererStackedWidget->addWidget( mRendererWidget );
609  if ( oldWidget )
610  {
611  //compare used bands in new and old renderer and reset transparency dialog if different
612  std::unique_ptr<QgsRasterRenderer> oldRenderer;
613  oldRenderer.reset( oldWidget->renderer() );
614  std::unique_ptr<QgsRasterRenderer> newRenderer;
615  newRenderer.reset( mRendererWidget->renderer() );
616  const QList<int> oldBands = oldRenderer->usesBands();
617  const QList<int> newBands = newRenderer->usesBands();
618  if ( oldBands != newBands )
619  {
620  mRasterTransparencyWidget->syncToLayer();
621  }
622  }
623  }
624  }
625 
626  const int widgetIndex = mRenderTypeComboBox->findData( rendererName );
627  if ( widgetIndex != -1 )
628  {
629  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
630  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
631  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
632  }
633 
634  if ( mRendererWidget != oldWidget )
635  delete oldWidget;
636 
637  if ( mHistogramWidget )
638  {
639  mHistogramWidget->setRendererWidget( rendererName, mRendererWidget );
640  }
641 }
642 
643 void QgsRasterLayerProperties::sync()
644 {
645  QgsSettings myQSettings;
646 
647  if ( !mSourceWidget )
648  {
649  mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mRasterLayer );
650  if ( mSourceWidget )
651  {
652  QHBoxLayout *layout = new QHBoxLayout();
653  layout->addWidget( mSourceWidget );
654  mSourceGroupBox->setLayout( layout );
655  mSourceGroupBox->show();
656 
657  connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [ = ]( bool isValid )
658  {
659  buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
660  buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
661  } );
662  }
663  }
664 
665  if ( mSourceWidget )
666  mSourceWidget->setSourceUri( mRasterLayer->source() );
667 
668  const QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
669  if ( !provider )
670  return;
671 
672  if ( provider->dataType( 1 ) == Qgis::DataType::ARGB32
673  || provider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
674  {
675  mRasterTransparencyWidget->gboxNoDataValue->setEnabled( false );
676  mRasterTransparencyWidget->gboxCustomTransparency->setEnabled( false );
677  mOptionsStackedWidget->setCurrentWidget( mOptsPage_Server );
678  }
679 
680  // TODO: Wouldn't it be better to just removeWidget() the tabs than delete them? [LS]
681  if ( !( provider->capabilities() & QgsRasterDataProvider::BuildPyramids ) )
682  {
683  if ( mOptsPage_Pyramids )
684  {
685  delete mOptsPage_Pyramids;
686  mOptsPage_Pyramids = nullptr;
687  }
688  }
689 
690  if ( !( provider->capabilities() & QgsRasterDataProvider::Size ) )
691  {
692  if ( mOptsPage_Histogram )
693  {
694  delete mOptsPage_Histogram;
695  mOptsPage_Histogram = nullptr;
696  delete mHistogramWidget;
697  mHistogramWidget = nullptr;
698  }
699  }
700 
701  QgsDebugMsgLevel( QStringLiteral( "populate transparency tab" ), 3 );
702 
703  /*
704  * Style tab
705  */
706 
707  //set brightness, contrast and gamma
708  QgsBrightnessContrastFilter *brightnessFilter = mRasterLayer->brightnessFilter();
709  if ( brightnessFilter )
710  {
711  mSliderBrightness->setValue( brightnessFilter->brightness() );
712  mSliderContrast->setValue( brightnessFilter->contrast() );
713  mGammaSpinBox->setValue( brightnessFilter->gamma() );
714  }
715 
716  // Hue and saturation color control
717  const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
718  //set hue and saturation controls to current values
719  if ( hueSaturationFilter )
720  {
721  sliderSaturation->setValue( hueSaturationFilter->saturation() );
722  comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
723 
724  // Set state of saturation controls based on grayscale mode choice
725  toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
726 
727  // Set state of colorize controls
728  mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
729  btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
730  toggleColorizeControls( hueSaturationFilter->colorizeOn() );
731  sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
732  mInvertColorsCheck->setChecked( hueSaturationFilter->invertColors() );
733  }
734 
735  /*
736  * Transparent Pixel Tab
737  */
738 
739  //set the transparency slider
740  QgsRasterRenderer *renderer = mRasterLayer->renderer();
741  if ( renderer )
742  {
743  mRasterTransparencyWidget->mOpacityWidget->setOpacity( renderer->opacity() );
744  mRasterTransparencyWidget->cboxTransparencyBand->setBand( renderer->alphaBand() );
745  }
746 
747  //add current NoDataValue to NoDataValue line edit
748  // TODO: should be per band
749  // TODO: no data ranges
750  if ( provider->sourceHasNoDataValue( 1 ) )
751  {
752  double v = QgsRasterBlock::printValue( provider->sourceNoDataValue( 1 ) ).toDouble();
753  mRasterTransparencyWidget->lblSrcNoDataValue->setText( QLocale().toString( v, 'g' ) );
754  }
755  else
756  {
757  mRasterTransparencyWidget->lblSrcNoDataValue->setText( tr( "not defined" ) );
758  }
759 
760  mRasterTransparencyWidget->mSrcNoDataValueCheckBox->setChecked( provider->useSourceNoDataValue( 1 ) );
761 
762  bool enableSrcNoData = provider->sourceHasNoDataValue( 1 ) && !std::isnan( provider->sourceNoDataValue( 1 ) );
763 
764  mRasterTransparencyWidget->mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData );
765  mRasterTransparencyWidget->lblSrcNoDataValue->setEnabled( enableSrcNoData );
766 
767  QgsRasterRangeList noDataRangeList = provider->userNoDataValues( 1 );
768  QgsDebugMsgLevel( QStringLiteral( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ), 3 );
769  if ( !noDataRangeList.isEmpty() )
770  {
771  mRasterTransparencyWidget->leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) );
772  }
773  else
774  {
775  mRasterTransparencyWidget->leNoDataValue->insert( QString() );
776  }
777 
778  mRefreshLayerCheckBox->setChecked( mRasterLayer->hasAutoRefreshEnabled() );
779  mRefreshLayerIntervalSpinBox->setEnabled( mRasterLayer->hasAutoRefreshEnabled() );
780  mRefreshLayerIntervalSpinBox->setValue( mRasterLayer->autoRefreshInterval() / 1000.0 );
781 
782  QgsDebugMsgLevel( QStringLiteral( "populate colormap tab" ), 3 );
783  /*
784  * Transparent Pixel Tab
785  */
786 
787  QgsDebugMsgLevel( QStringLiteral( "populate general tab" ), 3 );
788  /*
789  * General Tab
790  */
791 
792  mLayerOrigNameLineEd->setText( mRasterLayer->name() );
793 
794  QgsDebugMsgLevel( QStringLiteral( "populate metadata tab" ), 2 );
795  /*
796  * Metadata Tab
797  */
798  //populate the metadata tab's text browser widget with gdal metadata info
799  updateInformationContent();
800 
801  // WMS Name as layer short name
802  mLayerShortNameLineEdit->setText( mRasterLayer->shortName() );
803  // WMS Name validator
804  QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
805  mLayerShortNameLineEdit->setValidator( shortNameValidator );
806 
807  //layer title and abstract
808  mLayerTitleLineEdit->setText( mRasterLayer->title() );
809  mLayerAbstractTextEdit->setPlainText( mRasterLayer->abstract() );
810  mLayerKeywordListLineEdit->setText( mRasterLayer->keywordList() );
811  mLayerDataUrlLineEdit->setText( mRasterLayer->dataUrl() );
812  mLayerDataUrlFormatComboBox->setCurrentIndex(
813  mLayerDataUrlFormatComboBox->findText(
814  mRasterLayer->dataUrlFormat()
815  )
816  );
817 
818  //layer attribution
819  mLayerAttributionLineEdit->setText( mRasterLayer->attribution() );
820  mLayerAttributionUrlLineEdit->setText( mRasterLayer->attributionUrl() );
821 
822  // layer metadata url
823  const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mRasterLayer->serverProperties()->metadataUrls();
824  for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
825  {
826  const int row = mMetadataUrlModel->rowCount();
827  mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
828  mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
829  mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
830  }
831 
832  // layer legend url
833  mLayerLegendUrlLineEdit->setText( mRasterLayer->legendUrl() );
834  mLayerLegendUrlFormatComboBox->setCurrentIndex( mLayerLegendUrlFormatComboBox->findText( mRasterLayer->legendUrlFormat() ) );
835 
836  //WMS print layer
837  QVariant wmsPrintLayer = mRasterLayer->customProperty( QStringLiteral( "WMSPrintLayer" ) );
838  if ( wmsPrintLayer.isValid() )
839  {
840  mWMSPrintLayerLineEdit->setText( wmsPrintLayer.toString() );
841  }
842 
843  QVariant wmsPublishDataSourceUrl = mRasterLayer->customProperty( QStringLiteral( "WMSPublishDataSourceUrl" ), false );
844  mPublishDataSourceUrlCheckBox->setChecked( wmsPublishDataSourceUrl.toBool() );
845 
846  QVariant wmsBackgroundLayer = mRasterLayer->customProperty( QStringLiteral( "WMSBackgroundLayer" ), false );
847  mBackgroundLayerCheckBox->setChecked( wmsBackgroundLayer.toBool() );
848 
849  mLegendPlaceholderWidget->setLastPathSettingsKey( QStringLiteral( "lastLegendPlaceholderDir" ) );
850  mLegendPlaceholderWidget->setSource( mRasterLayer->legendPlaceholderImage() );
851  mLegendConfigEmbeddedWidget->setLayer( mRasterLayer );
852 
853  mTemporalWidget->syncToLayer();
854 
855  mPropertyCollection = mRasterLayer->pipe()->dataDefinedProperties();
856  updateDataDefinedButtons();
857 
858  for ( QgsMapLayerConfigWidget *page : std::as_const( mLayerPropertiesPages ) )
859  {
860  page->syncToLayer( mRasterLayer );
861  }
862 
863 }
864 
865 void QgsRasterLayerProperties::apply()
866 {
867  if ( mSourceWidget )
868  {
869  const QString newSource = mSourceWidget->sourceUri();
870  if ( newSource != mRasterLayer->source() )
871  {
872  mRasterLayer->setDataSource( newSource, mRasterLayer->name(), mRasterLayer->providerType(), QgsDataProvider::ProviderOptions() );
873  }
874  }
875 
876  // Do nothing on "bad" layers
877  if ( !mRasterLayer->isValid() )
878  return;
879 
880  /*
881  * Legend Tab
882  */
883  mRasterLayer->setLegendPlaceholderImage( mLegendPlaceholderWidget->source() );
884  mLegendConfigEmbeddedWidget->applyToLayer();
885 
886  QgsDebugMsgLevel( QStringLiteral( "apply processing symbology tab" ), 3 );
887  /*
888  * Symbology Tab
889  */
890 
891  //set whether the layer histogram should be inverted
892  //mRasterLayer->setInvertHistogram( cboxInvertColorMap->isChecked() );
893 
894  mRasterLayer->brightnessFilter()->setBrightness( mSliderBrightness->value() );
895  mRasterLayer->brightnessFilter()->setContrast( mSliderContrast->value() );
896  mRasterLayer->brightnessFilter()->setGamma( mGammaSpinBox->value() );
897 
898  QgsDebugMsgLevel( QStringLiteral( "processing transparency tab" ), 3 );
899  /*
900  * Transparent Pixel Tab
901  */
902 
903  //set NoDataValue
904  QgsRasterRangeList myNoDataRangeList;
905  if ( "" != mRasterTransparencyWidget->leNoDataValue->text() )
906  {
907  bool myDoubleOk = false;
908  double myNoDataValue = QgsDoubleValidator::toDouble( mRasterTransparencyWidget->leNoDataValue->text(), &myDoubleOk );
909  if ( myDoubleOk )
910  {
911  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
912  myNoDataRangeList << myNoDataRange;
913  }
914  }
915  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
916  {
917  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
918  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mRasterTransparencyWidget->mSrcNoDataValueCheckBox->isChecked() );
919  }
920 
921  //set renderer from widget
922  QgsRasterRendererWidget *rendererWidget = dynamic_cast<QgsRasterRendererWidget *>( mRendererStackedWidget->currentWidget() );
923  if ( rendererWidget )
924  {
925  rendererWidget->doComputations();
926 
927  mRasterLayer->setRenderer( rendererWidget->renderer() );
928  }
929 
930  mMetadataWidget->acceptMetadata();
931  mMetadataFilled = false;
932 
933  //transparency settings
934  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
935  if ( rasterRenderer )
936  {
937  rasterRenderer->setAlphaBand( mRasterTransparencyWidget->cboxTransparencyBand->currentBand() );
938  rasterRenderer->setNodataColor( mRasterTransparencyWidget->mNodataColorButton->color() );
939 
940  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
941  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
942  if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 4 )
943  {
945  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
946  for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
947  {
948  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
949  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
950  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
951  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
952  myTransparentThreeValuePixelList.append( myTransparentPixel );
953  }
954  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
955  }
956  else if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 3 )
957  {
959  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
960  for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
961  {
962  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
963  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
964  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
965 
966  myTransparentSingleValuePixelList.append( myTransparentPixel );
967  }
968  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
969  }
970 
971  rasterRenderer->setRasterTransparency( rasterTransparency );
972 
973  //set global transparency
974  rasterRenderer->setOpacity( mRasterTransparencyWidget->mOpacityWidget->opacity() );
975  }
976 
977  QgsDebugMsgLevel( QStringLiteral( "processing general tab" ), 3 );
978  /*
979  * General Tab
980  */
981  mRasterLayer->setName( mLayerOrigNameLineEd->text() );
982 
983  // set up the scale based layer visibility stuff....
984  mRasterLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
985  mRasterLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
986  mRasterLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
987 
988  mRasterLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
989  mRasterLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
990 
991  //update the legend pixmap
992  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
993  // pixmapLegend->setScaledContents( true );
994  // pixmapLegend->repaint();
995 
996  mResamplingUtils.refreshLayerFromWidgets();
997 
998  // Hue and saturation controls
999  QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
1000  if ( hueSaturationFilter )
1001  {
1002  hueSaturationFilter->setSaturation( sliderSaturation->value() );
1003  hueSaturationFilter->setGrayscaleMode( ( QgsHueSaturationFilter::GrayscaleMode ) comboGrayscale->currentIndex() );
1004  hueSaturationFilter->setColorizeOn( mColorizeCheck->checkState() );
1005  hueSaturationFilter->setColorizeColor( btnColorizeColor->color() );
1006  hueSaturationFilter->setColorizeStrength( sliderColorizeStrength->value() );
1007  hueSaturationFilter->setInvertColors( mInvertColorsCheck->isChecked() );
1008  }
1009 
1010  //set the blend mode for the layer
1011  mRasterLayer->setBlendMode( mBlendModeComboBox->blendMode() );
1012 
1013  // Update temporal properties
1014  mTemporalWidget->saveTemporalProperties();
1015 
1016  mRasterLayer->setCrs( mCrsSelector->crs() );
1017 
1018  if ( mRasterLayer->shortName() != mLayerShortNameLineEdit->text() )
1019  mMetadataFilled = false;
1020  mRasterLayer->setShortName( mLayerShortNameLineEdit->text() );
1021 
1022  if ( mRasterLayer->title() != mLayerTitleLineEdit->text() )
1023  mMetadataFilled = false;
1024  mRasterLayer->setTitle( mLayerTitleLineEdit->text() );
1025 
1026  if ( mRasterLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
1027  mMetadataFilled = false;
1028  mRasterLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
1029 
1030  if ( mRasterLayer->keywordList() != mLayerKeywordListLineEdit->text() )
1031  mMetadataFilled = false;
1032  mRasterLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
1033 
1034  if ( mRasterLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
1035  mMetadataFilled = false;
1036  mRasterLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
1037 
1038  if ( mRasterLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
1039  mMetadataFilled = false;
1040  mRasterLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
1041 
1042  //layer attribution
1043  if ( mRasterLayer->attribution() != mLayerAttributionLineEdit->text() )
1044  mMetadataFilled = false;
1045  mRasterLayer->setAttribution( mLayerAttributionLineEdit->text() );
1046 
1047  if ( mRasterLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
1048  mMetadataFilled = false;
1049  mRasterLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
1050 
1051  // Metadata URL
1052  QList<QgsMapLayerServerProperties::MetadataUrl> metaUrls;
1053  for ( int row = 0; row < mMetadataUrlModel->rowCount() ; row++ )
1054  {
1056  metaUrl.url = mMetadataUrlModel->item( row, 0 )->text();
1057  metaUrl.type = mMetadataUrlModel->item( row, 1 )->text();
1058  metaUrl.format = mMetadataUrlModel->item( row, 2 )->text();
1059  metaUrls.append( metaUrl );
1060  mMetadataFilled = false;
1061  }
1062  mRasterLayer->serverProperties()->setMetadataUrls( metaUrls );
1063 
1064  if ( mRasterLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
1065  mMetadataFilled = false;
1066  mRasterLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
1067 
1068  if ( mRasterLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
1069  mMetadataFilled = false;
1070  mRasterLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
1071 
1072  if ( !mWMSPrintLayerLineEdit->text().isEmpty() )
1073  {
1074  mRasterLayer->setCustomProperty( QStringLiteral( "WMSPrintLayer" ), mWMSPrintLayerLineEdit->text() );
1075  }
1076 
1077  mRasterLayer->setCustomProperty( "WMSPublishDataSourceUrl", mPublishDataSourceUrlCheckBox->isChecked() );
1078  mRasterLayer->setCustomProperty( "WMSBackgroundLayer", mBackgroundLayerCheckBox->isChecked() );
1079 
1080  mRasterLayer->pipe()->setDataDefinedProperties( mPropertyCollection );
1081 
1082  // Force a redraw of the legend
1083  mRasterLayer->setLegend( QgsMapLayerLegend::defaultRasterLegend( mRasterLayer ) );
1084 
1085  //make sure the layer is redrawn
1086  mRasterLayer->triggerRepaint();
1087 
1088  // notify the project we've made a change
1089  QgsProject::instance()->setDirty( true );
1090 }
1091 
1092 void QgsRasterLayerProperties::buttonBuildPyramids_clicked()
1093 {
1094  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1095 
1096  std::unique_ptr< QgsRasterBlockFeedback > feedback( new QgsRasterBlockFeedback() );
1097 
1098  connect( feedback.get(), &QgsRasterBlockFeedback::progressChanged, mPyramidProgress, &QProgressBar::setValue );
1099  //
1100  // Go through the list marking any files that are selected in the listview
1101  // as true so that we can generate pyramids for them.
1102  //
1103  QList< QgsRasterPyramid> myPyramidList = provider->buildPyramidList();
1104  for ( int myCounterInt = 0; myCounterInt < lbxPyramidResolutions->count(); myCounterInt++ )
1105  {
1106  QListWidgetItem *myItem = lbxPyramidResolutions->item( myCounterInt );
1107  //mark to be pyramided
1108  myPyramidList[myCounterInt].setBuild( myItem->isSelected() || myPyramidList[myCounterInt].getExists() );
1109  }
1110 
1111  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
1112  QString prefix = provider->name() + "/driverOptions/_pyramids/";
1113  QgsSettings mySettings;
1114  QString resamplingMethod( cboResamplingMethod->currentData().toString() );
1115  mySettings.setValue( prefix + "resampling", resamplingMethod );
1116 
1117  //
1118  // Ask raster layer to build the pyramids
1119  //
1120 
1121  // let the user know we're going to possibly be taking a while
1122  QApplication::setOverrideCursor( Qt::WaitCursor );
1123  QString res = provider->buildPyramids(
1124  myPyramidList,
1125  resamplingMethod,
1126  ( QgsRaster::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex(),
1127  QStringList(),
1128  feedback.get() );
1129  QApplication::restoreOverrideCursor();
1130  mPyramidProgress->setValue( 0 );
1131  buttonBuildPyramids->setEnabled( false );
1132  if ( !res.isNull() )
1133  {
1134  if ( res == QLatin1String( "CANCELED" ) )
1135  {
1136  // user canceled
1137  }
1138  else if ( res == QLatin1String( "ERROR_WRITE_ACCESS" ) )
1139  {
1140  QMessageBox::warning( this, tr( "Building Pyramids" ),
1141  tr( "Write access denied. Adjust the file permissions and try again." ) );
1142  }
1143  else if ( res == QLatin1String( "ERROR_WRITE_FORMAT" ) )
1144  {
1145  QMessageBox::warning( this, tr( "Building Pyramids" ),
1146  tr( "The file was not writable. Some formats do not "
1147  "support pyramid overviews. Consult the GDAL documentation if in doubt." ) );
1148  }
1149  else if ( res == QLatin1String( "FAILED_NOT_SUPPORTED" ) )
1150  {
1151  QMessageBox::warning( this, tr( "Building Pyramids" ),
1152  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1153  }
1154  else if ( res == QLatin1String( "ERROR_JPEG_COMPRESSION" ) )
1155  {
1156  QMessageBox::warning( this, tr( "Building Pyramids" ),
1157  tr( "Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." ) );
1158  }
1159  else if ( res == QLatin1String( "ERROR_VIRTUAL" ) )
1160  {
1161  QMessageBox::warning( this, tr( "Building Pyramids" ),
1162  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1163  }
1164 
1165  }
1166 
1167  //
1168  // repopulate the pyramids list
1169  //
1170  lbxPyramidResolutions->clear();
1171  // Need to rebuild list as some or all pyramids may have failed to build
1172  myPyramidList = provider->buildPyramidList();
1173  QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
1174  QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
1175 
1176  for ( const QgsRasterPyramid &pyramid : std::as_const( myPyramidList ) )
1177  {
1178  if ( pyramid.getExists() )
1179  {
1180  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
1181  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1182  QString::number( pyramid.getYDim() ) ) );
1183  }
1184  else
1185  {
1186  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
1187  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1188  QString::number( pyramid.getYDim() ) ) );
1189  }
1190  }
1191  //update the legend pixmap
1192  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
1193  // pixmapLegend->setScaledContents( true );
1194  // pixmapLegend->repaint();
1195 
1196  //populate the metadata tab's text browser widget with gdal metadata info
1197  updateInformationContent();
1198 }
1199 
1200 void QgsRasterLayerProperties::urlClicked( const QUrl &url )
1201 {
1202  QFileInfo file( url.toLocalFile() );
1203  if ( file.exists() && !file.isDir() )
1204  QgsGui::instance()->nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
1205  else
1206  QDesktopServices::openUrl( url );
1207 }
1208 
1209 void QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged( int index )
1210 {
1211  if ( index < 0 || mDisableRenderTypeComboBoxCurrentIndexChanged || ! mRasterLayer->renderer() )
1212  {
1213  return;
1214  }
1215 
1216  QString rendererName = mRenderTypeComboBox->itemData( index ).toString();
1217  setRendererWidget( rendererName );
1218 }
1219 
1220 void QgsRasterLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
1221 {
1222  QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mMapCanvas, tr( "Select Transformation" ) );
1223  mRasterLayer->setCrs( crs );
1224  mMetadataWidget->crsChanged();
1225 }
1226 
1227 void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double value )
1228 {
1229  QgsDebugMsgLevel( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ), 3 );
1230  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1231  if ( !provider ) return;
1232 
1233  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1234  if ( !renderer ) return;
1235  int nBands = renderer->usesBands().size();
1236 
1237  QLineEdit *lineEdit = new QLineEdit();
1238  lineEdit->setFrame( false ); // frame looks bad in table
1239  // Without margins row selection is not displayed (important for delete row)
1240  lineEdit->setContentsMargins( 1, 1, 1, 1 );
1241 
1242  if ( column == mRasterTransparencyWidget->tableTransparency->columnCount() - 1 )
1243  {
1244  // transparency
1245  // Who needs transparency as floating point?
1246  lineEdit->setValidator( new QIntValidator( nullptr ) );
1247  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
1248  }
1249  else
1250  {
1251  // value
1252  QString valueString;
1253  switch ( provider->sourceDataType( 1 ) )
1254  {
1257  lineEdit->setValidator( new QgsDoubleValidator( nullptr ) );
1258  if ( !std::isnan( value ) )
1259  {
1260  double v = QgsRasterBlock::printValue( value ).toDouble();
1261  valueString = QLocale().toString( v, 'g' ) ;
1262  }
1263  break;
1264  default:
1265  lineEdit->setValidator( new QIntValidator( nullptr ) );
1266  if ( !std::isnan( value ) )
1267  {
1268  valueString = QLocale().toString( static_cast<int>( value ) );
1269  }
1270  break;
1271  }
1272  lineEdit->setText( valueString );
1273  }
1274  mRasterTransparencyWidget->tableTransparency->setCellWidget( row, column, lineEdit );
1275  adjustTransparencyCellWidth( row, column );
1276 
1277  if ( nBands == 1 && ( column == 0 || column == 1 ) )
1278  {
1279  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerProperties::transparencyCellTextEdited );
1280  }
1281  mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1282 }
1283 
1284 void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, double value )
1285 {
1286  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1287  if ( !lineEdit ) return;
1288  double v = QgsRasterBlock::printValue( value ).toDouble();
1289  lineEdit->setText( QLocale().toString( v, 'g' ) );
1290  lineEdit->adjustSize();
1291  adjustTransparencyCellWidth( row, column );
1292  mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1293 }
1294 
1295 double QgsRasterLayerProperties::transparencyCellValue( int row, int column )
1296 {
1297  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1298  if ( !lineEdit || lineEdit->text().isEmpty() )
1299  {
1300  return std::numeric_limits<double>::quiet_NaN();
1301  }
1302  return QLocale().toDouble( lineEdit->text() );
1303 }
1304 
1305 void QgsRasterLayerProperties::adjustTransparencyCellWidth( int row, int column )
1306 {
1307  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1308  if ( !lineEdit ) return;
1309 
1310  int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
1311  width = std::max( width, mRasterTransparencyWidget->tableTransparency->columnWidth( column ) );
1312 
1313  lineEdit->setFixedWidth( width );
1314 }
1315 
1316 void QgsRasterLayerProperties::transparencyCellTextEdited( const QString &text )
1317 {
1318  Q_UNUSED( text )
1319  QgsDebugMsgLevel( QStringLiteral( "text = %1" ).arg( text ), 3 );
1320  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1321  if ( !renderer )
1322  {
1323  return;
1324  }
1325  int nBands = renderer->usesBands().size();
1326  if ( nBands == 1 )
1327  {
1328  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
1329  if ( !lineEdit ) return;
1330  int row = -1;
1331  int column = -1;
1332  for ( int r = 0; r < mRasterTransparencyWidget->tableTransparency->rowCount(); r++ )
1333  {
1334  for ( int c = 0; c < mRasterTransparencyWidget->tableTransparency->columnCount(); c++ )
1335  {
1336  if ( mRasterTransparencyWidget->tableTransparency->cellWidget( r, c ) == sender() )
1337  {
1338  row = r;
1339  column = c;
1340  break;
1341  }
1342  }
1343  if ( row != -1 ) break;
1344  }
1345  QgsDebugMsgLevel( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ), 3 );
1346 
1347  if ( column == 0 )
1348  {
1349  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, 1 ) );
1350  if ( !toLineEdit ) return;
1351  bool toChanged = mTransparencyToEdited.value( row );
1352  QgsDebugMsgLevel( QStringLiteral( "toChanged = %1" ).arg( toChanged ), 3 );
1353  if ( !toChanged )
1354  {
1355  toLineEdit->setText( lineEdit->text() );
1356  }
1357  }
1358  else if ( column == 1 )
1359  {
1360  setTransparencyToEdited( row );
1361  }
1362  }
1363 }
1364 
1365 void QgsRasterLayerProperties::aboutToShowStyleMenu()
1366 {
1367  // this should be unified with QgsVectorLayerProperties::aboutToShowStyleMenu()
1368 
1369  QMenu *m = qobject_cast<QMenu *>( sender() );
1370 
1372  // re-add style manager actions!
1373  m->addSeparator();
1375 }
1376 
1377 void QgsRasterLayerProperties::syncToLayer()
1378 {
1379  QgsRasterRenderer *renderer = mRasterLayer->renderer();
1380  if ( renderer )
1381  {
1382  setRendererWidget( renderer->type() );
1383  }
1384  sync();
1385  mRasterLayer->triggerRepaint();
1386 }
1387 
1388 void QgsRasterLayerProperties::setTransparencyToEdited( int row )
1389 {
1390  if ( row >= mTransparencyToEdited.size() )
1391  {
1392  mTransparencyToEdited.resize( row + 1 );
1393  }
1394  mTransparencyToEdited[row] = true;
1395 }
1396 
1398 {
1400 
1401  bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1402  mBtnStyle->setVisible( ! isMetadataPanel );
1403  mBtnMetadata->setVisible( isMetadataPanel );
1404 
1405  if ( !mHistogramWidget )
1406  return;
1407 
1408  if ( index == mOptStackedWidget->indexOf( mOptsPage_Histogram ) )
1409  {
1410  mHistogramWidget->setActive( true );
1411  }
1412  else
1413  {
1414  mHistogramWidget->setActive( false );
1415  }
1416 
1417  if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) || !mMetadataFilled )
1418  {
1419  //set the metadata contents (which can be expensive)
1420  updateInformationContent();
1421  }
1422 }
1423 
1424 void QgsRasterLayerProperties::initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsRasterPipe::Property key )
1425 {
1426  button->blockSignals( true );
1427  button->init( key, mPropertyCollection, QgsRasterPipe::propertyDefinitions(), nullptr );
1428  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsRasterLayerProperties::updateProperty );
1429  button->registerExpressionContextGenerator( this );
1430  button->blockSignals( false );
1431 }
1432 
1433 void QgsRasterLayerProperties::updateDataDefinedButtons()
1434 {
1435  const auto propertyOverrideButtons { findChildren< QgsPropertyOverrideButton * >() };
1436  for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
1437  {
1438  updateDataDefinedButton( button );
1439  }
1440 }
1441 
1442 void QgsRasterLayerProperties::updateDataDefinedButton( QgsPropertyOverrideButton *button )
1443 {
1444  if ( !button )
1445  return;
1446 
1447  if ( button->propertyKey() < 0 )
1448  return;
1449 
1450  QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1451  whileBlocking( button )->setToProperty( mPropertyCollection.property( key ) );
1452 }
1453 
1454 void QgsRasterLayerProperties::updateProperty()
1455 {
1456  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1457  QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1458  mPropertyCollection.setProperty( key, button->toProperty() );
1459 }
1460 
1461 void QgsRasterLayerProperties::toggleSaturationControls( int grayscaleMode )
1462 {
1463  // Enable or disable saturation controls based on choice of grayscale mode
1464  if ( grayscaleMode == 0 )
1465  {
1466  sliderSaturation->setEnabled( true );
1467  spinBoxSaturation->setEnabled( true );
1468  }
1469  else
1470  {
1471  sliderSaturation->setEnabled( false );
1472  spinBoxSaturation->setEnabled( false );
1473  }
1474 }
1475 
1476 void QgsRasterLayerProperties::toggleColorizeControls( bool colorizeEnabled )
1477 {
1478  // Enable or disable colorize controls based on checkbox
1479  btnColorizeColor->setEnabled( colorizeEnabled );
1480  sliderColorizeStrength->setEnabled( colorizeEnabled );
1481  spinColorizeStrength->setEnabled( colorizeEnabled );
1482 }
1483 
1484 
1485 QLinearGradient QgsRasterLayerProperties::redGradient()
1486 {
1487  //define a gradient
1488  // TODO change this to actual polygon dims
1489  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1490  myGradient.setColorAt( 0.0, QColor( 242, 14, 25, 190 ) );
1491  myGradient.setColorAt( 0.5, QColor( 175, 29, 37, 190 ) );
1492  myGradient.setColorAt( 1.0, QColor( 114, 17, 22, 190 ) );
1493  return myGradient;
1494 }
1495 QLinearGradient QgsRasterLayerProperties::greenGradient()
1496 {
1497  //define a gradient
1498  // TODO change this to actual polygon dims
1499  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1500  myGradient.setColorAt( 0.0, QColor( 48, 168, 5, 190 ) );
1501  myGradient.setColorAt( 0.8, QColor( 36, 122, 4, 190 ) );
1502  myGradient.setColorAt( 1.0, QColor( 21, 71, 2, 190 ) );
1503  return myGradient;
1504 }
1505 QLinearGradient QgsRasterLayerProperties::blueGradient()
1506 {
1507  //define a gradient
1508  // TODO change this to actual polygon dims
1509  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1510  myGradient.setColorAt( 0.0, QColor( 30, 0, 106, 190 ) );
1511  myGradient.setColorAt( 0.2, QColor( 30, 72, 128, 190 ) );
1512  myGradient.setColorAt( 1.0, QColor( 30, 223, 196, 190 ) );
1513  return myGradient;
1514 }
1515 QLinearGradient QgsRasterLayerProperties::grayGradient()
1516 {
1517  //define a gradient
1518  // TODO change this to actual polygon dims
1519  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1520  myGradient.setColorAt( 0.0, QColor( 5, 5, 5, 190 ) );
1521  myGradient.setColorAt( 0.8, QColor( 122, 122, 122, 190 ) );
1522  myGradient.setColorAt( 1.0, QColor( 220, 220, 220, 190 ) );
1523  return myGradient;
1524 }
1525 QLinearGradient QgsRasterLayerProperties::highlightGradient()
1526 {
1527  //define another gradient for the highlight
1528  // TODO change this to actual polygon dims
1529  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1530  myGradient.setColorAt( 1.0, QColor( 255, 255, 255, 50 ) );
1531  myGradient.setColorAt( 0.5, QColor( 255, 255, 255, 100 ) );
1532  myGradient.setColorAt( 0.0, QColor( 255, 255, 255, 150 ) );
1533  return myGradient;
1534 }
1535 
1536 void QgsRasterLayerProperties::addMetadataUrl()
1537 {
1538  const int row = mMetadataUrlModel->rowCount();
1539  mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
1540  mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
1541  mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
1542 }
1543 
1544 void QgsRasterLayerProperties::removeSelectedMetadataUrl()
1545 {
1546  const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
1547  if ( selectedRows.empty() )
1548  return;
1549  mMetadataUrlModel->removeRow( selectedRows[0].row() );
1550 }
1551 
1552 
1553 //
1554 //
1555 // Next four methods for saving and restoring qml style state
1556 //
1557 //
1558 void QgsRasterLayerProperties::loadDefaultStyle_clicked()
1559 {
1560  bool defaultLoadedFlag = false;
1561  QString myMessage = mRasterLayer->loadDefaultStyle( defaultLoadedFlag );
1562  //reset if the default style was loaded OK only
1563  if ( defaultLoadedFlag )
1564  {
1565  syncToLayer();
1566  }
1567  else
1568  {
1569  //otherwise let the user know what went wrong
1570  QMessageBox::information( this,
1571  tr( "Default Style" ),
1572  myMessage
1573  );
1574  }
1575 }
1576 
1577 void QgsRasterLayerProperties::saveDefaultStyle_clicked()
1578 {
1579 
1580  apply(); // make sure the style to save is up-to-date
1581 
1582  // a flag passed by reference
1583  bool defaultSavedFlag = false;
1584  // after calling this the above flag will be set true for success
1585  // or false if the save operation failed
1586  QString myMessage = mRasterLayer->saveDefaultStyle( defaultSavedFlag );
1587  if ( !defaultSavedFlag )
1588  {
1589  //let the user know what went wrong
1590  QMessageBox::information( this,
1591  tr( "Default Style" ),
1592  myMessage
1593  );
1594  }
1595 }
1596 
1597 
1598 void QgsRasterLayerProperties::loadStyle_clicked()
1599 {
1600  QgsSettings settings;
1601  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1602 
1603  QString fileName = QFileDialog::getOpenFileName(
1604  this,
1605  tr( "Load layer properties from style file" ),
1606  lastUsedDir,
1607  tr( "QGIS Layer Style File" ) + " (*.qml)" );
1608  if ( fileName.isEmpty() )
1609  return;
1610 
1611  // ensure the user never omits the extension from the file name
1612  if ( !fileName.endsWith( QLatin1String( ".qml" ), Qt::CaseInsensitive ) )
1613  fileName += QLatin1String( ".qml" );
1614 
1615  mOldStyle = mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() );
1616 
1617  bool defaultLoadedFlag = false;
1618  QString message = mRasterLayer->loadNamedStyle( fileName, defaultLoadedFlag );
1619  if ( defaultLoadedFlag )
1620  {
1621  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( fileName ).absolutePath() );
1622  syncToLayer();
1623  }
1624  else
1625  {
1626  QMessageBox::information( this, tr( "Save Style" ), message );
1627  }
1628 }
1629 
1630 
1631 void QgsRasterLayerProperties::saveStyleAs_clicked()
1632 {
1633  QgsSettings settings;
1634  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1635 
1636  QString selectedFilter;
1637  QString outputFileName = QFileDialog::getSaveFileName(
1638  this,
1639  tr( "Save layer properties as style file" ),
1640  lastUsedDir,
1641  tr( "QGIS Layer Style File" ) + " (*.qml)" + ";;" + tr( "Styled Layer Descriptor" ) + " (*.sld)",
1642  &selectedFilter );
1643  if ( outputFileName.isEmpty() )
1644  return;
1645 
1646  StyleType type;
1647  // use selectedFilter to set style type
1648  if ( selectedFilter.contains( QStringLiteral( ".qml" ), Qt::CaseInsensitive ) )
1649  {
1650  outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "qml" ) );
1651  type = StyleType::QML;
1652  }
1653  else
1654  {
1655  outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "sld" ) );
1656  type = StyleType::SLD;
1657  }
1658 
1659  apply(); // make sure the style to save is up-to-date
1660 
1661  // then export style
1662  bool defaultLoadedFlag = false;
1663  QString message;
1664  switch ( type )
1665  {
1666  case QML:
1667  {
1668  message = mRasterLayer->saveNamedStyle( outputFileName, defaultLoadedFlag );
1669  break;
1670  }
1671  case SLD:
1672  {
1673  message = mRasterLayer->saveSldStyle( outputFileName, defaultLoadedFlag );
1674  break;
1675  }
1676  }
1677  if ( defaultLoadedFlag )
1678  {
1679  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( outputFileName ).absolutePath() );
1680  sync();
1681  }
1682  else
1683  QMessageBox::information( this, tr( "Save Style" ), message );
1684 }
1685 
1686 void QgsRasterLayerProperties::restoreWindowModality()
1687 {
1688  hide();
1689  setModal( true );
1690  show();
1691  raise();
1692  activateWindow();
1693 }
1694 
1695 //
1696 //
1697 // Next four methods for saving and restoring QMD metadata
1698 //
1699 //
1700 
1701 void QgsRasterLayerProperties::loadMetadata()
1702 {
1703  QgsSettings myQSettings; // where we keep last used filter in persistent state
1704  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1705 
1706  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
1707  tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1708  if ( myFileName.isNull() )
1709  {
1710  return;
1711  }
1712 
1713  QString myMessage;
1714  bool defaultLoadedFlag = false;
1715  myMessage = mRasterLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1716 
1717  //reset if the default style was loaded OK only
1718  if ( defaultLoadedFlag )
1719  {
1720  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1721  }
1722  else
1723  {
1724  //let the user know what went wrong
1725  QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1726  }
1727 
1728  QFileInfo myFI( myFileName );
1729  QString myPath = myFI.path();
1730  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1731 
1732  activateWindow(); // set focus back to properties dialog
1733 }
1734 
1735 void QgsRasterLayerProperties::saveMetadataAs()
1736 {
1737  QgsSettings myQSettings; // where we keep last used filter in persistent state
1738  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1739 
1740  QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1741  myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1742  if ( myOutputFileName.isNull() ) //dialog canceled
1743  {
1744  return;
1745  }
1746 
1747  mMetadataWidget->acceptMetadata();
1748 
1749  //ensure the user never omitted the extension from the file name
1750  if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1751  {
1753  }
1754 
1755  bool defaultLoadedFlag = false;
1756  QString message = mRasterLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1757  if ( defaultLoadedFlag )
1758  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
1759  else
1760  QMessageBox::information( this, tr( "Save Metadata" ), message );
1761 }
1762 
1763 void QgsRasterLayerProperties::saveDefaultMetadata()
1764 {
1765  mMetadataWidget->acceptMetadata();
1766 
1767  bool defaultSavedFlag = false;
1768  QString errorMsg = mRasterLayer->saveDefaultMetadata( defaultSavedFlag );
1769  if ( !defaultSavedFlag )
1770  {
1771  QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1772  }
1773 }
1774 
1775 void QgsRasterLayerProperties::loadDefaultMetadata()
1776 {
1777  bool defaultLoadedFlag = false;
1778  QString myMessage = mRasterLayer->loadNamedMetadata( mRasterLayer->metadataUri(), defaultLoadedFlag );
1779  //reset if the default metadata was loaded OK only
1780  if ( defaultLoadedFlag )
1781  {
1782  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1783  }
1784  else
1785  {
1786  QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1787  }
1788 }
1789 
1790 
1791 void QgsRasterLayerProperties::toggleBuildPyramidsButton()
1792 {
1793  if ( lbxPyramidResolutions->selectedItems().empty() )
1794  {
1795  buttonBuildPyramids->setEnabled( false );
1796  }
1797  else
1798  {
1799  buttonBuildPyramids->setEnabled( true );
1800  }
1801 }
1802 
1803 void QgsRasterLayerProperties::mResetColorRenderingBtn_clicked()
1804 {
1805  mBlendModeComboBox->setBlendMode( QPainter::CompositionMode_SourceOver );
1806  mSliderBrightness->setValue( 0 );
1807  mSliderContrast->setValue( 0 );
1808  mGammaSpinBox->setValue( 1.0 );
1809  sliderSaturation->setValue( 0 );
1810  comboGrayscale->setCurrentIndex( ( int ) QgsHueSaturationFilter::GrayscaleOff );
1811  mColorizeCheck->setChecked( false );
1812  sliderColorizeStrength->setValue( 100 );
1813  mInvertColorsCheck->setChecked( false );
1814 }
1815 
1816 bool QgsRasterLayerProperties::rasterIsMultiBandColor()
1817 {
1818  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
1819 }
1820 
1821 void QgsRasterLayerProperties::updateInformationContent()
1822 {
1823  const QString myStyle = QgsApplication::reportStyleSheet( QgsApplication::StyleSheetType::WebBrowser );
1824  // Inject the stylesheet
1825  const QString html { mRasterLayer->htmlMetadata().replace( QLatin1String( "<head>" ), QStringLiteral( R"raw(<head><style type="text/css">%1</style>)raw" ) ).arg( myStyle ) };
1826  mMetadataViewer->setHtml( html );
1827  mMetadataFilled = true;
1828 }
1829 
1830 void QgsRasterLayerProperties::onCancel()
1831 {
1832  if ( mOldStyle.xmlData() != mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() ).xmlData() )
1833  {
1834  // need to reset style to previous - style applied directly to the layer (not in apply())
1835  QString myMessage;
1836  QDomDocument doc( QStringLiteral( "qgis" ) );
1837  int errorLine, errorColumn;
1838  doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
1839  mRasterLayer->importNamedStyle( doc, myMessage );
1840  syncToLayer();
1841  }
1842 }
1843 
1844 void QgsRasterLayerProperties::showHelp()
1845 {
1846  const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
1847 
1848  if ( helpPage.isValid() )
1849  {
1850  QgsHelp::openHelp( helpPage.toString() );
1851  }
1852  else
1853  {
1854  QgsHelp::openHelp( QStringLiteral( "working_with_raster/raster_properties.html" ) );
1855  }
1856 }
1857 
1858 void QgsRasterLayerProperties::updateGammaSpinBox( int value )
1859 {
1860  whileBlocking( mGammaSpinBox )->setValue( value / 100.0 );
1861 }
1862 
1863 void QgsRasterLayerProperties::updateGammaSlider( double value )
1864 {
1865  whileBlocking( mSliderGamma )->setValue( value * 100 );
1866 }
@ Float32
Thirty two bit floating point (float)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Float64
Sixty four bit floating point (double)
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QgsRasterRendererRegistry * rasterRendererRegistry()
Returns the application's raster renderer registry, used for managing raster layer renderers.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QRegularExpression shortNameRegularExpression()
Returns the short name regular expression for line edit validator.
Brightness/contrast and gamma correction filter pipe for rasters.
int contrast() const
Returns current contrast level.
int brightness() const
Returns current brightness level.
double gamma() const
Returns current gamma value.
void setGamma(double gamma)
Set gamma value.
void setContrast(int contrast)
Set contrast level.
void setBrightness(int brightness)
Set brightness level.
This class represents a coordinate reference system (CRS).
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
virtual QString name() const =0
Returns a provider name.
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...
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
static QgsProviderSourceWidgetProviderRegistry * sourceWidgetProviderRegistry()
Returns the registry of provider source widget providers.
Definition: qgsgui.cpp:103
static QgsGui * instance()
Returns a pointer to the singleton instance.
Definition: qgsgui.cpp:67
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition: qgsgui.cpp:73
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Factory method to create the renderer for this type.
Color and saturation filter pipe for rasters.
void setColorizeOn(bool colorizeOn)
void setSaturation(int saturation)
bool invertColors() const
Returns true if the filter inverts colors.
void setGrayscaleMode(QgsHueSaturationFilter::GrayscaleMode grayscaleMode)
void setInvertColors(bool invertColors)
Sets whether the filter will invert colors.
QgsHueSaturationFilter::GrayscaleMode grayscaleMode() const
void setColorizeColor(const QColor &colorizeColor)
void setColorizeStrength(int colorizeStrength)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:88
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Factory class for creating custom map layer property pages.
virtual bool supportsLayer(QgsMapLayer *layer) const
Check if the layer is supported for this widget.
virtual QIcon icon() const
The icon that will be shown in the UI for the panel.
virtual ParentPage parentPage() const
Returns the associated parent page, for factories which create sub-components of a standard page.
virtual QgsMapLayerConfigWidget * createWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, bool dockWidget=true, QWidget *parent=nullptr) const =0
Factory function to create the widget on demand as needed by the dock.
virtual QString title() const
The title of the panel.
virtual bool supportLayerPropertiesDialog() const
Flag if widget is supported for use in layer properties dialog.
@ Temporal
Factory creates sub-components of the temporal properties page (only supported for raster layer tempo...
@ NoParent
Factory creates pages itself, not sub-components.
virtual QString layerPropertiesPagePositionHint() const
Returns a tab name hinting at where this page should be inserted into the layer properties tab list.
A panel widget that can be shown in the map style dock.
static QgsMapLayerLegend * defaultRasterLegend(QgsRasterLayer *rl)
Create new legend implementation for raster layer.
void removesExtraMenuSeparators(QMenu *m)
removes extra separators from the menu
void addStyleManagerActions(QMenu *m, QgsMapLayer *layer)
adds actions to the menu in accordance to the layer
static QgsMapLayerStyleGuiUtils * instance()
returns a singleton instance of this class
QString currentStyle() const
Returns name of the current style.
bool isDefault(const QString &styleName) const
Returns true if this is the default style.
QgsMapLayerStyle style(const QString &name) const
Returns data of a stored style - accessed by its unique name.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
QString xmlData() const
Returns XML content of the style.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
void setShortName(const QString &shortName)
Sets the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:285
QString name
Definition: qgsmaplayer.h:76
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:1281
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:315
virtual QString saveSldStyle(const QString &uri, bool &resultFlag) const
Saves the properties of this layer to an SLD format file.
QString source() const
Returns the source for the layer.
void setLegendUrl(const QString &legendUrl)
Sets the URL for the layer's legend.
Definition: qgsmaplayer.h:1266
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
QString legendPlaceholderImage() const
Returns path to the placeholder image or an empty string if a generated legend is shown.
Definition: qgsmaplayer.h:1500
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:397
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 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.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
void setAttributionUrl(const QString &attribUrl)
Sets the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:406
void setAutoRefreshEnabled(bool enabled)
Sets whether auto refresh is enabled for the layer.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:323
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:377
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Definition: qgsmaplayer.h:423
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:350
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 ...
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:331
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:388
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
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 ...
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:368
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:307
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:359
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
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 ...
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:68
void setName(const QString &name)
Set the display name of the layer.
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
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...
bool isValid
Definition: qgsmaplayer.h:81
void setLegendPlaceholderImage(const QString &imgPath)
Set placeholder image for legend.
Definition: qgsmaplayer.h:1507
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:415
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
double minimumScale() const
Returns the minimum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
QString legendUrl() const
Returns the URL for the layer's legend.
Definition: qgsmaplayer.h:1271
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1276
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...
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
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...
int autoRefreshInterval
Definition: qgsmaplayer.h:77
double maximumScale() const
Returns the maximum map scale (i.e.
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:339
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:299
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer's CRS
void deactivated()
signal emitted once the map tool is deactivated
A wizard to edit metadata on a map layer.
void acceptMetadata()
Saves the metadata to the layer.
void crsChanged()
If the CRS is updated.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the widget.
void setMetadata(const QgsAbstractMetadataBase *metadata)
Sets the metadata to display in the widget.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Renderer for multiband images with the color components.
A base dialog for options and properties dialogs that offers vertical tabs.
void addPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QStringList &path=QStringList())
Adds a new page to the dialog pages.
virtual void optionsStackedWidget_CurrentChanged(int index)
Select relevant tab on current page change.
void insertPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QString &before, const QStringList &path=QStringList())
Inserts a new page into the dialog pages.
void restoreOptionsBaseUi(const QString &title=QString())
Restore the base ui.
QStackedWidget * mOptStackedWidget
void initOptionsBase(bool restoreUi=true, const QString &title=QString())
Set up the base ui connections for vertical tabs.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:518
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
A button for controlling property overrides which may apply to a widget.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
void changed()
Emitted when property definition changes.
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout).
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
int propertyKey() const
Returns the property key linked to the button.
QgsProviderSourceWidget * createWidget(QgsMapLayer *layer, QWidget *parent=nullptr)
Creates a new widget to configure the source of the specified layer.
void validChanged(bool isValid)
Emitted whenever the validation status of the widget changes.
virtual QString sourceUri() const =0
Returns the source URI as currently defined by the widget.
virtual void setSourceUri(const QString &uri)=0
Sets the source uri to show in the widget.
Feedback object tailored for raster block reading.
static QString printValue(double value)
Print double value with all necessary significant digits.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Widget creation function (mainly for the use by the renderer registry)
Base class for raster data providers.
virtual QString buildPyramids(const QList< QgsRasterPyramid > &pyramidList, const QString &resamplingMethod="NEAREST", QgsRaster::RasterPyramidsFormat format=QgsRaster::PyramidsGTiff, const QStringList &configOptions=QStringList(), QgsRasterBlockFeedback *feedback=nullptr)
Creates pyramid overviews.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
virtual bool useSourceNoDataValue(int bandNo) const
Returns the source nodata value usage.
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
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...
virtual void setUseSourceNoDataValue(int bandNo, bool use)
Sets the source nodata value usage.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
virtual QgsRasterRangeList userNoDataValues(int bandNo) const
Returns a list of user no data value ranges.
static QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns a list of pyramid resampling method name and label pairs for given provider.
virtual void setUserNoDataValue(int bandNo, const QgsRasterRangeList &noData)
void setRendererWidget(const QString &name, QgsRasterRendererWidget *rendererWidget=nullptr)
Sets the renderer widget (or just its name if there is no widget)
void setActive(bool activeFlag)
Activate the histogram widget.
@ BuildPyramids
Supports building of pyramids (overviews)
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
StyleType
enumeration for the different types of style
void addPropertiesPageFactory(const QgsMapLayerConfigWidgetFactory *factory)
Adds a properties page factory to the raster layer properties dialog.
QgsRasterLayerProperties(QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent=nullptr, Qt::WindowFlags=QgsGuiUtils::ModalDialogFlags)
Constructor.
void optionsStackedWidget_CurrentChanged(int index) override
auto slot executed when the active page in the main widget stack is changed
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
A widget for configuring the temporal properties for a raster layer.
void syncToLayer()
Updates the widget state to match the current layer state.
void saveTemporalProperties()
Save widget temporal properties inputs.
void addWidget(QgsMapLayerConfigWidget *widget SIP_TRANSFER)
Adds a child widget to the properties widget.
Represents a raster layer.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
QgsRasterPipe * pipe()
Returns the raster pipe.
QgsBrightnessContrastFilter * brightnessFilter() const
Returns the raster's brightness/contrast filter.
LayerType rasterType()
Returns the raster layer type (which is a read only property).
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
void setRenderer(QgsRasterRenderer *renderer)
Sets the raster's renderer.
QgsHueSaturationFilter * hueSaturationFilter() const
Returns the raster's hue/saturation filter.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the pipe's property collection, used for data defined overrides.
static QgsPropertiesDefinition propertyDefinitions()
Returns the definitions for data defined properties available for use in raster pipes.
Property
Data definable properties.
Definition: qgsrasterpipe.h:58
@ RendererOpacity
Raster renderer global opacity.
Definition: qgsrasterpipe.h:59
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the pipe's property collection, used for data defined overrides.
This struct is used to store pyramid info for the raster layer.
Raster values range container.
void insertWidgetFunction(const QString &rendererName, QgsRasterRendererWidgetCreateFunc func)
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QgsRasterRenderer * renderer()=0
virtual void doComputations()
Load programmatically with current values.
Raster renderer pipe that applies colors to a raster.
QColor nodataColor() const
Returns the color to use for shading nodata pixels.
virtual QString type() const
double opacity() const
Returns the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
void setAlphaBand(int band)
void setOpacity(double opacity)
Sets the opacity for the renderer, where opacity is a value between 0 (totally transparent) and 1....
void setRasterTransparency(QgsRasterTransparency *t)
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
void setNodataColor(const QColor &color)
Sets the color to use for shading nodata pixels.
Widget to control a layers transparency and related options.
void syncToLayer()
Sync the widget state to the layer set for the widget.
QgsMapToolEmitPoint * pixelSelectorTool() const
Returns the (possibly nullptr) map pixel selector tool.
Defines the list of pixel values to be considered as transparent or semi transparent when rendering r...
void setTransparentSingleValuePixelList(const QList< QgsRasterTransparency::TransparentSingleValuePixel > &newList)
Sets the transparent single value pixel list, replacing the whole existing list.
void setTransparentThreeValuePixelList(const QList< QgsRasterTransparency::TransparentThreeValuePixel > &newList)
Sets the transparent three value pixel list, replacing the whole existing list.
RasterPyramidsFormat
Definition: qgsraster.h:82
@ MultiBandColor
Definition: qgsraster.h:100
@ SingleBandGray
Definition: qgsraster.h:92
A rectangle specified with double values.
Definition: qgsrectangle.h:42
void setMetadataUrls(const QList< QgsServerMetadataUrlProperties::MetadataUrl > &metaUrls)
Sets a the list of metadata URL for the layer.
QList< QgsServerMetadataUrlProperties::MetadataUrl > metadataUrls() const
Returns a list of metadataUrl resources associated for the layer.
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
static QgsRasterRendererWidget * create(QgsRasterLayer *layer, const QgsRectangle &extent)
Creates new raster renderer widget.
The QgsWebView class is a collection of stubs to mimic the API of QWebView on systems where the real ...
Definition: qgswebview.h:66
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
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1173
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QList< QgsRasterRange > QgsRasterRangeList
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
Registry for raster renderer entries.
QgsRasterRendererWidgetCreateFunc widgetCreateFunction
QString format
Format specification of online resource.