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