From dbb674aa8e482606b1ffcd915783d692760da965 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sun, 14 May 2023 00:31:42 +0200 Subject: [PATCH] Add "Display" condition Allows you to check for the amount and name of the connected displays --- CMakeLists.txt | 2 + data/locale/en-US.ini | 4 + src/macro-core/macro-condition-display.cpp | 198 +++++++++++++++++++++ src/macro-core/macro-condition-display.hpp | 73 ++++++++ src/utils/utility.cpp | 1 + src/utils/utility.hpp | 1 - 6 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 src/macro-core/macro-condition-display.cpp create mode 100644 src/macro-core/macro-condition-display.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f36af5..36b08a02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,6 +163,8 @@ target_sources( src/macro-core/macro-condition-cursor.hpp src/macro-core/macro-condition-date.cpp src/macro-core/macro-condition-date.hpp + src/macro-core/macro-condition-display.cpp + src/macro-core/macro-condition-display.hpp src/macro-core/macro-condition-edit.cpp src/macro-core/macro-condition-edit.hpp src/macro-core/macro-condition-file.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 000d9daa..d6fd3a5a 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -442,6 +442,10 @@ AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}Check for exit code{ AdvSceneSwitcher.condition.midi="MIDI" AdvSceneSwitcher.condition.midi.entry="Mesasge was received from {{device}} which matches:" AdvSceneSwitcher.condition.midi.entry.listen="Set MIDI message selection to messages incoming on selected device: {{listenButton}}" +AdvSceneSwitcher.condition.display="Display" +AdvSceneSwitcher.condition.display.type.displayName="Name of connected displays matches" +AdvSceneSwitcher.condition.display.type.displayCount="Number of connected displays is" +AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}" ; Macro Actions AdvSceneSwitcher.action.switchScene="Switch scene" diff --git a/src/macro-core/macro-condition-display.cpp b/src/macro-core/macro-condition-display.cpp new file mode 100644 index 00000000..2104ca92 --- /dev/null +++ b/src/macro-core/macro-condition-display.cpp @@ -0,0 +1,198 @@ +#include "macro-condition-display.hpp" +#include "utility.hpp" + +#include + +namespace advss { + +const std::string MacroConditionDisplay::id = "display"; + +bool MacroConditionDisplay::_registered = MacroConditionFactory::Register( + MacroConditionDisplay::id, + {MacroConditionDisplay::Create, MacroConditionDisplayEdit::Create, + "AdvSceneSwitcher.condition.display"}); + +static std::map conditionTypes = { + {MacroConditionDisplay::Condition::DISPLAY_NAME, + "AdvSceneSwitcher.condition.display.type.displayName"}, + {MacroConditionDisplay::Condition::DISPLAY_COUNT, + "AdvSceneSwitcher.condition.display.type.displayCount"}, +}; + +static bool matchDisplayNames(const std::string &name, const RegexConfig ®ex) +{ + auto monitors = GetMonitorNames(); + if (regex.Enabled()) { + auto expr = regex.GetRegularExpression(name); + if (!expr.isValid()) { + return false; + } + + for (const auto &m : monitors) { + auto match = expr.match(m); + if (match.hasMatch()) { + return true; + } + } + } else { + for (const auto &m : monitors) { + if (m.toStdString() == name) { + return true; + } + } + } + return false; +} + +bool MacroConditionDisplay::CheckCondition() +{ + switch (_condition) { + case advss::MacroConditionDisplay::Condition::DISPLAY_NAME: + return matchDisplayNames(_displayName, _regexConf); + case advss::MacroConditionDisplay::Condition::DISPLAY_COUNT: + return _displayCount == QGuiApplication::screens().count(); + default: + break; + } + return false; +} + +bool MacroConditionDisplay::Save(obs_data_t *obj) const +{ + MacroCondition::Save(obj); + obs_data_set_int(obj, "condition", static_cast(_condition)); + _displayName.Save(obj, "displayName"); + _regexConf.Save(obj); + _displayCount.Save(obj, "displayCount"); + return true; +} + +bool MacroConditionDisplay::Load(obs_data_t *obj) +{ + MacroCondition::Load(obj); + _condition = static_cast(obs_data_get_int(obj, "condition")); + _displayName.Load(obj, "displayName"); + _regexConf.Load(obj); + _displayCount.Load(obj, "displayCount"); + return true; +} + +static inline void populateConditionSelection(QComboBox *list) +{ + for (const auto &entry : conditionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +MacroConditionDisplayEdit::MacroConditionDisplayEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent), + _conditions(new QComboBox()), + _displays(new QComboBox()), + _regex(new RegexConfigWidget()), + _displayCount(new VariableSpinBox(this)) +{ + populateConditionSelection(_conditions); + _displays->addItems(GetMonitorNames()); + _displays->setEditable(true); + + QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this, + SLOT(ConditionChanged(int))); + QWidget::connect(_displays, SIGNAL(currentTextChanged(const QString &)), + this, SLOT(DisplayNameChanged(const QString &))); + QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this, + SLOT(RegexChanged(RegexConfig))); + QWidget::connect( + _displayCount, + SIGNAL(NumberVariableChanged(const NumberVariable &)), + this, SLOT(DisplayCountChanged(const NumberVariable &))); + + auto mainLayout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{conditions}}", _conditions}, + {"{{displays}}", _displays}, + {"{{regex}}", _regex}, + {"{{displayCount}}", _displayCount}, + }; + PlaceWidgets( + obs_module_text("AdvSceneSwitcher.condition.display.entry"), + mainLayout, widgetPlaceholders); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroConditionDisplayEdit::ConditionChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_condition = + static_cast(value); + SetWidgetVisibility(); +} + +void MacroConditionDisplayEdit::DisplayNameChanged(const QString &display) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_displayName = display.toStdString(); +} + +void MacroConditionDisplayEdit::RegexChanged(RegexConfig conf) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_regexConf = conf; + + adjustSize(); + updateGeometry(); +} + +void MacroConditionDisplayEdit::DisplayCountChanged( + const NumberVariable &value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_displayCount = value; +} + +void MacroConditionDisplayEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _conditions->setCurrentIndex(static_cast(_entryData->_condition)); + _displays->setCurrentText(QString::fromStdString( + _entryData->_displayName.UnresolvedValue())); + _regex->SetRegexConfig(_entryData->_regexConf); + _displayCount->SetValue(_entryData->_displayCount); + SetWidgetVisibility(); +} + +void MacroConditionDisplayEdit::SetWidgetVisibility() +{ + _displays->setVisible(_entryData->_condition == + MacroConditionDisplay::Condition::DISPLAY_NAME); + _regex->setVisible(_entryData->_condition == + MacroConditionDisplay::Condition::DISPLAY_NAME); + _displayCount->setVisible( + _entryData->_condition == + MacroConditionDisplay::Condition::DISPLAY_COUNT); +} + +} // namespace advss diff --git a/src/macro-core/macro-condition-display.hpp b/src/macro-core/macro-condition-display.hpp new file mode 100644 index 00000000..60e80f9e --- /dev/null +++ b/src/macro-core/macro-condition-display.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "macro-condition-edit.hpp" +#include "variable-line-edit.hpp" +#include "variable-spinbox.hpp" +#include "regex-config.hpp" + +#include +#include + +namespace advss { + +class MacroConditionDisplay : public MacroCondition { +public: + MacroConditionDisplay(Macro *m) : MacroCondition(m, true) {} + bool CheckCondition(); + bool Save(obs_data_t *obj) const; + bool Load(obs_data_t *obj); + std::string GetId() const { return id; }; + static std::shared_ptr Create(Macro *m) + { + return std::make_shared(m); + } + + enum class Condition { + DISPLAY_NAME, + DISPLAY_COUNT, + }; + Condition _condition = Condition::DISPLAY_NAME; + StringVariable _displayName; + RegexConfig _regexConf; + IntVariable _displayCount; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroConditionDisplayEdit : public QWidget { + Q_OBJECT + +public: + MacroConditionDisplayEdit( + QWidget *parent, + std::shared_ptr cond = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr cond) + { + return new MacroConditionDisplayEdit( + parent, + std::dynamic_pointer_cast(cond)); + } + +private slots: + void ConditionChanged(int); + void DisplayNameChanged(const QString &); + void RegexChanged(RegexConfig conf); + void DisplayCountChanged(const NumberVariable &); + +protected: + QComboBox *_conditions; + QComboBox *_displays; + RegexConfigWidget *_regex; + VariableSpinBox *_displayCount; + std::shared_ptr _entryData; + +private: + void SetWidgetVisibility(); + + bool _loading = true; +}; + +} // namespace advss diff --git a/src/utils/utility.cpp b/src/utils/utility.cpp index 59d7fb13..2ba94fe2 100644 --- a/src/utils/utility.cpp +++ b/src/utils/utility.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/utils/utility.hpp b/src/utils/utility.hpp index 2c19b131..eecda3bd 100644 --- a/src/utils/utility.hpp +++ b/src/utils/utility.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include