39 connect( mForwardButton, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::togglePlayForward );
40 connect( mBackButton, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::togglePlayBackward );
41 connect( mStopButton, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::togglePause );
46 connect( mLoopingCheckBox, &QCheckBox::toggled,
this, [ = ](
bool state ) { mNavigationObject->
setLooping( state ); } );
48 setWidgetStateFromNavigationMode( mNavigationObject->
navigationMode() );
50 connect( mNavigationOff, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationOff_clicked );
51 connect( mNavigationFixedRange, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationFixedRange_clicked );
52 connect( mNavigationAnimated, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::mNavigationAnimated_clicked );
61 connect( mStartDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::startEndDateTime_changed );
62 connect( mEndDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::startEndDateTime_changed );
63 connect( mFixedRangeStartDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed );
64 connect( mFixedRangeEndDateTime, &QDateTimeEdit::dateTimeChanged,
this, &QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed );
65 connect( mStepSpinBox, qgis::overload<double>::of( &QDoubleSpinBox::valueChanged ),
this, &QgsTemporalControllerWidget::updateFrameDuration );
66 connect( mTimeStepsComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ),
this, &QgsTemporalControllerWidget::updateFrameDuration );
67 connect( mSlider, &QSlider::valueChanged,
this, &QgsTemporalControllerWidget::timeSlider_valueChanged );
69 mStepSpinBox->setClearValue( 1 );
73 connect( mSettings, &QPushButton::clicked,
this, &QgsTemporalControllerWidget::settings_clicked );
77 mRangeMenu.reset(
new QMenu(
this ) );
79 mRangeSetToAllLayersAction =
new QAction( tr(
"Set to Full Range" ), mRangeMenu.get() );
81 connect( mRangeSetToAllLayersAction, &QAction::triggered,
this, &QgsTemporalControllerWidget::mRangeSetToAllLayersAction_triggered );
82 mRangeMenu->addAction( mRangeSetToAllLayersAction );
84 mRangeSetToProjectAction =
new QAction( tr(
"Set to Preset Project Range" ), mRangeMenu.get() );
85 connect( mRangeSetToProjectAction, &QAction::triggered,
this, &QgsTemporalControllerWidget::mRangeSetToProjectAction_triggered );
86 mRangeMenu->addAction( mRangeSetToProjectAction );
88 mRangeMenu->addSeparator();
90 mRangeLayersSubMenu.reset(
new QMenu( tr(
"Set to Single Layer's Range" ), mRangeMenu.get() ) );
91 mRangeLayersSubMenu->setEnabled(
false );
92 mRangeMenu->addMenu( mRangeLayersSubMenu.get() );
93 connect( mRangeMenu.get(), &QMenu::aboutToShow,
this, &QgsTemporalControllerWidget::aboutToShowRangeMenu );
95 mSetRangeButton->setPopupMode( QToolButton::MenuButtonPopup );
96 mSetRangeButton->setMenu( mRangeMenu.get() );
97 mSetRangeButton->setDefaultAction( mRangeSetToAllLayersAction );
98 mFixedRangeSetRangeButton->setPopupMode( QToolButton::MenuButtonPopup );
99 mFixedRangeSetRangeButton->setMenu( mRangeMenu.get() );
100 mFixedRangeSetRangeButton->setDefaultAction( mRangeSetToAllLayersAction );
104 QgsDateTimeRange range;
109 mStartDateTime->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
110 mEndDateTime->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
111 mFixedRangeStartDateTime->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
112 mFixedRangeEndDateTime->setDisplayFormat(
"yyyy-MM-dd HH:mm:ss" );
114 if ( range.begin().isValid() && range.end().isValid() )
116 whileBlocking( mStartDateTime )->setDateTime( range.begin() );
118 whileBlocking( mFixedRangeStartDateTime )->setDateTime( range.begin() );
119 whileBlocking( mFixedRangeEndDateTime )->setDateTime( range.end() );
142 mStepSpinBox->setMinimum( 0.0000001 );
143 mStepSpinBox->setMaximum( std::numeric_limits<int>::max() );
144 mStepSpinBox->setSingleStep( 1 );
145 mStepSpinBox->setValue( 1 );
147 mForwardButton->setToolTip( tr(
"Play" ) );
148 mBackButton->setToolTip( tr(
"Reverse" ) );
149 mNextButton->setToolTip( tr(
"Go to next frame" ) );
150 mPreviousButton->setToolTip( tr(
"Go to previous frame" ) );
151 mStopButton->setToolTip( tr(
"Pause" ) );
152 mRewindButton->setToolTip( tr(
"Rewind to start" ) );
153 mFastForwardButton->setToolTip( tr(
"Fast forward to end" ) );
155 updateFrameDuration();
164 if ( mSlider->hasFocus() && e->key() == Qt::Key_Space )
168 QWidget::keyPressEvent( e );
171 void QgsTemporalControllerWidget::aboutToShowRangeMenu()
173 QgsDateTimeRange projectRange;
176 mRangeSetToProjectAction->setEnabled( projectRange.begin().isValid() && projectRange.end().isValid() );
178 mRangeLayersSubMenu->clear();
179 for (
int i = 0; i < mMapLayerModel->
rowCount(); ++i )
181 QModelIndex index = mMapLayerModel->
index( i, 0 );
186 QIcon icon = qvariant_cast<QIcon>( mMapLayerModel->
data( index, Qt::DecorationRole ) );
187 QString text = mMapLayerModel->
data( index, Qt::DisplayRole ).toString();
189 if ( range.begin().isValid() && range.end().isValid() )
191 QAction *action =
new QAction( icon, text, mRangeLayersSubMenu.get() );
192 connect( action, &QAction::triggered,
this, [ = ]
195 saveRangeToProject();
197 mRangeLayersSubMenu->addAction( action );
200 mRangeLayersSubMenu->setEnabled( !mRangeLayersSubMenu->actions().isEmpty() );
203 void QgsTemporalControllerWidget::togglePlayForward()
205 mPlayingForward =
true;
209 mStopButton->setChecked(
false );
210 mBackButton->setChecked(
false );
211 mForwardButton->setChecked(
true );
216 mBackButton->setChecked(
true );
217 mForwardButton->setChecked(
false );
218 mNavigationObject->
pause();
222 void QgsTemporalControllerWidget::togglePlayBackward()
224 mPlayingForward =
false;
228 mStopButton->setChecked(
false );
229 mBackButton->setChecked(
true );
230 mForwardButton->setChecked(
false );
235 mBackButton->setChecked(
true );
236 mBackButton->setChecked(
false );
237 mNavigationObject->
pause();
241 void QgsTemporalControllerWidget::togglePause()
245 mStopButton->setChecked(
true );
246 mBackButton->setChecked(
false );
247 mForwardButton->setChecked(
false );
248 mNavigationObject->
pause();
252 mBackButton->setChecked( mPlayingForward ?
false :
true );
253 mForwardButton->setChecked( mPlayingForward ?
false :
true );
254 if ( mPlayingForward )
265 void QgsTemporalControllerWidget::updateTemporalExtent()
267 QgsDateTimeRange temporalExtent = QgsDateTimeRange( mStartDateTime->dateTime(),
268 mEndDateTime->dateTime() );
271 mSlider->setValue( 0 );
274 void QgsTemporalControllerWidget::updateFrameDuration()
276 if ( mBlockSettingUpdates )
288 void QgsTemporalControllerWidget::setWidgetStateFromProject()
290 mBlockSettingUpdates++;
293 mBlockSettingUpdates--;
297 QStringLiteral(
"/NavigationMode" ), 0, &ok ) );
301 setWidgetStateFromNavigationMode( mode );
309 const QString startString =
QgsProject::instance()->
readEntry( QStringLiteral(
"TemporalControllerWidget" ), QStringLiteral(
"/StartDateTime" ) );
310 const QString endString =
QgsProject::instance()->
readEntry( QStringLiteral(
"TemporalControllerWidget" ), QStringLiteral(
"/EndDateTime" ) );
311 if ( !startString.isEmpty() && !endString.isEmpty() )
313 whileBlocking( mStartDateTime )->setDateTime( QDateTime::fromString( startString, Qt::ISODate ) );
314 whileBlocking( mEndDateTime )->setDateTime( QDateTime::fromString( endString, Qt::ISODate ) );
315 whileBlocking( mFixedRangeStartDateTime )->setDateTime( QDateTime::fromString( startString, Qt::ISODate ) );
316 whileBlocking( mFixedRangeEndDateTime )->setDateTime( QDateTime::fromString( endString, Qt::ISODate ) );
320 setDatesToProjectTime();
322 updateTemporalExtent();
323 updateFrameDuration();
329 void QgsTemporalControllerWidget::mNavigationOff_clicked()
338 void QgsTemporalControllerWidget::mNavigationFixedRange_clicked()
347 void QgsTemporalControllerWidget::mNavigationAnimated_clicked()
365 mNavigationModeStackedWidget->setCurrentIndex( 0 );
368 mNavigationModeStackedWidget->setCurrentIndex( 1 );
371 mNavigationModeStackedWidget->setCurrentIndex( 2 );
376 void QgsTemporalControllerWidget::onLayersAdded(
const QList<QgsMapLayer *> &layers )
378 if ( !mHasTemporalLayersLoaded )
382 if ( layer->temporalProperties() )
384 mHasTemporalLayersLoaded |= layer->temporalProperties()->isActive();
386 if ( !mHasTemporalLayersLoaded )
390 if ( layer->isValid() && layer->temporalProperties()->isActive() && !mHasTemporalLayersLoaded )
392 mHasTemporalLayersLoaded = true;
393 firstTemporalLayerLoaded( layer );
398 firstTemporalLayerLoaded( layer );
404 void QgsTemporalControllerWidget::firstTemporalLayerLoaded(
QgsMapLayer *layer )
406 setDatesToProjectTime();
408 QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( layer );
413 void QgsTemporalControllerWidget::onProjectCleared()
415 mHasTemporalLayersLoaded =
false;
420 whileBlocking( mStartDateTime )->setDateTime( QDateTime( QDate::currentDate(), QTime( 0, 0, 0, Qt::UTC ) ) );
421 whileBlocking( mEndDateTime )->setDateTime( mStartDateTime->dateTime() );
422 whileBlocking( mFixedRangeStartDateTime )->setDateTime( QDateTime( QDate::currentDate(), QTime( 0, 0, 0, Qt::UTC ) ) );
423 whileBlocking( mFixedRangeEndDateTime )->setDateTime( mStartDateTime->dateTime() );
424 updateTemporalExtent();
426 mStepSpinBox->setValue( 1 );
429 void QgsTemporalControllerWidget::updateSlider(
const QgsDateTimeRange &range )
432 updateRangeLabel( range );
435 void QgsTemporalControllerWidget::updateRangeLabel(
const QgsDateTimeRange &range )
440 mCurrentRangeLabel->setText( tr(
"Frame: %1 to %2" ).arg(
441 range.begin().toString(
"yyyy-MM-dd HH:mm:ss" ),
442 range.end().toString(
"yyyy-MM-dd HH:mm:ss" ) ) );
445 mCurrentRangeLabel->setText( tr(
"Range: %1 to %2" ).arg(
446 range.begin().toString(
"yyyy-MM-dd HH:mm:ss" ),
447 range.end().toString(
"yyyy-MM-dd HH:mm:ss" ) ) );
450 mCurrentRangeLabel->setText( tr(
"Temporal navigation disabled" ) );
457 return mNavigationObject;
460 void QgsTemporalControllerWidget::settings_clicked()
462 QgsTemporalMapSettingsWidget *settingsWidget =
new QgsTemporalMapSettingsWidget(
this );
463 settingsWidget->setFrameRateValue( mNavigationObject->
framesPerSecond() );
466 connect( settingsWidget, &QgsTemporalMapSettingsWidget::frameRateChanged,
this, [ = ](
double rate )
473 connect( settingsWidget, &QgsTemporalMapSettingsWidget::temporalRangeCumulativeChanged,
this, [ = ](
bool state )
482 void QgsTemporalControllerWidget::timeSlider_valueChanged(
int value )
487 void QgsTemporalControllerWidget::startEndDateTime_changed()
489 whileBlocking( mFixedRangeStartDateTime )->setDateTime( mStartDateTime->dateTime() );
490 whileBlocking( mFixedRangeEndDateTime )->setDateTime( mEndDateTime->dateTime() );
492 updateTemporalExtent();
493 saveRangeToProject();
496 void QgsTemporalControllerWidget::fixedRangeStartEndDateTime_changed()
498 whileBlocking( mStartDateTime )->setDateTime( mFixedRangeStartDateTime->dateTime() );
499 whileBlocking( mEndDateTime )->setDateTime( mFixedRangeEndDateTime->dateTime() );
501 updateTemporalExtent();
502 saveRangeToProject();
505 void QgsTemporalControllerWidget::mRangeSetToAllLayersAction_triggered()
507 setDatesToAllLayers();
508 saveRangeToProject();
511 void QgsTemporalControllerWidget::setTimeStep(
const QgsInterval &timeStep )
519 int selectedUnit = -1;
520 int stringSize = std::numeric_limits<int>::max();
521 int precision = mStepSpinBox->decimals();
522 double selectedValue = std::numeric_limits<double>::max();
523 for (
int i = 0; i < mTimeStepsComboBox->count(); ++i )
527 QString
string = QString::number( value,
'f',
precision );
528 string.remove( QRegExp(
"0+$" ) );
529 string.remove( QRegExp(
"[.]+$" ) );
532 &&
string.size() <= stringSize
533 && value < selectedValue )
536 selectedValue = value;
537 stringSize =
string.size();
539 else if (
string !=
'0'
541 &&
string.size() < stringSize )
544 selectedValue = value ;
545 stringSize =
string.size();
549 if ( selectedUnit >= 0 )
551 mStepSpinBox->setValue( selectedValue );
552 mTimeStepsComboBox->setCurrentIndex( selectedUnit );
555 updateFrameDuration();
558 void QgsTemporalControllerWidget::mRangeSetToProjectAction_triggered()
560 setDatesToProjectTime();
561 saveRangeToProject();
564 void QgsTemporalControllerWidget::setDates(
const QgsDateTimeRange &range )
566 if ( range.begin().isValid() && range.end().isValid() )
568 whileBlocking( mStartDateTime )->setDateTime( range.begin() );
570 whileBlocking( mFixedRangeStartDateTime )->setDateTime( range.begin() );
571 whileBlocking( mFixedRangeEndDateTime )->setDateTime( range.end() );
572 updateTemporalExtent();
576 void QgsTemporalControllerWidget::setDatesToAllLayers()
578 QgsDateTimeRange range;
583 void QgsTemporalControllerWidget::setDatesToProjectTime()
585 QgsDateTimeRange range;
592 if ( !range.begin().isValid() || !range.end().isValid() )
600 void QgsTemporalControllerWidget::saveRangeToProject()
603 QStringLiteral(
"/StartDateTime" ), mStartDateTime->dateTime().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
605 QStringLiteral(
"/EndDateTime" ), mEndDateTime->dateTime().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );