diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f7f6668..12168af8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ set(advanced-scene-switcher_HEADERS src/headers/macro-action-wait.hpp src/headers/macro-condition-edit.hpp src/headers/macro-condition-audio.hpp + src/headers/macro-condition-date.hpp src/headers/macro-condition-macro.hpp src/headers/macro-condition-file.hpp src/headers/macro-condition-filter.hpp @@ -179,6 +180,7 @@ set(advanced-scene-switcher_SOURCES src/macro-action-wait.cpp src/macro-condition-edit.cpp src/macro-condition-audio.cpp + src/macro-condition-date.cpp src/macro-condition-macro.cpp src/macro-condition-file.cpp src/macro-condition-filter.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index c59ff0a1..1d2645f4 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -177,6 +177,9 @@ AdvSceneSwitcher.condition.replay.state.stopped="Replay buffer stopped" 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}}" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/headers/macro-condition-date.hpp b/src/headers/macro-condition-date.hpp new file mode 100644 index 00000000..dfb919f4 --- /dev/null +++ b/src/headers/macro-condition-date.hpp @@ -0,0 +1,67 @@ +#pragma once +#include "macro.hpp" +#include +#include +#include +#include "duration-control.hpp" + +class MacroConditionDate : public MacroCondition { +public: + bool CheckCondition(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + std::string GetShortDesc(); + std::string GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + + QDateTime _dateTime; + bool _ignoreDate = false; + bool _ignoreTime = false; + bool _repeat = false; + Duration _duration; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroConditionDateEdit : public QWidget { + Q_OBJECT + +public: + MacroConditionDateEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionDateEdit( + parent, + std::dynamic_pointer_cast(cond)); + } + +private slots: + void DateTimeChanged(const QDateTime &datetime); + void IgnoreDateChanged(int state); + void IgnoreTimeChanged(int state); + void RepeatChanged(int state); + void DurationChanged(double seconds); + void DurationUnitChanged(DurationUnit unit); +signals: + void HeaderInfoChanged(const QString &); + +protected: + QDateTimeEdit *_dateTime; + QCheckBox *_ignoreDate; + QCheckBox *_ignoreTime; + QCheckBox *_repeat; + DurationSelection *_duration; + std::shared_ptr _entryData; + +private: + bool _loading = true; +}; diff --git a/src/macro-condition-date.cpp b/src/macro-condition-date.cpp new file mode 100644 index 00000000..f18a23ea --- /dev/null +++ b/src/macro-condition-date.cpp @@ -0,0 +1,189 @@ +#include "headers/macro-condition-edit.hpp" +#include "headers/macro-condition-date.hpp" +#include "headers/utility.hpp" +#include "headers/advanced-scene-switcher.hpp" + +const std::string MacroConditionDate::id = "date"; + +bool MacroConditionDate::_registered = MacroConditionFactory::Register( + MacroConditionDate::id, + {MacroConditionDate::Create, MacroConditionDateEdit::Create, + "AdvSceneSwitcher.condition.date", false}); + +bool MacroConditionDate::CheckCondition() +{ + bool match = false; + QDateTime cur = QDateTime::currentDateTime(); + if (_ignoreDate) { + _dateTime.setDate(cur.date()); + } + if (_ignoreTime) { + _dateTime.setTime(cur.time()); + } + + match = _dateTime >= cur && + _dateTime <= cur.addMSecs(switcher->interval); + if (match && _repeat) { + _dateTime = _dateTime.addSecs(_duration.seconds); + } + + return match; +} + +bool MacroConditionDate::Save(obs_data_t *obj) +{ + MacroCondition::Save(obj); + obs_data_set_string(obj, "dateTime", + _dateTime.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); + _duration.Save(obj); + + return true; +} + +bool MacroConditionDate::Load(obs_data_t *obj) +{ + MacroCondition::Load(obj); + _dateTime = QDateTime::fromString( + QString::fromStdString(obs_data_get_string(obj, "dateTime"))); + _ignoreDate = obs_data_get_bool(obj, "ignoreDate"); + _ignoreTime = obs_data_get_bool(obj, "ignoreTime"); + _repeat = obs_data_get_bool(obj, "repeat"); + _duration.Load(obj); + return true; +} + +std::string MacroConditionDate::GetShortDesc() +{ + return _dateTime.toString().toStdString(); +} + +MacroConditionDateEdit::MacroConditionDateEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _dateTime = new QDateTimeEdit(); + _dateTime->setCalendarPopup(true); + _dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss"); + _ignoreDate = new QCheckBox(); + _ignoreTime = new QCheckBox(); + _repeat = new QCheckBox(); + _duration = new DurationSelection(); + + QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)), + this, SLOT(DateTimeChanged(const QDateTime &))); + QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this, + SLOT(IgnoreDateChanged(int))); + QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this, + SLOT(IgnoreTimeChanged(int))); + QWidget::connect(_repeat, SIGNAL(stateChanged(int)), this, + SLOT(RepeatChanged(int))); + QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this, + SLOT(DurationChanged(double))); + QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this, + SLOT(DurationUnitChanged(DurationUnit))); + + auto line1Layout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{dateTime}}", _dateTime}, + {"{{ignoreDate}}", _ignoreDate}, + {"{{ignoreTime}}", _ignoreTime}, + {"{{repeat}}", _repeat}, + {"{{duration}}", _duration}, + }; + placeWidgets( + obs_module_text("AdvSceneSwitcher.condition.date.entry.line1"), + line1Layout, widgetPlaceholders); + auto line2Layout = new QHBoxLayout; + placeWidgets( + obs_module_text("AdvSceneSwitcher.condition.date.entry.line2"), + line2Layout, widgetPlaceholders); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addLayout(line1Layout); + mainLayout->addLayout(line2Layout); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_dateTime = datetime; + + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); +} + +void MacroConditionDateEdit::IgnoreDateChanged(int state) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_ignoreDate = state; +} + +void MacroConditionDateEdit::IgnoreTimeChanged(int state) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_ignoreTime = state; +} + +void MacroConditionDateEdit::RepeatChanged(int state) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_repeat = state; + _duration->setDisabled(!state); +} + +void MacroConditionDateEdit::DurationChanged(double seconds) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_duration.seconds = seconds; +} + +void MacroConditionDateEdit::DurationUnitChanged(DurationUnit unit) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_duration.displayUnit = unit; +} + +void MacroConditionDateEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + _dateTime->setDateTime(_entryData->_dateTime); + _ignoreDate->setChecked(_entryData->_ignoreDate); + _ignoreTime->setChecked(_entryData->_ignoreTime); + _repeat->setChecked(_entryData->_repeat); + _duration->SetDuration(_entryData->_duration); + _duration->setDisabled(!_entryData->_repeat); +}