Skip to content

Commit 37faa0d

Browse files
authoredMar 15, 2019
Add option to format time in mesh layer (#9452)
[feature] [mesh] #20731 add option to format time in mesh layer There is new settings dialog that can be opened by button next to time slider. User can set reference time and time format (e.g. 2019-03-21 22:01:11).
1 parent 95930ed commit 37faa0d

19 files changed

+1026
-58
lines changed
 

‎python/core/auto_generated/mesh/qgsmeshlayer.sip.in

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,31 @@ Returns renderer settings
139139
void setRendererSettings( const QgsMeshRendererSettings &settings );
140140
%Docstring
141141
Sets new renderer settings
142+
%End
143+
144+
QgsMeshTimeSettings timeSettings() const;
145+
%Docstring
146+
Returns time format settings
147+
148+
.. versionadded:: 3.8
149+
%End
150+
151+
void setTimeSettings( const QgsMeshTimeSettings &settings );
152+
%Docstring
153+
Sets time format settings
154+
155+
.. versionadded:: 3.8
156+
%End
157+
158+
QString formatTime( double hours );
159+
%Docstring
160+
Returns (date) time in hours formatted to human readable form
161+
162+
:param hours: time in double in hours
163+
164+
:return: formatted time string
165+
166+
.. versionadded:: 3.8
142167
%End
143168

144169
QgsMeshDatasetValue datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point ) const;
@@ -176,6 +201,13 @@ Emitted when active scalar dataset is changed
176201
Emitted when active vector dataset is changed
177202

178203
.. versionadded:: 3.4
204+
%End
205+
206+
void timeSettingsChanged( );
207+
%Docstring
208+
Emitted when time format is changed
209+
210+
.. versionadded:: 3.8
179211
%End
180212

181213
private: // Private methods
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/mesh/qgsmeshtimesettings.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsMeshTimeSettings
14+
{
15+
%Docstring
16+
17+
Represents a mesh time settings for mesh datasets
18+
19+
.. versionadded:: 3.8
20+
%End
21+
22+
%TypeHeaderCode
23+
#include "qgsmeshtimesettings.h"
24+
%End
25+
public:
26+
QgsMeshTimeSettings();
27+
%Docstring
28+
Default constructor for relative time formate and 0 offset
29+
%End
30+
QgsMeshTimeSettings( double relativeTimeOffsetHours, const QString &relativeTimeFormat );
31+
%Docstring
32+
Constructs relative time format settings with defined offset in hours
33+
%End
34+
QgsMeshTimeSettings( const QDateTime &absoluteTimeReferenceTime, const QString &absoluteTimeFormat );
35+
%Docstring
36+
Constructs absolute time format settings with defined reference time
37+
%End
38+
39+
QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const;
40+
%Docstring
41+
Writes configuration to a new DOM element
42+
%End
43+
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
44+
%Docstring
45+
Reads configuration from the given DOM element
46+
%End
47+
48+
bool useAbsoluteTime() const;
49+
%Docstring
50+
Returns whether to use absolute time format
51+
%End
52+
void setUseAbsoluteTime( bool useAbsoluteTime );
53+
%Docstring
54+
Sets use absolute time flag
55+
%End
56+
57+
double relativeTimeOffsetHours() const;
58+
%Docstring
59+
Returns number of offset hours for relative time formatting
60+
%End
61+
void setRelativeTimeOffsetHours( double relativeTimeOffsetHours );
62+
%Docstring
63+
Sets number of offset hours for relative time formatting
64+
%End
65+
66+
QString relativeTimeFormat() const;
67+
%Docstring
68+
Returns format used for relative time
69+
%End
70+
void setRelativeTimeFormat( const QString &relativeTimeFormat );
71+
%Docstring
72+
Sets format used for relative time
73+
%End
74+
75+
QDateTime absoluteTimeReferenceTime() const;
76+
%Docstring
77+
Returns reference time used for absolute time format
78+
%End
79+
void setAbsoluteTimeReferenceTime( const QDateTime &absoluteTimeReferenceTime );
80+
%Docstring
81+
Sets reference time used for absolute time format
82+
%End
83+
84+
QString absoluteTimeFormat() const;
85+
%Docstring
86+
Returns format used for absolute time
87+
%End
88+
void setAbsoluteTimeFormat( const QString &absoluteTimeFormat );
89+
%Docstring
90+
Sets format used for absolute time
91+
%End
92+
93+
};
94+
95+
96+
/************************************************************************
97+
* This file has been generated automatically from *
98+
* *
99+
* src/core/mesh/qgsmeshtimesettings.h *
100+
* *
101+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
102+
************************************************************************/

‎python/core/core_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@
241241
%Include auto_generated/mesh/qgsmeshlayerinterpolator.sip
242242
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
243243
%Include auto_generated/mesh/qgsmeshspatialindex.sip
244+
%Include auto_generated/mesh/qgsmeshtimesettings.sip
244245
%Include auto_generated/scalebar/qgsdoubleboxscalebarrenderer.sip
245246
%Include auto_generated/scalebar/qgsnumericscalebarrenderer.sip
246247
%Include auto_generated/scalebar/qgsscalebarsettings.sip

‎src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ SET(QGIS_APP_SRCS
244244
mesh/qgsmeshrendereractivedatasetwidget.cpp
245245
mesh/qgsmeshdatasetgrouptreeview.cpp
246246
mesh/qgsmeshcalculatordialog.cpp
247+
mesh/qgsmeshtimeformatdialog.cpp
247248
)
248249

249250
SET (QGIS_APP_MOC_HDRS
@@ -470,6 +471,7 @@ SET (QGIS_APP_MOC_HDRS
470471
mesh/qgsmeshrendereractivedatasetwidget.h
471472
mesh/qgsmeshdatasetgrouptreeview.h
472473
mesh/qgsmeshcalculatordialog.h
474+
mesh/qgsmeshtimeformatdialog.h
473475
)
474476

475477

‎src/app/mesh/qgsmeshcalculatordialog.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include "qgsmaplayerproxymodel.h"
2727
#include "qgswkbtypes.h"
2828
#include "qgsfeatureiterator.h"
29-
#include "qgsmeshrendereractivedatasetwidget.h"
3029

3130
#include "cpl_string.h"
3231
#include "gdal.h"
@@ -527,8 +526,7 @@ void QgsMeshCalculatorDialog::repopulateTimeCombos()
527526
{
528527
const QgsMeshDatasetMetadata meta = dp->datasetMetadata( QgsMeshDatasetIndex( groupIndex, datasetIndex ) );
529528
const double time = meta.time();
530-
531-
const QString timestr = QgsMeshRendererActiveDatasetWidget::formatTime( time ); // the format is "HH:mm:ss"
529+
const QString timestr = layer->formatTime( time );
532530

533531
times[timestr] = time;
534532
}

‎src/app/mesh/qgsmeshrendereractivedatasetwidget.cpp

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgsmeshlayer.h"
2222
#include "qgsmessagelog.h"
2323
#include "qgsmeshrenderersettings.h"
24+
#include "qgsmeshtimeformatdialog.h"
2425

2526
QgsMeshRendererActiveDatasetWidget::QgsMeshRendererActiveDatasetWidget( QWidget *parent )
2627
: QWidget( parent )
@@ -30,6 +31,7 @@ QgsMeshRendererActiveDatasetWidget::QgsMeshRendererActiveDatasetWidget( QWidget
3031
connect( mTimeComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsMeshRendererActiveDatasetWidget::onActiveTimeChanged );
3132
connect( mDatasetSlider, &QSlider::valueChanged, mTimeComboBox, &QComboBox::setCurrentIndex );
3233

34+
connect( mTimeFormatButton, &QToolButton::clicked, this, &QgsMeshRendererActiveDatasetWidget::onTimeSettingsClicked );
3335
connect( mFirstDatasetButton, &QToolButton::clicked, this, &QgsMeshRendererActiveDatasetWidget::onFirstTimeClicked );
3436
connect( mPreviousDatasetButton, &QToolButton::clicked, this, &QgsMeshRendererActiveDatasetWidget::onPreviousTimeClicked );
3537
connect( mNextDatasetButton, &QToolButton::clicked, this, &QgsMeshRendererActiveDatasetWidget::onNextTimeClicked );
@@ -45,6 +47,12 @@ void QgsMeshRendererActiveDatasetWidget::setLayer( QgsMeshLayer *layer )
4547
{
4648
mMeshLayer = layer;
4749
mDatasetGroupTreeView->setLayer( layer );
50+
setTimeRange();
51+
52+
if ( layer )
53+
{
54+
connect( mMeshLayer, &QgsMeshLayer::timeSettingsChanged, this, &QgsMeshRendererActiveDatasetWidget::setTimeRange );
55+
}
4856
}
4957

5058
int QgsMeshRendererActiveDatasetWidget::activeScalarDatasetGroup() const
@@ -102,7 +110,7 @@ void QgsMeshRendererActiveDatasetWidget::setTimeRange()
102110
QgsMeshDatasetIndex index( groupWithMaximumDatasets, i );
103111
QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( index );
104112
double time = meta.time();
105-
mTimeComboBox->addItem( formatTime( time ), time );
113+
mTimeComboBox->addItem( mMeshLayer->formatTime( time ), time );
106114
}
107115
}
108116
mTimeComboBox->blockSignals( false );
@@ -111,6 +119,7 @@ void QgsMeshRendererActiveDatasetWidget::setTimeRange()
111119
bool isTimeVarying = datasetCount > 1;
112120
mTimeComboBox->setEnabled( isTimeVarying );
113121
mDatasetSlider->setEnabled( isTimeVarying );
122+
mTimeFormatButton->setEnabled( isTimeVarying );
114123
mFirstDatasetButton->setEnabled( isTimeVarying );
115124
mPreviousDatasetButton->setEnabled( isTimeVarying );
116125
mNextDatasetButton->setEnabled( isTimeVarying );
@@ -123,7 +132,6 @@ void QgsMeshRendererActiveDatasetWidget::onActiveScalarGroupChanged( int groupIn
123132
return;
124133

125134
mActiveScalarDatasetGroup = groupIndex;
126-
127135
// keep the same timestep if possible
128136
onActiveTimeChanged( mTimeComboBox->currentIndex() );
129137
emit activeScalarGroupChanged( mActiveScalarDatasetGroup );
@@ -176,6 +184,15 @@ void QgsMeshRendererActiveDatasetWidget::onActiveTimeChanged( int value )
176184
}
177185
}
178186

187+
void QgsMeshRendererActiveDatasetWidget::onTimeSettingsClicked()
188+
{
189+
if ( !mMeshLayer )
190+
return;
191+
QgsMeshTimeFormatDialog dlg( mMeshLayer );
192+
dlg.setModal( true );
193+
dlg.exec();
194+
}
195+
179196
void QgsMeshRendererActiveDatasetWidget::onFirstTimeClicked()
180197
{
181198
mTimeComboBox->setCurrentIndex( 0 );
@@ -249,21 +266,6 @@ void QgsMeshRendererActiveDatasetWidget::updateMetadata()
249266
mActiveDatasetMetadata->setText( msg );
250267
}
251268

252-
QString QgsMeshRendererActiveDatasetWidget::formatTime( double hours )
253-
{
254-
// time should be in hours
255-
int seconds = static_cast<int>( qgsRound( hours * 3600.0, 0 ) );
256-
int days = static_cast<int>( floor( hours / 24.0 ) );
257-
QTime t = QTime( 0, 0 ).addSecs( seconds );
258-
if ( days > 0 )
259-
{
260-
return QStringLiteral( "%1 d %2" ).arg( days ).arg( t.toString() ); // the format is "d HH:mm:ss
261-
}
262-
else
263-
{
264-
return t.toString(); // the format is "HH:mm:ss"
265-
}
266-
}
267269

268270
QString QgsMeshRendererActiveDatasetWidget::metadata( QgsMeshDatasetIndex datasetIndex )
269271
{
@@ -276,9 +278,11 @@ QString QgsMeshRendererActiveDatasetWidget::metadata( QgsMeshDatasetIndex datase
276278
.arg( tr( "Is valid" ) )
277279
.arg( meta.isValid() ? tr( "Yes" ) : tr( "No" ) );
278280

279-
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
281+
const double time = meta.time();
282+
msg += QStringLiteral( "<tr><td>%1</td><td>%2 (%3)</td></tr>" )
280283
.arg( tr( "Time" ) )
281-
.arg( meta.time() );
284+
.arg( mMeshLayer->formatTime( time ) )
285+
.arg( time );
282286

283287
const QgsMeshDatasetGroupMetadata gmeta = mMeshLayer->dataProvider()->datasetGroupMetadata( datasetIndex );
284288
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )

‎src/app/mesh/qgsmeshrendereractivedatasetwidget.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,6 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
6161
//! Synchronizes widgets state with associated mesh layer
6262
void syncToLayer();
6363

64-
/**
65-
* Formats time to human readable string
66-
* \param hours time in double in hours
67-
* \returns formatted time string
68-
*/
69-
static QString formatTime( double hours );
70-
7164
signals:
7265

7366
//! Emitted when the current scalar group gets changed
@@ -83,6 +76,7 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
8376
void onActiveScalarGroupChanged( int groupIndex );
8477
void onActiveVectorGroupChanged( int groupIndex );
8578
void onActiveTimeChanged( int value );
79+
void onTimeSettingsClicked();
8680
void onFirstTimeClicked();
8781
void onPreviousTimeClicked();
8882
void onNextTimeClicked();
@@ -91,8 +85,9 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
9185
QString metadata( QgsMeshDatasetIndex datasetIndex );
9286

9387
private:
94-
//! Loop through all dataset groups and find the maximum number of datasets
88+
//! Loops through all dataset groups and finds the maximum number of datasets
9589
void setTimeRange();
90+
9691
void updateMetadata();
9792

9893
QgsMeshLayer *mMeshLayer = nullptr; // not owned
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/***************************************************************************
2+
qgsmeshtimeformatdialog.cpp
3+
---------------------------
4+
begin : March 2019
5+
copyright : (C) 2019 by Peter Petrik
6+
email : zilolv at gmail dot com
7+
***************************************************************************/
8+
/***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
#include "qgsmeshtimeformatdialog.h"
18+
#include "qgsgui.h"
19+
#include "qgsmeshtimesettings.h"
20+
21+
QgsMeshTimeFormatDialog::QgsMeshTimeFormatDialog( QgsMeshLayer *meshLayer, QWidget *parent, Qt::WindowFlags f )
22+
: QDialog( parent, f ),
23+
mLayer( meshLayer )
24+
{
25+
setupUi( this );
26+
QgsGui::enableAutoGeometryRestore( this );
27+
28+
if ( !meshLayer )
29+
return;
30+
31+
loadSettings();
32+
33+
connect( mUseTimeComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsMeshTimeFormatDialog::saveSettings );
34+
connect( mReferenceDateTimeEdit, &QDateTimeEdit::timeChanged, this, &QgsMeshTimeFormatDialog::saveSettings );
35+
connect( mAbsoluteTimeFormatComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsMeshTimeFormatDialog::saveSettings ); connect( mUseTimeComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsMeshTimeFormatDialog::saveSettings );
36+
connect( mRelativeTimeFormatComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &QgsMeshTimeFormatDialog::saveSettings );
37+
connect( mOffsetHoursSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ), this, &QgsMeshTimeFormatDialog::saveSettings );
38+
}
39+
40+
void QgsMeshTimeFormatDialog::loadSettings()
41+
{
42+
const QgsMeshTimeSettings settings = mLayer->timeSettings();
43+
44+
enableGroups( settings.useAbsoluteTime() ) ;
45+
if ( settings.useAbsoluteTime() )
46+
{
47+
mUseTimeComboBox->setCurrentIndex( 0 );
48+
}
49+
else
50+
{
51+
mUseTimeComboBox->setCurrentIndex( 1 );
52+
}
53+
54+
mReferenceDateTimeEdit->setDateTime( settings.absoluteTimeReferenceTime() );
55+
mReferenceDateTimeEdit->setDisplayFormat( settings.absoluteTimeFormat() );
56+
57+
int index = mAbsoluteTimeFormatComboBox->findText( settings.absoluteTimeFormat() );
58+
if ( index < 0 )
59+
{
60+
index = mAbsoluteTimeFormatComboBox->count();
61+
mAbsoluteTimeFormatComboBox->addItem( settings.absoluteTimeFormat() );
62+
}
63+
mAbsoluteTimeFormatComboBox->setCurrentIndex( index );
64+
65+
index = mRelativeTimeFormatComboBox->findText( settings.relativeTimeFormat() );
66+
if ( index < 0 )
67+
{
68+
index = mRelativeTimeFormatComboBox->count();
69+
mRelativeTimeFormatComboBox->addItem( settings.relativeTimeFormat() );
70+
}
71+
mRelativeTimeFormatComboBox->setCurrentIndex( index );
72+
73+
mOffsetHoursSpinBox->setValue( settings.relativeTimeOffsetHours() );
74+
}
75+
76+
void QgsMeshTimeFormatDialog::saveSettings()
77+
{
78+
QgsMeshTimeSettings settings;
79+
settings.setUseAbsoluteTime( mUseTimeComboBox->currentIndex() == 0 );
80+
settings.setAbsoluteTimeReferenceTime( mReferenceDateTimeEdit->dateTime() );
81+
settings.setAbsoluteTimeFormat( mAbsoluteTimeFormatComboBox->currentText() );
82+
settings.setRelativeTimeOffsetHours( mOffsetHoursSpinBox->value() );
83+
settings.setRelativeTimeFormat( mRelativeTimeFormatComboBox->currentText() );
84+
enableGroups( settings.useAbsoluteTime() ) ;
85+
mLayer->setTimeSettings( settings );
86+
}
87+
88+
void QgsMeshTimeFormatDialog::enableGroups( bool useAbsoluteTime )
89+
{
90+
mAbsoluteTimeGroupBox->setEnabled( useAbsoluteTime );
91+
mRelativeTimeGroupBox->setEnabled( ! useAbsoluteTime );
92+
}
93+
94+
QgsMeshTimeFormatDialog::~QgsMeshTimeFormatDialog() = default;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/***************************************************************************
2+
qgsmeshtimeformatdialog.h
3+
-------------------------
4+
begin : March 2019
5+
copyright : (C) 2019 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+
#ifndef QGSMESHTIMEFORMATDIALOG_H
19+
#define QGSMESHTIMEFORMATDIALOG_H
20+
21+
#include "ui_qgsmeshtimeformatdialog.h"
22+
#include "qgsmeshcalculator.h"
23+
#include "qgshelp.h"
24+
#include "qgis_app.h"
25+
26+
//! A dialog to enter a mesh calculation expression
27+
class APP_EXPORT QgsMeshTimeFormatDialog: public QDialog, private Ui::QgsMeshTimeFormatDialog
28+
{
29+
Q_OBJECT
30+
public:
31+
32+
/**
33+
* Constructor for raster calculator dialog
34+
* \param meshLayer main mesh layer, will be used for default extent and projection
35+
* \param parent widget
36+
* \param f window flags
37+
*/
38+
QgsMeshTimeFormatDialog( QgsMeshLayer *meshLayer = nullptr, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr );
39+
~QgsMeshTimeFormatDialog();
40+
41+
private slots:
42+
43+
private:
44+
void loadSettings();
45+
void saveSettings();
46+
void enableGroups( bool useAbsoluteTime );
47+
48+
QgsMeshLayer *mLayer;
49+
};
50+
51+
#endif // QGSMESHTIMEFORMATDIALOG_H

‎src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ SET(QGIS_CORE_SRCS
484484
mesh/qgsmeshspatialindex.cpp
485485
mesh/qgsmeshvectorrenderer.cpp
486486
mesh/qgstriangularmesh.cpp
487+
mesh/qgsmeshtimesettings.cpp
487488

488489
geometry/qgsabstractgeometry.cpp
489490
geometry/qgsbox3d.cpp
@@ -1117,6 +1118,7 @@ SET(QGIS_CORE_HDRS
11171118
mesh/qgsmeshspatialindex.h
11181119
mesh/qgsmeshvectorrenderer.h
11191120
mesh/qgstriangularmesh.h
1121+
mesh/qgsmeshtimesettings.h
11201122

11211123
scalebar/qgsdoubleboxscalebarrenderer.h
11221124
scalebar/qgsnumericscalebarrenderer.h

‎src/core/mesh/qgsmeshlayer.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
#include "qgsmeshlayer.h"
2828
#include "qgsmeshlayerrenderer.h"
2929
#include "qgsmeshlayerutils.h"
30+
#include "qgsmeshtimesettings.h"
3031
#include "qgspainting.h"
3132
#include "qgsproviderregistry.h"
3233
#include "qgsreadwritecontext.h"
3334
#include "qgsstyle.h"
3435
#include "qgstriangularmesh.h"
3536

36-
3737
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
3838
const QString &baseName,
3939
const QString &providerKey,
@@ -144,6 +144,22 @@ void QgsMeshLayer::setRendererSettings( const QgsMeshRendererSettings &settings
144144
triggerRepaint();
145145
}
146146

147+
QgsMeshTimeSettings QgsMeshLayer::timeSettings() const
148+
{
149+
return mTimeSettings;
150+
}
151+
152+
void QgsMeshLayer::setTimeSettings( const QgsMeshTimeSettings &settings )
153+
{
154+
mTimeSettings = settings;
155+
emit timeSettingsChanged();
156+
}
157+
158+
QString QgsMeshLayer::formatTime( double hours )
159+
{
160+
return QgsMeshLayerUtils::formatTime( hours, mTimeSettings );
161+
}
162+
147163
QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point ) const
148164
{
149165
QgsMeshDatasetValue value;
@@ -281,6 +297,10 @@ bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
281297
if ( !elemRendererSettings.isNull() )
282298
mRendererSettings.readXml( elemRendererSettings );
283299

300+
QDomElement elemTimeSettings = elem.firstChildElement( "mesh-time-settings" );
301+
if ( !elemTimeSettings.isNull() )
302+
mTimeSettings.readXml( elemTimeSettings, context );
303+
284304
// get and set the blend mode if it exists
285305
QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
286306
if ( !blendModeNode.isNull() )
@@ -305,6 +325,9 @@ bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &e
305325
QDomElement elemRendererSettings = mRendererSettings.writeXml( doc );
306326
elem.appendChild( elemRendererSettings );
307327

328+
QDomElement elemTimeSettings = mTimeSettings.writeXml( doc, context );
329+
elem.appendChild( elemTimeSettings );
330+
308331
// add blend mode node
309332
QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
310333
QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );

‎src/core/mesh/qgsmeshlayer.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgsmaplayer.h"
2525
#include "qgsmeshdataprovider.h"
2626
#include "qgsmeshrenderersettings.h"
27+
#include "qgsmeshtimesettings.h"
2728

2829
class QgsMapLayerRenderer;
2930
struct QgsMeshLayerRendererCache;
@@ -178,6 +179,28 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
178179
//! Sets new renderer settings
179180
void setRendererSettings( const QgsMeshRendererSettings &settings );
180181

182+
/**
183+
* Returns time format settings
184+
*
185+
* \since QGIS 3.8
186+
*/
187+
QgsMeshTimeSettings timeSettings() const;
188+
189+
/**
190+
* Sets time format settings
191+
*
192+
* \since QGIS 3.8
193+
*/
194+
void setTimeSettings( const QgsMeshTimeSettings &settings );
195+
196+
/**
197+
* Returns (date) time in hours formatted to human readable form
198+
* \param hours time in double in hours
199+
* \returns formatted time string
200+
* \since QGIS 3.8
201+
*/
202+
QString formatTime( double hours );
203+
181204
/**
182205
* Interpolates the value on the given point from given dataset.
183206
*
@@ -211,6 +234,13 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
211234
*/
212235
void activeVectorDatasetChanged( const QgsMeshDatasetIndex &index );
213236

237+
/**
238+
* Emitted when time format is changed
239+
*
240+
* \since QGIS 3.8
241+
*/
242+
void timeSettingsChanged( );
243+
214244
private: // Private methods
215245

216246
/**
@@ -252,6 +282,9 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
252282

253283
//! Renderer configuration
254284
QgsMeshRendererSettings mRendererSettings;
285+
286+
//! Time format configuration
287+
QgsMeshTimeSettings mTimeSettings;
255288
};
256289

257290
#endif //QGSMESHLAYER_H

‎src/core/mesh/qgsmeshlayerutils.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
***************************************************************************/
1717

1818
#include "qgsmeshlayerutils.h"
19+
#include "qgsmeshtimesettings.h"
1920

2021
#include <limits>
22+
#include <QTime>
23+
#include <QDateTime>
2124

2225
///@cond PRIVATE
2326

@@ -127,4 +130,93 @@ QgsRectangle QgsMeshLayerUtils::triangleBoundingBox( const QgsPointXY &p1, const
127130
return bbox;
128131
}
129132

133+
QString QgsMeshLayerUtils::formatTime( double hours, const QgsMeshTimeSettings &settings )
134+
{
135+
QString ret;
136+
if ( settings.useAbsoluteTime() )
137+
{
138+
QString format( settings.absoluteTimeFormat() );
139+
QDateTime dateTime( settings.absoluteTimeReferenceTime() );
140+
int seconds = static_cast<int>( hours * 3600.0 );
141+
dateTime = dateTime.addSecs( seconds );
142+
ret = dateTime.toString( format );
143+
if ( ret.isEmpty() ) // error
144+
ret = dateTime.toString();
145+
}
146+
else
147+
{
148+
QString format( settings.relativeTimeFormat() );
149+
format = format.trimmed();
150+
hours = hours + settings.relativeTimeOffsetHours();
151+
int totalHours = static_cast<int>( hours );
152+
153+
if ( format == QStringLiteral( "hh:mm:ss.zzz" ) )
154+
{
155+
int ms = static_cast<int>( hours * 3600.0 * 1000 );
156+
int seconds = ms / 1000;
157+
int z = ms % 1000;
158+
int m = seconds / 60;
159+
int s = seconds % 60;
160+
int h = m / 60;
161+
m = m % 60;
162+
ret = QStringLiteral( "%1:%2:%3.%4" ).
163+
arg( h, 2, 10, QLatin1Char( '0' ) ).
164+
arg( m, 2, 10, QLatin1Char( '0' ) ).
165+
arg( s, 2, 10, QLatin1Char( '0' ) ).
166+
arg( z, 3, 10, QLatin1Char( '0' ) );
167+
}
168+
else if ( format == QStringLiteral( "hh:mm:ss" ) )
169+
{
170+
int seconds = static_cast<int>( hours * 3600.0 );
171+
int m = seconds / 60;
172+
int s = seconds % 60;
173+
int h = m / 60;
174+
m = m % 60;
175+
ret = QStringLiteral( "%1:%2:%3" ).
176+
arg( h, 2, 10, QLatin1Char( '0' ) ).
177+
arg( m, 2, 10, QLatin1Char( '0' ) ).
178+
arg( s, 2, 10, QLatin1Char( '0' ) );
179+
180+
}
181+
else if ( format == QStringLiteral( "d hh:mm:ss" ) )
182+
{
183+
int seconds = static_cast<int>( hours * 3600.0 );
184+
int m = seconds / 60;
185+
int s = seconds % 60;
186+
int h = m / 60;
187+
m = m % 60;
188+
int d = totalHours / 24;
189+
h = totalHours % 24;
190+
ret = QStringLiteral( "%1 d %2:%3:%4" ).
191+
arg( d ).
192+
arg( h, 2, 10, QLatin1Char( '0' ) ).
193+
arg( m, 2, 10, QLatin1Char( '0' ) ).
194+
arg( s, 2, 10, QLatin1Char( '0' ) );
195+
}
196+
else if ( format == QStringLiteral( "d hh" ) )
197+
{
198+
int d = totalHours / 24;
199+
int h = totalHours % 24;
200+
ret = QStringLiteral( "%1 d %2" ).
201+
arg( d ).
202+
arg( h );
203+
}
204+
else if ( format == QStringLiteral( "d" ) )
205+
{
206+
int d = totalHours / 24;
207+
ret = QStringLiteral( "%1" ).arg( d );
208+
}
209+
else if ( format == QStringLiteral( "ss" ) )
210+
{
211+
int seconds = static_cast<int>( hours * 3600.0 );
212+
ret = QStringLiteral( "%1" ).arg( seconds );
213+
}
214+
else // "hh"
215+
{
216+
ret = QStringLiteral( "%1" ).arg( hours );
217+
}
218+
}
219+
return ret;
220+
}
221+
130222
///@endcond

‎src/core/mesh/qgsmeshlayerutils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
///@cond PRIVATE
3232

33+
class QgsMeshTimeSettings;
34+
3335
/**
3436
* \ingroup core
3537
* Misc utility functions used for mesh layer support
@@ -101,6 +103,11 @@ class CORE_EXPORT QgsMeshLayerUtils
101103
* \returns bounding box of the triangle
102104
*/
103105
static QgsRectangle triangleBoundingBox( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3 );
106+
107+
/**
108+
* Formats hours in human readable string based on settings
109+
*/
110+
static QString formatTime( double hours, const QgsMeshTimeSettings &settings );
104111
};
105112

106113
///@endcond

‎src/core/mesh/qgsmeshtimesettings.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/***************************************************************************
2+
qgsmeshtimesettings.cpp
3+
-- ---------------------
4+
begin : March 2019
5+
copyright : (C) 2019 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 "qgsmeshtimesettings.h"
19+
20+
QgsMeshTimeSettings::QgsMeshTimeSettings() = default;
21+
22+
QgsMeshTimeSettings::QgsMeshTimeSettings( double relativeTimeOffsetHours, const QString &relativeTimeFormat )
23+
: mUseAbsoluteTime( false )
24+
, mRelativeTimeOffsetHours( relativeTimeOffsetHours )
25+
, mRelativeTimeFormat( relativeTimeFormat )
26+
{}
27+
28+
QgsMeshTimeSettings::QgsMeshTimeSettings( const QDateTime &absoluteTimeReferenceTime, const QString &absoluteTimeFormat )
29+
: mUseAbsoluteTime( true )
30+
, mAbsoluteTimeReferenceTime( absoluteTimeReferenceTime )
31+
, mAbsoluteTimeFormat( absoluteTimeFormat )
32+
{}
33+
34+
QDomElement QgsMeshTimeSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
35+
{
36+
Q_UNUSED( context );
37+
QDomElement elem = doc.createElement( QStringLiteral( "mesh-time-settings" ) );
38+
elem.setAttribute( QStringLiteral( "use-absolute-time" ), mUseAbsoluteTime ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
39+
elem.setAttribute( QStringLiteral( "relative-time-offset-hours" ), mRelativeTimeOffsetHours );
40+
elem.setAttribute( QStringLiteral( "relative-time-format" ), mRelativeTimeFormat );
41+
elem.setAttribute( QStringLiteral( "absolute-time-reference-time" ), mAbsoluteTimeReferenceTime.toString() );
42+
elem.setAttribute( QStringLiteral( "absolute-time-format" ), mAbsoluteTimeFormat );
43+
return elem;
44+
}
45+
46+
void QgsMeshTimeSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
47+
{
48+
Q_UNUSED( context );
49+
mUseAbsoluteTime = elem.attribute( QStringLiteral( "use-absolute-time" ) ).toInt(); //bool
50+
mRelativeTimeOffsetHours = elem.attribute( QStringLiteral( "relative-time-offset-hours" ) ).toDouble();
51+
mRelativeTimeFormat = elem.attribute( QStringLiteral( "relative-time-format" ) );
52+
mAbsoluteTimeReferenceTime = QDateTime::fromString( elem.attribute( QStringLiteral( "absolute-time-reference-time" ) ) );
53+
mAbsoluteTimeFormat = elem.attribute( QStringLiteral( "absolute-time-format" ) );
54+
}
55+
56+
bool QgsMeshTimeSettings::useAbsoluteTime() const
57+
{
58+
return mUseAbsoluteTime;
59+
}
60+
61+
void QgsMeshTimeSettings::setUseAbsoluteTime( bool useAbsoluteTime )
62+
{
63+
mUseAbsoluteTime = useAbsoluteTime;
64+
}
65+
66+
67+
double QgsMeshTimeSettings::relativeTimeOffsetHours() const
68+
{
69+
return mRelativeTimeOffsetHours;
70+
}
71+
72+
void QgsMeshTimeSettings::setRelativeTimeOffsetHours( double relativeTimeOffsetHours )
73+
{
74+
mRelativeTimeOffsetHours = relativeTimeOffsetHours;
75+
}
76+
77+
QString QgsMeshTimeSettings::relativeTimeFormat() const
78+
{
79+
return mRelativeTimeFormat;
80+
}
81+
82+
void QgsMeshTimeSettings::setRelativeTimeFormat( const QString &relativeTimeFormat )
83+
{
84+
mRelativeTimeFormat = relativeTimeFormat;
85+
}
86+
87+
QDateTime QgsMeshTimeSettings::absoluteTimeReferenceTime() const
88+
{
89+
return mAbsoluteTimeReferenceTime;
90+
}
91+
92+
void QgsMeshTimeSettings::setAbsoluteTimeReferenceTime( const QDateTime &absoluteTimeReferenceTime )
93+
{
94+
mAbsoluteTimeReferenceTime = absoluteTimeReferenceTime;
95+
}
96+
97+
QString QgsMeshTimeSettings::absoluteTimeFormat() const
98+
{
99+
return mAbsoluteTimeFormat;
100+
}
101+
102+
void QgsMeshTimeSettings::setAbsoluteTimeFormat( const QString &absoluteTimeFormat )
103+
{
104+
mAbsoluteTimeFormat = absoluteTimeFormat;
105+
}

‎src/core/mesh/qgsmeshtimesettings.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/***************************************************************************
2+
qgsmeshtimesettings.h
3+
---------------------
4+
begin : March 2019
5+
copyright : (C) 2019 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+
#ifndef QGSMESHTIMESETTINGS_H
19+
#define QGSMESHTIMESETTINGS_H
20+
21+
#include <QDateTime>
22+
#include <QDomDocument>
23+
24+
#include "qgis_core.h"
25+
#include "qgis.h"
26+
#include "qgsreadwritecontext.h"
27+
28+
/**
29+
* \ingroup core
30+
*
31+
* Represents a mesh time settings for mesh datasets
32+
*
33+
* \since QGIS 3.8
34+
*/
35+
class CORE_EXPORT QgsMeshTimeSettings
36+
{
37+
public:
38+
//! Default constructor for relative time formate and 0 offset
39+
QgsMeshTimeSettings();
40+
//! Constructs relative time format settings with defined offset in hours
41+
QgsMeshTimeSettings( double relativeTimeOffsetHours, const QString &relativeTimeFormat );
42+
//! Constructs absolute time format settings with defined reference time
43+
QgsMeshTimeSettings( const QDateTime &absoluteTimeReferenceTime, const QString &absoluteTimeFormat );
44+
45+
//! Writes configuration to a new DOM element
46+
QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const;
47+
//! Reads configuration from the given DOM element
48+
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
49+
50+
//! Returns whether to use absolute time format
51+
bool useAbsoluteTime() const;
52+
//! Sets use absolute time flag
53+
void setUseAbsoluteTime( bool useAbsoluteTime );
54+
55+
//! Returns number of offset hours for relative time formatting
56+
double relativeTimeOffsetHours() const;
57+
//! Sets number of offset hours for relative time formatting
58+
void setRelativeTimeOffsetHours( double relativeTimeOffsetHours );
59+
60+
//! Returns format used for relative time
61+
QString relativeTimeFormat() const;
62+
//! Sets format used for relative time
63+
void setRelativeTimeFormat( const QString &relativeTimeFormat );
64+
65+
//! Returns reference time used for absolute time format
66+
QDateTime absoluteTimeReferenceTime() const;
67+
//! Sets reference time used for absolute time format
68+
void setAbsoluteTimeReferenceTime( const QDateTime &absoluteTimeReferenceTime );
69+
70+
//! Returns format used for absolute time
71+
QString absoluteTimeFormat() const;
72+
//! Sets format used for absolute time
73+
void setAbsoluteTimeFormat( const QString &absoluteTimeFormat );
74+
75+
private:
76+
bool mUseAbsoluteTime = false;
77+
78+
double mRelativeTimeOffsetHours = 0;
79+
QString mRelativeTimeFormat = QStringLiteral( "d hh:mm:ss" );
80+
81+
QDateTime mAbsoluteTimeReferenceTime;
82+
QString mAbsoluteTimeFormat = QStringLiteral( "dd.MM.yyyy hh:mm:ss" );
83+
};
84+
85+
Q_DECLARE_METATYPE( QgsMeshTimeSettings );
86+
87+
#endif // QGSMESHTIMESETTINGS_H

‎src/ui/mesh/qgsmeshrendereractivedatasetwidgetbase.ui

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
<class>QgsMeshRendererActiveDatasetWidgetBase</class>
44
<widget class="QWidget" name="QgsMeshRendererActiveDatasetWidgetBase">
55
<property name="enabled">
6-
<bool>false</bool>
6+
<bool>true</bool>
77
</property>
88
<property name="geometry">
99
<rect>
1010
<x>0</x>
1111
<y>0</y>
12-
<width>286</width>
12+
<width>292</width>
1313
<height>337</height>
1414
</rect>
1515
</property>
@@ -36,50 +36,47 @@
3636
</item>
3737
<item>
3838
<layout class="QGridLayout" name="mTimeLayout">
39-
<item row="0" column="0" colspan="6">
40-
<widget class="QSlider" name="mDatasetSlider">
41-
<property name="orientation">
42-
<enum>Qt::Horizontal</enum>
43-
</property>
44-
<property name="tickPosition">
45-
<enum>QSlider::TicksBelow</enum>
39+
<item row="2" column="0" colspan="2">
40+
<widget class="QComboBox" name="mTimeComboBox">
41+
<property name="editable">
42+
<bool>true</bool>
4643
</property>
47-
<property name="tickInterval">
48-
<number>1</number>
44+
<property name="insertPolicy">
45+
<enum>QComboBox::NoInsert</enum>
4946
</property>
5047
</widget>
5148
</item>
52-
<item row="1" column="5">
53-
<widget class="QToolButton" name="mLastDatasetButton">
49+
<item row="2" column="5">
50+
<widget class="QToolButton" name="mNextDatasetButton">
5451
<property name="text">
55-
<string>&gt;|</string>
52+
<string>&gt;</string>
5653
</property>
5754
<property name="autoRaise">
5855
<bool>true</bool>
5956
</property>
6057
</widget>
6158
</item>
62-
<item row="1" column="4">
63-
<widget class="QToolButton" name="mNextDatasetButton">
59+
<item row="2" column="4">
60+
<widget class="QToolButton" name="mPreviousDatasetButton">
6461
<property name="text">
65-
<string>&gt;</string>
62+
<string>&lt;</string>
6663
</property>
6764
<property name="autoRaise">
6865
<bool>true</bool>
6966
</property>
7067
</widget>
7168
</item>
72-
<item row="1" column="3">
73-
<widget class="QToolButton" name="mPreviousDatasetButton">
69+
<item row="2" column="6">
70+
<widget class="QToolButton" name="mLastDatasetButton">
7471
<property name="text">
75-
<string>&lt;</string>
72+
<string>&gt;|</string>
7673
</property>
7774
<property name="autoRaise">
7875
<bool>true</bool>
7976
</property>
8077
</widget>
8178
</item>
82-
<item row="1" column="2">
79+
<item row="2" column="3">
8380
<widget class="QToolButton" name="mFirstDatasetButton">
8481
<property name="text">
8582
<string>|&lt;</string>
@@ -89,13 +86,33 @@
8986
</property>
9087
</widget>
9188
</item>
92-
<item row="1" column="0" colspan="2">
93-
<widget class="QComboBox" name="mTimeComboBox">
94-
<property name="editable">
89+
<item row="2" column="2">
90+
<widget class="QToolButton" name="mTimeFormatButton">
91+
<property name="toolTip">
92+
<string>Time Format Options</string>
93+
</property>
94+
<property name="text">
95+
<string notr="true"/>
96+
</property>
97+
<property name="icon">
98+
<iconset resource="../../../images/images.qrc">
99+
<normaloff>:/images/themes/default/console/iconSettingsConsole.svg</normaloff>:/images/themes/default/console/iconSettingsConsole.svg</iconset>
100+
</property>
101+
<property name="autoRaise">
95102
<bool>true</bool>
96103
</property>
97-
<property name="insertPolicy">
98-
<enum>QComboBox::NoInsert</enum>
104+
</widget>
105+
</item>
106+
<item row="1" column="0" colspan="7">
107+
<widget class="QSlider" name="mDatasetSlider">
108+
<property name="orientation">
109+
<enum>Qt::Horizontal</enum>
110+
</property>
111+
<property name="tickPosition">
112+
<enum>QSlider::TicksBelow</enum>
113+
</property>
114+
<property name="tickInterval">
115+
<number>1</number>
99116
</property>
100117
</widget>
101118
</item>
@@ -135,6 +152,8 @@
135152
<header>mesh/qgsmeshdatasetgrouptreeview.h</header>
136153
</customwidget>
137154
</customwidgets>
138-
<resources/>
155+
<resources>
156+
<include location="../../../images/images.qrc"/>
157+
</resources>
139158
<connections/>
140159
</ui>
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsMeshTimeFormatDialog</class>
4+
<widget class="QDialog" name="QgsMeshTimeFormatDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>271</width>
10+
<height>382</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Time Display Options</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout_4">
17+
<item>
18+
<widget class="QComboBox" name="mUseTimeComboBox">
19+
<property name="currentIndex">
20+
<number>1</number>
21+
</property>
22+
<item>
23+
<property name="text">
24+
<string>Use absolute time</string>
25+
</property>
26+
</item>
27+
<item>
28+
<property name="text">
29+
<string>Use relative time</string>
30+
</property>
31+
</item>
32+
</widget>
33+
</item>
34+
<item>
35+
<widget class="QGroupBox" name="mAbsoluteTimeGroupBox">
36+
<property name="enabled">
37+
<bool>true</bool>
38+
</property>
39+
<property name="title">
40+
<string>Use absolute time </string>
41+
</property>
42+
<property name="flat">
43+
<bool>false</bool>
44+
</property>
45+
<property name="checkable">
46+
<bool>false</bool>
47+
</property>
48+
<property name="checked">
49+
<bool>false</bool>
50+
</property>
51+
<layout class="QVBoxLayout" name="verticalLayout_2">
52+
<item>
53+
<widget class="QLabel" name="refLabel">
54+
<property name="text">
55+
<string>Reference date/time</string>
56+
</property>
57+
</widget>
58+
</item>
59+
<item>
60+
<widget class="QDateTimeEdit" name="mReferenceDateTimeEdit">
61+
<property name="dateTime">
62+
<datetime>
63+
<hour>0</hour>
64+
<minute>0</minute>
65+
<second>0</second>
66+
<year>2019</year>
67+
<month>1</month>
68+
<day>1</day>
69+
</datetime>
70+
</property>
71+
<property name="calendarPopup">
72+
<bool>true</bool>
73+
</property>
74+
</widget>
75+
</item>
76+
<item>
77+
<widget class="QLabel" name="label">
78+
<property name="text">
79+
<string>Date/time Format</string>
80+
</property>
81+
</widget>
82+
</item>
83+
<item>
84+
<widget class="QComboBox" name="mAbsoluteTimeFormatComboBox">
85+
<property name="editable">
86+
<bool>false</bool>
87+
</property>
88+
<item>
89+
<property name="text">
90+
<string>dd.MM.yyyy hh:mm:ss</string>
91+
</property>
92+
</item>
93+
<item>
94+
<property name="text">
95+
<string>dd.MM.yyyy hh:mm</string>
96+
</property>
97+
</item>
98+
<item>
99+
<property name="text">
100+
<string>dd.MM.yyyy hh</string>
101+
</property>
102+
</item>
103+
<item>
104+
<property name="text">
105+
<string>dd.MM.yyyy</string>
106+
</property>
107+
</item>
108+
<item>
109+
<property name="text">
110+
<string>dd/MM/yyyy hh:mm:ss</string>
111+
</property>
112+
</item>
113+
<item>
114+
<property name="text">
115+
<string>dd/MM/yyyy hh:mm</string>
116+
</property>
117+
</item>
118+
<item>
119+
<property name="text">
120+
<string>dd/MM/yyyy hh</string>
121+
</property>
122+
</item>
123+
<item>
124+
<property name="text">
125+
<string>dd/MM/yyyy</string>
126+
</property>
127+
</item>
128+
<item>
129+
<property name="text">
130+
<string>MM/dd/yyyy hh:mm:ss</string>
131+
</property>
132+
</item>
133+
<item>
134+
<property name="text">
135+
<string>MM/dd/yyyy hh:mm</string>
136+
</property>
137+
</item>
138+
<item>
139+
<property name="text">
140+
<string>MM/dd/yyyy hh</string>
141+
</property>
142+
</item>
143+
<item>
144+
<property name="text">
145+
<string>MM/dd/yyyy</string>
146+
</property>
147+
</item>
148+
</widget>
149+
</item>
150+
</layout>
151+
</widget>
152+
</item>
153+
<item>
154+
<widget class="QGroupBox" name="mRelativeTimeGroupBox">
155+
<property name="title">
156+
<string>Use relative time</string>
157+
</property>
158+
<layout class="QVBoxLayout" name="verticalLayout_3">
159+
<item>
160+
<widget class="QWidget" name="widget" native="true">
161+
<layout class="QHBoxLayout" name="horizontalLayout">
162+
<item>
163+
<widget class="QLabel" name="label_2">
164+
<property name="text">
165+
<string>Offset by</string>
166+
</property>
167+
</widget>
168+
</item>
169+
<item>
170+
<widget class="QDoubleSpinBox" name="mOffsetHoursSpinBox">
171+
<property name="suffix">
172+
<string> hours</string>
173+
</property>
174+
<property name="decimals">
175+
<number>1</number>
176+
</property>
177+
<property name="minimum">
178+
<double>-100000.000000000000000</double>
179+
</property>
180+
<property name="maximum">
181+
<double>100000.000000000000000</double>
182+
</property>
183+
</widget>
184+
</item>
185+
</layout>
186+
</widget>
187+
</item>
188+
<item>
189+
<widget class="QWidget" name="widget_2" native="true">
190+
<layout class="QVBoxLayout" name="verticalLayout">
191+
<item>
192+
<widget class="QLabel" name="label_4">
193+
<property name="text">
194+
<string>Time Format</string>
195+
</property>
196+
</widget>
197+
</item>
198+
<item>
199+
<widget class="QComboBox" name="mRelativeTimeFormatComboBox">
200+
<property name="editable">
201+
<bool>false</bool>
202+
</property>
203+
<item>
204+
<property name="text">
205+
<string>hh:mm:ss</string>
206+
</property>
207+
</item>
208+
<item>
209+
<property name="text">
210+
<string>hh:mm:ss.zzz</string>
211+
</property>
212+
</item>
213+
<item>
214+
<property name="text">
215+
<string>hh</string>
216+
</property>
217+
</item>
218+
<item>
219+
<property name="text">
220+
<string>d hh:mm:ss</string>
221+
</property>
222+
</item>
223+
<item>
224+
<property name="text">
225+
<string>d hh</string>
226+
</property>
227+
</item>
228+
<item>
229+
<property name="text">
230+
<string>d</string>
231+
</property>
232+
</item>
233+
<item>
234+
<property name="text">
235+
<string>ss</string>
236+
</property>
237+
</item>
238+
</widget>
239+
</item>
240+
</layout>
241+
</widget>
242+
</item>
243+
</layout>
244+
</widget>
245+
</item>
246+
</layout>
247+
</widget>
248+
<resources/>
249+
<connections/>
250+
<slots>
251+
<slot>shaftLengthMethodChanged()</slot>
252+
<slot>apply()</slot>
253+
</slots>
254+
</ui>

‎tests/src/core/testqgsmeshlayer.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "qgsproviderregistry.h"
2727
#include "qgsproject.h"
2828
#include "qgstriangularmesh.h"
29+
#include "qgsmeshlayerutils.h"
2930

3031
/**
3132
* \ingroup UnitTests
@@ -60,6 +61,9 @@ class TestQgsMeshLayer : public QObject
6061
void test_read_face_vector_dataset();
6162
void test_read_vertex_scalar_dataset_with_inactive_face();
6263
void test_extent();
64+
65+
void test_time_format_data();
66+
void test_time_format();
6367
};
6468

6569
QString TestQgsMeshLayer::readFile( const QString &fname ) const
@@ -426,5 +430,68 @@ void TestQgsMeshLayer::test_write_read_project()
426430
QVERIFY( layers.size() == 2 );
427431
}
428432

433+
void TestQgsMeshLayer::test_time_format_data()
434+
{
435+
QTest::addColumn<QgsMeshTimeSettings>( "settings" );
436+
QTest::addColumn<double>( "hours" );
437+
QTest::addColumn<QString>( "expectedTime" );
438+
439+
QTest::newRow( "rel1" ) << QgsMeshTimeSettings( 0, "hh:mm:ss.zzz" ) << 0.0 << QString( "00:00:00.000" );
440+
QTest::newRow( "rel2" ) << QgsMeshTimeSettings( 0, "hh:mm:ss" ) << 0.0 << QString( "00:00:00" );
441+
QTest::newRow( "rel3" ) << QgsMeshTimeSettings( 0, "d hh:mm:ss" ) << 0.0 << QString( "0 d 00:00:00" );
442+
QTest::newRow( "rel4" ) << QgsMeshTimeSettings( 0, "d hh" ) << 0.0 << QString( "0 d 0" );
443+
QTest::newRow( "rel5" ) << QgsMeshTimeSettings( 0, "d" ) << 0.0 << QString( "0" );
444+
QTest::newRow( "rel6" ) << QgsMeshTimeSettings( 0, "hh" ) << 0.0 << QString( "0" );
445+
QTest::newRow( "rel7" ) << QgsMeshTimeSettings( 0, "ss" ) << 0.0 << QString( "0" );
446+
QTest::newRow( "rel8" ) << QgsMeshTimeSettings( 0, "some-invalid-format" ) << 0.0 << QString( "0" );
447+
448+
QTest::newRow( "rel9" ) << QgsMeshTimeSettings( 100.11111, "hh:mm:ss.zzz" ) << 0.0 << QString( "100:06:39.996" );
449+
QTest::newRow( "rel10" ) << QgsMeshTimeSettings( 0, "hh:mm:ss.zzz" ) << 100.11111 << QString( "100:06:39.996" );
450+
QTest::newRow( "rel11" ) << QgsMeshTimeSettings( 0, "hh:mm:ss" ) << 100.11111 << QString( "100:06:39" );
451+
QTest::newRow( "rel12" ) << QgsMeshTimeSettings( 0, "d hh:mm:ss" ) << 100.11111 << QString( "4 d 04:06:39" );
452+
QTest::newRow( "rel13" ) << QgsMeshTimeSettings( 0, "d hh" ) << 100.11111 << QString( "4 d 4" );
453+
QTest::newRow( "rel14" ) << QgsMeshTimeSettings( 0, "d" ) << 100.11111 << QString( "4" );
454+
QTest::newRow( "rel15" ) << QgsMeshTimeSettings( 0, "hh" ) << 100.11111 << QString( "100.111" );
455+
QTest::newRow( "rel16" ) << QgsMeshTimeSettings( 0, "ss" ) << 100.11111 << QString( "360399" );
456+
QTest::newRow( "rel17" ) << QgsMeshTimeSettings( 0, "some-invalid-format" ) << 100.11111 << QString( "100.111" );
457+
458+
QDateTime dt = QDateTime::fromString( "2019-03-21 11:01:02", "yyyy-MM-dd HH:mm:ss" );
459+
QTest::newRow( "abs1" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh:mm:ss" ) << 0.0 << QString( "21.03.2019 11:01:02" );
460+
QTest::newRow( "abs2" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh:mm" ) << 0.0 << QString( "21.03.2019 11:01" );
461+
QTest::newRow( "abs3" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh" ) << 0.0 << QString( "21.03.2019 11" );
462+
QTest::newRow( "abs4" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy" ) << 0.0 << QString( "21.03.2019" );
463+
QTest::newRow( "abs5" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh:mm:ss" ) << 0.0 << QString( "21/03/2019 11:01:02" );
464+
QTest::newRow( "abs6" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh:mm" ) << 0.0 << QString( "21/03/2019 11:01" );
465+
QTest::newRow( "abs7" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh" ) << 0.0 << QString( "21/03/2019 11" );
466+
QTest::newRow( "abs8" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy" ) << 0.0 << QString( "21/03/2019" );
467+
QTest::newRow( "abs9" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh:mm:ss" ) << 0.0 << QString( "03/21/2019 11:01:02" );
468+
QTest::newRow( "abs10" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh:mm" ) << 0.0 << QString( "03/21/2019 11:01" );
469+
QTest::newRow( "abs11" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh" ) << 0.0 << QString( "03/21/2019 11" );
470+
QTest::newRow( "abs12" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy" ) << 0.0 << QString( "03/21/2019" );
471+
472+
QTest::newRow( "abs13" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh:mm:ss" ) << 100.11111 << QString( "25.03.2019 15:07:41" );
473+
QTest::newRow( "abs14" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh:mm" ) << 100.11111 << QString( "25.03.2019 15:07" );
474+
QTest::newRow( "abs15" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy hh" ) << 100.11111 << QString( "25.03.2019 15" );
475+
QTest::newRow( "abs16" ) << QgsMeshTimeSettings( dt, "dd.MM.yyyy" ) << 100.11111 << QString( "25.03.2019" );
476+
QTest::newRow( "abs17" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh:mm:ss" ) << 100.11111 << QString( "25/03/2019 15:07:41" );
477+
QTest::newRow( "abs18" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh:mm" ) << 100.11111 << QString( "25/03/2019 15:07" );
478+
QTest::newRow( "abs19" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy hh" ) << 100.11111 << QString( "25/03/2019 15" );
479+
QTest::newRow( "abs20" ) << QgsMeshTimeSettings( dt, "dd/MM/yyyy" ) << 100.11111 << QString( "25/03/2019" );
480+
QTest::newRow( "abs21" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh:mm:ss" ) << 100.11111 << QString( "03/25/2019 15:07:41" );
481+
QTest::newRow( "abs22" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh:mm" ) << 100.11111 << QString( "03/25/2019 15:07" );
482+
QTest::newRow( "abs23" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy hh" ) << 100.11111 << QString( "03/25/2019 15" );
483+
QTest::newRow( "abs24" ) << QgsMeshTimeSettings( dt, "MM/dd/yyyy" ) << 100.11111 << QString( "03/25/2019" );
484+
}
485+
486+
void TestQgsMeshLayer::test_time_format()
487+
{
488+
QFETCH( QgsMeshTimeSettings, settings );
489+
QFETCH( double, hours );
490+
QFETCH( QString, expectedTime );
491+
492+
QString time = QgsMeshLayerUtils::formatTime( hours, settings );
493+
QCOMPARE( time, expectedTime );
494+
}
495+
429496
QGSTEST_MAIN( TestQgsMeshLayer )
430497
#include "testqgsmeshlayer.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.