35#include <QRegularExpression>
38#include "moc_qgstemporalcontrollerwidget.cpp"
40using namespace Qt::StringLiterals;
49 mStartDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
50 mEndDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
51 mFixedRangeStartDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
52 mFixedRangeEndDateTime->setDateTimeRange( QDateTime( QDate( 1, 1, 1 ), QTime( 0, 0, 0 ) ), mStartDateTime->maximumDateTime() );
58 mNavigationObject->rewindToStart();
62 mNavigationObject->previous();
66 mNavigationObject->playBackward();
70 mNavigationObject->pause();
74 mNavigationObject->playForward();
78 mNavigationObject->next();
82 mNavigationObject->skipToEnd();
89 connect( mAnimationLoopingCheckBox, &QCheckBox::toggled,
this, [
this](
bool state ) {
90 mNavigationObject->setLooping( state );
91 mMovieLoopingCheckBox->setChecked( state );
93 connect( mMovieLoopingCheckBox, &QCheckBox::toggled,
this, [
this](
bool state ) {
94 mNavigationObject->setLooping( state );
95 mAnimationLoopingCheckBox->setChecked( state );
98 setWidgetStateFromNavigationMode( mNavigationObject->navigationMode() );
102 if ( mBlockFrameDurationUpdates )
105 mBlockFrameDurationUpdates++;
106 updateTimeStepInputs( timeStep );
107 mBlockFrameDurationUpdates--;
109 connect( mNavigationOff, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationOff_clicked );
110 connect( mNavigationFixedRange, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationFixedRange_clicked );
111 connect( mNavigationAnimated, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationAnimated_clicked );
112 connect( mNavigationMovie, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationMovie_clicked );
115 mAnimationController->setState( state );
116 mMovieController->setState( state );
119 connect( mStartDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::startEndDateTime_changed );
120 connect( mEndDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::startEndDateTime_changed );
121 connect( mFixedRangeStartDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed );
122 connect( mFixedRangeEndDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed );
123 connect( mStepSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ),
this, &QgsTemporalControllerWidget::updateFrameDuration );
124 connect( mTimeStepsComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsTemporalControllerWidget::updateFrameDuration );
125 connect( mAnimationSlider, &QSlider::valueChanged,
this, &QgsTemporalControllerWidget::timeSlider_valueChanged );
126 connect( mMovieSlider, &QSlider::valueChanged,
this, &QgsTemporalControllerWidget::timeSlider_valueChanged );
128 connect( mTotalFramesSpinBox, qOverload<int>( &QSpinBox::valueChanged ),
this, [
this](
int frames ) { mNavigationObject->setTotalMovieFrames( frames ); } );
130 mStepSpinBox->setClearValue( 1 );
135 connect( mSettings, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::settings_clicked );
139 mRangeMenu = std::make_unique<QMenu>(
this );
141 mRangeSetToAllLayersAction =
new QAction( tr(
"Set to Full Range" ), mRangeMenu.get() );
143 connect( mRangeSetToAllLayersAction, &QAction::triggered,
this, &QgsTemporalControllerWidget::mRangeSetToAllLayersAction_triggered );
144 mRangeMenu->addAction( mRangeSetToAllLayersAction );
146 mRangeSetToProjectAction =
new QAction( tr(
"Set to Preset Project Range" ), mRangeMenu.get() );
147 connect( mRangeSetToProjectAction, &QAction::triggered,
this, &QgsTemporalControllerWidget::mRangeSetToProjectAction_triggered );
148 mRangeMenu->addAction( mRangeSetToProjectAction );
150 mRangeMenu->addSeparator();
152 mRangeLayersSubMenu = std::make_unique<QMenu>( tr(
"Set to Single Layer's Range" ), mRangeMenu.get() );
153 mRangeLayersSubMenu->setEnabled(
false );
154 mRangeMenu->addMenu( mRangeLayersSubMenu.get() );
155 connect( mRangeMenu.get(), &QMenu::aboutToShow,
this, &QgsTemporalControllerWidget::aboutToShowRangeMenu );
157 mSetRangeButton->setPopupMode( QToolButton::MenuButtonPopup );
158 mSetRangeButton->setMenu( mRangeMenu.get() );
159 mSetRangeButton->setDefaultAction( mRangeSetToAllLayersAction );
160 mFixedRangeSetRangeButton->setPopupMode( QToolButton::MenuButtonPopup );
161 mFixedRangeSetRangeButton->setMenu( mRangeMenu.get() );
162 mFixedRangeSetRangeButton->setDefaultAction( mRangeSetToAllLayersAction );
172 if ( range.
begin().isValid() && range.
end().isValid() )
201 mStepSpinBox->setDecimals( 3 );
203 mStepSpinBox->setMinimum( 0.001 );
204 mStepSpinBox->setMaximum( std::numeric_limits<int>::max() );
205 mStepSpinBox->setSingleStep( 1 );
206 mStepSpinBox->setValue( 1 );
208 updateFrameDuration();
222 if ( ( mAnimationSlider->hasFocus() || mMovieSlider->hasFocus() ) && e->key() == Qt::Key_Space )
224 mAnimationController->togglePause();
230void QgsTemporalControllerWidget::aboutToShowRangeMenu()
235 mRangeSetToProjectAction->setEnabled( projectRange.
begin().isValid() && projectRange.
end().isValid() );
237 mRangeLayersSubMenu->clear();
238 for (
int i = 0; i < mMapLayerModel->
rowCount(); ++i )
240 const QModelIndex index = mMapLayerModel->
index( i, 0 );
245 const QIcon icon = qvariant_cast<QIcon>( mMapLayerModel->
data( index, Qt::DecorationRole ) );
246 const QString text = mMapLayerModel->
data( index, Qt::DisplayRole ).toString();
248 if ( range.
begin().isValid() && range.
end().isValid() )
250 QAction *action =
new QAction( icon, text, mRangeLayersSubMenu.get() );
251 connect( action, &QAction::triggered,
this, [
this, range] {
253 saveRangeToProject();
255 mRangeLayersSubMenu->addAction( action );
258 mRangeLayersSubMenu->setEnabled( !mRangeLayersSubMenu->actions().isEmpty() );
261void QgsTemporalControllerWidget::updateTemporalExtent()
265 const QDateTime start = mStartDateTime->dateTime();
266 const QDateTime end = mEndDateTime->dateTime();
267 const bool isTimeInstant = start == end;
269 mNavigationObject->setTemporalExtents( temporalExtent );
270 mAnimationSlider->setRange( 0, mNavigationObject->totalFrameCount() - 1 );
271 mAnimationSlider->setValue( mNavigationObject->currentFrameNumber() );
272 mMovieSlider->setRange( 0, mNavigationObject->totalFrameCount() - 1 );
273 mMovieSlider->setValue( mNavigationObject->currentFrameNumber() );
276void QgsTemporalControllerWidget::updateFrameDuration()
278 if ( mBlockSettingUpdates )
286 if ( !mBlockFrameDurationUpdates )
289 mAnimationSlider->setValue( mNavigationObject->currentFrameNumber() );
291 mAnimationSlider->setRange( 0, mNavigationObject->totalFrameCount() - 1 );
292 mAnimationSlider->setValue( mNavigationObject->currentFrameNumber() );
293 mMovieSlider->setRange( 0, mNavigationObject->totalFrameCount() - 1 );
294 mMovieSlider->setValue( mNavigationObject->currentFrameNumber() );
298 mStepSpinBox->setEnabled(
false );
299 mStepSpinBox->setValue( 1 );
300 mAnimationSlider->setTickInterval( 1 );
301 mAnimationSlider->setTickPosition( QSlider::TicksBothSides );
305 mStepSpinBox->setEnabled(
true );
306 mAnimationSlider->setTickInterval( 0 );
307 mAnimationSlider->setTickPosition( QSlider::NoTicks );
311void QgsTemporalControllerWidget::setWidgetStateFromProject()
313 mBlockSettingUpdates++;
316 mBlockSettingUpdates--;
322 mNavigationObject->setNavigationMode( mode );
323 setWidgetStateFromNavigationMode( mode );
331 mNavigationObject->setTotalMovieFrames(
QgsProject::instance()->timeSettings()->totalMovieFrames() );
336 if ( !startString.isEmpty() && !endString.isEmpty() )
338 whileBlocking( mStartDateTime )->setDateTime( QDateTime::fromString( startString, Qt::ISODateWithMs ) );
339 whileBlocking( mEndDateTime )->setDateTime( QDateTime::fromString( endString, Qt::ISODateWithMs ) );
340 whileBlocking( mFixedRangeStartDateTime )->setDateTime( QDateTime::fromString( startString, Qt::ISODateWithMs ) );
341 whileBlocking( mFixedRangeEndDateTime )->setDateTime( QDateTime::fromString( endString, Qt::ISODateWithMs ) );
345 setDatesToProjectTime(
false );
347 updateTemporalExtent();
348 updateFrameDuration();
350 mNavigationObject->setFramesPerSecond(
QgsProject::instance()->timeSettings()->framesPerSecond() );
351 mNavigationObject->setTemporalRangeCumulative(
QgsProject::instance()->timeSettings()->isTemporalRangeCumulative() );
354void QgsTemporalControllerWidget::mNavigationOff_clicked()
362void QgsTemporalControllerWidget::mNavigationFixedRange_clicked()
370void QgsTemporalControllerWidget::mNavigationAnimated_clicked()
378void QgsTemporalControllerWidget::mNavigationMovie_clicked()
396 mNavigationModeStackedWidget->setCurrentIndex( 0 );
399 mNavigationModeStackedWidget->setCurrentIndex( 1 );
402 mNavigationModeStackedWidget->setCurrentIndex( 2 );
405 mNavigationModeStackedWidget->setCurrentIndex( 3 );
410void QgsTemporalControllerWidget::onLayersAdded(
const QList<QgsMapLayer *> &layers )
412 if ( !mHasTemporalLayersLoaded )
414 for ( QgsMapLayer *layer : layers )
416 if ( layer->temporalProperties() )
418 mHasTemporalLayersLoaded |= layer->temporalProperties()->isActive();
420 if ( !mHasTemporalLayersLoaded )
423 if ( layer->isValid() && layer->temporalProperties()->isActive() && !mHasTemporalLayersLoaded )
425 mHasTemporalLayersLoaded =
true;
426 firstTemporalLayerLoaded( layer );
432 firstTemporalLayerLoaded( layer );
440void QgsTemporalControllerWidget::firstTemporalLayerLoaded(
QgsMapLayer *layer )
442 setDatesToProjectTime(
true );
444 if ( QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( layer ) )
446 mBlockFrameDurationUpdates++;
447 setTimeStep( meshLayer->firstValidTimeStep() );
448 mBlockFrameDurationUpdates--;
449 updateFrameDuration();
451 else if ( QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer ) )
453 if ( rasterLayer->dataProvider() && rasterLayer->dataProvider()->temporalCapabilities() )
455 mBlockFrameDurationUpdates++;
456 setTimeStep( rasterLayer->dataProvider()->temporalCapabilities()->defaultInterval() );
457 mBlockFrameDurationUpdates--;
458 updateFrameDuration();
463void QgsTemporalControllerWidget::onProjectCleared()
465 mHasTemporalLayersLoaded =
false;
472 const QTime startOfCurrentHour = QTime( QTime::currentTime().hour(), 0, 0 );
473 const QDateTime end = QDateTime( QDate::currentDate(), startOfCurrentHour, Qt::UTC );
474 const QDateTime start = end.addSecs( -24 * 60 * 60 );
478 whileBlocking( mFixedRangeStartDateTime )->setDateTime( start );
481 updateTemporalExtent();
483 mStepSpinBox->setValue( 1 );
486void QgsTemporalControllerWidget::updateSlider(
const QgsDateTimeRange &range )
488 whileBlocking( mAnimationSlider )->setValue( mNavigationObject->currentFrameNumber() );
489 whileBlocking( mMovieSlider )->setValue( mNavigationObject->currentFrameNumber() );
490 updateRangeLabel( range );
493void QgsTemporalControllerWidget::totalMovieFramesChanged(
long long frames )
496 mTotalFramesSpinBox->setValue( frames );
497 mCurrentRangeLabel->setText( tr(
"Current frame: %1/%2" ).arg( mNavigationObject->currentFrameNumber() ).arg( frames ) );
500void QgsTemporalControllerWidget::updateRangeLabel(
const QgsDateTimeRange &range )
502 QString timeFrameFormat = u
"yyyy-MM-dd HH:mm:ss"_s;
505 timeFrameFormat = u
"yyyy-MM-dd HH:mm:ss.zzz"_s;
506 switch ( mNavigationObject->navigationMode() )
509 mCurrentRangeLabel->setText( tr(
"Current frame: %1 ≤ <i>t</i> < %2" ).arg( range.
begin().toString( timeFrameFormat ), range.
end().toString( timeFrameFormat ) ) );
512 mCurrentRangeLabel->setText( tr(
"Range: %1 ≤ <i>t</i> < %2" ).arg( range.
begin().toString( timeFrameFormat ), range.
end().toString( timeFrameFormat ) ) );
515 mCurrentRangeLabel->setText( tr(
"Temporal navigation disabled" ) );
518 mCurrentRangeLabel->setText( tr(
"Current frame: %1/%2" ).arg( mNavigationObject->currentFrameNumber() ).arg( mNavigationObject->totalMovieFrames() ) );
525 return mNavigationObject;
528void QgsTemporalControllerWidget::settings_clicked()
530 QgsTemporalMapSettingsWidget *settingsWidget =
new QgsTemporalMapSettingsWidget(
this );
531 settingsWidget->setFrameRateValue( mNavigationObject->
framesPerSecond() );
534 connect( settingsWidget, &QgsTemporalMapSettingsWidget::frameRateChanged,
this, [
this](
double rate ) {
540 connect( settingsWidget, &QgsTemporalMapSettingsWidget::temporalRangeCumulativeChanged,
this, [
this](
bool state ) {
543 mNavigationObject->setTemporalRangeCumulative( state );
548void QgsTemporalControllerWidget::timeSlider_valueChanged(
int value )
550 mNavigationObject->setCurrentFrameNumber( value );
553void QgsTemporalControllerWidget::startEndDateTime_changed()
555 whileBlocking( mFixedRangeStartDateTime )->setDateTime( mStartDateTime->dateTime() );
556 whileBlocking( mFixedRangeEndDateTime )->setDateTime( mEndDateTime->dateTime() );
558 updateTemporalExtent();
559 saveRangeToProject();
562void QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed()
564 whileBlocking( mStartDateTime )->setDateTime( mFixedRangeStartDateTime->dateTime() );
565 whileBlocking( mEndDateTime )->setDateTime( mFixedRangeEndDateTime->dateTime() );
567 updateTemporalExtent();
568 saveRangeToProject();
571void QgsTemporalControllerWidget::mRangeSetToAllLayersAction_triggered()
573 setDatesToAllLayers();
574 saveRangeToProject();
577void QgsTemporalControllerWidget::setTimeStep(
const QgsInterval &timeStep )
582 int selectedUnit = -1;
583 double selectedValue = std::numeric_limits<double>::max();
589 int stringSize = std::numeric_limits<int>::max();
590 const int precision = mStepSpinBox->decimals();
591 for (
int i = 0; i < mTimeStepsComboBox->count(); ++i )
595 QString
string = QString::number( value,
'f', precision );
597 const thread_local QRegularExpression trailingZeroRegEx = QRegularExpression( u
"0+$"_s );
599 string.remove( trailingZeroRegEx );
601 const thread_local QRegularExpression trailingPointRegEx = QRegularExpression( u
"[.]+$"_s );
603 string.remove( trailingPointRegEx );
606 &&
string.size() <= stringSize
607 && value < selectedValue )
610 selectedValue = value;
611 stringSize =
string.size();
613 else if (
string !=
'0'
614 &&
string.size() < precision + 2
615 &&
string.size() < stringSize )
618 selectedValue = value;
619 stringSize =
string.size();
625 selectedUnit = mTimeStepsComboBox->findData(
static_cast<int>( timeStep.
originalUnit() ) );
629 if ( selectedUnit >= 0 )
631 mStepSpinBox->setValue( selectedValue );
632 mTimeStepsComboBox->setCurrentIndex( selectedUnit );
635 updateFrameDuration();
638void QgsTemporalControllerWidget::updateTimeStepInputs(
const QgsInterval &timeStep )
643 QString timeDisplayFormat = u
"yyyy-MM-dd HH:mm:ss"_s;
646 timeDisplayFormat = u
"yyyy-MM-dd HH:mm:ss.zzz"_s;
648 updateTemporalExtent();
650 mStartDateTime->setDisplayFormat( timeDisplayFormat );
651 mEndDateTime->setDisplayFormat( timeDisplayFormat );
652 mFixedRangeStartDateTime->setDisplayFormat( timeDisplayFormat );
653 mFixedRangeEndDateTime->setDisplayFormat( timeDisplayFormat );
656 if ( timeStep == QgsInterval( mStepSpinBox->value(),
static_cast<Qgis::TemporalUnit>( mTimeStepsComboBox->currentData().toInt() ) ) )
662 mTimeStepsComboBox->setCurrentIndex( mTimeStepsComboBox->findData(
static_cast<int>( timeStep.
originalUnit() ) ) );
665 updateFrameDuration();
668void QgsTemporalControllerWidget::mRangeSetToProjectAction_triggered()
670 setDatesToProjectTime(
false );
671 saveRangeToProject();
676 if ( range.
begin().isValid() && range.
end().isValid() )
682 updateTemporalExtent();
686void QgsTemporalControllerWidget::setDatesToAllLayers()
695void QgsTemporalControllerWidget::setDatesToProjectTime(
bool tryLastStoredRange )
699 if ( tryLastStoredRange )
703 if ( !startString.isEmpty() && !endString.isEmpty() )
705 range =
QgsDateTimeRange( QDateTime::fromString( startString, Qt::ISODateWithMs ), QDateTime::fromString( endString, Qt::ISODateWithMs ) );
714 if ( !range.
begin().isValid() || !range.
end().isValid() )
724void QgsTemporalControllerWidget::saveRangeToProject()
726 QgsProject::instance()->
writeEntry( u
"TemporalControllerWidget"_s, u
"/StartDateTime"_s, mStartDateTime->dateTime().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODateWithMs ) );
727 QgsProject::instance()->
writeEntry( u
"TemporalControllerWidget"_s, u
"/EndDateTime"_s, mEndDateTime->dateTime().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODateWithMs ) );
TemporalNavigationMode
Temporal navigation modes.
@ Animated
Temporal navigation relies on frames within a datetime range.
@ Movie
Movie mode – behaves like a video player, with a fixed frame duration and no temporal range.
@ FixedRange
Temporal navigation relies on a fixed datetime range.
@ Disabled
Temporal navigation is disabled.
PlaybackOperation
Media playback operations.
@ PlayReverse
Play in reverse.
@ PlayForward
Play forward.
@ SkipToStart
Jump to start of playback.
@ PreviousFrame
Step to previous frame.
@ SkipToEnd
Jump to end of playback.
@ NextFrame
Step to next frame.
TemporalUnit
Temporal units.
@ IrregularStep
Special 'irregular step' time unit, used for temporal data which uses irregular, non-real-world unit ...
@ Milliseconds
Milliseconds.
@ Unknown
Unknown time unit.
AnimationState
Animation states.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A representation of the interval between two datetime values.
double originalDuration() const
Returns the original interval duration.
bool isValid() const
Returns true if the interval is valid.
double seconds() const
Returns the interval duration in seconds.
Qgis::TemporalUnit originalUnit() const
Returns the original interval temporal unit.
A model for display of map layers in widgets.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
@ Layer
Stores pointer to the map layer itself.
virtual QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
Base class for all map layer types.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
QgsDateTimeRange temporalRange() const
Returns the project's temporal range, which indicates the earliest and latest datetime ranges associa...
void setTotalMovieFrames(long long frames)
Sets the total number of frames for the movie.
void setFramesPerSecond(double rate)
Sets the project's default animation frame rate, in frames per second.
Qgis::TemporalUnit timeStepUnit() const
Returns the project's time step (length of one animation frame) unit, which is used as the default va...
void setTimeStepUnit(Qgis::TemporalUnit unit)
Sets the project's time step (length of one animation frame) unit, which is used as the default value...
void setIsTemporalRangeCumulative(bool state)
Sets the project's temporal range as cumulative in animation settings.
void setTimeStep(double step)
Sets the project's time step (length of one animation frame), which is used as the default value when...
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
Reads an integer from the specified scope and key.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void cleared()
Emitted when the project is cleared (and additionally when an open project is cleared just before a n...
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Reads a string from the specified scope and key.
bool writeEntry(const QString &scope, const QString &key, bool value)
Write a boolean value to the project file.
void readProject(const QDomDocument &document)
Emitted when a project is being read.
void layersAdded(const QList< QgsMapLayer * > &layers)
Emitted when one or more layers were added to the registry.
const QgsProjectTimeSettings * timeSettings() const
Returns the project's time settings, which contains the project's temporal range and other time based...
void updateTemporalRange(const QgsDateTimeRange &range)
Signals that a temporal range has changed and needs to be updated in all connected objects.
Implements a temporal controller based on a frame by frame navigation and animation.
void stateChanged(Qgis::AnimationState state)
Emitted whenever the animation state changes.
double framesPerSecond() const
Returns the animation frame rate, in frames per second.
void navigationModeChanged(Qgis::TemporalNavigationMode mode)
Emitted whenever the navigation mode changes.
void temporalFrameDurationChanged(const QgsInterval &interval)
Emitted whenever the frameDuration interval of the controller changes.
void setFramesPerSecond(double rate)
Sets the animation frame rate, in frames per second.
bool temporalRangeCumulative() const
Returns the animation temporal range cumulative settings.
void totalMovieFramesChanged(long long frames)
Emitted whenever the total number of frames in the movie is changed.
void temporalExtentsChanged(const QgsDateTimeRange &extent)
Emitted whenever the temporalExtent extent changes.
bool isActive() const
Returns true if the temporal property is active.
T begin() const
Returns the beginning of the range.
T end() const
Returns the upper bound of the range.
static QgsDateTimeRange calculateTemporalRangeForProject(QgsProject *project)
Calculates the temporal range for a project.
static QList< QgsDateTimeRange > usedTemporalRangesForProject(QgsProject *project)
Calculates all temporal ranges which are in use for a project.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.