From 2af0735a2f89f0f92788950b5a251efc172b7339 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 8 Aug 2021 20:37:10 +0200 Subject: [PATCH] Expand date condition functionality The date condition now supports the condition types "after", "before" and specifying a time range. --- data/locale/en-US.ini | 8 ++- src/headers/macro-condition-date.hpp | 15 +++++ src/macro-condition-date.cpp | 94 +++++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 4 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 7d19fb5f..fd845ee7 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -185,8 +185,12 @@ AdvSceneSwitcher.condition.replay.state.started="Replay buffer started" AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved" AdvSceneSwitcher.condition.replay.entry="{{state}}" AdvSceneSwitcher.condition.date="Date" -AdvSceneSwitcher.condition.date.entry.line1="{{dateTime}} {{ignoreDate}} Ignore date selection {{ignoreTime}} Ignore time selection" -AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}}" +AdvSceneSwitcher.condition.date.state.at="At" +AdvSceneSwitcher.condition.date.state.after="After" +AdvSceneSwitcher.condition.date.state.before="Before" +AdvSceneSwitcher.condition.date.state.between="Between" +AdvSceneSwitcher.condition.date.entry.line1="{{condition}} {{dateTime}} {{dateTime2}} {{ignoreDate}} Ignore date component {{ignoreTime}} Ignore time component" +AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Reschedule {{duration}} later when matching" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/macro-condition-date.hpp b/src/headers/macro-condition-date.hpp index d9bf5dc8..9fb6f56a 100644 --- a/src/headers/macro-condition-date.hpp +++ b/src/headers/macro-condition-date.hpp @@ -4,6 +4,14 @@ #include #include +#include + +enum class DateCondition { + AT, + AFTER, + BEFORE, + BETWEEN, +}; class MacroConditionDate : public MacroCondition { public: @@ -18,10 +26,12 @@ public: } QDateTime _dateTime; + QDateTime _dateTime2; bool _ignoreDate = false; bool _ignoreTime = false; bool _repeat = false; Duration _duration; + DateCondition _condition = DateCondition::AT; private: static bool _registered; @@ -45,7 +55,9 @@ public: } private slots: + void ConditionChanged(int cond); void DateTimeChanged(const QDateTime &datetime); + void DateTime2Changed(const QDateTime &datetime); void IgnoreDateChanged(int state); void IgnoreTimeChanged(int state); void RepeatChanged(int state); @@ -55,7 +67,9 @@ signals: void HeaderInfoChanged(const QString &); protected: + QComboBox *_condition; QDateTimeEdit *_dateTime; + QDateTimeEdit *_dateTime2; QCheckBox *_ignoreDate; QCheckBox *_ignoreTime; QCheckBox *_repeat; @@ -63,5 +77,6 @@ protected: std::shared_ptr _entryData; private: + void ShowSecondDateSelection(bool visible); bool _loading = true; }; diff --git a/src/macro-condition-date.cpp b/src/macro-condition-date.cpp index f18a23ea..220a0e1c 100644 --- a/src/macro-condition-date.cpp +++ b/src/macro-condition-date.cpp @@ -10,21 +10,52 @@ bool MacroConditionDate::_registered = MacroConditionFactory::Register( {MacroConditionDate::Create, MacroConditionDateEdit::Create, "AdvSceneSwitcher.condition.date", false}); +static std::map dateConditionTypes = { + {DateCondition::AT, "AdvSceneSwitcher.condition.date.state.at"}, + {DateCondition::AFTER, "AdvSceneSwitcher.condition.date.state.after"}, + {DateCondition::BEFORE, "AdvSceneSwitcher.condition.date.state.before"}, + {DateCondition::BETWEEN, + "AdvSceneSwitcher.condition.date.state.between"}, +}; + bool MacroConditionDate::CheckCondition() { bool match = false; QDateTime cur = QDateTime::currentDateTime(); if (_ignoreDate) { _dateTime.setDate(cur.date()); + _dateTime2.setDate(cur.date()); } if (_ignoreTime) { _dateTime.setTime(cur.time()); + _dateTime2.setTime(cur.time()); + } + + switch (_condition) { + case DateCondition::AT: + match = _dateTime >= cur && + _dateTime <= cur.addMSecs(switcher->interval); + break; + case DateCondition::AFTER: + match = cur >= _dateTime; + break; + case DateCondition::BEFORE: + match = cur <= _dateTime; + break; + case DateCondition::BETWEEN: + if (_dateTime2 > _dateTime) { + match = cur >= _dateTime && cur <= _dateTime2; + } else { + match = cur >= _dateTime2 && cur <= _dateTime; + } + break; + default: + break; } - match = _dateTime >= cur && - _dateTime <= cur.addMSecs(switcher->interval); if (match && _repeat) { _dateTime = _dateTime.addSecs(_duration.seconds); + _dateTime2 = _dateTime2.addSecs(_duration.seconds); } return match; @@ -33,8 +64,11 @@ bool MacroConditionDate::CheckCondition() bool MacroConditionDate::Save(obs_data_t *obj) { MacroCondition::Save(obj); + obs_data_set_int(obj, "condition", static_cast(_condition)); obs_data_set_string(obj, "dateTime", _dateTime.toString().toStdString().c_str()); + obs_data_set_string(obj, "dateTime2", + _dateTime2.toString().toStdString().c_str()); obs_data_set_bool(obj, "ignoreDate", _ignoreDate); obs_data_set_bool(obj, "ignoreTime", _ignoreTime); obs_data_set_bool(obj, "repeat", _repeat); @@ -46,8 +80,12 @@ bool MacroConditionDate::Save(obs_data_t *obj) bool MacroConditionDate::Load(obs_data_t *obj) { MacroCondition::Load(obj); + _condition = + static_cast(obs_data_get_int(obj, "condition")); _dateTime = QDateTime::fromString( QString::fromStdString(obs_data_get_string(obj, "dateTime"))); + _dateTime2 = QDateTime::fromString( + QString::fromStdString(obs_data_get_string(obj, "dateTime2"))); _ignoreDate = obs_data_get_bool(obj, "ignoreDate"); _ignoreTime = obs_data_get_bool(obj, "ignoreTime"); _repeat = obs_data_get_bool(obj, "repeat"); @@ -60,20 +98,35 @@ std::string MacroConditionDate::GetShortDesc() return _dateTime.toString().toStdString(); } +static inline void populateConditionSelection(QComboBox *list) +{ + for (auto entry : dateConditionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + MacroConditionDateEdit::MacroConditionDateEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { + _condition = new QComboBox(); _dateTime = new QDateTimeEdit(); _dateTime->setCalendarPopup(true); _dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss"); + _dateTime2 = new QDateTimeEdit(); + _dateTime2->setCalendarPopup(true); + _dateTime2->setDisplayFormat("yyyy.MM.dd hh:mm:ss"); _ignoreDate = new QCheckBox(); _ignoreTime = new QCheckBox(); _repeat = new QCheckBox(); _duration = new DurationSelection(); + QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this, + SLOT(ConditionChanged(int))); QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)), this, SLOT(DateTimeChanged(const QDateTime &))); + QWidget::connect(_dateTime2, SIGNAL(dateTimeChanged(const QDateTime &)), + this, SLOT(DateTime2Changed(const QDateTime &))); QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this, SLOT(IgnoreDateChanged(int))); QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this, @@ -85,9 +138,13 @@ MacroConditionDateEdit::MacroConditionDateEdit( QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this, SLOT(DurationUnitChanged(DurationUnit))); + populateConditionSelection(_condition); + auto line1Layout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { + {"{{condition}}", _condition}, {"{{dateTime}}", _dateTime}, + {"{{dateTime2}}", _dateTime2}, {"{{ignoreDate}}", _ignoreDate}, {"{{ignoreTime}}", _ignoreTime}, {"{{repeat}}", _repeat}, @@ -111,6 +168,18 @@ MacroConditionDateEdit::MacroConditionDateEdit( _loading = false; } +void MacroConditionDateEdit::ConditionChanged(int cond) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_condition = static_cast(cond); + ShowSecondDateSelection(_entryData->_condition == + DateCondition::BETWEEN); +} + void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime) { if (_loading || !_entryData) { @@ -124,6 +193,16 @@ void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime) QString::fromStdString(_entryData->GetShortDesc())); } +void MacroConditionDateEdit::DateTime2Changed(const QDateTime &datetime) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_dateTime2 = datetime; +} + void MacroConditionDateEdit::IgnoreDateChanged(int state) { if (_loading || !_entryData) { @@ -180,10 +259,21 @@ void MacroConditionDateEdit::UpdateEntryData() if (!_entryData) { return; } + + _condition->setCurrentIndex(static_cast(_entryData->_condition)); _dateTime->setDateTime(_entryData->_dateTime); + _dateTime2->setDateTime(_entryData->_dateTime2); _ignoreDate->setChecked(_entryData->_ignoreDate); _ignoreTime->setChecked(_entryData->_ignoreTime); _repeat->setChecked(_entryData->_repeat); _duration->SetDuration(_entryData->_duration); _duration->setDisabled(!_entryData->_repeat); + ShowSecondDateSelection(_entryData->_condition == + DateCondition::BETWEEN); +} + +void MacroConditionDateEdit::ShowSecondDateSelection(bool visible) +{ + _dateTime2->setVisible(visible); + adjustSize(); }