QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsmeshlayerproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshlayerproperties.cpp
3 --------------------------
4 begin : Jun 2018
5 copyright : (C) 2018 by Peter Petrik
6 email : zilolv at gmail dot com
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 "qgsapplication.h"
22#include "qgsfileutils.h"
23#include "qgshelp.h"
24#include "qgslogger.h"
25#include "qgsmapcanvas.h"
28#include "qgsmeshlayer.h"
31#include "qgsproject.h"
34#include "qgssettings.h"
37#include "qgsgui.h"
38#include "qgsnative.h"
39#include "qgsmetadatawidget.h"
40
41#include <QDesktopServices>
42#include <QFileDialog>
43#include <QMessageBox>
44
45QgsMeshLayerProperties::QgsMeshLayerProperties( QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags fl )
46 : QgsOptionsDialogBase( QStringLiteral( "MeshLayerProperties" ), parent, fl )
47 , mMeshLayer( qobject_cast<QgsMeshLayer *>( lyr ) )
48 , mCanvas( canvas )
49{
50 Q_ASSERT( mMeshLayer );
51
52 setupUi( this );
53 mRendererMeshPropertiesWidget = new QgsRendererMeshPropertiesWidget( mMeshLayer, canvas, this );
54 mConfigWidgets << mRendererMeshPropertiesWidget;
55 mOptsPage_StyleContent->layout()->addWidget( mRendererMeshPropertiesWidget );
56
57 mSimplifyReductionFactorSpinBox->setClearValue( 10.0 );
58 mSimplifyMeshResolutionSpinBox->setClearValue( 5 );
59
60 mStaticDatasetWidget->setLayer( mMeshLayer );
61 mIsMapSettingsTemporal = mMeshLayer && canvas && canvas->mapSettings().isTemporal();
62
63 mTemporalProviderTimeUnitComboBox->addItem( tr( "Seconds" ), QgsUnitTypes::TemporalSeconds );
64 mTemporalProviderTimeUnitComboBox->addItem( tr( "Minutes" ), QgsUnitTypes::TemporalMinutes );
65 mTemporalProviderTimeUnitComboBox->addItem( tr( "Hours" ), QgsUnitTypes::TemporalHours );
66 mTemporalProviderTimeUnitComboBox->addItem( tr( "Days" ), QgsUnitTypes::TemporalDays );
67
68 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsMeshLayerProperties::changeCrs );
69 connect( mDatasetGroupTreeWidget, &QgsMeshDatasetGroupTreeWidget::datasetGroupAdded, this, &QgsMeshLayerProperties::syncToLayer );
70
71 // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
72 // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
73 // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
74 initOptionsBase( false );
75
76 connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMeshLayerProperties::syncAndRepaint );
77
78 connect( this, &QDialog::accepted, this, &QgsMeshLayerProperties::apply );
79 connect( this, &QDialog::rejected, this, &QgsMeshLayerProperties::onCancel );
80 connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsMeshLayerProperties::apply );
81
82 connect( mMeshLayer, &QgsMeshLayer::dataChanged, this, &QgsMeshLayerProperties::syncAndRepaint );
83 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsMeshLayerProperties::showHelp );
84
85 connect( mTemporalReloadButton, &QPushButton::clicked, this, &QgsMeshLayerProperties::reloadTemporalProperties );
86 connect( mTemporalDateTimeReference, &QDateTimeEdit::dateTimeChanged, this, &QgsMeshLayerProperties::onTimeReferenceChange );
89
90 mScaleRangeWidget->setMapCanvas( mCanvas );
91 chkUseScaleDependentRendering->setChecked( lyr->hasScaleBasedVisibility() );
92 mScaleRangeWidget->setScaleRange( lyr->minimumScale(), lyr->maximumScale() );
93
94 connect( mAlwaysTimeFromSourceCheckBox, &QCheckBox::stateChanged, this, [this]
95 {
96 mTemporalDateTimeReference->setEnabled( !mAlwaysTimeFromSourceCheckBox->isChecked() );
97 if ( mAlwaysTimeFromSourceCheckBox->isChecked() )
98 reloadTemporalProperties();
99 } );
100
101 mComboBoxTemporalDatasetMatchingMethod->addItem( tr( "Find Closest Dataset Before Requested Time" ),
103 mComboBoxTemporalDatasetMatchingMethod->addItem( tr( "Find Closest Dataset From Requested Time (After or Before)" ),
105
106 QVBoxLayout *layout = new QVBoxLayout( metadataFrame );
107 layout->setContentsMargins( 0, 0, 0, 0 );
108 metadataFrame->setContentsMargins( 0, 0, 0, 0 );
109 mMetadataWidget = new QgsMetadataWidget( this, mMeshLayer );
110 mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
111 mMetadataWidget->setMapCanvas( mCanvas );
112 layout->addWidget( mMetadataWidget );
113 metadataFrame->setLayout( layout );
114 mOptsPage_Metadata->setContentsMargins( 0, 0, 0, 0 );
115 mBackupCrs = mMeshLayer->crs();
116
117 mTemporalDateTimeStart->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
118 mTemporalDateTimeEnd->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
119 mTemporalDateTimeReference->setDisplayFormat( "yyyy-MM-dd HH:mm:ss" );
120
121 // update based on lyr's current state
122 syncToLayer();
123
124 QgsSettings settings;
125 // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
126 // this will be read by restoreOptionsBaseUi()
127 if ( !settings.contains( QStringLiteral( "/Windows/MeshLayerProperties/tab" ) ) )
128 {
129 settings.setValue( QStringLiteral( "Windows/MeshLayerProperties/tab" ),
130 mOptStackedWidget->indexOf( mOptsPage_Style ) );
131 }
132
133 //Add help page references
134 mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#information-properties" ) );
135 mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#source-properties" ) );
136 mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#symbology-properties" ) );
137 mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#rendering-properties" ) );
138 mOptsPage_Temporal->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#temporal-properties" ) );
139 mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_mesh/mesh_properties.html#metadata-properties" ) );
140
141 mBtnStyle = new QPushButton( tr( "Style" ) );
142 QMenu *menuStyle = new QMenu( this );
143 menuStyle->addAction( tr( "Load Style…" ), this, &QgsMeshLayerProperties::loadStyle );
144 menuStyle->addAction( tr( "Save Style…" ), this, &QgsMeshLayerProperties::saveStyleAs );
145 menuStyle->addSeparator();
146 menuStyle->addAction( tr( "Save as Default" ), this, &QgsMeshLayerProperties::saveDefaultStyle );
147 menuStyle->addAction( tr( "Restore Default" ), this, &QgsMeshLayerProperties::loadDefaultStyle );
148 mBtnStyle->setMenu( menuStyle );
149 connect( menuStyle, &QMenu::aboutToShow, this, &QgsMeshLayerProperties::aboutToShowStyleMenu );
150
151 buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
152
153 mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
154 QMenu *menuMetadata = new QMenu( this );
155 mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsMeshLayerProperties::loadMetadata );
156 mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsMeshLayerProperties::saveMetadataAs );
157 mBtnMetadata->setMenu( menuMetadata );
158 buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
159
160 QString title = tr( "Layer Properties — %1" ).arg( lyr->name() );
161
162 if ( !mMeshLayer->styleManager()->isDefault( mMeshLayer->styleManager()->currentStyle() ) )
163 title += QStringLiteral( " (%1)" ).arg( mMeshLayer->styleManager()->currentStyle() );
164 restoreOptionsBaseUi( title );
165}
166
168{
169 if ( !factory->supportsLayer( mMeshLayer ) || !factory->supportLayerPropertiesDialog() )
170 {
171 return;
172 }
173
174 QgsMapLayerConfigWidget *page = factory->createWidget( mMeshLayer, mCanvas, false, this );
175 mConfigWidgets << page;
176
177 const QString beforePage = factory->layerPropertiesPagePositionHint();
178 if ( beforePage.isEmpty() )
179 addPage( factory->title(), factory->title(), factory->icon(), page );
180 else
181 insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage );
182
183 page->syncToLayer( mMeshLayer );
184
185}
186
188{
190
191 bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
192 mBtnStyle->setVisible( ! isMetadataPanel );
193 mBtnMetadata->setVisible( isMetadataPanel );
194}
195
196void QgsMeshLayerProperties::syncToLayer()
197{
198 Q_ASSERT( mRendererMeshPropertiesWidget );
199
200 QgsDebugMsgLevel( QStringLiteral( "populate general information tab" ), 4 );
201 /*
202 * Information Tab
203 */
204 QString myStyle = QgsApplication::reportStyleSheet();
205 myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
206 mInformationTextBrowser->clear();
207 mInformationTextBrowser->document()->setDefaultStyleSheet( myStyle );
208 mInformationTextBrowser->setHtml( mMeshLayer->htmlMetadata() );
209 mInformationTextBrowser->setOpenLinks( false );
210 connect( mInformationTextBrowser, &QTextBrowser::anchorClicked, this, &QgsMeshLayerProperties::urlClicked );
211
212 QgsDebugMsgLevel( QStringLiteral( "populate source tab" ), 4 );
213 /*
214 * Source Tab
215 */
216 mLayerOrigNameLineEd->setText( mMeshLayer->name() );
217 whileBlocking( mCrsSelector )->setCrs( mMeshLayer->crs() );
218
219 if ( mMeshLayer )
220 mDatasetGroupTreeWidget->syncToLayer( mMeshLayer );
221
222 QgsDebugMsgLevel( QStringLiteral( "populate config tab" ), 4 );
223 for ( QgsMapLayerConfigWidget *w : std::as_const( mConfigWidgets ) )
224 w->syncToLayer( mMeshLayer );
225
226 QgsDebugMsgLevel( QStringLiteral( "populate rendering tab" ), 4 );
227 if ( mMeshLayer->isEditable() )
228 mSimplifyMeshGroupBox->setEnabled( false );
229
230 QgsMeshSimplificationSettings simplifySettings = mMeshLayer->meshSimplificationSettings();
231 mSimplifyMeshGroupBox->setChecked( simplifySettings.isEnabled() );
232 mSimplifyReductionFactorSpinBox->setValue( simplifySettings.reductionFactor() );
233 mSimplifyMeshResolutionSpinBox->setValue( simplifySettings.meshResolution() );
234
235 QgsDebugMsgLevel( QStringLiteral( "populate temporal tab" ), 4 );
236 const QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< const QgsMeshLayerTemporalProperties * >( mMeshLayer->temporalProperties() );
237 whileBlocking( mTemporalDateTimeReference )->setDateTime( temporalProperties->referenceTime() );
238 const QgsDateTimeRange timeRange = temporalProperties->timeExtent();
239 mTemporalDateTimeStart->setDateTime( timeRange.begin() );
240 mTemporalDateTimeEnd->setDateTime( timeRange.end() );
241 if ( mMeshLayer->dataProvider() )
242 {
243 mTemporalProviderTimeUnitComboBox->setCurrentIndex(
244 mTemporalProviderTimeUnitComboBox->findData( mMeshLayer->dataProvider()->temporalCapabilities()->temporalUnit() ) );
245 }
246 mAlwaysTimeFromSourceCheckBox->setChecked( temporalProperties->alwaysLoadReferenceTimeFromSource() );
247 mComboBoxTemporalDatasetMatchingMethod->setCurrentIndex(
248 mComboBoxTemporalDatasetMatchingMethod->findData( temporalProperties->matchingMethod() ) );
249
250 mStaticDatasetWidget->syncToLayer();
251 mStaticDatasetGroupBox->setChecked( !mMeshLayer->temporalProperties()->isActive() );
252}
253
254void QgsMeshLayerProperties::loadDefaultStyle()
255{
256 bool defaultLoadedFlag = false;
257 QString myMessage = mMeshLayer->loadDefaultStyle( defaultLoadedFlag );
258 // reset if the default style was loaded OK only
259 if ( defaultLoadedFlag )
260 {
261 syncToLayer();
262 }
263 else
264 {
265 // otherwise let the user know what went wrong
266 QMessageBox::information( this,
267 tr( "Default Style" ),
268 myMessage
269 );
270 }
271}
272
273void QgsMeshLayerProperties::saveDefaultStyle()
274{
275 apply(); // make sure the style to save is up-to-date
276
277 // a flag passed by reference
278 bool defaultSavedFlag = false;
279 // TODO Once the deprecated `saveDefaultStyle()` method is gone, just
280 // remove the NOWARN_DEPRECATED tags
282 // after calling this the above flag will be set true for success
283 // or false if the save operation failed
284 QString myMessage = mMeshLayer->saveDefaultStyle( defaultSavedFlag );
286 if ( !defaultSavedFlag )
287 {
288 // let the user know what went wrong
289 QMessageBox::information( this,
290 tr( "Default Style" ),
291 myMessage
292 );
293 }
294}
295
296void QgsMeshLayerProperties::loadStyle()
297{
298 QgsSettings settings;
299 QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
300
301 QString fileName = QFileDialog::getOpenFileName(
302 this,
303 tr( "Load rendering setting from style file" ),
304 lastUsedDir,
305 tr( "QGIS Layer Style File" ) + " (*.qml)" );
306 if ( fileName.isEmpty() )
307 return;
308
309 // ensure the user never omits the extension from the file name
310 if ( !fileName.endsWith( QLatin1String( ".qml" ), Qt::CaseInsensitive ) )
311 fileName += QLatin1String( ".qml" );
312
313 mOldStyle = mMeshLayer->styleManager()->style( mMeshLayer->styleManager()->currentStyle() );
314
315 bool defaultLoadedFlag = false;
316 QString message = mMeshLayer->loadNamedStyle( fileName, defaultLoadedFlag );
317 if ( defaultLoadedFlag )
318 {
319 settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( fileName ).absolutePath() );
320 syncToLayer();
321 }
322 else
323 {
324 QMessageBox::information( this, tr( "Load Style" ), message );
325 }
326}
327
328void QgsMeshLayerProperties::saveStyleAs()
329{
330 QgsSettings settings;
331 QString lastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
332
333 QString outputFileName = QFileDialog::getSaveFileName(
334 this,
335 tr( "Save layer properties as style file" ),
336 lastUsedDir,
337 tr( "QGIS Layer Style File" ) + " (*.qml)" );
338 if ( outputFileName.isEmpty() )
339 return;
340
341 // ensure the user never omits the extension from the file name
342 outputFileName = QgsFileUtils::ensureFileNameHasExtension( outputFileName, QStringList() << QStringLiteral( "qml" ) );
343
344 apply(); // make sure the style to save is up-to-date
345
346 // then export style
347 bool defaultLoadedFlag = false;
348 QString message;
349 message = mMeshLayer->saveNamedStyle( outputFileName, defaultLoadedFlag );
350
351 if ( defaultLoadedFlag )
352 {
353 settings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( outputFileName ).absolutePath() );
354 }
355 else
356 QMessageBox::information( this, tr( "Save Style" ), message );
357}
358
359void QgsMeshLayerProperties::apply()
360{
361 Q_ASSERT( mRendererMeshPropertiesWidget );
362
363 QgsDebugMsgLevel( QStringLiteral( "processing general tab" ), 4 );
364 /*
365 * General Tab
366 */
367 mMeshLayer->setName( mLayerOrigNameLineEd->text() );
368
369 QgsDebugMsgLevel( QStringLiteral( "processing source tab" ), 4 );
370 /*
371 * Source Tab
372 */
373 mDatasetGroupTreeWidget->apply();
374
375 QgsDebugMsgLevel( QStringLiteral( "processing config tabs" ), 4 );
376
377 for ( QgsMapLayerConfigWidget *w : std::as_const( mConfigWidgets ) )
378 w->apply();
379
380 QgsDebugMsgLevel( QStringLiteral( "processing rendering tab" ), 4 );
381 /*
382 * Rendering Tab
383 */
384 QgsMeshSimplificationSettings simplifySettings;
385 simplifySettings.setEnabled( mSimplifyMeshGroupBox->isChecked() );
386 simplifySettings.setReductionFactor( mSimplifyReductionFactorSpinBox->value() );
387 simplifySettings.setMeshResolution( mSimplifyMeshResolutionSpinBox->value() );
388 bool needMeshUpdating = ( ( simplifySettings.isEnabled() != mMeshLayer->meshSimplificationSettings().isEnabled() ) ||
389 ( simplifySettings.reductionFactor() != mMeshLayer->meshSimplificationSettings().reductionFactor() ) );
390
391 mMeshLayer->setMeshSimplificationSettings( simplifySettings );
392
393 mMeshLayer->setScaleBasedVisibility( chkUseScaleDependentRendering->isChecked() );
394 mMeshLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
395 mMeshLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
396
397 QgsDebugMsgLevel( QStringLiteral( "processing temporal tab" ), 4 );
398 /*
399 * Temporal Tab
400 */
401
402 mMeshLayer->setReferenceTime( mTemporalDateTimeReference->dateTime() );
403 if ( mMeshLayer->dataProvider() )
404 mMeshLayer->dataProvider()->setTemporalUnit(
405 static_cast<QgsUnitTypes::TemporalUnit>( mTemporalProviderTimeUnitComboBox->currentData().toInt() ) );
406
407 mStaticDatasetWidget->apply();
408 bool needEmitRendererChanged = mMeshLayer->temporalProperties()->isActive() == mStaticDatasetGroupBox->isChecked();
409 mMeshLayer->temporalProperties()->setIsActive( !mStaticDatasetGroupBox->isChecked() );
411 mComboBoxTemporalDatasetMatchingMethod->currentData().toInt() ) );
412 static_cast<QgsMeshLayerTemporalProperties *>(
413 mMeshLayer->temporalProperties() )->setAlwaysLoadReferenceTimeFromSource( mAlwaysTimeFromSourceCheckBox->isChecked() );
414
415 mMetadataWidget->acceptMetadata();
416
417 mBackupCrs = mMeshLayer->crs();
418
419 if ( needMeshUpdating )
420 mMeshLayer->reload();
421
422 if ( needEmitRendererChanged )
423 emit mMeshLayer->rendererChanged();
424
425 //make sure the layer is redrawn
426 mMeshLayer->triggerRepaint();
427
428 // notify the project we've made a change
430
431 // Resync what have to be resync (widget that can be changed by other properties part)
432 mStaticDatasetWidget->syncToLayer();
433 for ( QgsMapLayerConfigWidget *w : std::as_const( mConfigWidgets ) )
434 w->syncToLayer( mMeshLayer );
435}
436
437void QgsMeshLayerProperties::changeCrs( const QgsCoordinateReferenceSystem &crs )
438{
439 QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mCanvas, tr( "Select Transformation" ) );
440 mMeshLayer->setCrs( crs );
441}
442
443void QgsMeshLayerProperties::syncAndRepaint()
444{
445 syncToLayer();
446 mMeshLayer->triggerRepaint();
447}
448
449void QgsMeshLayerProperties::showHelp()
450{
451 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
452
453 if ( helpPage.isValid() )
454 {
455 QgsHelp::openHelp( helpPage.toString() );
456 }
457 else
458 {
459 QgsHelp::openHelp( QStringLiteral( "working_with_mesh/mesh_properties.html" ) );
460 }
461}
462
463void QgsMeshLayerProperties::aboutToShowStyleMenu()
464{
465 QMenu *m = qobject_cast<QMenu *>( sender() );
466
468 // re-add style manager actions!
469 m->addSeparator();
471}
472
473void QgsMeshLayerProperties::reloadTemporalProperties()
474{
475 if ( !mMeshLayer->dataProvider() )
476 return;
477 QgsMeshDataProviderTemporalCapabilities *temporalCapabalities = mMeshLayer->dataProvider()->temporalCapabilities();
478 QgsDateTimeRange timeExtent;
479 QDateTime referenceTime = temporalCapabalities->referenceTime();
480 if ( referenceTime.isValid() )
481 {
482 timeExtent = temporalCapabalities->timeExtent();
483 whileBlocking( mTemporalDateTimeReference )->setDateTime( referenceTime );
484 }
485 else
486 // The reference time already here is used again to define the time extent
487 timeExtent = temporalCapabalities->timeExtent( mTemporalDateTimeReference->dateTime() );
488
489 mTemporalDateTimeStart->setDateTime( timeExtent.begin() );
490 mTemporalDateTimeEnd->setDateTime( timeExtent.end() );
491}
492
493void QgsMeshLayerProperties::onTimeReferenceChange()
494{
495 if ( !mMeshLayer->dataProvider() )
496 return;
497 const QgsDateTimeRange &timeExtent = mMeshLayer->dataProvider()->temporalCapabilities()->timeExtent( mTemporalDateTimeReference->dateTime() );
498 mTemporalDateTimeStart->setDateTime( timeExtent.begin() );
499 mTemporalDateTimeEnd->setDateTime( timeExtent.end() );
500}
501
502void QgsMeshLayerProperties::urlClicked( const QUrl &url )
503{
504 QFileInfo file( url.toLocalFile() );
505 if ( file.exists() && !file.isDir() )
506 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
507 else
508 QDesktopServices::openUrl( url );
509}
510
511void QgsMeshLayerProperties::loadMetadata()
512{
513 QgsSettings myQSettings; // where we keep last used filter in persistent state
514 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
515
516 QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer metadata from metadata file" ), myLastUsedDir,
517 tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
518 if ( myFileName.isNull() )
519 {
520 return;
521 }
522
523 QString myMessage;
524 bool defaultLoadedFlag = false;
525 myMessage = mMeshLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
526
527 //reset if the default style was loaded OK only
528 if ( defaultLoadedFlag )
529 {
530 mMetadataWidget->setMetadata( &mMeshLayer->metadata() );
531 }
532 else
533 {
534 //let the user know what went wrong
535 QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
536 }
537
538 QFileInfo myFI( myFileName );
539 QString myPath = myFI.path();
540 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
541
542 activateWindow(); // set focus back to properties dialog
543}
544
545void QgsMeshLayerProperties::saveMetadataAs()
546{
547 QgsSettings myQSettings; // where we keep last used filter in persistent state
548 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
549
550 QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
551 myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
552 if ( myOutputFileName.isNull() ) //dialog canceled
553 {
554 return;
555 }
556
557 mMetadataWidget->acceptMetadata();
558
559 //ensure the user never omitted the extension from the file name
560 if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
561 {
563 }
564
565 bool defaultLoadedFlag = false;
566 QString message = mMeshLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
567 if ( defaultLoadedFlag )
568 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), QFileInfo( myOutputFileName ).absolutePath() );
569 else
570 QMessageBox::information( this, tr( "Save Metadata" ), message );
571}
572
573void QgsMeshLayerProperties::onCancel()
574{
575 if ( mBackupCrs != mMeshLayer->crs() )
576 mMeshLayer->setCrs( mBackupCrs );
577}
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
This class represents a coordinate reference system (CRS).
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...
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
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
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.
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 QString title() const
The title of the panel.
virtual bool supportLayerPropertiesDialog() const
Flag if widget is supported for use in layer properties dialog.
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.
virtual void syncToLayer(QgsMapLayer *layer)
Reset to original (vector layer) values.
void removesExtraMenuSeparators(QMenu *m)
removes extra separators from the menu
void addStyleManagerActions(QMenu *m, QgsMapLayer *layer)
adds actions to the menu in accordance to the layer
static QgsMapLayerStyleGuiUtils * instance()
returns a singleton instance of this class
QString currentStyle() const
Returns name of the current style.
static bool isDefault(const QString &styleName)
Returns true if this is the default style.
QgsMapLayerStyle style(const QString &name) const
Returns data of a stored style - accessed by its unique name.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
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 ...
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
void rendererChanged()
Signal emitted when renderer is changed.
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
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 dataChanged()
Data of layer changed.
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.
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...
double minimumScale() const
Returns the minimum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
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...
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.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Class for handling properties relating to a mesh data provider's temporal capabilities.
QgsUnitTypes::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
QDateTime referenceTime() const
Returns the reference time.
QgsDateTimeRange timeExtent() const
Returns the time extent using the internal reference time and the first and last times available from...
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
@ FindClosestDatasetFromStartRangeTime
Finds the closest dataset which have its time before the requested start range time.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
void setTemporalUnit(QgsUnitTypes::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
void optionsStackedWidget_CurrentChanged(int index) override
QgsMeshLayerProperties(QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent=nullptr, Qt::WindowFlags=QgsGuiUtils::ModalDialogFlags)
Constructor.
void addPropertiesPageFactory(const QgsMapLayerConfigWidgetFactory *factory)
Adds properties page from a factory.
Implementation of map layer temporal properties for mesh layers.
QDateTime referenceTime() const
Returns the reference time.
QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod matchingMethod() const
Returns the method used to match dataset from temporal capabilities.
bool alwaysLoadReferenceTimeFromSource() const
Returns whether the time proporties are automatically reloaded from provider when project is opened o...
QgsDateTimeRange timeExtent() const
Returns the time extent.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:100
void setMeshSimplificationSettings(const QgsMeshSimplificationSettings &meshSimplificationSettings)
Sets mesh simplification settings.
void activeScalarDatasetGroupChanged(int index)
Emitted when active scalar group dataset is changed.
void activeVectorDatasetGroupChanged(int index)
Emitted when active vector group dataset is changed.
void reload() override
Synchronises with changes in the datasource.
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
QgsMeshSimplificationSettings meshSimplificationSettings() const
Returns mesh simplification settings.
bool isEditable() const override
Returns true if the layer can be edited.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
void setReferenceTime(const QDateTime &referenceTime)
Sets the reference time of the layer.
void setTemporalMatchingMethod(const QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod &matchingMethod)
Sets the method used to match the temporal dataset from a requested time, see activeVectorDatasetAtTi...
Represents an overview renderer settings.
void setMeshResolution(int meshResolution)
Sets the mesh resolution i.e., the minimum size (average) of triangles in pixels This value is used d...
void setEnabled(bool isEnabled)
Sets if the overview is active.
double reductionFactor() const
Returns the reduction factor used to build simplified mesh.
bool isEnabled() const
Returns if the overview is active.
int meshResolution() const
Returns the mesh resolution i.e., the minimum size (average) of triangles in pixels.
void setReductionFactor(double value)
Sets the reduction factor used to build simplified mesh.
void setScalarDatasetGroup(int index)
Sets the scalar dataset group.
void setVectorDatasetGroup(int index)
Sets the vector dataset group.
A wizard to edit metadata on a map layer.
void acceptMetadata()
Saves the metadata to the layer.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the widget.
void setMetadata(const QgsAbstractMetadataBase *metadata)
Sets the metadata to display in the widget.
A base dialog for options and properties dialogs that offers vertical tabs.
void addPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QStringList &path=QStringList())
Adds a new page to the dialog pages.
virtual void optionsStackedWidget_CurrentChanged(int index)
Select relevant tab on current page change.
void insertPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QString &before, const QStringList &path=QStringList())
Inserts a new page into the dialog pages.
void restoreOptionsBaseUi(const QString &title=QString())
Restore the base ui.
QStackedWidget * mOptStackedWidget
void initOptionsBase(bool restoreUi=true, const QString &title=QString())
Set up the base ui connections for vertical tabs.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:573
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
Widget for renderer properties of the mesh, contours (scalars) and vectors data associated with the m...
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.
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
bool isTemporal() const
Returns true if the object's temporal range is enabled, and the object will be filtered when renderin...
TemporalUnit
Temporal units.
Definition: qgsunittypes.h:150
@ TemporalDays
Days.
Definition: qgsunittypes.h:155
@ TemporalSeconds
Seconds.
Definition: qgsunittypes.h:152
@ TemporalMinutes
Minutes.
Definition: qgsunittypes.h:153
@ TemporalHours
Hours.
Definition: qgsunittypes.h:154
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:3061
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:3060
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2453
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
const QgsCoordinateReferenceSystem & crs