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