diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index dc15f51d..6437331f 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -2754,32 +2754,10 @@ AdvSceneSwitcher.macroScheduleEntry.endDate.action.none="No action" AdvSceneSwitcher.macroScheduleEntry.endDate.action.disableEntry="Disable schedule entry" AdvSceneSwitcher.macroScheduleEntry.endDate.action.pauseMacro="Pause macro" AdvSceneSwitcher.macroScheduleEntry.endDate.action.stopMacro="Stop macro" -AdvSceneSwitcher.macroScheduleEntry.repeat="Repeat:" -AdvSceneSwitcher.macroScheduleEntry.repeat.none="None" -AdvSceneSwitcher.macroScheduleEntry.repeat.minutely="Every N minutes" -AdvSceneSwitcher.macroScheduleEntry.repeat.hourly="Hourly" -AdvSceneSwitcher.macroScheduleEntry.repeat.daily="Daily" -AdvSceneSwitcher.macroScheduleEntry.repeat.weekly="Weekly" -AdvSceneSwitcher.macroScheduleEntry.repeat.monthly="Monthly" +AdvSceneSwitcher.macroScheduleEntry.repeat="Repeat" AdvSceneSwitcher.macroScheduleEntry.repeat.once="Once" -AdvSceneSwitcher.macroScheduleEntry.repeat.everyOne="Every %1" -AdvSceneSwitcher.macroScheduleEntry.repeat.everyN="Every %1 %2" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.minute="minute" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.minutes="minutes" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.hour="hour" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.hours="hours" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.day="day" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.days="days" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.week="week" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.weeks="weeks" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.month="month" -AdvSceneSwitcher.macroScheduleEntry.repeat.unit.months="months" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.prefix="Every" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.minute="minute(s)" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.hour="hour(s)" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.day="day(s)" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.week="week(s)" -AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.month="month(s)" +AdvSceneSwitcher.macroScheduleEntry.repeat.every="Every %1" +AdvSceneSwitcher.macroScheduleEntry.repeat.interval="Repeat interval:" AdvSceneSwitcher.macroScheduleEntry.noMacro="(no macro)" AdvSceneSwitcher.macroScheduleEntry.repeatEnd="End repeat:" AdvSceneSwitcher.macroScheduleEntry.repeatEnd.never="Never" diff --git a/plugins/schedule/macro-schedule-entry-dialog.cpp b/plugins/schedule/macro-schedule-entry-dialog.cpp index ec4de87d..63a419e0 100644 --- a/plugins/schedule/macro-schedule-entry-dialog.cpp +++ b/plugins/schedule/macro-schedule-entry-dialog.cpp @@ -35,10 +35,10 @@ MacroScheduleEntryDialog::MacroScheduleEntryDialog( this)), _endDate(new QDateTimeEdit(this)), _endDateAction(new QComboBox(this)), - _repeatType(new QComboBox(this)), - _intervalRow(new QWidget(this)), - _repeatInterval(new QSpinBox(_intervalRow)), - _intervalUnitLabel(new QLabel("", _intervalRow)), + _doesRepeat(new QCheckBox( + obs_module_text("AdvSceneSwitcher.macroScheduleEntry.repeat"), + this)), + _repeatInterval(new DurationSelection(this, true, 0.1)), _repeatEndGroup(new QGroupBox( obs_module_text( "AdvSceneSwitcher.macroScheduleEntry.repeatEnd"), @@ -153,50 +153,27 @@ MacroScheduleEntryDialog::MacroScheduleEntryDialog( } }); - // --- Repeat type --- - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.none"), - static_cast(MacroScheduleEntry::RepeatType::NONE)); - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.minutely"), - static_cast(MacroScheduleEntry::RepeatType::MINUTELY)); - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.hourly"), - static_cast(MacroScheduleEntry::RepeatType::HOURLY)); - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.daily"), - static_cast(MacroScheduleEntry::RepeatType::DAILY)); - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.weekly"), - static_cast(MacroScheduleEntry::RepeatType::WEEKLY)); - _repeatType->addItem( - obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.monthly"), - static_cast(MacroScheduleEntry::RepeatType::MONTHLY)); - form->addRow( - obs_module_text("AdvSceneSwitcher.macroScheduleEntry.repeat"), - _repeatType); + // --- Repeat --- + form->addRow(QString(), _doesRepeat); - // --- Repeat interval row (hidden when NONE) --- - auto intervalLayout = new QHBoxLayout(_intervalRow); - intervalLayout->setContentsMargins(0, 0, 0, 0); - auto everyLabel = new QLabel( + _repeatInterval->setVisible(false); + form->addRow( obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.prefix"), - _intervalRow); - _repeatInterval->setMinimum(1); - _repeatInterval->setMaximum(999); - _repeatInterval->setValue(1); - intervalLayout->addWidget(everyLabel); - intervalLayout->addWidget(_repeatInterval); - intervalLayout->addWidget(_intervalUnitLabel); - intervalLayout->addStretch(); - form->addRow(QString(), _intervalRow); + "AdvSceneSwitcher.macroScheduleEntry.repeat.interval"), + _repeatInterval); + if (auto *label = form->labelForField(_repeatInterval)) { + label->setVisible(false); + } + + connect(_doesRepeat, &QCheckBox::toggled, this, + [form, this](bool checked) { + _repeatInterval->setVisible(checked); + if (auto *label = + form->labelForField(_repeatInterval)) { + label->setVisible(checked); + } + _repeatEndGroup->setVisible(checked); + }); // --- Repeat end group (hidden when NONE) --- @@ -229,6 +206,7 @@ MacroScheduleEntryDialog::MacroScheduleEntryDialog( untilRow->addStretch(); repeatEndLayout->addLayout(untilRow); + _repeatEndGroup->setVisible(false); form->addRow(_repeatEndGroup); // Enable/disable child widgets based on radio selection @@ -277,13 +255,7 @@ MacroScheduleEntryDialog::MacroScheduleEntryDialog( mainLayout->addWidget(buttons); setLayout(mainLayout); - // Connect repeat type change - connect(_repeatType, - QOverload::of(&QComboBox::currentIndexChanged), this, - [this](int) { UpdateRepeatVisibility(); }); - PopulateFromEntry(entry); - UpdateRepeatVisibility(); } void MacroScheduleEntryDialog::PopulateFromEntry(const MacroScheduleEntry &entry) @@ -309,12 +281,9 @@ void MacroScheduleEntryDialog::PopulateFromEntry(const MacroScheduleEntry &entry } } - const int repeatIdx = - _repeatType->findData(static_cast(entry.repeatType)); - if (repeatIdx >= 0) { - _repeatType->setCurrentIndex(repeatIdx); - } - _repeatInterval->setValue(entry.repeatInterval); + _doesRepeat->setChecked(entry.doesRepeat); + _repeatInterval->SetDuration(entry.repeatInterval); + _doesRepeat->toggled(entry.doesRepeat); switch (entry.repeatEndType) { case MacroScheduleEntry::RepeatEndType::NEVER: @@ -367,10 +336,8 @@ void MacroScheduleEntryDialog::ApplyToEntry(MacroScheduleEntry &entry) const } entry.endDateActionApplied = false; - const int repeatData = _repeatType->currentData().toInt(); - entry.repeatType = - static_cast(repeatData); - entry.repeatInterval = _repeatInterval->value(); + entry.doesRepeat = _doesRepeat->isChecked(); + entry.repeatInterval = _repeatInterval->GetDuration(); if (_endNever->isChecked()) { entry.repeatEndType = MacroScheduleEntry::RepeatEndType::NEVER; @@ -394,43 +361,6 @@ void MacroScheduleEntryDialog::ApplyToEntry(MacroScheduleEntry &entry) const entry.enabled = _enabled->isChecked(); } -static QString repeatTypeUnitLabel(MacroScheduleEntry::RepeatType type) -{ - switch (type) { - case MacroScheduleEntry::RepeatType::MINUTELY: - return obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.minute"); - case MacroScheduleEntry::RepeatType::HOURLY: - return obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.hour"); - case MacroScheduleEntry::RepeatType::DAILY: - return obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.day"); - case MacroScheduleEntry::RepeatType::WEEKLY: - return obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.week"); - case MacroScheduleEntry::RepeatType::MONTHLY: - return obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.interval.unit.month"); - default: - return ""; - } -} - -void MacroScheduleEntryDialog::UpdateRepeatVisibility() -{ - const int data = _repeatType->currentData().toInt(); - const auto type = static_cast(data); - const bool repeating = (type != MacroScheduleEntry::RepeatType::NONE); - - _intervalRow->setVisible(repeating); - _repeatEndGroup->setVisible(repeating); - - if (repeating) { - _intervalUnitLabel->setText(repeatTypeUnitLabel(type)); - } -} - void MacroScheduleEntryDialog::UpdateColorButton() { // Fill the button with the chosen color so it acts as a swatch diff --git a/plugins/schedule/macro-schedule-entry-dialog.hpp b/plugins/schedule/macro-schedule-entry-dialog.hpp index afbf61a6..85187d0b 100644 --- a/plugins/schedule/macro-schedule-entry-dialog.hpp +++ b/plugins/schedule/macro-schedule-entry-dialog.hpp @@ -1,5 +1,6 @@ #pragma once +#include "duration-control.hpp" #include "macro-schedule.hpp" #include "macro-selection.hpp" @@ -33,7 +34,6 @@ private: void PopulateFromEntry(const MacroScheduleEntry &entry); void ApplyToEntry(MacroScheduleEntry &entry) const; - void UpdateRepeatVisibility(); // Basic fields QLineEdit *_name; @@ -45,13 +45,9 @@ private: QDateTimeEdit *_endDate; QComboBox *_endDateAction; - // Repeat type - QComboBox *_repeatType; - - // Repeat interval (hidden when type == NONE) - QWidget *_intervalRow; - QSpinBox *_repeatInterval; - QLabel *_intervalUnitLabel; + // Repeat + QCheckBox *_doesRepeat; + DurationSelection *_repeatInterval; // Repeat end (hidden when type == NONE) QGroupBox *_repeatEndGroup; diff --git a/plugins/schedule/macro-schedule-tab.cpp b/plugins/schedule/macro-schedule-tab.cpp index 9aedefe0..b11e8b2f 100644 --- a/plugins/schedule/macro-schedule-tab.cpp +++ b/plugins/schedule/macro-schedule-tab.cpp @@ -120,7 +120,7 @@ EntryToCalendarEvents(const MacroScheduleEntry &entry, const QDate &rangeStart, result.append(ev); } - if (entry.repeatType == MacroScheduleEntry::RepeatType::NONE) { + if (!entry.doesRepeat) { break; // one-shot — no more occurrences } diff --git a/plugins/schedule/macro-schedule.cpp b/plugins/schedule/macro-schedule.cpp index 9ada0979..ac9fd014 100644 --- a/plugins/schedule/macro-schedule.cpp +++ b/plugins/schedule/macro-schedule.cpp @@ -149,8 +149,8 @@ void MacroScheduleEntry::Save(obs_data_t *obj) const static_cast(endDateAction)); } - obs_data_set_int(obj, "repeatType", static_cast(repeatType)); - obs_data_set_int(obj, "repeatInterval", repeatInterval); + obs_data_set_bool(obj, "doesRepeat", doesRepeat); + repeatInterval.Save(obj, "repeatInterval"); obs_data_set_int(obj, "repeatEndType", static_cast(repeatEndType)); obs_data_set_int(obj, "repeatMaxCount", repeatMaxCount); if (repeatEndType == RepeatEndType::UNTIL_DATE && @@ -195,10 +195,8 @@ void MacroScheduleEntry::Load(obs_data_t *obj) obs_data_get_int(obj, "endDateAction")); } - repeatType = - static_cast(obs_data_get_int(obj, "repeatType")); - obs_data_set_default_int(obj, "repeatInterval", 1); - repeatInterval = (int)obs_data_get_int(obj, "repeatInterval"); + doesRepeat = obs_data_get_bool(obj, "doesRepeat"); + repeatInterval.Load(obj, "repeatInterval"); repeatEndType = static_cast( obs_data_get_int(obj, "repeatEndType")); obs_data_set_default_int(obj, "repeatMaxCount", 1); @@ -212,20 +210,11 @@ void MacroScheduleEntry::Load(obs_data_t *obj) QDateTime MacroScheduleEntry::advanceFrom(const QDateTime &base) const { - switch (repeatType) { - case RepeatType::MINUTELY: - return base.addSecs((qint64)repeatInterval * 60); - case RepeatType::HOURLY: - return base.addSecs((qint64)repeatInterval * 3600); - case RepeatType::DAILY: - return base.addDays(repeatInterval); - case RepeatType::WEEKLY: - return base.addDays((qint64)repeatInterval * 7); - case RepeatType::MONTHLY: - return base.addMonths(repeatInterval); - default: + const qint64 ms = qRound64(repeatInterval.Seconds() * 1000.0); + if (ms <= 0) { return QDateTime(); } + return base.addMSecs(ms); } QDateTime MacroScheduleEntry::NextTriggerTime() const @@ -233,7 +222,7 @@ QDateTime MacroScheduleEntry::NextTriggerTime() const if (!lastTriggered.isValid()) { return startDateTime; } - if (repeatType == RepeatType::NONE) { + if (!doesRepeat) { // If the start was moved beyond the last trigger, treat as not yet fired. if (startDateTime > lastTriggered) { return startDateTime; @@ -254,7 +243,7 @@ QDateTime MacroScheduleEntry::NextTriggerTime() const bool MacroScheduleEntry::IsExpired() const { - if (repeatType == RepeatType::NONE && lastTriggered.isValid()) { + if (!doesRepeat && lastTriggered.isValid()) { return lastTriggered >= startDateTime; } switch (repeatEndType) { @@ -302,7 +291,7 @@ void MacroScheduleEntry::FastForwardTo(const QDateTime &now) return; } - if (repeatType == RepeatType::NONE) { + if (!doesRepeat) { // One-shot: count it as triggered if the start lies in the past. if (startDateTime <= now) { timesTriggered = 1; @@ -327,55 +316,13 @@ void MacroScheduleEntry::FastForwardTo(const QDateTime &now) QString MacroScheduleEntry::GetRepeatDescription() const { - if (repeatType == RepeatType::NONE) { + if (!doesRepeat) { return obs_module_text( "AdvSceneSwitcher.macroScheduleEntry.repeat.once"); } - const char *unitSingular = ""; - const char *unitPlural = ""; - switch (repeatType) { - case RepeatType::MINUTELY: - unitSingular = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.minute"); - unitPlural = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.minutes"); - break; - case RepeatType::HOURLY: - unitSingular = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.hour"); - unitPlural = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.hours"); - break; - case RepeatType::DAILY: - unitSingular = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.day"); - unitPlural = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.days"); - break; - case RepeatType::WEEKLY: - unitSingular = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.week"); - unitPlural = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.weeks"); - break; - case RepeatType::MONTHLY: - unitSingular = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.month"); - unitPlural = obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.unit.months"); - break; - default: - break; - } - if (repeatInterval == 1) { - return QString(obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.everyOne")) - .arg(unitSingular); - } return QString(obs_module_text( - "AdvSceneSwitcher.macroScheduleEntry.repeat.everyN")) - .arg(repeatInterval) - .arg(unitPlural); + "AdvSceneSwitcher.macroScheduleEntry.repeat.every")) + .arg(QString::fromStdString(repeatInterval.ToString())); } QString MacroScheduleEntry::GetSummary() const diff --git a/plugins/schedule/macro-schedule.hpp b/plugins/schedule/macro-schedule.hpp index 22a97b3e..e80d3f01 100644 --- a/plugins/schedule/macro-schedule.hpp +++ b/plugins/schedule/macro-schedule.hpp @@ -1,4 +1,5 @@ #pragma once +#include "duration.hpp" #include "macro-ref.hpp" #include @@ -10,15 +11,6 @@ namespace advss { class MacroScheduleEntry { public: - enum class RepeatType { - NONE, - MINUTELY, - HOURLY, - DAILY, - WEEKLY, - MONTHLY, - }; - enum class RepeatEndType { NEVER, AFTER_N_TIMES, @@ -60,8 +52,8 @@ public: QDateTime endDate; EndDateAction endDateAction = EndDateAction::NONE; - RepeatType repeatType = RepeatType::NONE; - int repeatInterval = 1; + bool doesRepeat = false; + Duration repeatInterval = 120; RepeatEndType repeatEndType = RepeatEndType::NEVER; int repeatMaxCount = 1;