From 0fc6c60d491a59d78711969b6ce5fce268b5ab7a Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Wed, 14 Oct 2020 20:55:11 +0200 Subject: [PATCH] add new UI for Time tab --- forms/advanced-scene-switcher.ui | 77 +----- src/headers/advanced-scene-switcher.hpp | 3 - src/headers/switch-time.hpp | 43 ++- src/headers/switcher-data-structs.hpp | 2 +- src/switch-time.cpp | 334 ++++++++++-------------- 5 files changed, 168 insertions(+), 291 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index dfb9033e..212e32fa 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -260,7 +260,7 @@ - Enable verbose logging (Only needed for debugging) + Enable verbose logging @@ -2688,81 +2688,6 @@ Time - - - - - - - 100 - 0 - - - - - - - - at - - - - - - - HH:mm:ss - - - - - - - switch to - - - - - - - - 100 - 0 - - - - - - - - using the - - - - - - - - - - transition - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index a6080e4a..77eb86c0 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -42,10 +42,8 @@ public: int SceneTransitionsFindByData(const QString &scene1, const QString &scene2); int DefaultTransitionsFindByData(const QString &scene); - int executableFindByData(const QString &exe); int IgnoreIdleWindowsFindByData(const QString &window); int randomFindByData(const QString &scene); - int timeFindByData(const timeTrigger &trigger, const QTime &time); void UpdateNonMatchingScene(const QString &name); void UpdateAutoStopScene(const QString &name); @@ -187,7 +185,6 @@ public slots: void on_mediaUp_clicked(); void on_mediaDown_clicked(); - void on_timeSwitches_currentRowChanged(int idx); void on_timeAdd_clicked(); void on_timeRemove_clicked(); void on_timeUp_clicked(); diff --git a/src/headers/switch-time.hpp b/src/headers/switch-time.hpp index 98c2f867..dcf6d057 100644 --- a/src/headers/switch-time.hpp +++ b/src/headers/switch-time.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include -#include "utility.hpp" +#include + #include "switch-generic.hpp" constexpr auto time_func = 7; @@ -20,24 +20,43 @@ typedef enum { } timeTrigger; struct TimeSwitch : SceneSwitcherEntry { - timeTrigger trigger; - QTime time; - std::string timeSwitchStr; + timeTrigger trigger = ANY_DAY; + QTime time = QTime(); const char *getType() { return "time"; } + inline TimeSwitch(){}; inline TimeSwitch(OBSWeakSource scene_, OBSWeakSource transition_, timeTrigger trigger_, QTime time_, - bool usePreviousScene_, std::string timeSwitchStr_) + bool usePreviousScene_) : SceneSwitcherEntry(scene_, transition_, usePreviousScene_), trigger(trigger_), - time(time_), - timeSwitchStr(timeSwitchStr_) + time(time_) { } }; -static inline QString MakeTimeSwitchName(const QString &scene, - const QString &transition, - const timeTrigger &trigger, - const QTime &time); +class TimeSwitchWidget : public SwitchWidget { + Q_OBJECT + +public: + TimeSwitchWidget(TimeSwitch *s); + TimeSwitch *getSwitchData(); + void setSwitchData(TimeSwitch *s); + + static void swapSwitchData(TimeSwitchWidget *s1, TimeSwitchWidget *s2); + +private slots: + void TriggerChanged(int index); + void TimeChanged(const QTime &time); + +private: + QComboBox *triggers; + QTimeEdit *time; + + QLabel *atLabel; + QLabel *switchLabel; + QLabel *usingLabel; + + TimeSwitch *switchData; +}; diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index a8dfbdc4..609ee0ff 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -95,7 +95,7 @@ struct SwitcherData { std::deque mediaSwitches; - std::vector timeSwitches; + std::deque timeSwitches; QDateTime liveTime; std::deque audioSwitches; diff --git a/src/switch-time.cpp b/src/switch-time.cpp index c8723815..6286244f 100644 --- a/src/switch-time.cpp +++ b/src/switch-time.cpp @@ -1,117 +1,21 @@ #include "headers/advanced-scene-switcher.hpp" -static std::vector> triggerTable = { - {"On any day", timeTrigger::ANY_DAY}, - {"Mondays", timeTrigger::MONDAY}, - {"Tuesdays", timeTrigger::TUSEDAY}, - {"Wednesdays", timeTrigger::WEDNESDAY}, - {"Thursdays", timeTrigger::THURSDAY}, - {"Fridays", timeTrigger::FRIDAY}, - {"Saturdays", timeTrigger::SATURDAY}, - {"Sundays", timeTrigger::SUNDAY}, - {"Atfer streaming/recording start", timeTrigger::LIVE}}; - -void SceneSwitcher::on_timeSwitches_currentRowChanged(int idx) -{ - if (loading) - return; - if (idx == -1) - return; - - QListWidgetItem *item = ui->timeSwitches->item(idx); - - QString timeScenestr = item->data(Qt::UserRole).toString(); - - std::lock_guard lock(switcher->m); - for (auto &s : switcher->timeSwitches) { - if (timeScenestr.compare(s.timeSwitchStr.c_str()) == 0) { - QString sceneName = GetWeakSourceName(s.scene).c_str(); - QString transitionName = - GetWeakSourceName(s.transition).c_str(); - ui->timeScenes->setCurrentText(sceneName); - ui->timeTrigger->setCurrentIndex(s.trigger); - ui->timeEdit->setTime(s.time); - ui->timeTransitions->setCurrentText(transitionName); - break; - } - } -} - -int SceneSwitcher::timeFindByData(const timeTrigger &trigger, const QTime &time) -{ - QRegExp rx(MakeTimeSwitchName(QStringLiteral(".*"), - QStringLiteral(".*"), trigger, time)); - int count = ui->timeSwitches->count(); - - for (int i = 0; i < count; i++) { - QListWidgetItem *item = ui->timeSwitches->item(i); - QString str = item->data(Qt::UserRole).toString(); - - if (rx.exactMatch(str)) - return i; - } - - return -1; -} +static QMetaObject::Connection addPulse; void SceneSwitcher::on_timeAdd_clicked() { - QString sceneName = ui->timeScenes->currentText(); - QString transitionName = ui->timeTransitions->currentText(); - QTime time = ui->timeEdit->time(); + ui->timeAdd->disconnect(addPulse); - if (sceneName.isEmpty()) - return; + std::lock_guard lock(switcher->m); + switcher->timeSwitches.emplace_back(); - OBSWeakSource source = GetWeakSourceByQString(sceneName); - OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - - std::string triggerStr = ui->timeTrigger->currentText().toStdString(); - auto it = std::find_if( - triggerTable.begin(), triggerTable.end(), - [&triggerStr]( - const std::pair &element) { - return element.first == triggerStr; - }); - timeTrigger trigger = it->second; - - QString text = - MakeTimeSwitchName(sceneName, transitionName, trigger, time); - QVariant v = QVariant::fromValue(text); - - int idx = timeFindByData(trigger, time); - - if (idx == -1) { - std::lock_guard lock(switcher->m); - switcher->timeSwitches.emplace_back( - source, transition, trigger, time, - (sceneName == QString(previous_scene_name)), - text.toUtf8().constData()); - - QListWidgetItem *item = - new QListWidgetItem(text, ui->timeSwitches); - item->setData(Qt::UserRole, v); - } else { - QListWidgetItem *item = ui->timeSwitches->item(idx); - item->setText(text); - item->setData(Qt::UserRole, v); - - { - std::lock_guard lock(switcher->m); - for (auto &s : switcher->timeSwitches) { - if (s.trigger == trigger && s.time == time) { - s.scene = source; - s.transition = transition; - s.usePreviousScene = - (sceneName == - QString(previous_scene_name)); - s.timeSwitchStr = - text.toUtf8().constData(); - break; - } - } - } - } + QListWidgetItem *item; + item = new QListWidgetItem(ui->timeSwitches); + ui->timeSwitches->addItem(item); + TimeSwitchWidget *sw = + new TimeSwitchWidget(&switcher->timeSwitches.back()); + item->setSizeHint(sw->minimumSizeHint()); + ui->timeSwitches->setItemWidget(item, sw); } void SceneSwitcher::on_timeRemove_clicked() @@ -120,21 +24,11 @@ void SceneSwitcher::on_timeRemove_clicked() if (!item) return; - std::string text = - item->data(Qt::UserRole).toString().toUtf8().constData(); - { std::lock_guard lock(switcher->m); + int idx = ui->timeSwitches->currentRow(); auto &switches = switcher->timeSwitches; - - for (auto it = switches.begin(); it != switches.end(); ++it) { - auto &s = *it; - - if (s.timeSwitchStr == text) { - switches.erase(it); - break; - } - } + switches.erase(switches.begin() + idx); } delete item; @@ -143,31 +37,38 @@ void SceneSwitcher::on_timeRemove_clicked() void SceneSwitcher::on_timeUp_clicked() { int index = ui->timeSwitches->currentRow(); - if (index != -1 && index != 0) { - ui->timeSwitches->insertItem(index - 1, - ui->timeSwitches->takeItem(index)); - ui->timeSwitches->setCurrentRow(index - 1); + if (!listMoveUp(ui->timeSwitches)) + return; - std::lock_guard lock(switcher->m); + TimeSwitchWidget *s1 = (TimeSwitchWidget *)ui->timeSwitches->itemWidget( + ui->timeSwitches->item(index)); + TimeSwitchWidget *s2 = (TimeSwitchWidget *)ui->timeSwitches->itemWidget( + ui->timeSwitches->item(index - 1)); + TimeSwitchWidget::swapSwitchData(s1, s2); - iter_swap(switcher->timeSwitches.begin() + index, - switcher->timeSwitches.begin() + index - 1); - } + std::lock_guard lock(switcher->m); + + std::swap(switcher->timeSwitches[index], + switcher->timeSwitches[index - 1]); } void SceneSwitcher::on_timeDown_clicked() { int index = ui->timeSwitches->currentRow(); - if (index != -1 && index != ui->timeSwitches->count() - 1) { - ui->timeSwitches->insertItem(index + 1, - ui->timeSwitches->takeItem(index)); - ui->timeSwitches->setCurrentRow(index + 1); - std::lock_guard lock(switcher->m); + if (!listMoveDown(ui->timeSwitches)) + return; - iter_swap(switcher->timeSwitches.begin() + index, - switcher->timeSwitches.begin() + index + 1); - } + TimeSwitchWidget *s1 = (TimeSwitchWidget *)ui->timeSwitches->itemWidget( + ui->timeSwitches->item(index)); + TimeSwitchWidget *s2 = (TimeSwitchWidget *)ui->timeSwitches->itemWidget( + ui->timeSwitches->item(index + 1)); + TimeSwitchWidget::swapSwitchData(s1, s2); + + std::lock_guard lock(switcher->m); + + std::swap(switcher->timeSwitches[index], + switcher->timeSwitches[index + 1]); } bool timesAreInInterval(QTime &time1, QTime &time2, int &interval) @@ -282,16 +183,10 @@ void SwitcherData::loadTimeSwitches(obs_data_t *obj) QTime time = QTime::fromString( obs_data_get_string(array_obj, "time")); - std::string timeSwitchStr = - MakeTimeSwitchName(scene, transition, trigger, time) - .toUtf8() - .constData(); - switcher->timeSwitches.emplace_back( GetWeakSourceByName(scene), GetWeakTransitionByName(transition), trigger, time, - (strcmp(scene, previous_scene_name) == 0), - timeSwitchStr); + (strcmp(scene, previous_scene_name) == 0)); obs_data_release(array_obj); } @@ -303,70 +198,111 @@ void SceneSwitcher::setupTimeTab() populateSceneSelection(ui->timeScenes, true); populateTransitionSelection(ui->timeTransitions); - for (auto t : triggerTable) { - ui->timeTrigger->addItem(t.first.c_str()); + for (auto &s : switcher->timeSwitches) { + QListWidgetItem *item; + item = new QListWidgetItem(ui->timeSwitches); + ui->timeSwitches->addItem(item); + TimeSwitchWidget *sw = new TimeSwitchWidget(&s); + item->setSizeHint(sw->minimumSizeHint()); + ui->timeSwitches->setItemWidget(item, sw); } - // assuming the streaming / recording entry is always last - ui->timeTrigger->setItemData( - (int)triggerTable.size() - 1, + if (switcher->timeSwitches.size() == 0) + addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green)); +} + +void populateTriggers(QComboBox *list) +{ + list->addItem("On any day"); + list->addItem("Mondays"); + list->addItem("Tuesdays"); + list->addItem("Wednesdays"); + list->addItem("Thursdays"); + list->addItem("Fridays"); + list->addItem("Saturdays"); + list->addItem("Sundays"); + list->addItem("Atfer streaming/recording start"); + + list->setItemData( + 8, "The time relative to the start of streaming / recording will be used", Qt::ToolTipRole); - - for (auto &s : switcher->timeSwitches) { - std::string sceneName = (s.usePreviousScene) - ? previous_scene_name - : GetWeakSourceName(s.scene); - std::string transitionName = GetWeakSourceName(s.transition); - QString listText = MakeTimeSwitchName(sceneName.c_str(), - transitionName.c_str(), - s.trigger, s.time); - - QListWidgetItem *item = - new QListWidgetItem(listText, ui->timeSwitches); - item->setData(Qt::UserRole, listText); - } } -static inline QString MakeTimeSwitchName(const QString &scene, - const QString &transition, - const timeTrigger &trigger, - const QTime &time) +TimeSwitchWidget::TimeSwitchWidget(TimeSwitch *s) : SwitchWidget(s, false) { - QString switchName; + triggers = new QComboBox(); + time = new QTimeEdit(); - switch (trigger) { - case ANY_DAY: - switchName = QStringLiteral("On any weekday"); - break; - case MONDAY: - switchName = QStringLiteral("Mondays"); - break; - case TUSEDAY: - switchName = QStringLiteral("Tusedays"); - break; - case WEDNESDAY: - switchName = QStringLiteral("Wednesdays"); - break; - case THURSDAY: - switchName = QStringLiteral("Thursdays"); - break; - case FRIDAY: - switchName = QStringLiteral("Fridays"); - break; - case SATURDAY: - switchName = QStringLiteral("Saturdays"); - break; - case SUNDAY: - switchName = QStringLiteral("Sundays"); - break; - case LIVE: - switchName = QStringLiteral( - "Relative to starting streaming / recording"); - break; + atLabel = new QLabel("at"); + switchLabel = new QLabel("switch to"); + usingLabel = new QLabel("using"); + + QWidget::connect(triggers, SIGNAL(currentIndexChanged(int)), this, + SLOT(TriggerChanged(int))); + QWidget::connect(time, SIGNAL(timeChanged(const QTime &)), this, + SLOT(TimeChanged(const QTime &))); + + populateTriggers(triggers); + time->setDisplayFormat("HH:mm:ss"); + + if (s) { + triggers->setCurrentIndex(s->trigger); + time->setTime(s->time); } - switchName += QStringLiteral(" at ") + time.toString() + - QStringLiteral(" switch to ") + scene + - QStringLiteral(" using ") + transition; - return switchName; + + setStyleSheet("* { background-color: transparent; }"); + + QHBoxLayout *mainLayout = new QHBoxLayout; + + mainLayout->addWidget(triggers); + mainLayout->addWidget(atLabel); + mainLayout->addWidget(time); + mainLayout->addWidget(switchLabel); + mainLayout->addWidget(scenes); + mainLayout->addWidget(usingLabel); + mainLayout->addWidget(transitions); + mainLayout->addStretch(); + + setLayout(mainLayout); + + switchData = s; + + loading = false; +} + +TimeSwitch *TimeSwitchWidget::getSwitchData() +{ + return switchData; +} + +void TimeSwitchWidget::setSwitchData(TimeSwitch *s) +{ + switchData = s; +} + +void TimeSwitchWidget::swapSwitchData(TimeSwitchWidget *s1, + TimeSwitchWidget *s2) +{ + SwitchWidget::swapSwitchData(s1, s2); + + TimeSwitch *t = s1->getSwitchData(); + s1->setSwitchData(s2->getSwitchData()); + s2->setSwitchData(t); +} + +void TimeSwitchWidget::TriggerChanged(int index) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->trigger = (timeTrigger)index; +} + +void TimeSwitchWidget::TimeChanged(const QTime &time) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->time = time; }