QGIS API Documentation 3.27.0-Master (f261cc1f8b)
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
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"
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"
48#include "qgsrasterlayer.h"
50#include "qgsrasterpyramid.h"
51#include "qgsrasterrange.h"
52#include "qgsrasterrenderer.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
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
97QgsRasterLayerProperties::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
570void 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
648void 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 {
672 mSourceWidget->setMapCanvas( mMapCanvas );
673 mSourceWidget->setSourceUri( mRasterLayer->source() );
674 }
675
676 const QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
677 if ( !provider )
678 return;
679
680 if ( provider->dataType( 1 ) == Qgis::DataType::ARGB32
682 {
683 mRasterTransparencyWidget->gboxNoDataValue->setEnabled( false );
684 mRasterTransparencyWidget->gboxCustomTransparency->setEnabled( false );
685 mOptionsStackedWidget->setCurrentWidget( mOptsPage_Server );
686 }
687
688 // TODO: Wouldn't it be better to just removeWidget() the tabs than delete them? [LS]
689 if ( !( provider->capabilities() & QgsRasterDataProvider::BuildPyramids ) )
690 {
691 if ( mOptsPage_Pyramids )
692 {
693 delete mOptsPage_Pyramids;
694 mOptsPage_Pyramids = nullptr;
695 }
696 }
697
698 if ( !( provider->capabilities() & QgsRasterDataProvider::Size ) )
699 {
700 if ( mOptsPage_Histogram )
701 {
702 delete mOptsPage_Histogram;
703 mOptsPage_Histogram = nullptr;
704 delete mHistogramWidget;
705 mHistogramWidget = nullptr;
706 }
707 }
708
709 QgsDebugMsgLevel( QStringLiteral( "populate transparency tab" ), 3 );
710
711 /*
712 * Style tab
713 */
714
715 //set brightness, contrast and gamma
716 QgsBrightnessContrastFilter *brightnessFilter = mRasterLayer->brightnessFilter();
717 if ( brightnessFilter )
718 {
719 mSliderBrightness->setValue( brightnessFilter->brightness() );
720 mSliderContrast->setValue( brightnessFilter->contrast() );
721 mGammaSpinBox->setValue( brightnessFilter->gamma() );
722 }
723
724 // Hue and saturation color control
725 const QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
726 //set hue and saturation controls to current values
727 if ( hueSaturationFilter )
728 {
729 sliderSaturation->setValue( hueSaturationFilter->saturation() );
730 comboGrayscale->setCurrentIndex( ( int ) hueSaturationFilter->grayscaleMode() );
731
732 // Set state of saturation controls based on grayscale mode choice
733 toggleSaturationControls( static_cast<int>( hueSaturationFilter->grayscaleMode() ) );
734
735 // Set state of colorize controls
736 mColorizeCheck->setChecked( hueSaturationFilter->colorizeOn() );
737 btnColorizeColor->setColor( hueSaturationFilter->colorizeColor() );
738 toggleColorizeControls( hueSaturationFilter->colorizeOn() );
739 sliderColorizeStrength->setValue( hueSaturationFilter->colorizeStrength() );
740 mInvertColorsCheck->setChecked( hueSaturationFilter->invertColors() );
741 }
742
743
744 mRefreshLayerCheckBox->setChecked( mRasterLayer->hasAutoRefreshEnabled() );
745 mRefreshLayerIntervalSpinBox->setEnabled( mRasterLayer->hasAutoRefreshEnabled() );
746 mRefreshLayerIntervalSpinBox->setValue( mRasterLayer->autoRefreshInterval() / 1000.0 );
747
748 QgsDebugMsgLevel( QStringLiteral( "populate general tab" ), 3 );
749 /*
750 * General Tab
751 */
752
753 mLayerOrigNameLineEd->setText( mRasterLayer->name() );
754
755 QgsDebugMsgLevel( QStringLiteral( "populate metadata tab" ), 2 );
756 /*
757 * Metadata Tab
758 */
759 //populate the metadata tab's text browser widget with gdal metadata info
760 updateInformationContent();
761
762 // WMS Name as layer short name
763 mLayerShortNameLineEdit->setText( mRasterLayer->shortName() );
764 // WMS Name validator
765 QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
766 mLayerShortNameLineEdit->setValidator( shortNameValidator );
767
768 //layer title and abstract
769 mLayerTitleLineEdit->setText( mRasterLayer->title() );
770 mLayerAbstractTextEdit->setPlainText( mRasterLayer->abstract() );
771 mLayerKeywordListLineEdit->setText( mRasterLayer->keywordList() );
772 mLayerDataUrlLineEdit->setText( mRasterLayer->dataUrl() );
773 mLayerDataUrlFormatComboBox->setCurrentIndex(
774 mLayerDataUrlFormatComboBox->findText(
775 mRasterLayer->dataUrlFormat()
776 )
777 );
778
779 //layer attribution
780 mLayerAttributionLineEdit->setText( mRasterLayer->attribution() );
781 mLayerAttributionUrlLineEdit->setText( mRasterLayer->attributionUrl() );
782
783 // layer metadata url
784 const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mRasterLayer->serverProperties()->metadataUrls();
785 for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
786 {
787 const int row = mMetadataUrlModel->rowCount();
788 mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
789 mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
790 mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
791 }
792
793 // layer legend url
794 mLayerLegendUrlLineEdit->setText( mRasterLayer->legendUrl() );
795 mLayerLegendUrlFormatComboBox->setCurrentIndex( mLayerLegendUrlFormatComboBox->findText( mRasterLayer->legendUrlFormat() ) );
796
797 //WMS print layer
798 QVariant wmsPrintLayer = mRasterLayer->customProperty( QStringLiteral( "WMSPrintLayer" ) );
799 if ( wmsPrintLayer.isValid() )
800 {
801 mWMSPrintLayerLineEdit->setText( wmsPrintLayer.toString() );
802 }
803
804 QVariant wmsPublishDataSourceUrl = mRasterLayer->customProperty( QStringLiteral( "WMSPublishDataSourceUrl" ), false );
805 mPublishDataSourceUrlCheckBox->setChecked( wmsPublishDataSourceUrl.toBool() );
806
807 QVariant wmsBackgroundLayer = mRasterLayer->customProperty( QStringLiteral( "WMSBackgroundLayer" ), false );
808 mBackgroundLayerCheckBox->setChecked( wmsBackgroundLayer.toBool() );
809
810 mLegendPlaceholderWidget->setLastPathSettingsKey( QStringLiteral( "lastLegendPlaceholderDir" ) );
811 mLegendPlaceholderWidget->setSource( mRasterLayer->legendPlaceholderImage() );
812 mLegendConfigEmbeddedWidget->setLayer( mRasterLayer );
813
814 mTemporalWidget->syncToLayer();
815
816 mPropertyCollection = mRasterLayer->pipe()->dataDefinedProperties();
817 updateDataDefinedButtons();
818
819 for ( QgsMapLayerConfigWidget *page : std::as_const( mLayerPropertiesPages ) )
820 {
821 page->syncToLayer( mRasterLayer );
822 }
823
824}
825
826void QgsRasterLayerProperties::apply()
827{
828 if ( mSourceWidget )
829 {
830 const QString newSource = mSourceWidget->sourceUri();
831 if ( newSource != mRasterLayer->source() )
832 {
833 mRasterLayer->setDataSource( newSource, mRasterLayer->name(), mRasterLayer->providerType(), QgsDataProvider::ProviderOptions() );
834 }
835 }
836
837 // Do nothing on "bad" layers
838 if ( !mRasterLayer->isValid() )
839 return;
840
841 // apply all plugin dialogs
842 for ( QgsMapLayerConfigWidget *page : std::as_const( mLayerPropertiesPages ) )
843 {
844 page->apply();
845 }
846
847
848 /*
849 * Legend Tab
850 */
851 mRasterLayer->setLegendPlaceholderImage( mLegendPlaceholderWidget->source() );
852 mLegendConfigEmbeddedWidget->applyToLayer();
853
854 QgsDebugMsgLevel( QStringLiteral( "apply processing symbology tab" ), 3 );
855 /*
856 * Symbology Tab
857 */
858
859 //set whether the layer histogram should be inverted
860 //mRasterLayer->setInvertHistogram( cboxInvertColorMap->isChecked() );
861
862 mRasterLayer->brightnessFilter()->setBrightness( mSliderBrightness->value() );
863 mRasterLayer->brightnessFilter()->setContrast( mSliderContrast->value() );
864 mRasterLayer->brightnessFilter()->setGamma( mGammaSpinBox->value() );
865
866 QgsDebugMsgLevel( QStringLiteral( "processing transparency tab" ), 3 );
867 /*
868 * Transparent Pixel Tab
869 */
870
871 //set NoDataValue
872 QgsRasterRangeList myNoDataRangeList;
873 if ( "" != mRasterTransparencyWidget->leNoDataValue->text() )
874 {
875 bool myDoubleOk = false;
876 double myNoDataValue = QgsDoubleValidator::toDouble( mRasterTransparencyWidget->leNoDataValue->text(), &myDoubleOk );
877 if ( myDoubleOk )
878 {
879 QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue );
880 myNoDataRangeList << myNoDataRange;
881 }
882 }
883 for ( int bandNo = 1; bandNo <= mRasterLayer->dataProvider()->bandCount(); bandNo++ )
884 {
885 mRasterLayer->dataProvider()->setUserNoDataValue( bandNo, myNoDataRangeList );
886 mRasterLayer->dataProvider()->setUseSourceNoDataValue( bandNo, mRasterTransparencyWidget->mSrcNoDataValueCheckBox->isChecked() );
887 }
888
889 //set renderer from widget
890 QgsRasterRendererWidget *rendererWidget = dynamic_cast<QgsRasterRendererWidget *>( mRendererStackedWidget->currentWidget() );
891 if ( rendererWidget )
892 {
893 rendererWidget->doComputations();
894
895 mRasterLayer->setRenderer( rendererWidget->renderer() );
896 }
897
898 mBackupCrs = mRasterLayer->crs();
899 mMetadataWidget->acceptMetadata();
900 mMetadataFilled = false;
901
902 //transparency settings
903 QgsRasterRenderer *rasterRenderer = mRasterLayer->renderer();
904 if ( rasterRenderer )
905 {
906 rasterRenderer->setAlphaBand( mRasterTransparencyWidget->cboxTransparencyBand->currentBand() );
907 rasterRenderer->setNodataColor( mRasterTransparencyWidget->mNodataColorButton->color() );
908
909 //Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
910 QgsRasterTransparency *rasterTransparency = new QgsRasterTransparency();
911 if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 4 )
912 {
914 QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList;
915 for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
916 {
917 myTransparentPixel.red = transparencyCellValue( myListRunner, 0 );
918 myTransparentPixel.green = transparencyCellValue( myListRunner, 1 );
919 myTransparentPixel.blue = transparencyCellValue( myListRunner, 2 );
920 myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 3 );
921 myTransparentThreeValuePixelList.append( myTransparentPixel );
922 }
923 rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
924 }
925 else if ( mRasterTransparencyWidget->tableTransparency->columnCount() == 3 )
926 {
928 QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList;
929 for ( int myListRunner = 0; myListRunner < mRasterTransparencyWidget->tableTransparency->rowCount(); myListRunner++ )
930 {
931 myTransparentPixel.min = transparencyCellValue( myListRunner, 0 );
932 myTransparentPixel.max = transparencyCellValue( myListRunner, 1 );
933 myTransparentPixel.percentTransparent = transparencyCellValue( myListRunner, 2 );
934
935 myTransparentSingleValuePixelList.append( myTransparentPixel );
936 }
937 rasterTransparency->setTransparentSingleValuePixelList( myTransparentSingleValuePixelList );
938 }
939
940 rasterRenderer->setRasterTransparency( rasterTransparency );
941
942 // Sync the layer styling widget
943 mRasterLayer->emitStyleChanged();
944
945 //set global transparency
946 rasterRenderer->setOpacity( mRasterTransparencyWidget->mOpacityWidget->opacity() );
947 }
948
949 QgsDebugMsgLevel( QStringLiteral( "processing general tab" ), 3 );
950 /*
951 * General Tab
952 */
953 mRasterLayer->setName( mLayerOrigNameLineEd->text() );
954
955 // set up the scale based layer visibility stuff....
956 mRasterLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
957 mRasterLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
958 mRasterLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
959
960 mRasterLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
961 mRasterLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
962
963 //update the legend pixmap
964 // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
965 // pixmapLegend->setScaledContents( true );
966 // pixmapLegend->repaint();
967
968 mResamplingUtils.refreshLayerFromWidgets();
969
970 // Hue and saturation controls
971 QgsHueSaturationFilter *hueSaturationFilter = mRasterLayer->hueSaturationFilter();
972 if ( hueSaturationFilter )
973 {
974 hueSaturationFilter->setSaturation( sliderSaturation->value() );
975 hueSaturationFilter->setGrayscaleMode( ( QgsHueSaturationFilter::GrayscaleMode ) comboGrayscale->currentIndex() );
976 hueSaturationFilter->setColorizeOn( mColorizeCheck->checkState() );
977 hueSaturationFilter->setColorizeColor( btnColorizeColor->color() );
978 hueSaturationFilter->setColorizeStrength( sliderColorizeStrength->value() );
979 hueSaturationFilter->setInvertColors( mInvertColorsCheck->isChecked() );
980 }
981
982 //set the blend mode for the layer
983 mRasterLayer->setBlendMode( mBlendModeComboBox->blendMode() );
984
985 // Update temporal properties
986 mTemporalWidget->saveTemporalProperties();
987
988 mRasterLayer->setCrs( mCrsSelector->crs() );
989
990 if ( mRasterLayer->shortName() != mLayerShortNameLineEdit->text() )
991 mMetadataFilled = false;
992 mRasterLayer->setShortName( mLayerShortNameLineEdit->text() );
993
994 if ( mRasterLayer->title() != mLayerTitleLineEdit->text() )
995 mMetadataFilled = false;
996 mRasterLayer->setTitle( mLayerTitleLineEdit->text() );
997
998 if ( mRasterLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
999 mMetadataFilled = false;
1000 mRasterLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
1001
1002 if ( mRasterLayer->keywordList() != mLayerKeywordListLineEdit->text() )
1003 mMetadataFilled = false;
1004 mRasterLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
1005
1006 if ( mRasterLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
1007 mMetadataFilled = false;
1008 mRasterLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
1009
1010 if ( mRasterLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
1011 mMetadataFilled = false;
1012 mRasterLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
1013
1014 //layer attribution
1015 if ( mRasterLayer->attribution() != mLayerAttributionLineEdit->text() )
1016 mMetadataFilled = false;
1017 mRasterLayer->setAttribution( mLayerAttributionLineEdit->text() );
1018
1019 if ( mRasterLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
1020 mMetadataFilled = false;
1021 mRasterLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
1022
1023 // Metadata URL
1024 QList<QgsMapLayerServerProperties::MetadataUrl> metaUrls;
1025 for ( int row = 0; row < mMetadataUrlModel->rowCount() ; row++ )
1026 {
1028 metaUrl.url = mMetadataUrlModel->item( row, 0 )->text();
1029 metaUrl.type = mMetadataUrlModel->item( row, 1 )->text();
1030 metaUrl.format = mMetadataUrlModel->item( row, 2 )->text();
1031 metaUrls.append( metaUrl );
1032 mMetadataFilled = false;
1033 }
1034 mRasterLayer->serverProperties()->setMetadataUrls( metaUrls );
1035
1036 if ( mRasterLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
1037 mMetadataFilled = false;
1038 mRasterLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
1039
1040 if ( mRasterLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
1041 mMetadataFilled = false;
1042 mRasterLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
1043
1044 if ( !mWMSPrintLayerLineEdit->text().isEmpty() )
1045 {
1046 mRasterLayer->setCustomProperty( QStringLiteral( "WMSPrintLayer" ), mWMSPrintLayerLineEdit->text() );
1047 }
1048
1049 mRasterLayer->setCustomProperty( "WMSPublishDataSourceUrl", mPublishDataSourceUrlCheckBox->isChecked() );
1050 mRasterLayer->setCustomProperty( "WMSBackgroundLayer", mBackgroundLayerCheckBox->isChecked() );
1051
1052 mRasterLayer->pipe()->setDataDefinedProperties( mPropertyCollection );
1053
1054 // Force a redraw of the legend
1055 mRasterLayer->setLegend( QgsMapLayerLegend::defaultRasterLegend( mRasterLayer ) );
1056
1057 //make sure the layer is redrawn
1058 mRasterLayer->triggerRepaint();
1059
1060 // notify the project we've made a change
1061 QgsProject::instance()->setDirty( true );
1062}
1063
1064void QgsRasterLayerProperties::buttonBuildPyramids_clicked()
1065{
1066 QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1067
1068 std::unique_ptr< QgsRasterBlockFeedback > feedback( new QgsRasterBlockFeedback() );
1069
1070 connect( feedback.get(), &QgsRasterBlockFeedback::progressChanged, mPyramidProgress, &QProgressBar::setValue );
1071 //
1072 // Go through the list marking any files that are selected in the listview
1073 // as true so that we can generate pyramids for them.
1074 //
1075 QList< QgsRasterPyramid> myPyramidList = provider->buildPyramidList();
1076 for ( int myCounterInt = 0; myCounterInt < lbxPyramidResolutions->count(); myCounterInt++ )
1077 {
1078 QListWidgetItem *myItem = lbxPyramidResolutions->item( myCounterInt );
1079 //mark to be pyramided
1080 myPyramidList[myCounterInt].setBuild( myItem->isSelected() || myPyramidList[myCounterInt].getExists() );
1081 }
1082
1083 // keep it in sync with qgsrasterpyramidsoptionwidget.cpp
1084 QString prefix = provider->name() + "/driverOptions/_pyramids/";
1085 QgsSettings mySettings;
1086 QString resamplingMethod( cboResamplingMethod->currentData().toString() );
1087 mySettings.setValue( prefix + "resampling", resamplingMethod );
1088
1089 //
1090 // Ask raster layer to build the pyramids
1091 //
1092
1093 // let the user know we're going to possibly be taking a while
1094 QApplication::setOverrideCursor( Qt::WaitCursor );
1095 QString res = provider->buildPyramids(
1096 myPyramidList,
1097 resamplingMethod,
1098 ( QgsRaster::RasterPyramidsFormat ) cbxPyramidsFormat->currentIndex(),
1099 QStringList(),
1100 feedback.get() );
1101 QApplication::restoreOverrideCursor();
1102 mPyramidProgress->setValue( 0 );
1103 buttonBuildPyramids->setEnabled( false );
1104 if ( !res.isNull() )
1105 {
1106 if ( res == QLatin1String( "CANCELED" ) )
1107 {
1108 // user canceled
1109 }
1110 else if ( res == QLatin1String( "ERROR_WRITE_ACCESS" ) )
1111 {
1112 QMessageBox::warning( this, tr( "Building Pyramids" ),
1113 tr( "Write access denied. Adjust the file permissions and try again." ) );
1114 }
1115 else if ( res == QLatin1String( "ERROR_WRITE_FORMAT" ) )
1116 {
1117 QMessageBox::warning( this, tr( "Building Pyramids" ),
1118 tr( "The file was not writable. Some formats do not "
1119 "support pyramid overviews. Consult the GDAL documentation if in doubt." ) );
1120 }
1121 else if ( res == QLatin1String( "FAILED_NOT_SUPPORTED" ) )
1122 {
1123 QMessageBox::warning( this, tr( "Building Pyramids" ),
1124 tr( "Building pyramid overviews is not supported on this type of raster." ) );
1125 }
1126 else if ( res == QLatin1String( "ERROR_JPEG_COMPRESSION" ) )
1127 {
1128 QMessageBox::warning( this, tr( "Building Pyramids" ),
1129 tr( "Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." ) );
1130 }
1131 else if ( res == QLatin1String( "ERROR_VIRTUAL" ) )
1132 {
1133 QMessageBox::warning( this, tr( "Building Pyramids" ),
1134 tr( "Building pyramid overviews is not supported on this type of raster." ) );
1135 }
1136
1137 }
1138
1139 //
1140 // repopulate the pyramids list
1141 //
1142 lbxPyramidResolutions->clear();
1143 // Need to rebuild list as some or all pyramids may have failed to build
1144 myPyramidList = provider->buildPyramidList();
1145 QIcon myPyramidPixmap( QgsApplication::getThemeIcon( "/mIconPyramid.svg" ) );
1146 QIcon myNoPyramidPixmap( QgsApplication::getThemeIcon( "/mIconNoPyramid.svg" ) );
1147
1148 for ( const QgsRasterPyramid &pyramid : std::as_const( myPyramidList ) )
1149 {
1150 if ( pyramid.getExists() )
1151 {
1152 lbxPyramidResolutions->addItem( new QListWidgetItem( myPyramidPixmap,
1153 QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1154 QString::number( pyramid.getYDim() ) ) );
1155 }
1156 else
1157 {
1158 lbxPyramidResolutions->addItem( new QListWidgetItem( myNoPyramidPixmap,
1159 QString::number( pyramid.getXDim() ) + QStringLiteral( " x " ) +
1160 QString::number( pyramid.getYDim() ) ) );
1161 }
1162 }
1163 //update the legend pixmap
1164 // pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
1165 // pixmapLegend->setScaledContents( true );
1166 // pixmapLegend->repaint();
1167
1168 //populate the metadata tab's text browser widget with gdal metadata info
1169 updateInformationContent();
1170}
1171
1172void QgsRasterLayerProperties::urlClicked( const QUrl &url )
1173{
1174 QFileInfo file( url.toLocalFile() );
1175 if ( file.exists() && !file.isDir() )
1176 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
1177 else
1178 QDesktopServices::openUrl( url );
1179}
1180
1181void QgsRasterLayerProperties::mRenderTypeComboBox_currentIndexChanged( int index )
1182{
1183 if ( index < 0 || mDisableRenderTypeComboBoxCurrentIndexChanged || ! mRasterLayer->renderer() )
1184 {
1185 return;
1186 }
1187
1188 QString rendererName = mRenderTypeComboBox->itemData( index ).toString();
1189 setRendererWidget( rendererName );
1190}
1191
1192void QgsRasterLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
1193{
1194 QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mMapCanvas, tr( "Select Transformation" ) );
1195 mRasterLayer->setCrs( crs );
1196 mMetadataWidget->crsChanged();
1197}
1198
1199void QgsRasterLayerProperties::setTransparencyCell( int row, int column, double value )
1200{
1201 QgsDebugMsgLevel( QStringLiteral( "value = %1" ).arg( value, 0, 'g', 17 ), 3 );
1202 QgsRasterDataProvider *provider = mRasterLayer->dataProvider();
1203 if ( !provider ) return;
1204
1205 QgsRasterRenderer *renderer = mRendererWidget->renderer();
1206 if ( !renderer ) return;
1207 int nBands = renderer->usesBands().size();
1208
1209 QLineEdit *lineEdit = new QLineEdit();
1210 lineEdit->setFrame( false ); // frame looks bad in table
1211 // Without margins row selection is not displayed (important for delete row)
1212 lineEdit->setContentsMargins( 1, 1, 1, 1 );
1213
1214 if ( column == mRasterTransparencyWidget->tableTransparency->columnCount() - 1 )
1215 {
1216 // transparency
1217 // Who needs transparency as floating point?
1218 lineEdit->setValidator( new QIntValidator( nullptr ) );
1219 lineEdit->setText( QString::number( static_cast<int>( value ) ) );
1220 }
1221 else
1222 {
1223 // value
1224 QString valueString;
1225 switch ( provider->sourceDataType( 1 ) )
1226 {
1229 lineEdit->setValidator( new QgsDoubleValidator( nullptr ) );
1230 if ( !std::isnan( value ) )
1231 {
1232 double v = QgsRasterBlock::printValue( value ).toDouble();
1233 valueString = QLocale().toString( v, 'g' ) ;
1234 }
1235 break;
1236 default:
1237 lineEdit->setValidator( new QIntValidator( nullptr ) );
1238 if ( !std::isnan( value ) )
1239 {
1240 valueString = QLocale().toString( static_cast<int>( value ) );
1241 }
1242 break;
1243 }
1244 lineEdit->setText( valueString );
1245 }
1246 mRasterTransparencyWidget->tableTransparency->setCellWidget( row, column, lineEdit );
1247 adjustTransparencyCellWidth( row, column );
1248
1249 if ( nBands == 1 && ( column == 0 || column == 1 ) )
1250 {
1251 connect( lineEdit, &QLineEdit::textEdited, this, &QgsRasterLayerProperties::transparencyCellTextEdited );
1252 }
1253 mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1254}
1255
1256void QgsRasterLayerProperties::setTransparencyCellValue( int row, int column, double value )
1257{
1258 QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1259 if ( !lineEdit ) return;
1260 double v = QgsRasterBlock::printValue( value ).toDouble();
1261 lineEdit->setText( QLocale().toString( v, 'g' ) );
1262 lineEdit->adjustSize();
1263 adjustTransparencyCellWidth( row, column );
1264 mRasterTransparencyWidget->tableTransparency->resizeColumnsToContents();
1265}
1266
1267double QgsRasterLayerProperties::transparencyCellValue( int row, int column )
1268{
1269 QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1270 if ( !lineEdit || lineEdit->text().isEmpty() )
1271 {
1272 return std::numeric_limits<double>::quiet_NaN();
1273 }
1274 return QLocale().toDouble( lineEdit->text() );
1275}
1276
1277void QgsRasterLayerProperties::adjustTransparencyCellWidth( int row, int column )
1278{
1279 QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, column ) );
1280 if ( !lineEdit ) return;
1281
1282 int width = std::max( lineEdit->fontMetrics().boundingRect( lineEdit->text() ).width() + 10, 100 );
1283 width = std::max( width, mRasterTransparencyWidget->tableTransparency->columnWidth( column ) );
1284
1285 lineEdit->setFixedWidth( width );
1286}
1287
1288void QgsRasterLayerProperties::transparencyCellTextEdited( const QString &text )
1289{
1290 Q_UNUSED( text )
1291 QgsDebugMsgLevel( QStringLiteral( "text = %1" ).arg( text ), 3 );
1292 QgsRasterRenderer *renderer = mRendererWidget->renderer();
1293 if ( !renderer )
1294 {
1295 return;
1296 }
1297 int nBands = renderer->usesBands().size();
1298 if ( nBands == 1 )
1299 {
1300 QLineEdit *lineEdit = qobject_cast<QLineEdit *>( sender() );
1301 if ( !lineEdit ) return;
1302 int row = -1;
1303 int column = -1;
1304 for ( int r = 0; r < mRasterTransparencyWidget->tableTransparency->rowCount(); r++ )
1305 {
1306 for ( int c = 0; c < mRasterTransparencyWidget->tableTransparency->columnCount(); c++ )
1307 {
1308 if ( mRasterTransparencyWidget->tableTransparency->cellWidget( r, c ) == sender() )
1309 {
1310 row = r;
1311 column = c;
1312 break;
1313 }
1314 }
1315 if ( row != -1 ) break;
1316 }
1317 QgsDebugMsgLevel( QStringLiteral( "row = %1 column =%2" ).arg( row ).arg( column ), 3 );
1318
1319 if ( column == 0 )
1320 {
1321 QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mRasterTransparencyWidget->tableTransparency->cellWidget( row, 1 ) );
1322 if ( !toLineEdit ) return;
1323 bool toChanged = mTransparencyToEdited.value( row );
1324 QgsDebugMsgLevel( QStringLiteral( "toChanged = %1" ).arg( toChanged ), 3 );
1325 if ( !toChanged )
1326 {
1327 toLineEdit->setText( lineEdit->text() );
1328 }
1329 }
1330 else if ( column == 1 )
1331 {
1332 setTransparencyToEdited( row );
1333 }
1334 }
1335}
1336
1337void QgsRasterLayerProperties::aboutToShowStyleMenu()
1338{
1339 // this should be unified with QgsVectorLayerProperties::aboutToShowStyleMenu()
1340
1341 QMenu *m = qobject_cast<QMenu *>( sender() );
1342
1344 // re-add style manager actions!
1345 m->addSeparator();
1347}
1348
1349void QgsRasterLayerProperties::syncToLayer()
1350{
1351 QgsRasterRenderer *renderer = mRasterLayer->renderer();
1352 if ( renderer )
1353 {
1354 setRendererWidget( renderer->type() );
1355 }
1356 sync();
1357 mRasterLayer->triggerRepaint();
1358}
1359
1360void QgsRasterLayerProperties::setTransparencyToEdited( int row )
1361{
1362 if ( row >= mTransparencyToEdited.size() )
1363 {
1364 mTransparencyToEdited.resize( row + 1 );
1365 }
1366 mTransparencyToEdited[row] = true;
1367}
1368
1370{
1372
1373 bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1374 mBtnStyle->setVisible( ! isMetadataPanel );
1375 mBtnMetadata->setVisible( isMetadataPanel );
1376
1377 if ( !mHistogramWidget )
1378 return;
1379
1380 if ( index == mOptStackedWidget->indexOf( mOptsPage_Histogram ) )
1381 {
1382 mHistogramWidget->setActive( true );
1383 }
1384 else
1385 {
1386 mHistogramWidget->setActive( false );
1387 }
1388
1389 if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) || !mMetadataFilled )
1390 {
1391 //set the metadata contents (which can be expensive)
1392 updateInformationContent();
1393 }
1394}
1395
1396void QgsRasterLayerProperties::initializeDataDefinedButton( QgsPropertyOverrideButton *button, QgsRasterPipe::Property key )
1397{
1398 button->blockSignals( true );
1399 button->init( key, mPropertyCollection, QgsRasterPipe::propertyDefinitions(), nullptr );
1400 connect( button, &QgsPropertyOverrideButton::changed, this, &QgsRasterLayerProperties::updateProperty );
1401 button->registerExpressionContextGenerator( this );
1402 button->blockSignals( false );
1403}
1404
1405void QgsRasterLayerProperties::updateDataDefinedButtons()
1406{
1407 const auto propertyOverrideButtons { findChildren< QgsPropertyOverrideButton * >() };
1408 for ( QgsPropertyOverrideButton *button : propertyOverrideButtons )
1409 {
1410 updateDataDefinedButton( button );
1411 }
1412}
1413
1414void QgsRasterLayerProperties::updateDataDefinedButton( QgsPropertyOverrideButton *button )
1415{
1416 if ( !button )
1417 return;
1418
1419 if ( button->propertyKey() < 0 )
1420 return;
1421
1422 QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1423 whileBlocking( button )->setToProperty( mPropertyCollection.property( key ) );
1424}
1425
1426void QgsRasterLayerProperties::updateProperty()
1427{
1428 QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
1429 QgsRasterPipe::Property key = static_cast< QgsRasterPipe::Property >( button->propertyKey() );
1430 mPropertyCollection.setProperty( key, button->toProperty() );
1431}
1432
1433void QgsRasterLayerProperties::toggleSaturationControls( int grayscaleMode )
1434{
1435 // Enable or disable saturation controls based on choice of grayscale mode
1436 if ( grayscaleMode == 0 )
1437 {
1438 sliderSaturation->setEnabled( true );
1439 spinBoxSaturation->setEnabled( true );
1440 }
1441 else
1442 {
1443 sliderSaturation->setEnabled( false );
1444 spinBoxSaturation->setEnabled( false );
1445 }
1446}
1447
1448void QgsRasterLayerProperties::toggleColorizeControls( bool colorizeEnabled )
1449{
1450 // Enable or disable colorize controls based on checkbox
1451 btnColorizeColor->setEnabled( colorizeEnabled );
1452 sliderColorizeStrength->setEnabled( colorizeEnabled );
1453 spinColorizeStrength->setEnabled( colorizeEnabled );
1454}
1455
1456
1457QLinearGradient QgsRasterLayerProperties::redGradient()
1458{
1459 //define a gradient
1460 // TODO change this to actual polygon dims
1461 QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1462 myGradient.setColorAt( 0.0, QColor( 242, 14, 25, 190 ) );
1463 myGradient.setColorAt( 0.5, QColor( 175, 29, 37, 190 ) );
1464 myGradient.setColorAt( 1.0, QColor( 114, 17, 22, 190 ) );
1465 return myGradient;
1466}
1467QLinearGradient QgsRasterLayerProperties::greenGradient()
1468{
1469 //define a gradient
1470 // TODO change this to actual polygon dims
1471 QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1472 myGradient.setColorAt( 0.0, QColor( 48, 168, 5, 190 ) );
1473 myGradient.setColorAt( 0.8, QColor( 36, 122, 4, 190 ) );
1474 myGradient.setColorAt( 1.0, QColor( 21, 71, 2, 190 ) );
1475 return myGradient;
1476}
1477QLinearGradient QgsRasterLayerProperties::blueGradient()
1478{
1479 //define a gradient
1480 // TODO change this to actual polygon dims
1481 QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1482 myGradient.setColorAt( 0.0, QColor( 30, 0, 106, 190 ) );
1483 myGradient.setColorAt( 0.2, QColor( 30, 72, 128, 190 ) );
1484 myGradient.setColorAt( 1.0, QColor( 30, 223, 196, 190 ) );
1485 return myGradient;
1486}
1487QLinearGradient QgsRasterLayerProperties::grayGradient()
1488{
1489 //define a gradient
1490 // TODO change this to actual polygon dims
1491 QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1492 myGradient.setColorAt( 0.0, QColor( 5, 5, 5, 190 ) );
1493 myGradient.setColorAt( 0.8, QColor( 122, 122, 122, 190 ) );
1494 myGradient.setColorAt( 1.0, QColor( 220, 220, 220, 190 ) );
1495 return myGradient;
1496}
1497QLinearGradient QgsRasterLayerProperties::highlightGradient()
1498{
1499 //define another gradient for the highlight
1500 // TODO change this to actual polygon dims
1501 QLinearGradient myGradient = QLinearGradient( mGradientWidth, 0, mGradientWidth, mGradientHeight );
1502 myGradient.setColorAt( 1.0, QColor( 255, 255, 255, 50 ) );
1503 myGradient.setColorAt( 0.5, QColor( 255, 255, 255, 100 ) );
1504 myGradient.setColorAt( 0.0, QColor( 255, 255, 255, 150 ) );
1505 return myGradient;
1506}
1507
1508void QgsRasterLayerProperties::addMetadataUrl()
1509{
1510 const int row = mMetadataUrlModel->rowCount();
1511 mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
1512 mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
1513 mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
1514}
1515
1516void QgsRasterLayerProperties::removeSelectedMetadataUrl()
1517{
1518 const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
1519 if ( selectedRows.empty() )
1520 return;
1521 mMetadataUrlModel->removeRow( selectedRows[0].row() );
1522}
1523
1524
1525//
1526//
1527// Next four methods for saving and restoring qml style state
1528//
1529//
1530void QgsRasterLayerProperties::loadDefaultStyle_clicked()
1531{
1532 bool defaultLoadedFlag = false;
1533 QString myMessage = mRasterLayer->loadDefaultStyle( defaultLoadedFlag );
1534 //reset if the default style was loaded OK only
1535 if ( defaultLoadedFlag )
1536 {
1537 syncToLayer();
1538 }
1539 else
1540 {
1541 //otherwise let the user know what went wrong
1542 QMessageBox::information( this,
1543 tr( "Default Style" ),
1544 myMessage
1545 );
1546 }
1547}
1548
1549void QgsRasterLayerProperties::saveDefaultStyle_clicked()
1550{
1551
1552 apply(); // make sure the style to save is up-to-date
1553
1554 // a flag passed by reference
1555 bool defaultSavedFlag = false;
1556 // TODO Once the deprecated `saveDefaultStyle()` method is gone, just
1557 // remove the NOWARN_DEPRECATED tags
1559 // after calling this the above flag will be set true for success
1560 // or false if the save operation failed
1561 QString myMessage = mRasterLayer->saveDefaultStyle( defaultSavedFlag );
1563 if ( !defaultSavedFlag )
1564 {
1565 //let the user know what went wrong
1566 QMessageBox::information( this,
1567 tr( "Default Style" ),
1568 myMessage
1569 );
1570 }
1571}
1572
1573
1574void QgsRasterLayerProperties::loadStyle_clicked()
1575{
1576 QgsSettings settings;
1577 QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1578
1579 QString fileName = QFileDialog::getOpenFileName(
1580 this,
1581 tr( "Load layer properties from style file" ),
1582 lastUsedDir,
1583 tr( "QGIS Layer Style File" ) + " (*.qml)" );
1584 if ( fileName.isEmpty() )
1585 return;
1586
1587 // ensure the user never omits the extension from the file name
1588 if ( !fileName.endsWith( QLatin1String( ".qml" ), Qt::CaseInsensitive ) )
1589 fileName += QLatin1String( ".qml" );
1590
1591 mOldStyle = mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() );
1592
1593 bool defaultLoadedFlag = false;
1594 QString message = mRasterLayer->loadNamedStyle( fileName, defaultLoadedFlag );
1595 if ( defaultLoadedFlag )
1596 {
1597 settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( fileName ).absolutePath() );
1598 syncToLayer();
1599 }
1600 else
1601 {
1602 QMessageBox::information( this, tr( "Save Style" ), message );
1603 }
1604}
1605
1606
1607void QgsRasterLayerProperties::saveStyleAs_clicked()
1608{
1609 QgsSettings settings;
1610 QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1611
1612 QString selectedFilter;
1613 QString outputFileName = QFileDialog::getSaveFileName(
1614 this,
1615 tr( "Save layer properties as style file" ),
1616 lastUsedDir,
1617 tr( "QGIS Layer Style File" ) + " (*.qml)" + ";;" + tr( "Styled Layer Descriptor" ) + " (*.sld)",
1618 &selectedFilter );
1619 if ( outputFileName.isEmpty() )
1620 return;
1621
1622 StyleType type;
1623 // use selectedFilter to set style type
1624 if ( selectedFilter.contains( QStringLiteral( ".qml" ), Qt::CaseInsensitive ) )
1625 {
1626 outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "qml" ) );
1627 type = StyleType::QML;
1628 }
1629 else
1630 {
1631 outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "sld" ) );
1632 type = StyleType::SLD;
1633 }
1634
1635 apply(); // make sure the style to save is up-to-date
1636
1637 // then export style
1638 bool defaultLoadedFlag = false;
1639 QString message;
1640 switch ( type )
1641 {
1642 case QML:
1643 {
1644 message = mRasterLayer->saveNamedStyle( outputFileName, defaultLoadedFlag );
1645 break;
1646 }
1647 case SLD:
1648 {
1649 message = mRasterLayer->saveSldStyle( outputFileName, defaultLoadedFlag );
1650 break;
1651 }
1652 }
1653 if ( defaultLoadedFlag )
1654 {
1655 settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( outputFileName ).absolutePath() );
1656 sync();
1657 }
1658 else
1659 QMessageBox::information( this, tr( "Save Style" ), message );
1660}
1661
1662void QgsRasterLayerProperties::restoreWindowModality()
1663{
1664 hide();
1665 setModal( true );
1666 show();
1667 raise();
1668 activateWindow();
1669}
1670
1671//
1672//
1673// Next four methods for saving and restoring QMD metadata
1674//
1675//
1676
1677void QgsRasterLayerProperties::loadMetadata()
1678{
1679 QgsSettings myQSettings; // where we keep last used filter in persistent state
1680 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1681
1682 QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
1683 tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1684 if ( myFileName.isNull() )
1685 {
1686 return;
1687 }
1688
1689 QString myMessage;
1690 bool defaultLoadedFlag = false;
1691 myMessage = mRasterLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1692
1693 //reset if the default style was loaded OK only
1694 if ( defaultLoadedFlag )
1695 {
1696 mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1697 }
1698 else
1699 {
1700 //let the user know what went wrong
1701 QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1702 }
1703
1704 QFileInfo myFI( myFileName );
1705 QString myPath = myFI.path();
1706 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1707
1708 activateWindow(); // set focus back to properties dialog
1709}
1710
1711void QgsRasterLayerProperties::saveMetadataAs()
1712{
1713 QgsSettings myQSettings; // where we keep last used filter in persistent state
1714 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1715
1716 QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1717 myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1718 if ( myOutputFileName.isNull() ) //dialog canceled
1719 {
1720 return;
1721 }
1722
1723 mMetadataWidget->acceptMetadata();
1724
1725 //ensure the user never omitted the extension from the file name
1726 if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1727 {
1729 }
1730
1731 bool defaultLoadedFlag = false;
1732 QString message = mRasterLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1733 if ( defaultLoadedFlag )
1734 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
1735 else
1736 QMessageBox::information( this, tr( "Save Metadata" ), message );
1737}
1738
1739void QgsRasterLayerProperties::saveDefaultMetadata()
1740{
1741 mMetadataWidget->acceptMetadata();
1742
1743 bool defaultSavedFlag = false;
1744 QString errorMsg = mRasterLayer->saveDefaultMetadata( defaultSavedFlag );
1745 if ( !defaultSavedFlag )
1746 {
1747 QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1748 }
1749}
1750
1751void QgsRasterLayerProperties::loadDefaultMetadata()
1752{
1753 bool defaultLoadedFlag = false;
1754 QString myMessage = mRasterLayer->loadNamedMetadata( mRasterLayer->metadataUri(), defaultLoadedFlag );
1755 //reset if the default metadata was loaded OK only
1756 if ( defaultLoadedFlag )
1757 {
1758 mMetadataWidget->setMetadata( &mRasterLayer->metadata() );
1759 }
1760 else
1761 {
1762 QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1763 }
1764}
1765
1766
1767void QgsRasterLayerProperties::toggleBuildPyramidsButton()
1768{
1769 if ( lbxPyramidResolutions->selectedItems().empty() )
1770 {
1771 buttonBuildPyramids->setEnabled( false );
1772 }
1773 else
1774 {
1775 buttonBuildPyramids->setEnabled( true );
1776 }
1777}
1778
1779void QgsRasterLayerProperties::mResetColorRenderingBtn_clicked()
1780{
1781 mBlendModeComboBox->setBlendMode( QPainter::CompositionMode_SourceOver );
1782 mSliderBrightness->setValue( 0 );
1783 mSliderContrast->setValue( 0 );
1784 mGammaSpinBox->setValue( 1.0 );
1785 sliderSaturation->setValue( 0 );
1786 comboGrayscale->setCurrentIndex( ( int ) QgsHueSaturationFilter::GrayscaleOff );
1787 mColorizeCheck->setChecked( false );
1788 sliderColorizeStrength->setValue( 100 );
1789 mInvertColorsCheck->setChecked( false );
1790}
1791
1792bool QgsRasterLayerProperties::rasterIsMultiBandColor()
1793{
1794 return mRasterLayer && nullptr != dynamic_cast<QgsMultiBandColorRenderer *>( mRasterLayer->renderer() );
1795}
1796
1797void QgsRasterLayerProperties::updateInformationContent()
1798{
1799 const QString myStyle = QgsApplication::reportStyleSheet( QgsApplication::StyleSheetType::WebBrowser );
1800 // Inject the stylesheet
1801 const QString html { mRasterLayer->htmlMetadata().replace( QLatin1String( "<head>" ), QStringLiteral( R"raw(<head><style type="text/css">%1</style>)raw" ) ).arg( myStyle ) };
1802 mMetadataViewer->setHtml( html );
1803 mMetadataFilled = true;
1804}
1805
1806void QgsRasterLayerProperties::onCancel()
1807{
1808 if ( mOldStyle.xmlData() != mRasterLayer->styleManager()->style( mRasterLayer->styleManager()->currentStyle() ).xmlData() )
1809 {
1810 // need to reset style to previous - style applied directly to the layer (not in apply())
1811 QString myMessage;
1812 QDomDocument doc( QStringLiteral( "qgis" ) );
1813 int errorLine, errorColumn;
1814 doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
1815 mRasterLayer->importNamedStyle( doc, myMessage );
1816 syncToLayer();
1817 }
1818 if ( mBackupCrs != mRasterLayer->crs() )
1819 mRasterLayer->setCrs( mBackupCrs );
1820}
1821
1822void QgsRasterLayerProperties::showHelp()
1823{
1824 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
1825
1826 if ( helpPage.isValid() )
1827 {
1828 QgsHelp::openHelp( helpPage.toString() );
1829 }
1830 else
1831 {
1832 QgsHelp::openHelp( QStringLiteral( "working_with_raster/raster_properties.html" ) );
1833 }
1834}
1835
1836void QgsRasterLayerProperties::updateGammaSpinBox( int value )
1837{
1838 whileBlocking( mGammaSpinBox )->setValue( value / 100.0 );
1839}
1840
1841void QgsRasterLayerProperties::updateGammaSlider( double value )
1842{
1843 whileBlocking( mSliderGamma )->setValue( value * 100 );
1844}
@ 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:110
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition: qgsgui.cpp:75
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 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 ParentPage parentPage() const
Returns the associated parent page, for factories which create sub-components of a standard page.
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.
static bool isDefault(const QString &styleName)
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:1297
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:1282
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:1516
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Definition: qgsmaplayer.h:426
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
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
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:1523
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:1287
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1292
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
virtual QString saveDefaultStyle(bool &resultFlag, StyleCategories categories)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
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:480
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:576
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 setMapCanvas(QgsMapCanvas *mapCanvas)
Sets a map canvas associated with 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.
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)
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
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 void doComputations()
Load programmatically with current values.
virtual QgsRasterRenderer * renderer()=0
Creates a new renderer, using the properties defined in the widget.
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....
virtual QList< int > usesBands() const
Returns a list of band numbers used by the renderer.
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)
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
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2951
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2950
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2322
#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.