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