QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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  mBackupCrs = mRasterLayer->crs();
236 
237  // Handles window modality raising canvas
238  if ( mMapCanvas && mRasterTransparencyWidget->pixelSelectorTool() )
239  {
240 
241  connect( mRasterTransparencyWidget->pixelSelectorTool(), &QgsMapToolEmitPoint::deactivated, this, [ = ]
242  {
243  hide();
244  setModal( true );
245  show();
246  raise();
247  activateWindow();
248  } );
249 
250  connect( mRasterTransparencyWidget->pbnAddValuesFromDisplay, &QPushButton::clicked, this, [ = ]
251  {
252  hide();
253  setModal( false );
254 
255  // Transfer focus to the canvas to use the selector tool
256  mMapCanvas->window()->raise();
257  mMapCanvas->window()->activateWindow();
258  mMapCanvas->window()->setFocus();
259  } );
260  }
261 
265  if ( mMapCanvas )
266  mContext << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() );
267  mContext << QgsExpressionContextUtils::layerScope( mRasterLayer );
268 
269  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
270 
271  // Only do pyramids if dealing directly with GDAL.
272  if ( provider && provider->capabilities() & QgsRasterDataProvider::BuildPyramids )
273  {
274  // initialize resampling methods
275  cboResamplingMethod->clear();
276 
277  const auto constProviderType = QgsRasterDataProvider::pyramidResamplingMethods( mRasterLayer->providerType() );
278  for ( const QPair<QString, QString> &method : std::as_const( constProviderType ) )
279  {
280  cboResamplingMethod->addItem( method.second, method.first );
281  }
282 
283  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
284  QString prefix = provider->name() + "/driverOptions/_pyramids/";
285  QgsSettings mySettings;
286  QString defaultMethod = mySettings.value( prefix + "resampling", "AVERAGE" ).toString();
287  int idx = cboResamplingMethod->findData( defaultMethod );
288  if ( idx >= 0 )
289  cboResamplingMethod->setCurrentIndex( idx );
290 
291 
292  // build pyramid list
293  const QList< QgsRasterPyramid > myPyramidList = provider->buildPyramidList();
294 
295  for ( const QgsRasterPyramid &pyramid : myPyramidList )
296  {
297  if ( pyramid.getExists() )
298  {
299  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
300  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
301  QString::number( pyramid.getYDim() ) ) );
302  }
303  else
304  {
305  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
306  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
307  QString::number( pyramid.getYDim() ) ) );
308  }
309  }
310  }
311  else
312  {
313  // disable Pyramids tab completely
314  mOptsPage_Pyramids->setEnabled( false );
315  }
316 
317  // We can calculate histogram for all data sources but estimated only if
318  // size is unknown - could also be enabled if well supported (estimated histogram
319  // and let user know that it is estimated)
320  if ( !provider || !( provider->capabilities() & QgsRasterDataProvider::Size ) )
321  {
322  // disable Histogram tab completely
323  mOptsPage_Histogram->setEnabled( false );
324  }
325 
326  QVBoxLayout *layout = new QVBoxLayout( metadataFrame );
327  layout->setContentsMargins( 0, 0, 0, 0 );
328  mMetadataWidget = new QgsMetadataWidget( this, mRasterLayer );
329  mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
330  mMetadataWidget->setMapCanvas( mMapCanvas );
331  layout->addWidget( mMetadataWidget );
332  metadataFrame->setLayout( layout );
333 
334  QVBoxLayout *temporalLayout = new QVBoxLayout( temporalFrame );
335  temporalLayout->setContentsMargins( 0, 0, 0, 0 );
336  mTemporalWidget = new QgsRasterLayerTemporalPropertiesWidget( this, mRasterLayer );
337  temporalLayout->addWidget( mTemporalWidget );
338 
339  QgsDebugMsgLevel( "Setting crs to " + mRasterLayer->crs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ), 2 );
340  QgsDebugMsgLevel( "Setting crs to " + mRasterLayer->crs().userFriendlyIdentifier(), 2 );
341  mCrsSelector->setCrs( mRasterLayer->crs() );
342 
343  // Set text for pyramid info box
344  QString pyramidFormat( QStringLiteral( "<h2>%1</h2><p>%2 %3 %4</p><b><font color='red'><p>%5</p><p>%6</p>" ) );
345  QString pyramidHeader = tr( "Description" );
346  QString pyramidSentence1 = tr( "Large resolution raster layers can slow navigation in QGIS." );
347  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." );
348  QString pyramidSentence3 = tr( "You must have write access in the directory where the original data is stored to build pyramids." );
349  QString pyramidSentence4 = tr( "Please note that building internal pyramids may alter the original data file and once created they cannot be removed!" );
350  QString pyramidSentence5 = tr( "Please note that building internal pyramids could corrupt your image - always make a backup of your data first!" );
351 
352  tePyramidDescription->setHtml( pyramidFormat.arg( pyramidHeader,
353  pyramidSentence1,
354  pyramidSentence2,
355  pyramidSentence3,
356  pyramidSentence4,
357  pyramidSentence5 ) );
358 
359  //resampling
360  mResamplingGroupBox->setSaveCheckedState( true );
361  mResamplingUtils.initWidgets( mRasterLayer, mZoomedInResamplingComboBox, mZoomedOutResamplingComboBox, mMaximumOversamplingSpinBox, mCbEarlyResampling );
362  mResamplingUtils.refreshWidgetsFromLayer();
363 
364  const QgsRasterRenderer *renderer = mRasterLayer->renderer();
365 
366  btnColorizeColor->setColorDialogTitle( tr( "Select Color" ) );
367  btnColorizeColor->setContext( QStringLiteral( "symbology" ) );
368 
369  // Hue and saturation color control
370  const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
371  //set hue and saturation controls to current values
372  if ( hueSaturationFilter )
373  {
374  sliderSaturation->setValue( hueSaturationFilter->saturation() );
375  comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
376 
377  // Set initial state of saturation controls based on grayscale mode choice
378  toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
379 
380  // Set initial state of colorize controls
381  mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
382  btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
383  toggleColorizeControls( hueSaturationFilter->colorizeOn() );
384  sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
385  mInvertColorsCheck->setChecked( hueSaturationFilter->invertColors() );
386  }
387 
388  //blend mode
389  mBlendModeComboBox->setBlendMode( mRasterLayer->blendMode() );
390 
391  //transparency band
392  if ( provider )
393  {
394  mRasterTransparencyWidget->cboxTransparencyBand->setShowNotSetOption( true, tr( "None" ) );
395  mRasterTransparencyWidget->cboxTransparencyBand->setLayer( mRasterLayer );
396 
397 // Alpha band is set in sync()
398 #if 0
399  if ( renderer )
400  {
401  QgsDebugMsg( QStringLiteral( "alphaBand = %1" ).arg( renderer->alphaBand() ) );
402  if ( renderer->alphaBand() > 0 )
403  {
404  cboxTransparencyBand->setCurrentIndex( cboxTransparencyBand->findData( renderer->alphaBand() ) );
405  }
406  }
407 #endif
408  }
409 
410  // create histogram widget
411  mHistogramWidget = nullptr;
412  if ( mOptsPage_Histogram->isEnabled() )
413  {
414  mHistogramWidget = new QgsRasterHistogramWidget( mRasterLayer, mOptsPage_Histogram );
415  mHistogramStackedWidget->addWidget( mHistogramWidget );
416  }
417 
418  //insert renderer widgets into registry
425 
426  //fill available renderers into combo box
428  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
429  const auto constRenderersList = QgsApplication::rasterRendererRegistry()->renderersList();
430  for ( const QString &name : constRenderersList )
431  {
432  if ( QgsApplication::rasterRendererRegistry()->rendererData( name, entry ) )
433  {
434  if ( ( mRasterLayer->rasterType() != QgsRasterLayer::ColorLayer && entry.name != QLatin1String( "singlebandcolordata" ) ) ||
435  ( mRasterLayer->rasterType() == QgsRasterLayer::ColorLayer && entry.name == QLatin1String( "singlebandcolordata" ) ) )
436  {
437  mRenderTypeComboBox->addItem( entry.visibleName, entry.name );
438  }
439  }
440  }
441  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
442 
443  int widgetIndex = 0;
444  if ( renderer )
445  {
446  QString rendererType = renderer->type();
447  widgetIndex = mRenderTypeComboBox->findData( rendererType );
448  if ( widgetIndex != -1 )
449  {
450  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
451  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
452  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
453  }
454 
455  if ( rendererType == QLatin1String( "singlebandcolordata" ) && mRenderTypeComboBox->count() == 1 )
456  {
457  // no band rendering options for singlebandcolordata, so minimize group box
458  QSizePolicy sizep = mBandRenderingGrpBx->sizePolicy();
459  sizep.setVerticalStretch( 0 );
460  sizep.setVerticalPolicy( QSizePolicy::Maximum );
461  mBandRenderingGrpBx->setSizePolicy( sizep );
462  mBandRenderingGrpBx->updateGeometry();
463  }
464 
465  if ( mRasterLayer->providerType() != QLatin1String( "wms" ) )
466  {
467  mWMSPrintGroupBox->hide();
468  mPublishDataSourceUrlCheckBox->hide();
469  mBackgroundLayerCheckBox->hide();
470  }
471  }
472 
473 #ifdef WITH_QTWEBKIT
474  // Setup information tab
475 
476  const int horizontalDpi = logicalDpiX();
477 
478  // Adjust zoom: text is ok, but HTML seems rather big at least on Linux/KDE
479  if ( horizontalDpi > 96 )
480  {
481  mMetadataViewer->setZoomFactor( mMetadataViewer->zoomFactor() * 0.9 );
482  }
483  mMetadataViewer->page()->setLinkDelegationPolicy( QWebPage::LinkDelegationPolicy::DelegateAllLinks );
484  connect( mMetadataViewer->page(), &QWebPage::linkClicked, this, &QgsRasterLayerProperties::urlClicked );
485  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
486  mMetadataViewer->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
487 
488 #endif
489 
490  initializeDataDefinedButton( mRasterTransparencyWidget->mOpacityDDBtn, QgsRasterPipe::RendererOpacity );
491 
492  mRenderTypeComboBox_currentIndexChanged( widgetIndex );
493 
494  // update based on lyr's current state
495  sync();
496 
497  QgsSettings settings;
498  // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
499  // this will be read by restoreOptionsBaseUi()
500  if ( !settings.contains( QStringLiteral( "/Windows/RasterLayerProperties/tab" ) ) )
501  {
502  settings.setValue( QStringLiteral( "Windows/RasterLayerProperties/tab" ),
503  mOptStackedWidget->indexOf( mOptsPage_Style ) );
504  }
505 
506  mResetColorRenderingBtn->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
507 
508  QString title = tr( "Layer Properties — %1" ).arg( lyr->name() );
509 
510  if ( !mRasterLayer->styleManager()->isDefault( mRasterLayer->styleManager()->currentStyle() ) )
511  title += QStringLiteral( " (%1)" ).arg( mRasterLayer->styleManager()->currentStyle() );
512  restoreOptionsBaseUi( title );
513  optionsStackedWidget_CurrentChanged( mOptionsStackedWidget->currentIndex() );
514 
515  //Add help page references
516  mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#information-properties" ) );
517  mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#source-properties" ) );
518  mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#symbology-properties" ) );
519  mOptsPage_Transparency->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#transparency-properties" ) );
520 
521  if ( mOptsPage_Histogram )
522  mOptsPage_Histogram->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#histogram-properties" ) );
523 
524  mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#rendering-properties" ) );
525 
526  if ( mOptsPage_Pyramids )
527  mOptsPage_Pyramids->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#pyramids-properties" ) );
528 
529  mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#metadata-properties" ) );
530  mOptsPage_Legend->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#legend-properties" ) );
531  mOptsPage_Server->setProperty( "helpPage", QStringLiteral( "working_with_raster/raster_properties.html#server-properties" ) );
532 }
533 
535 {
536  if ( !factory->supportsLayer( mRasterLayer ) || !factory->supportLayerPropertiesDialog() )
537  {
538  return;
539  }
540 
541  QgsMapLayerConfigWidget *page = factory->createWidget( mRasterLayer, nullptr, false, this );
542  switch ( factory->parentPage() )
543  {
545  {
546  mLayerPropertiesPages << page;
547 
548  const QString beforePage = factory->layerPropertiesPagePositionHint();
549  if ( beforePage.isEmpty() )
550  addPage( factory->title(), factory->title(), factory->icon(), page );
551  else
552  insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage );
553  break;
554  }
555 
557  mTemporalWidget->addWidget( page );
558  break;
559  }
560 }
561 
563 {
564  return mContext;
565 }
566 
567 void QgsRasterLayerProperties::setRendererWidget( const QString &rendererName )
568 {
569  QgsDebugMsgLevel( "rendererName = " + rendererName, 3 );
570  QgsRasterRendererWidget *oldWidget = mRendererWidget;
571  QgsRasterRenderer *oldRenderer = mRasterLayer->renderer();
572 
573  int alphaBand = -1;
574  double opacity = 1;
575  QColor nodataColor;
576  if ( oldRenderer )
577  {
578  // Retain alpha band and opacity when switching renderer
579  alphaBand = oldRenderer->alphaBand();
580  opacity = oldRenderer->opacity();
581  nodataColor = oldRenderer->nodataColor();
582  }
583 
584  QgsRasterRendererRegistryEntry rendererEntry;
585  if ( QgsApplication::rasterRendererRegistry()->rendererData( rendererName, rendererEntry ) )
586  {
587  if ( rendererEntry.widgetCreateFunction ) //single band color data renderer e.g. has no widget
588  {
589  QgsDebugMsgLevel( QStringLiteral( "renderer has widgetCreateFunction" ), 3 );
590  // Current canvas extent (used to calc min/max) in layer CRS
591  QgsRectangle myExtent = mMapCanvas->mapSettings().outputExtentToLayerExtent( mRasterLayer, mMapCanvas->extent() );
592  if ( oldWidget && ( !oldRenderer || rendererName != oldRenderer->type() ) )
593  {
594  if ( rendererName == QLatin1String( "singlebandgray" ) )
595  {
596  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::SingleBandGray, mRasterLayer->dataProvider() ) );
597  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
598  }
599  else if ( rendererName == QLatin1String( "multibandcolor" ) )
600  {
601  whileBlocking( mRasterLayer )->setRenderer( QgsApplication::rasterRendererRegistry()->defaultRendererForDrawingStyle( QgsRaster::MultiBandColor, mRasterLayer->dataProvider() ) );
602  whileBlocking( mRasterLayer )->setDefaultContrastEnhancement();
603  }
604  }
605  mRasterLayer->renderer()->setAlphaBand( alphaBand );
606  mRasterLayer->renderer()->setOpacity( opacity );
607  mRasterLayer->renderer()->setNodataColor( nodataColor );
608  mRendererWidget = rendererEntry.widgetCreateFunction( mRasterLayer, myExtent );
609  mRendererWidget->setMapCanvas( mMapCanvas );
610  mRendererStackedWidget->addWidget( mRendererWidget );
611  if ( oldWidget )
612  {
613  //compare used bands in new and old renderer and reset transparency dialog if different
614  std::unique_ptr<QgsRasterRenderer> oldRenderer;
615  oldRenderer.reset( oldWidget->renderer() );
616  std::unique_ptr<QgsRasterRenderer> newRenderer;
617  newRenderer.reset( mRendererWidget->renderer() );
618  const QList<int> oldBands = oldRenderer->usesBands();
619  const QList<int> newBands = newRenderer->usesBands();
620  if ( oldBands != newBands )
621  {
622  mRasterTransparencyWidget->syncToLayer();
623  }
624  }
625  }
626  }
627 
628  const int widgetIndex = mRenderTypeComboBox->findData( rendererName );
629  if ( widgetIndex != -1 )
630  {
631  mDisableRenderTypeComboBoxCurrentIndexChanged = true;
632  mRenderTypeComboBox->setCurrentIndex( widgetIndex );
633  mDisableRenderTypeComboBoxCurrentIndexChanged = false;
634  }
635 
636  if ( mRendererWidget != oldWidget )
637  delete oldWidget;
638 
639  if ( mHistogramWidget )
640  {
641  mHistogramWidget->setRendererWidget( rendererName, mRendererWidget );
642  }
643 }
644 
645 void QgsRasterLayerProperties::sync()
646 {
647  QgsSettings myQSettings;
648 
649  if ( !mSourceWidget )
650  {
651  mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mRasterLayer );
652  if ( mSourceWidget )
653  {
654  QHBoxLayout *layout = new QHBoxLayout();
655  layout->addWidget( mSourceWidget );
656  mSourceGroupBox->setLayout( layout );
657  mSourceGroupBox->show();
658 
659  connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [ = ]( bool isValid )
660  {
661  buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
662  buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
663  } );
664  }
665  }
666 
667  if ( mSourceWidget )
668  mSourceWidget->setSourceUri( mRasterLayer->source() );
669 
670  const QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
671  if ( !provider )
672  return;
673 
674  if ( provider->dataType( 1 ) == Qgis::DataType::ARGB32
675  || provider->dataType( 1 ) == Qgis::DataType::ARGB32_Premultiplied )
676  {
677  mRasterTransparencyWidget->gboxNoDataValue->setEnabled( false );
678  mRasterTransparencyWidget->gboxCustomTransparency->setEnabled( false );
679  mOptionsStackedWidget->setCurrentWidget( mOptsPage_Server );
680  }
681 
682  // TODO: Wouldn't it be better to just removeWidget() the tabs than delete them? [LS]
683  if ( !( provider->capabilities() & QgsRasterDataProvider::BuildPyramids ) )
684  {
685  if ( mOptsPage_Pyramids )
686  {
687  delete mOptsPage_Pyramids;
688  mOptsPage_Pyramids = nullptr;
689  }
690  }
691 
692  if ( !( provider->capabilities() & QgsRasterDataProvider::Size ) )
693  {
694  if ( mOptsPage_Histogram )
695  {
696  delete mOptsPage_Histogram;
697  mOptsPage_Histogram = nullptr;
698  delete mHistogramWidget;
699  mHistogramWidget = nullptr;
700  }
701  }
702 
703  QgsDebugMsgLevel( QStringLiteral( "populate transparency tab" ), 3 );
704 
705  /*
706  * Style tab
707  */
708 
709  //set brightness, contrast and gamma
710  QgsBrightnessContrastFilter *brightnessFilter = mRasterLayer->brightnessFilter();
711  if ( brightnessFilter )
712  {
713  mSliderBrightness->setValue( brightnessFilter->brightness() );
714  mSliderContrast->setValue( brightnessFilter->contrast() );
715  mGammaSpinBox->setValue( brightnessFilter->gamma() );
716  }
717 
718  // Hue and saturation color control
719  const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
720  //set hue and saturation controls to current values
721  if ( hueSaturationFilter )
722  {
723  sliderSaturation->setValue( hueSaturationFilter->saturation() );
724  comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
725 
726  // Set state of saturation controls based on grayscale mode choice
727  toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
728 
729  // Set state of colorize controls
730  mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
731  btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
732  toggleColorizeControls( hueSaturationFilter->colorizeOn() );
733  sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
734  mInvertColorsCheck->setChecked( hueSaturationFilter->invertColors() );
735  }
736 
737 
738  mRefreshLayerCheckBox->setChecked( mRasterLayer->hasAutoRefreshEnabled() );
739  mRefreshLayerIntervalSpinBox->setEnabled( mRasterLayer->hasAutoRefreshEnabled() );
740  mRefreshLayerIntervalSpinBox->setValue( mRasterLayer->autoRefreshInterval() / 1000.0 );
741 
742  QgsDebugMsgLevel( QStringLiteral( "populate general tab" ), 3 );
743  /*
744  * General Tab
745  */
746 
747  mLayerOrigNameLineEd->setText( mRasterLayer->name() );
748 
749  QgsDebugMsgLevel( QStringLiteral( "populate metadata tab" ), 2 );
750  /*
751  * Metadata Tab
752  */
753  //populate the metadata tab's text browser widget with gdal metadata info
754  updateInformationContent();
755 
756  // WMS Name as layer short name
757  mLayerShortNameLineEdit->setText( mRasterLayer->shortName() );
758  // WMS Name validator
759  QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
760  mLayerShortNameLineEdit->setValidator( shortNameValidator );
761 
762  //layer title and abstract
763  mLayerTitleLineEdit->setText( mRasterLayer->title() );
764  mLayerAbstractTextEdit->setPlainText( mRasterLayer->abstract() );
765  mLayerKeywordListLineEdit->setText( mRasterLayer->keywordList() );
766  mLayerDataUrlLineEdit->setText( mRasterLayer->dataUrl() );
767  mLayerDataUrlFormatComboBox->setCurrentIndex(
768  mLayerDataUrlFormatComboBox->findText(
769  mRasterLayer->dataUrlFormat()
770  )
771  );
772 
773  //layer attribution
774  mLayerAttributionLineEdit->setText( mRasterLayer->attribution() );
775  mLayerAttributionUrlLineEdit->setText( mRasterLayer->attributionUrl() );
776 
777  // layer metadata url
778  const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mRasterLayer->serverProperties()->metadataUrls();
779  for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
780  {
781  const int row = mMetadataUrlModel->rowCount();
782  mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
783  mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
784  mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
785  }
786 
787  // layer legend url
788  mLayerLegendUrlLineEdit->setText( mRasterLayer->legendUrl() );
789  mLayerLegendUrlFormatComboBox->setCurrentIndex( mLayerLegendUrlFormatComboBox->findText( mRasterLayer->legendUrlFormat() ) );
790 
791  //WMS print layer
792  QVariant wmsPrintLayer = mRasterLayer->customProperty( QStringLiteral( "WMSPrintLayer" ) );
793  if ( wmsPrintLayer.isValid() )
794  {
795  mWMSPrintLayerLineEdit->setText( wmsPrintLayer.toString() );
796  }
797 
798  QVariant wmsPublishDataSourceUrl = mRasterLayer->customProperty( QStringLiteral( "WMSPublishDataSourceUrl" ), false );
799  mPublishDataSourceUrlCheckBox->setChecked( wmsPublishDataSourceUrl.toBool() );
800 
801  QVariant wmsBackgroundLayer = mRasterLayer->customProperty( QStringLiteral( "WMSBackgroundLayer" ), false );
802  mBackgroundLayerCheckBox->setChecked( wmsBackgroundLayer.toBool() );
803 
804  mLegendPlaceholderWidget->setLastPathSettingsKey( QStringLiteral( "lastLegendPlaceholderDir" ) );
805  mLegendPlaceholderWidget->setSource( mRasterLayer->legendPlaceholderImage() );
806  mLegendConfigEmbeddedWidget->setLayer( mRasterLayer );
807 
808  mTemporalWidget->syncToLayer();
809 
810  mPropertyCollection = mRasterLayer->pipe()->dataDefinedProperties();
811  updateDataDefinedButtons();
812 
813  for ( QgsMapLayerConfigWidget *page : std::as_const( mLayerPropertiesPages ) )
814  {
815  page->syncToLayer( mRasterLayer );
816  }
817 
818 }
819 
820 void QgsRasterLayerProperties::apply()
821 {
822  if ( mSourceWidget )
823  {
824  const QString newSource = mSourceWidget->sourceUri();
825  if ( newSource != mRasterLayer->source() )
826  {
827  mRasterLayer->setDataSource( newSource, mRasterLayer->name(), mRasterLayer->providerType(), QgsDataProvider::ProviderOptions() );
828  }
829  }
830 
831  // Do nothing on "bad" layers
832  if ( !mRasterLayer->isValid() )
833  return;
834 
835  // apply all plugin dialogs
836  for ( QgsMapLayerConfigWidget *page : std::as_const( mLayerPropertiesPages ) )
837  {
838  page->apply();
839  }
840 
841 
842  /*
843  * Legend Tab
844  */
845  mRasterLayer->setLegendPlaceholderImage( mLegendPlaceholderWidget->source() );
846  mLegendConfigEmbeddedWidget->applyToLayer();
847 
848  QgsDebugMsgLevel( QStringLiteral( "apply processing symbology tab" ), 3 );
849  /*
850  * Symbology Tab
851  */
852 
853  //set whether the layer histogram should be inverted
854  //mRasterLayer->setInvertHistogram( cboxInvertColorMap->isChecked() );
855 
856  mRasterLayer->brightnessFilter()->setBrightness( mSliderBrightness->value() );
857  mRasterLayer->brightnessFilter()->setContrast( mSliderContrast->value() );
858  mRasterLayer->brightnessFilter()->setGamma( mGammaSpinBox->value() );
859 
860  QgsDebugMsgLevel( QStringLiteral( "processing transparency tab" ), 3 );
861  /*
862  * Transparent Pixel Tab
863  */
864 
865  //set NoDataValue
866  QgsRasterRangeList myNoDataRangeList;
867  if ( "" != mRasterTransparencyWidget->leNoDataValue->text() )
868  {
869  bool myDoubleOk = false;
870  double myNoDataValue = QgsDoubleValidator::toDouble( mRasterTransparencyWidget->leNoDataValue->text(), &myDoubleOk );
871  if ( myDoubleOk )
872  {
873  QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
874  myNoDataRangeList << myNoDataRange;
875  }
876  }
877  for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
878  {
879  mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
880  mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mRasterTransparencyWidget->mSrcNoDataValueCheckBox->isChecked() );
881  }
882 
883  //set renderer from widget
884  QgsRasterRendererWidget *rendererWidget = dynamic_cast<QgsRasterRendererWidget *>( mRendererStackedWidget->currentWidget() );
885  if ( rendererWidget )
886  {
887  rendererWidget->doComputations();
888 
889  mRasterLayer->setRenderer( rendererWidget->renderer() );
890  }
891 
892  mBackupCrs = mRasterLayer->crs();
893  mMetadataWidget->acceptMetadata();
894  mMetadataFilled = false;
895 
896  //transparency settings
897  QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
898  if ( rasterRenderer )
899  {
900  rasterRenderer->setAlphaBand( mRasterTransparencyWidget->cboxTransparencyBand->currentBand() );
901  rasterRenderer->setNodataColor( mRasterTransparencyWidget->mNodataColorButton->color() );
902 
903  //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
904  QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
905  if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 4 )
906  {
908  QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
909  for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
910  {
911  myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
912  myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
913  myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
914  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
915  myTransparentThreeValuePixelList.append( myTransparentPixel );
916  }
917  rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
918  }
919  else if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 3 )
920  {
922  QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
923  for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
924  {
925  myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
926  myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
927  myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
928 
929  myTransparentSingleValuePixelList.append( myTransparentPixel );
930  }
931  rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
932  }
933 
934  rasterRenderer->setRasterTransparency( rasterTransparency );
935 
936  // Sync the layer styling widget
937  mRasterLayer->emitStyleChanged();
938 
939  //set global transparency
940  rasterRenderer->setOpacity( mRasterTransparencyWidget->mOpacityWidget->opacity() );
941  }
942 
943  QgsDebugMsgLevel( QStringLiteral( "processing general tab" ), 3 );
944  /*
945  * General Tab
946  */
947  mRasterLayer->setName( mLayerOrigNameLineEd->text() );
948 
949  // set up the scale based layer visibility stuff....
950  mRasterLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
951  mRasterLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
952  mRasterLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
953 
954  mRasterLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
955  mRasterLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
956 
957  //update the legend pixmap
958  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
959  // pixmapLegend->setScaledContents( true );
960  // pixmapLegend->repaint();
961 
962  mResamplingUtils.refreshLayerFromWidgets();
963 
964  // Hue and saturation controls
965  QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
966  if ( hueSaturationFilter )
967  {
968  hueSaturationFilter->setSaturation( sliderSaturation->value() );
969  hueSaturationFilter->setGrayscaleMode( ( QgsHueSaturationFilter::GrayscaleMode ) comboGrayscale->currentIndex() );
970  hueSaturationFilter->setColorizeOn( mColorizeCheck->checkState() );
971  hueSaturationFilter->setColorizeColor( btnColorizeColor->color() );
972  hueSaturationFilter->setColorizeStrength( sliderColorizeStrength->value() );
973  hueSaturationFilter->setInvertColors( mInvertColorsCheck->isChecked() );
974  }
975 
976  //set the blend mode for the layer
977  mRasterLayer->setBlendMode( mBlendModeComboBox->blendMode() );
978 
979  // Update temporal properties
980  mTemporalWidget->saveTemporalProperties();
981 
982  mRasterLayer->setCrs( mCrsSelector->crs() );
983 
984  if ( mRasterLayer->shortName() != mLayerShortNameLineEdit->text() )
985  mMetadataFilled = false;
986  mRasterLayer->setShortName( mLayerShortNameLineEdit->text() );
987 
988  if ( mRasterLayer->title() != mLayerTitleLineEdit->text() )
989  mMetadataFilled = false;
990  mRasterLayer->setTitle( mLayerTitleLineEdit->text() );
991 
992  if ( mRasterLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
993  mMetadataFilled = false;
994  mRasterLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
995 
996  if ( mRasterLayer->keywordList() != mLayerKeywordListLineEdit->text() )
997  mMetadataFilled = false;
998  mRasterLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
999 
1000  if ( mRasterLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
1001  mMetadataFilled = false;
1002  mRasterLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
1003 
1004  if ( mRasterLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
1005  mMetadataFilled = false;
1006  mRasterLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
1007 
1008  //layer attribution
1009  if ( mRasterLayer->attribution() != mLayerAttributionLineEdit->text() )
1010  mMetadataFilled = false;
1011  mRasterLayer->setAttribution( mLayerAttributionLineEdit->text() );
1012 
1013  if ( mRasterLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
1014  mMetadataFilled = false;
1015  mRasterLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
1016 
1017  // Metadata URL
1018  QList<QgsMapLayerServerProperties::MetadataUrl> metaUrls;
1019  for ( int row = 0; row < mMetadataUrlModel->rowCount() ; row++ )
1020  {
1022  metaUrl.url = mMetadataUrlModel->item( row, 0 )->text();
1023  metaUrl.type = mMetadataUrlModel->item( row, 1 )->text();
1024  metaUrl.format = mMetadataUrlModel->item( row, 2 )->text();
1025  metaUrls.append( metaUrl );
1026  mMetadataFilled = false;
1027  }
1028  mRasterLayer->serverProperties()->setMetadataUrls( metaUrls );
1029 
1030  if ( mRasterLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
1031  mMetadataFilled = false;
1032  mRasterLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
1033 
1034  if ( mRasterLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
1035  mMetadataFilled = false;
1036  mRasterLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
1037 
1038  if ( !mWMSPrintLayerLineEdit->text().isEmpty() )
1039  {
1040  mRasterLayer->setCustomProperty( QStringLiteral( "WMSPrintLayer" ), mWMSPrintLayerLineEdit->text() );
1041  }
1042 
1043  mRasterLayer->setCustomProperty( "WMSPublishDataSourceUrl", mPublishDataSourceUrlCheckBox->isChecked() );
1044  mRasterLayer->setCustomProperty( "WMSBackgroundLayer", mBackgroundLayerCheckBox->isChecked() );
1045 
1046  mRasterLayer->pipe()->setDataDefinedProperties( mPropertyCollection );
1047 
1048  // Force a redraw of the legend
1049  mRasterLayer->setLegend( QgsMapLayerLegend::defaultRasterLegend( mRasterLayer ) );
1050 
1051  //make sure the layer is redrawn
1052  mRasterLayer->triggerRepaint();
1053 
1054  // notify the project we've made a change
1055  QgsProject::instance()->setDirty( true );
1056 }
1057 
1058 void QgsRasterLayerProperties::buttonBuildPyramids_clicked()
1059 {
1060  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1061 
1062  std::unique_ptr< QgsRasterBlockFeedback > feedback( new QgsRasterBlockFeedback() );
1063 
1064  connect( feedback.get(), &QgsRasterBlockFeedback::progressChanged, mPyramidProgress, &QProgressBar::setValue );
1065  //
1066  // Go through the list marking any files that are selected in the listview
1067  // as true so that we can generate pyramids for them.
1068  //
1069  QList< QgsRasterPyramid> myPyramidList = provider->buildPyramidList();
1070  for ( int myCounterInt = 0; myCounterInt < lbxPyramidResolutions->count(); myCounterInt++ )
1071  {
1072  QListWidgetItem *myItem = lbxPyramidResolutions->item( myCounterInt );
1073  //mark to be pyramided
1074  myPyramidList[myCounterInt].setBuild( myItem->isSelected() || myPyramidList[myCounterInt].getExists() );
1075  }
1076 
1077  // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
1078  QString prefix = provider->name() + "/driverOptions/_pyramids/";
1079  QgsSettings mySettings;
1080  QString resamplingMethod( cboResamplingMethod->currentData().toString() );
1081  mySettings.setValue( prefix + "resampling", resamplingMethod );
1082 
1083  //
1084  // Ask raster layer to build the pyramids
1085  //
1086 
1087  // let the user know we're going to possibly be taking a while
1088  QApplication::setOverrideCursor( Qt::WaitCursor );
1089  QString res = provider->buildPyramids(
1090  myPyramidList,
1091  resamplingMethod,
1092  ( QgsRaster::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex(),
1093  QStringList(),
1094  feedback.get() );
1095  QApplication::restoreOverrideCursor();
1096  mPyramidProgress->setValue( 0 );
1097  buttonBuildPyramids->setEnabled( false );
1098  if ( !res.isNull() )
1099  {
1100  if ( res == QLatin1String( "CANCELED" ) )
1101  {
1102  // user canceled
1103  }
1104  else if ( res == QLatin1String( "ERROR_WRITE_ACCESS" ) )
1105  {
1106  QMessageBox::warning( this, tr( "Building Pyramids" ),
1107  tr( "Write access denied. Adjust the file permissions and try again." ) );
1108  }
1109  else if ( res == QLatin1String( "ERROR_WRITE_FORMAT" ) )
1110  {
1111  QMessageBox::warning( this, tr( "Building Pyramids" ),
1112  tr( "The file was not writable. Some formats do not "
1113  "support pyramid overviews. Consult the GDAL documentation if in doubt." ) );
1114  }
1115  else if ( res == QLatin1String( "FAILED_NOT_SUPPORTED" ) )
1116  {
1117  QMessageBox::warning( this, tr( "Building Pyramids" ),
1118  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1119  }
1120  else if ( res == QLatin1String( "ERROR_JPEG_COMPRESSION" ) )
1121  {
1122  QMessageBox::warning( this, tr( "Building Pyramids" ),
1123  tr( "Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." ) );
1124  }
1125  else if ( res == QLatin1String( "ERROR_VIRTUAL" ) )
1126  {
1127  QMessageBox::warning( this, tr( "Building Pyramids" ),
1128  tr( "Building pyramid overviews is not supported on this type of raster." ) );
1129  }
1130 
1131  }
1132 
1133  //
1134  // repopulate the pyramids list
1135  //
1136  lbxPyramidResolutions->clear();
1137  // Need to rebuild list as some or all pyramids may have failed to build
1138  myPyramidList = provider->buildPyramidList();
1139  QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
1140  QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
1141 
1142  for ( const QgsRasterPyramid &pyramid : std::as_const( myPyramidList ) )
1143  {
1144  if ( pyramid.getExists() )
1145  {
1146  lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
1147  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1148  QString::number( pyramid.getYDim() ) ) );
1149  }
1150  else
1151  {
1152  lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
1153  QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1154  QString::number( pyramid.getYDim() ) ) );
1155  }
1156  }
1157  //update the legend pixmap
1158  // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
1159  // pixmapLegend->setScaledContents( true );
1160  // pixmapLegend->repaint();
1161 
1162  //populate the metadata tab's text browser widget with gdal metadata info
1163  updateInformationContent();
1164 }
1165 
1166 void QgsRasterLayerProperties::urlClicked( const QUrl &url )
1167 {
1168  QFileInfo file( url.toLocalFile() );
1169  if ( file.exists() && !file.isDir() )
1170  QgsGui::instance()->nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
1171  else
1172  QDesktopServices::openUrl( url );
1173 }
1174 
1175 void QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged( int index )
1176 {
1177  if ( index < 0 || mDisableRenderTypeComboBoxCurrentIndexChanged || ! mRasterLayer->renderer() )
1178  {
1179  return;
1180  }
1181 
1182  QString rendererName = mRenderTypeComboBox->itemData( index ).toString();
1183  setRendererWidget( rendererName );
1184 }
1185 
1186 void QgsRasterLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
1187 {
1188  QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mMapCanvas, tr( "Select Transformation" ) );
1189  mRasterLayer->setCrs( crs );
1190  mMetadataWidget->crsChanged();
1191 }
1192 
1193 void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double value )
1194 {
1195  QgsDebugMsgLevel( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ), 3 );
1196  QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1197  if ( !provider ) return;
1198 
1199  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1200  if ( !renderer ) return;
1201  int nBands = renderer->usesBands().size();
1202 
1203  QLineEdit *lineEdit = new QLineEdit();
1204  lineEdit->setFrame( false ); // frame looks bad in table
1205  // Without margins row selection is not displayed (important for delete row)
1206  lineEdit->setContentsMargins( 1, 1, 1, 1 );
1207 
1208  if ( column == mRasterTransparencyWidget->tableTransparency->columnCount() - 1 )
1209  {
1210  // transparency
1211  // Who needs transparency as floating point?
1212  lineEdit->setValidator( new QIntValidator( nullptr ) );
1213  lineEdit->setText( QString::number( static_cast<int>( value ) ) );
1214  }
1215  else
1216  {
1217  // value
1218  QString valueString;
1219  switch ( provider->sourceDataType( 1 ) )
1220  {
1223  lineEdit->setValidator( new QgsDoubleValidator( nullptr ) );
1224  if ( !std::isnan( value ) )
1225  {
1226  double v = QgsRasterBlock::printValue( value ).toDouble();
1227  valueString = QLocale().toString( v, 'g' ) ;
1228  }
1229  break;
1230  default:
1231  lineEdit->setValidator( new QIntValidator( nullptr ) );
1232  if ( !std::isnan( value ) )
1233  {
1234  valueString = QLocale().toString( static_cast<int>( value ) );
1235  }
1236  break;
1237  }
1238  lineEdit->setText( valueString );
1239  }
1240  mRasterTransparencyWidget->tableTransparency->setCellWidget( row, column, lineEdit );
1241  adjustTransparencyCellWidth( row, column );
1242 
1243  if ( nBands == 1 && ( column == 0 || column == 1 ) )
1244  {
1245  connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerProperties::transparencyCellTextEdited );
1246  }
1247  mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1248 }
1249 
1250 void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, double value )
1251 {
1252  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1253  if ( !lineEdit ) return;
1254  double v = QgsRasterBlock::printValue( value ).toDouble();
1255  lineEdit->setText( QLocale().toString( v, 'g' ) );
1256  lineEdit->adjustSize();
1257  adjustTransparencyCellWidth( row, column );
1258  mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1259 }
1260 
1261 double QgsRasterLayerProperties::transparencyCellValue( int row, int column )
1262 {
1263  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1264  if ( !lineEdit || lineEdit->text().isEmpty() )
1265  {
1266  return std::numeric_limits<double>::quiet_NaN();
1267  }
1268  return QLocale().toDouble( lineEdit->text() );
1269 }
1270 
1271 void QgsRasterLayerProperties::adjustTransparencyCellWidth( int row, int column )
1272 {
1273  QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1274  if ( !lineEdit ) return;
1275 
1276  int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
1277  width = std::max( width, mRasterTransparencyWidget->tableTransparency->columnWidth( column ) );
1278 
1279  lineEdit->setFixedWidth( width );
1280 }
1281 
1282 void QgsRasterLayerProperties::transparencyCellTextEdited( const QString &text )
1283 {
1284  Q_UNUSED( text )
1285  QgsDebugMsgLevel( QStringLiteral( "text = %1" ).arg( text ), 3 );
1286  QgsRasterRenderer *renderer = mRendererWidget->renderer();
1287  if ( !renderer )
1288  {
1289  return;
1290  }
1291  int nBands = renderer->usesBands().size();
1292  if ( nBands == 1 )
1293  {
1294  QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
1295  if ( !lineEdit ) return;
1296  int row = -1;
1297  int column = -1;
1298  for ( int r = 0; r < mRasterTransparencyWidget->tableTransparency->rowCount(); r++ )
1299  {
1300  for ( int c = 0; c < mRasterTransparencyWidget->tableTransparency->columnCount(); c++ )
1301  {
1302  if ( mRasterTransparencyWidget->tableTransparency->cellWidget( r, c ) == sender() )
1303  {
1304  row = r;
1305  column = c;
1306  break;
1307  }
1308  }
1309  if ( row != -1 ) break;
1310  }
1311  QgsDebugMsgLevel( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ), 3 );
1312 
1313  if ( column == 0 )
1314  {
1315  QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, 1 ) );
1316  if ( !toLineEdit ) return;
1317  bool toChanged = mTransparencyToEdited.value( row );
1318  QgsDebugMsgLevel( QStringLiteral( "toChanged = %1" ).arg( toChanged ), 3 );
1319  if ( !toChanged )
1320  {
1321  toLineEdit->setText( lineEdit->text() );
1322  }
1323  }
1324  else if ( column == 1 )
1325  {
1326  setTransparencyToEdited( row );
1327  }
1328  }
1329 }
1330 
1331 void QgsRasterLayerProperties::aboutToShowStyleMenu()
1332 {
1333  // this should be unified with QgsVectorLayerProperties::aboutToShowStyleMenu()
1334 
1335  QMenu *m = qobject_cast<QMenu *>( sender() );
1336 
1338  // re-add style manager actions!
1339  m->addSeparator();
1341 }
1342 
1343 void QgsRasterLayerProperties::syncToLayer()
1344 {
1345  QgsRasterRenderer *renderer = mRasterLayer->renderer();
1346  if ( renderer )
1347  {
1348  setRendererWidget( renderer->type() );
1349  }
1350  sync();
1351  mRasterLayer->triggerRepaint();
1352 }
1353 
1354 void QgsRasterLayerProperties::setTransparencyToEdited( int row )
1355 {
1356  if ( row >= mTransparencyToEdited.size() )
1357  {
1358  mTransparencyToEdited.resize( row + 1 );
1359  }
1360  mTransparencyToEdited[row] = true;
1361 }
1362 
1364 {
1366 
1367  bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1368  mBtnStyle->setVisible( ! isMetadataPanel );
1369  mBtnMetadata->setVisible( isMetadataPanel );
1370 
1371  if ( !mHistogramWidget )
1372  return;
1373 
1374  if ( index == mOptStackedWidget->indexOf( mOptsPage_Histogram ) )
1375  {
1376  mHistogramWidget->setActive( true );
1377  }
1378  else
1379  {
1380  mHistogramWidget->setActive( false );
1381  }
1382 
1383  if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) || !mMetadataFilled )
1384  {
1385  //set the metadata contents (which can be expensive)
1386  updateInformationContent();
1387  }
1388 }
1389 
1390 void QgsRasterLayerProperties::initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsRasterPipe::Property key )
1391 {
1392  button->blockSignals( true );
1393  button->init( key, mPropertyCollection, QgsRasterPipe::propertyDefinitions(), nullptr );
1394  connect( button, &QgsPropertyOverrideButton::changed, this, &QgsRasterLayerProperties::updateProperty );
1395  button->registerExpressionContextGenerator( this );
1396  button->blockSignals( false );
1397 }
1398 
1399 void QgsRasterLayerProperties::updateDataDefinedButtons()
1400 {
1401  const auto propertyOverrideButtons { findChildren< QgsPropertyOverrideButton * >() };
1402  for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
1403  {
1404  updateDataDefinedButton( button );
1405  }
1406 }
1407 
1408 void QgsRasterLayerProperties::updateDataDefinedButton( QgsPropertyOverrideButton *button )
1409 {
1410  if ( !button )
1411  return;
1412 
1413  if ( button->propertyKey() < 0 )
1414  return;
1415 
1416  QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1417  whileBlocking( button )->setToProperty( mPropertyCollection.property( key ) );
1418 }
1419 
1420 void QgsRasterLayerProperties::updateProperty()
1421 {
1422  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1423  QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1424  mPropertyCollection.setProperty( key, button->toProperty() );
1425 }
1426 
1427 void QgsRasterLayerProperties::toggleSaturationControls( int grayscaleMode )
1428 {
1429  // Enable or disable saturation controls based on choice of grayscale mode
1430  if ( grayscaleMode == 0 )
1431  {
1432  sliderSaturation->setEnabled( true );
1433  spinBoxSaturation->setEnabled( true );
1434  }
1435  else
1436  {
1437  sliderSaturation->setEnabled( false );
1438  spinBoxSaturation->setEnabled( false );
1439  }
1440 }
1441 
1442 void QgsRasterLayerProperties::toggleColorizeControls( bool colorizeEnabled )
1443 {
1444  // Enable or disable colorize controls based on checkbox
1445  btnColorizeColor->setEnabled( colorizeEnabled );
1446  sliderColorizeStrength->setEnabled( colorizeEnabled );
1447  spinColorizeStrength->setEnabled( colorizeEnabled );
1448 }
1449 
1450 
1451 QLinearGradient QgsRasterLayerProperties::redGradient()
1452 {
1453  //define a gradient
1454  // TODO change this to actual polygon dims
1455  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1456  myGradient.setColorAt( 0.0, QColor( 242, 14, 25, 190 ) );
1457  myGradient.setColorAt( 0.5, QColor( 175, 29, 37, 190 ) );
1458  myGradient.setColorAt( 1.0, QColor( 114, 17, 22, 190 ) );
1459  return myGradient;
1460 }
1461 QLinearGradient QgsRasterLayerProperties::greenGradient()
1462 {
1463  //define a gradient
1464  // TODO change this to actual polygon dims
1465  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1466  myGradient.setColorAt( 0.0, QColor( 48, 168, 5, 190 ) );
1467  myGradient.setColorAt( 0.8, QColor( 36, 122, 4, 190 ) );
1468  myGradient.setColorAt( 1.0, QColor( 21, 71, 2, 190 ) );
1469  return myGradient;
1470 }
1471 QLinearGradient QgsRasterLayerProperties::blueGradient()
1472 {
1473  //define a gradient
1474  // TODO change this to actual polygon dims
1475  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1476  myGradient.setColorAt( 0.0, QColor( 30, 0, 106, 190 ) );
1477  myGradient.setColorAt( 0.2, QColor( 30, 72, 128, 190 ) );
1478  myGradient.setColorAt( 1.0, QColor( 30, 223, 196, 190 ) );
1479  return myGradient;
1480 }
1481 QLinearGradient QgsRasterLayerProperties::grayGradient()
1482 {
1483  //define a gradient
1484  // TODO change this to actual polygon dims
1485  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1486  myGradient.setColorAt( 0.0, QColor( 5, 5, 5, 190 ) );
1487  myGradient.setColorAt( 0.8, QColor( 122, 122, 122, 190 ) );
1488  myGradient.setColorAt( 1.0, QColor( 220, 220, 220, 190 ) );
1489  return myGradient;
1490 }
1491 QLinearGradient QgsRasterLayerProperties::highlightGradient()
1492 {
1493  //define another gradient for the highlight
1494  // TODO change this to actual polygon dims
1495  QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1496  myGradient.setColorAt( 1.0, QColor( 255, 255, 255, 50 ) );
1497  myGradient.setColorAt( 0.5, QColor( 255, 255, 255, 100 ) );
1498  myGradient.setColorAt( 0.0, QColor( 255, 255, 255, 150 ) );
1499  return myGradient;
1500 }
1501 
1502 void QgsRasterLayerProperties::addMetadataUrl()
1503 {
1504  const int row = mMetadataUrlModel->rowCount();
1505  mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
1506  mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
1507  mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
1508 }
1509 
1510 void QgsRasterLayerProperties::removeSelectedMetadataUrl()
1511 {
1512  const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
1513  if ( selectedRows.empty() )
1514  return;
1515  mMetadataUrlModel->removeRow( selectedRows[0].row() );
1516 }
1517 
1518 
1519 //
1520 //
1521 // Next four methods for saving and restoring qml style state
1522 //
1523 //
1524 void QgsRasterLayerProperties::loadDefaultStyle_clicked()
1525 {
1526  bool defaultLoadedFlag = false;
1527  QString myMessage = mRasterLayer->loadDefaultStyle( defaultLoadedFlag );
1528  //reset if the default style was loaded OK only
1529  if ( defaultLoadedFlag )
1530  {
1531  syncToLayer();
1532  }
1533  else
1534  {
1535  //otherwise let the user know what went wrong
1536  QMessageBox::information( this,
1537  tr( "Default Style" ),
1538  myMessage
1539  );
1540  }
1541 }
1542 
1543 void QgsRasterLayerProperties::saveDefaultStyle_clicked()
1544 {
1545 
1546  apply(); // make sure the style to save is up-to-date
1547 
1548  // a flag passed by reference
1549  bool defaultSavedFlag = false;
1550  // after calling this the above flag will be set true for success
1551  // or false if the save operation failed
1552  QString myMessage = mRasterLayer->saveDefaultStyle( defaultSavedFlag );
1553  if ( !defaultSavedFlag )
1554  {
1555  //let the user know what went wrong
1556  QMessageBox::information( this,
1557  tr( "Default Style" ),
1558  myMessage
1559  );
1560  }
1561 }
1562 
1563 
1564 void QgsRasterLayerProperties::loadStyle_clicked()
1565 {
1566  QgsSettings settings;
1567  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1568 
1569  QString fileName = QFileDialog::getOpenFileName(
1570  this,
1571  tr( "Load layer properties from style file" ),
1572  lastUsedDir,
1573  tr( "QGIS Layer Style File" ) + " (*.qml)" );
1574  if ( fileName.isEmpty() )
1575  return;
1576 
1577  // ensure the user never omits the extension from the file name
1578  if ( !fileName.endsWith( QLatin1String( ".qml" ), Qt::CaseInsensitive ) )
1579  fileName += QLatin1String( ".qml" );
1580 
1581  mOldStyle = mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() );
1582 
1583  bool defaultLoadedFlag = false;
1584  QString message = mRasterLayer->loadNamedStyle( fileName, defaultLoadedFlag );
1585  if ( defaultLoadedFlag )
1586  {
1587  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( fileName ).absolutePath() );
1588  syncToLayer();
1589  }
1590  else
1591  {
1592  QMessageBox::information( this, tr( "Save Style" ), message );
1593  }
1594 }
1595 
1596 
1597 void QgsRasterLayerProperties::saveStyleAs_clicked()
1598 {
1599  QgsSettings settings;
1600  QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1601 
1602  QString selectedFilter;
1603  QString outputFileName = QFileDialog::getSaveFileName(
1604  this,
1605  tr( "Save layer properties as style file" ),
1606  lastUsedDir,
1607  tr( "QGIS Layer Style File" ) + " (*.qml)" + ";;" + tr( "Styled Layer Descriptor" ) + " (*.sld)",
1608  &selectedFilter );
1609  if ( outputFileName.isEmpty() )
1610  return;
1611 
1612  StyleType type;
1613  // use selectedFilter to set style type
1614  if ( selectedFilter.contains( QStringLiteral( ".qml" ), Qt::CaseInsensitive ) )
1615  {
1616  outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "qml" ) );
1617  type = StyleType::QML;
1618  }
1619  else
1620  {
1621  outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "sld" ) );
1622  type = StyleType::SLD;
1623  }
1624 
1625  apply(); // make sure the style to save is up-to-date
1626 
1627  // then export style
1628  bool defaultLoadedFlag = false;
1629  QString message;
1630  switch ( type )
1631  {
1632  case QML:
1633  {
1634  message = mRasterLayer->saveNamedStyle( outputFileName, defaultLoadedFlag );
1635  break;
1636  }
1637  case SLD:
1638  {
1639  message = mRasterLayer->saveSldStyle( outputFileName, defaultLoadedFlag );
1640  break;
1641  }
1642  }
1643  if ( defaultLoadedFlag )
1644  {
1645  settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( outputFileName ).absolutePath() );
1646  sync();
1647  }
1648  else
1649  QMessageBox::information( this, tr( "Save Style" ), message );
1650 }
1651 
1652 void QgsRasterLayerProperties::restoreWindowModality()
1653 {
1654  hide();
1655  setModal( true );
1656  show();
1657  raise();
1658  activateWindow();
1659 }
1660 
1661 //
1662 //
1663 // Next four methods for saving and restoring QMD metadata
1664 //
1665 //
1666 
1667 void QgsRasterLayerProperties::loadMetadata()
1668 {
1669  QgsSettings myQSettings; // where we keep last used filter in persistent state
1670  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1671 
1672  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
1673  tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1674  if ( myFileName.isNull() )
1675  {
1676  return;
1677  }
1678 
1679  QString myMessage;
1680  bool defaultLoadedFlag = false;
1681  myMessage = mRasterLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1682 
1683  //reset if the default style was loaded OK only
1684  if ( defaultLoadedFlag )
1685  {
1686  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1687  }
1688  else
1689  {
1690  //let the user know what went wrong
1691  QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1692  }
1693 
1694  QFileInfo myFI( myFileName );
1695  QString myPath = myFI.path();
1696  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1697 
1698  activateWindow(); // set focus back to properties dialog
1699 }
1700 
1701 void QgsRasterLayerProperties::saveMetadataAs()
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 myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1707  myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1708  if ( myOutputFileName.isNull() ) //dialog canceled
1709  {
1710  return;
1711  }
1712 
1713  mMetadataWidget->acceptMetadata();
1714 
1715  //ensure the user never omitted the extension from the file name
1716  if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1717  {
1719  }
1720 
1721  bool defaultLoadedFlag = false;
1722  QString message = mRasterLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1723  if ( defaultLoadedFlag )
1724  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
1725  else
1726  QMessageBox::information( this, tr( "Save Metadata" ), message );
1727 }
1728 
1729 void QgsRasterLayerProperties::saveDefaultMetadata()
1730 {
1731  mMetadataWidget->acceptMetadata();
1732 
1733  bool defaultSavedFlag = false;
1734  QString errorMsg = mRasterLayer->saveDefaultMetadata( defaultSavedFlag );
1735  if ( !defaultSavedFlag )
1736  {
1737  QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1738  }
1739 }
1740 
1741 void QgsRasterLayerProperties::loadDefaultMetadata()
1742 {
1743  bool defaultLoadedFlag = false;
1744  QString myMessage = mRasterLayer->loadNamedMetadata( mRasterLayer->metadataUri(), defaultLoadedFlag );
1745  //reset if the default metadata was loaded OK only
1746  if ( defaultLoadedFlag )
1747  {
1748  mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1749  }
1750  else
1751  {
1752  QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1753  }
1754 }
1755 
1756 
1757 void QgsRasterLayerProperties::toggleBuildPyramidsButton()
1758 {
1759  if ( lbxPyramidResolutions->selectedItems().empty() )
1760  {
1761  buttonBuildPyramids->setEnabled( false );
1762  }
1763  else
1764  {
1765  buttonBuildPyramids->setEnabled( true );
1766  }
1767 }
1768 
1769 void QgsRasterLayerProperties::mResetColorRenderingBtn_clicked()
1770 {
1771  mBlendModeComboBox->setBlendMode( QPainter::CompositionMode_SourceOver );
1772  mSliderBrightness->setValue( 0 );
1773  mSliderContrast->setValue( 0 );
1774  mGammaSpinBox->setValue( 1.0 );
1775  sliderSaturation->setValue( 0 );
1776  comboGrayscale->setCurrentIndex( ( int ) QgsHueSaturationFilter::GrayscaleOff );
1777  mColorizeCheck->setChecked( false );
1778  sliderColorizeStrength->setValue( 100 );
1779  mInvertColorsCheck->setChecked( false );
1780 }
1781 
1782 bool QgsRasterLayerProperties::rasterIsMultiBandColor()
1783 {
1784  return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
1785 }
1786 
1787 void QgsRasterLayerProperties::updateInformationContent()
1788 {
1789  const QString myStyle = QgsApplication::reportStyleSheet( QgsApplication::StyleSheetType::WebBrowser );
1790  // Inject the stylesheet
1791  const QString html { mRasterLayer->htmlMetadata().replace( QLatin1String( "<head>" ), QStringLiteral( R"raw(<head><style type="text/css">%1</style>)raw" ) ).arg( myStyle ) };
1792  mMetadataViewer->setHtml( html );
1793  mMetadataFilled = true;
1794 }
1795 
1796 void QgsRasterLayerProperties::onCancel()
1797 {
1798  if ( mOldStyle.xmlData() != mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() ).xmlData() )
1799  {
1800  // need to reset style to previous - style applied directly to the layer (not in apply())
1801  QString myMessage;
1802  QDomDocument doc( QStringLiteral( "qgis" ) );
1803  int errorLine, errorColumn;
1804  doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
1805  mRasterLayer->importNamedStyle( doc, myMessage );
1806  syncToLayer();
1807  }
1808  if ( mBackupCrs != mRasterLayer->crs() )
1809  mRasterLayer->setCrs( mBackupCrs );
1810 }
1811 
1812 void QgsRasterLayerProperties::showHelp()
1813 {
1814  const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
1815 
1816  if ( helpPage.isValid() )
1817  {
1818  QgsHelp::openHelp( helpPage.toString() );
1819  }
1820  else
1821  {
1822  QgsHelp::openHelp( QStringLiteral( "working_with_raster/raster_properties.html" ) );
1823  }
1824 }
1825 
1826 void QgsRasterLayerProperties::updateGammaSpinBox( int value )
1827 {
1828  whileBlocking( mGammaSpinBox )->setValue( value / 100.0 );
1829 }
1830 
1831 void QgsRasterLayerProperties::updateGammaSlider( double value )
1832 {
1833  whileBlocking( mSliderGamma )->setValue( value * 100 );
1834 }
@ 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:89
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 ...
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
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 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.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
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)
Abstract base class for widgets which configure a QgsRasterRenderer.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QgsRasterRenderer * renderer()=0
Creates a new renderer, using the properties defined in the widget.
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.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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:1185
#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.