mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-27 19:56:07 -05:00
Enable use of variables in filter selection
This commit is contained in:
@@ -251,6 +251,8 @@ target_sources(
|
||||
src/utils/log-helper.hpp
|
||||
src/utils/file-selection.cpp
|
||||
src/utils/file-selection.hpp
|
||||
src/utils/filter-selection.cpp
|
||||
src/utils/filter-selection.hpp
|
||||
src/utils/macro-list.cpp
|
||||
src/utils/macro-list.hpp
|
||||
src/utils/math-helpers.cpp
|
||||
|
||||
@@ -319,7 +319,7 @@ AdvSceneSwitcher.condition.filter.type.settings="Settings match"
|
||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}}{{getSettings}}"
|
||||
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
|
||||
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
|
||||
|
||||
@@ -19,24 +19,9 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
|
||||
void MacroActionFilter::ResolveVariables()
|
||||
{
|
||||
if (_source.GetType() == SourceSelection::Type::SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = GetWeakSourceName(_filter);
|
||||
if (!name.empty()) {
|
||||
_filterName = name;
|
||||
}
|
||||
_filter = GetWeakFilterByName(_source.GetSource(), _filterName.c_str());
|
||||
}
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
{
|
||||
ResolveVariables();
|
||||
|
||||
auto s = obs_weak_source_get_source(_filter);
|
||||
auto s = obs_weak_source_get_source(_filter.GetFilter(_source));
|
||||
switch (_action) {
|
||||
case Action::ENABLE:
|
||||
obs_source_set_enabled(s, true);
|
||||
@@ -60,7 +45,7 @@ void MacroActionFilter::LogAction() const
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for filter \"%s\" on source \"%s\"",
|
||||
it->second.c_str(), GetWeakSourceName(_filter).c_str(),
|
||||
it->second.c_str(), _filter.ToString().c_str(),
|
||||
_source.ToString(true).c_str());
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown filter action %d",
|
||||
@@ -72,7 +57,7 @@ bool MacroActionFilter::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_source.Save(obj);
|
||||
obs_data_set_string(obj, "filter", _filterName.c_str());
|
||||
_filter.Save(obj, "filter");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_settings.Save(obj, "settings");
|
||||
return true;
|
||||
@@ -82,9 +67,7 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_source.Load(obj);
|
||||
_filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source.GetSource(),
|
||||
_filterName.c_str());
|
||||
_filter.Load(obj, _source, "filter");
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_settings.Load(obj, "settings");
|
||||
return true;
|
||||
@@ -92,8 +75,8 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionFilter::GetShortDesc() const
|
||||
{
|
||||
if (_filter && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + GetWeakSourceName(_filter);
|
||||
if (!_filter.ToString().empty() && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + _filter.ToString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -109,7 +92,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_filters(new QComboBox()),
|
||||
_filters(new FilterSelectionWidget(this, _sources, true)),
|
||||
_actions(new QComboBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.filter.getSettings"))),
|
||||
@@ -127,8 +110,9 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_filters,
|
||||
SIGNAL(FilterChanged(const FilterSelection &)), this,
|
||||
SLOT(FilterChanged(const FilterSelection &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
@@ -147,6 +131,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
@@ -167,9 +152,7 @@ void MacroActionFilterEdit::UpdateEntryData()
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->SetSource(_entryData->_source);
|
||||
PopulateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_filters->SetFilter(_entryData->_source, _entryData->_filter);
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
SetWidgetVisibility(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
@@ -183,25 +166,19 @@ void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = source;
|
||||
}
|
||||
_filters->clear();
|
||||
PopulateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->adjustSize();
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = source;
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::FilterChanged(const QString &text)
|
||||
void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_filterName = text.toStdString();
|
||||
_entryData->_filter =
|
||||
GetWeakFilterByQString(_entryData->_source.GetSource(), text);
|
||||
_entryData->_filter = filter;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -220,13 +197,13 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
|
||||
void MacroActionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_source.GetSource() ||
|
||||
!_entryData->_filter) {
|
||||
if (_loading || !_entryData ||
|
||||
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(
|
||||
FormatJsonString(GetSourceSettings(_entryData->_filter)));
|
||||
_settings->setPlainText(FormatJsonString(GetSourceSettings(
|
||||
_entryData->_filter.GetFilter(_entryData->_source))));
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SettingsChanged()
|
||||
@@ -247,6 +224,7 @@ void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "filter-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
@@ -30,18 +31,13 @@ public:
|
||||
};
|
||||
|
||||
SourceSelection _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterSelection _filter;
|
||||
Action _action = Action::ENABLE;
|
||||
StringVariable _settings = "";
|
||||
|
||||
private:
|
||||
void ResolveVariables();
|
||||
std::string _filterName = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
friend class MacroActionFilterEdit;
|
||||
};
|
||||
|
||||
class MacroActionFilterEdit : public QWidget {
|
||||
@@ -62,7 +58,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void FilterChanged(const QString &);
|
||||
void FilterChanged(const FilterSelection &);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
@@ -71,7 +67,7 @@ signals:
|
||||
|
||||
protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_filters;
|
||||
FilterSelectionWidget *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
|
||||
@@ -22,47 +22,34 @@ static std::map<MacroConditionFilter::Condition, std::string>
|
||||
"AdvSceneSwitcher.condition.filter.type.settings"},
|
||||
};
|
||||
|
||||
void MacroConditionFilter::ResolveVariables()
|
||||
{
|
||||
if (_source.GetType() == SourceSelection::Type::SOURCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = GetWeakSourceName(_filter);
|
||||
if (!name.empty()) {
|
||||
_filterName = name;
|
||||
}
|
||||
_filter = GetWeakFilterByName(_source.GetSource(), _filterName.c_str());
|
||||
}
|
||||
|
||||
bool MacroConditionFilter::CheckCondition()
|
||||
{
|
||||
ResolveVariables();
|
||||
if (!_source.GetSource()) {
|
||||
auto filterWeakSource = _filter.GetFilter(_source);
|
||||
if (!filterWeakSource) {
|
||||
return false;
|
||||
}
|
||||
auto filterSource = obs_weak_source_get_source(filterWeakSource);
|
||||
|
||||
bool ret = false;
|
||||
auto s = obs_weak_source_get_source(_filter);
|
||||
|
||||
switch (_condition) {
|
||||
case Condition::ENABLED:
|
||||
ret = obs_source_enabled(s);
|
||||
ret = obs_source_enabled(filterSource);
|
||||
break;
|
||||
case Condition::DISABLED:
|
||||
ret = !obs_source_enabled(s);
|
||||
ret = !obs_source_enabled(filterSource);
|
||||
break;
|
||||
case Condition::SETTINGS:
|
||||
ret = CompareSourceSettings(_filter, _settings, _regex);
|
||||
ret = CompareSourceSettings(filterWeakSource, _settings,
|
||||
_regex);
|
||||
if (IsReferencedInVars()) {
|
||||
SetVariableValue(GetSourceSettings(_filter));
|
||||
SetVariableValue(GetSourceSettings(filterWeakSource));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
obs_source_release(s);
|
||||
obs_source_release(filterSource);
|
||||
|
||||
if (GetVariableValue().empty()) {
|
||||
SetVariableValue(ret ? "true" : "false");
|
||||
@@ -75,7 +62,7 @@ bool MacroConditionFilter::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_source.Save(obj);
|
||||
obs_data_set_string(obj, "filter", _filterName.c_str());
|
||||
_filter.Save(obj, "filter");
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
_settings.Save(obj, "settings");
|
||||
_regex.Save(obj);
|
||||
@@ -86,9 +73,7 @@ bool MacroConditionFilter::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_source.Load(obj);
|
||||
_filterName = obs_data_get_string(obj, "filter");
|
||||
_filter = GetWeakFilterByQString(_source.GetSource(),
|
||||
_filterName.c_str());
|
||||
_filter.Load(obj, _source, "filter");
|
||||
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||
_settings.Load(obj, "settings");
|
||||
_regex.Load(obj);
|
||||
@@ -102,8 +87,8 @@ bool MacroConditionFilter::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroConditionFilter::GetShortDesc() const
|
||||
{
|
||||
if (_filter && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + GetWeakSourceName(_filter);
|
||||
if (!_filter.ToString().empty() && !_source.ToString().empty()) {
|
||||
return _source.ToString() + " - " + _filter.ToString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -119,14 +104,13 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionFilter> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_filters(new QComboBox()),
|
||||
_filters(new FilterSelectionWidget(this, _sources, true)),
|
||||
_conditions(new QComboBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.getSettings"))),
|
||||
_settings(new VariableTextEdit(this)),
|
||||
_regex(new RegexConfigWidget(parent))
|
||||
{
|
||||
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
populateConditionSelection(_conditions);
|
||||
auto sources = GetSourcesWithFilterNames();
|
||||
sources.sort();
|
||||
@@ -135,8 +119,9 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_filters, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(FilterChanged(const QString &)));
|
||||
QWidget::connect(_filters,
|
||||
SIGNAL(FilterChanged(const FilterSelection &)), this,
|
||||
SLOT(FilterChanged(const FilterSelection &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
@@ -146,20 +131,23 @@ MacroConditionFilterEdit::MacroConditionFilterEdit(
|
||||
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
||||
SLOT(RegexChanged(RegexConfig)));
|
||||
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources}, {"{{filters}}", _filters},
|
||||
{"{{conditions}}", _conditions}, {"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings}, {"{{regex}}", _regex},
|
||||
};
|
||||
auto line1Layout = new QHBoxLayout;
|
||||
line1Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
auto line2Layout = new QHBoxLayout;
|
||||
line2Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line2"),
|
||||
line2Layout, widgetPlaceholders, false);
|
||||
auto line3Layout = new QHBoxLayout;
|
||||
line3Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.filter.entry.line3"),
|
||||
line3Layout, widgetPlaceholders);
|
||||
@@ -180,25 +168,19 @@ void MacroConditionFilterEdit::SourceChanged(const SourceSelection &source)
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = source;
|
||||
}
|
||||
_filters->clear();
|
||||
PopulateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->adjustSize();
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = source;
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::FilterChanged(const QString &text)
|
||||
void MacroConditionFilterEdit::FilterChanged(const FilterSelection &filter)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_filterName = text.toStdString();
|
||||
_entryData->_filter =
|
||||
GetWeakFilterByQString(_entryData->_source.GetSource(), text);
|
||||
_entryData->_filter = filter;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -218,11 +200,13 @@ void MacroConditionFilterEdit::ConditionChanged(int index)
|
||||
|
||||
void MacroConditionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData || !_entryData->_source.GetSource()) {
|
||||
if (_loading || !_entryData ||
|
||||
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString json = FormatJsonString(GetSourceSettings(_entryData->_filter));
|
||||
QString json = FormatJsonString(GetSourceSettings(
|
||||
_entryData->_filter.GetFilter(_entryData->_source)));
|
||||
if (_entryData->_regex.Enabled()) {
|
||||
json = EscapeForRegex(json);
|
||||
}
|
||||
@@ -261,6 +245,7 @@ void MacroConditionFilterEdit::SetSettingsSelectionVisible(bool visible)
|
||||
_getSettings->setVisible(visible);
|
||||
_regex->setVisible(visible);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::UpdateEntryData()
|
||||
@@ -270,9 +255,7 @@ void MacroConditionFilterEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_sources->SetSource(_entryData->_source);
|
||||
PopulateFilterSelection(_filters, _entryData->_source.GetSource());
|
||||
_filters->setCurrentText(
|
||||
GetWeakSourceName(_entryData->_filter).c_str());
|
||||
_filters->SetFilter(_entryData->_source, _entryData->_filter);
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "filter-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
@@ -30,19 +31,14 @@ public:
|
||||
};
|
||||
|
||||
SourceSelection _source;
|
||||
OBSWeakSource _filter;
|
||||
FilterSelection _filter;
|
||||
Condition _condition = Condition::ENABLED;
|
||||
StringVariable _settings = "";
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
void ResolveVariables();
|
||||
std::string _filterName = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
friend class MacroConditionFilterEdit;
|
||||
};
|
||||
|
||||
class MacroConditionFilterEdit : public QWidget {
|
||||
@@ -63,7 +59,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void FilterChanged(const QString &text);
|
||||
void FilterChanged(const FilterSelection &);
|
||||
void ConditionChanged(int cond);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
@@ -73,7 +69,7 @@ signals:
|
||||
|
||||
protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_filters;
|
||||
FilterSelectionWidget *_filters;
|
||||
QComboBox *_conditions;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
|
||||
260
src/utils/filter-selection.cpp
Normal file
260
src/utils/filter-selection.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "filter-selection.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
constexpr std::string_view typeSaveName = "type";
|
||||
constexpr std::string_view nameSaveName = "name";
|
||||
|
||||
void FilterSelection::Save(obs_data_t *obj, const char *name) const
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
obs_data_set_int(data, typeSaveName.data(), static_cast<int>(_type));
|
||||
switch (_type) {
|
||||
case Type::SOURCE:
|
||||
obs_data_set_string(data, nameSaveName.data(),
|
||||
_filter ? GetWeakSourceName(_filter).c_str()
|
||||
: _filterName.c_str());
|
||||
break;
|
||||
case Type::VARIABLE: {
|
||||
auto var = _variable.lock();
|
||||
if (!var) {
|
||||
break;
|
||||
}
|
||||
obs_data_set_string(data, nameSaveName.data(),
|
||||
var->Name().c_str());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obs_data_set_obj(obj, name, data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void FilterSelection::Load(obs_data_t *obj, const SourceSelection &source,
|
||||
const char *name)
|
||||
{
|
||||
auto data = obs_data_get_obj(obj, name);
|
||||
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
|
||||
_filterName = obs_data_get_string(data, nameSaveName.data());
|
||||
switch (_type) {
|
||||
case Type::SOURCE:
|
||||
_filter = GetWeakFilterByName(source.GetSource(),
|
||||
_filterName.c_str());
|
||||
break;
|
||||
case Type::VARIABLE:
|
||||
_variable = GetWeakVariableByName(_filterName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!obs_data_has_user_value(data, typeSaveName.data())) {
|
||||
LoadFallback(obj, source, name);
|
||||
}
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void FilterSelection::LoadFallback(obs_data_t *obj,
|
||||
const SourceSelection &source,
|
||||
const char *name)
|
||||
{
|
||||
blog(LOG_INFO, "Falling back to Load() without variable support");
|
||||
_type = Type::SOURCE;
|
||||
_filter = GetWeakFilterByName(source.GetSource(), name);
|
||||
_filterName = obs_data_get_string(obj, name);
|
||||
}
|
||||
|
||||
OBSWeakSource FilterSelection::GetFilter(const SourceSelection &source) const
|
||||
{
|
||||
switch (_type) {
|
||||
case Type::SOURCE:
|
||||
return GetWeakFilterByName(
|
||||
source.GetSource(),
|
||||
_filter ? GetWeakSourceName(_filter).c_str()
|
||||
: _filterName.c_str());
|
||||
case Type::VARIABLE: {
|
||||
auto var = _variable.lock();
|
||||
if (!var) {
|
||||
return nullptr;
|
||||
}
|
||||
return GetWeakFilterByName(source.GetSource(),
|
||||
var->Value().c_str());
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string FilterSelection::ToString(bool resolve) const
|
||||
{
|
||||
switch (_type) {
|
||||
case Type::SOURCE:
|
||||
return _filter ? GetWeakSourceName(_filter) : _filterName;
|
||||
case Type::VARIABLE: {
|
||||
auto var = _variable.lock();
|
||||
if (!var) {
|
||||
return "";
|
||||
}
|
||||
if (resolve) {
|
||||
return var->Name() + "[" + var->Value() + "]";
|
||||
}
|
||||
return var->Name();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
FilterSelection FilterSelectionWidget::CurrentSelection()
|
||||
{
|
||||
FilterSelection s;
|
||||
const int idx = currentIndex();
|
||||
const auto name = currentText();
|
||||
|
||||
if (idx < _variablesEndIdx) {
|
||||
s._type = FilterSelection::Type::VARIABLE;
|
||||
s._variable = GetWeakVariableByQString(name);
|
||||
} else if (idx < _filterEndIdx) {
|
||||
s._type = FilterSelection::Type::SOURCE;
|
||||
s._filter = GetWeakSourceByQString(name);
|
||||
s._filterName = name.toStdString();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::Reset()
|
||||
{
|
||||
auto previousSelection = _currentSelection;
|
||||
PopulateSelection();
|
||||
SetFilter(_source, previousSelection);
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::PopulateSelection()
|
||||
{
|
||||
const QSignalBlocker b(this);
|
||||
clear();
|
||||
AddSelectionEntry(this,
|
||||
obs_module_text("AdvSceneSwitcher.selectFilter"));
|
||||
insertSeparator(count());
|
||||
|
||||
if (_addVariables) {
|
||||
const QStringList variables = GetVariablesNameList();
|
||||
AddSelectionGroup(this, variables);
|
||||
}
|
||||
_variablesEndIdx = count();
|
||||
|
||||
AddSelectionGroup(this, GetFilterNames(_source.GetSource()));
|
||||
_filterEndIdx = count();
|
||||
|
||||
// Remove last separator
|
||||
removeItem(count() - 1);
|
||||
setCurrentIndex(0);
|
||||
}
|
||||
|
||||
FilterSelectionWidget::FilterSelectionWidget(QWidget *parent,
|
||||
SourceSelectionWidget *sources,
|
||||
bool addVariables)
|
||||
: QComboBox(parent), _addVariables(addVariables)
|
||||
{
|
||||
setDuplicatesEnabled(true);
|
||||
|
||||
QWidget::connect(this, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(SelectionChanged(const QString &)));
|
||||
QWidget::connect(sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
|
||||
// Variables
|
||||
QWidget::connect(window(), SIGNAL(VariableAdded(const QString &)), this,
|
||||
SLOT(ItemAdd(const QString &)));
|
||||
QWidget::connect(window(), SIGNAL(VariableRemoved(const QString &)),
|
||||
this, SLOT(ItemRemove(const QString &)));
|
||||
QWidget::connect(
|
||||
window(),
|
||||
SIGNAL(VariableRenamed(const QString &, const QString &)), this,
|
||||
SLOT(ItemRename(const QString &, const QString &)));
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::SetFilter(const SourceSelection &source,
|
||||
const FilterSelection &filter)
|
||||
{
|
||||
_source = source;
|
||||
PopulateSelection();
|
||||
|
||||
int idx = 0;
|
||||
|
||||
switch (filter.GetType()) {
|
||||
case FilterSelection::Type::SOURCE: {
|
||||
if (_filterEndIdx == -1) {
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
idx = FindIdxInRagne(this, _variablesEndIdx, _filterEndIdx,
|
||||
filter.ToString());
|
||||
break;
|
||||
}
|
||||
case FilterSelection::Type::VARIABLE: {
|
||||
if (_variablesEndIdx == -1) {
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
idx = FindIdxInRagne(this, _selectIdx, _variablesEndIdx,
|
||||
filter.ToString());
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setCurrentIndex(idx);
|
||||
_currentSelection = filter;
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::SourceChanged(const SourceSelection &source)
|
||||
{
|
||||
if (source == _source) {
|
||||
return;
|
||||
}
|
||||
_source = source;
|
||||
_currentSelection = FilterSelection();
|
||||
Reset();
|
||||
emit FilterChanged(_currentSelection);
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::SelectionChanged(const QString &)
|
||||
{
|
||||
emit FilterChanged(CurrentSelection());
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::ItemAdd(const QString &)
|
||||
{
|
||||
const QSignalBlocker b(this);
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool FilterSelectionWidget::NameUsed(const QString &name)
|
||||
{
|
||||
return _currentSelection._type == FilterSelection::Type::VARIABLE &&
|
||||
currentText() == name;
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::ItemRemove(const QString &name)
|
||||
{
|
||||
if (NameUsed(name)) {
|
||||
_currentSelection = FilterSelection();
|
||||
emit FilterChanged(_currentSelection);
|
||||
}
|
||||
const QSignalBlocker b(this);
|
||||
Reset();
|
||||
}
|
||||
|
||||
void FilterSelectionWidget::ItemRename(const QString &, const QString &)
|
||||
{
|
||||
const QSignalBlocker b(this);
|
||||
Reset();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
74
src/utils/filter-selection.hpp
Normal file
74
src/utils/filter-selection.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
#include "source-selection.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class FilterSelection {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *name = "filter") const;
|
||||
void Load(obs_data_t *obj, const SourceSelection &source,
|
||||
const char *name = "filter");
|
||||
|
||||
enum class Type {
|
||||
SOURCE,
|
||||
VARIABLE,
|
||||
};
|
||||
|
||||
Type GetType() const { return _type; }
|
||||
OBSWeakSource GetFilter(const SourceSelection &source) const;
|
||||
std::string ToString(bool resolve = false) const;
|
||||
|
||||
private:
|
||||
// TODO: Remove in future version
|
||||
// Used for backwards compatability to older settings versions
|
||||
void LoadFallback(obs_data_t *obj, const SourceSelection &source,
|
||||
const char *name);
|
||||
|
||||
OBSWeakSource _filter;
|
||||
// Storing the name separately as depending on the source selection
|
||||
// the filter source might not be available at the moment.
|
||||
std::string _filterName = "";
|
||||
std::weak_ptr<Variable> _variable;
|
||||
Type _type = Type::SOURCE;
|
||||
friend class FilterSelectionWidget;
|
||||
};
|
||||
|
||||
class FilterSelectionWidget : public QComboBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterSelectionWidget(QWidget *parent, SourceSelectionWidget *sources,
|
||||
bool addVariables = true);
|
||||
void SetFilter(const SourceSelection &, const FilterSelection &);
|
||||
|
||||
signals:
|
||||
void FilterChanged(const FilterSelection &);
|
||||
|
||||
public slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
private slots:
|
||||
void SelectionChanged(const QString &name);
|
||||
void ItemAdd(const QString &name);
|
||||
void ItemRemove(const QString &name);
|
||||
void ItemRename(const QString &oldName, const QString &newName);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
FilterSelection CurrentSelection();
|
||||
void PopulateSelection();
|
||||
bool NameUsed(const QString &name);
|
||||
|
||||
bool _addVariables;
|
||||
FilterSelection _currentSelection;
|
||||
SourceSelection _source;
|
||||
|
||||
// Order of entries
|
||||
// 1. "select entry" entry
|
||||
// 2. Variables
|
||||
// 3. Regular filters
|
||||
const int _selectIdx = 0;
|
||||
int _variablesEndIdx = -1;
|
||||
int _filterEndIdx = -1;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -105,6 +105,21 @@ std::string SourceSelection::ToString(bool resolve) const
|
||||
return "";
|
||||
}
|
||||
|
||||
bool SourceSelection::operator==(const SourceSelection &other) const
|
||||
{
|
||||
if (_type != other._type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_type == Type::SOURCE) {
|
||||
return _source == other._source;
|
||||
}
|
||||
|
||||
auto v1 = _variable.lock();
|
||||
auto v2 = other._variable.lock();
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
SourceSelection SourceSelectionWidget::CurrentSelection()
|
||||
{
|
||||
SourceSelection s;
|
||||
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
void SetSource(OBSWeakSource);
|
||||
std::string ToString(bool resolve = false) const;
|
||||
|
||||
bool operator==(const SourceSelection &) const;
|
||||
|
||||
private:
|
||||
// TODO: Remove in future version
|
||||
// Used for backwards compatability to older settings versions
|
||||
|
||||
@@ -511,6 +511,25 @@ QStringList GetSourceNames()
|
||||
return list;
|
||||
}
|
||||
|
||||
QStringList GetFilterNames(OBSWeakSource weakSource)
|
||||
{
|
||||
if (!weakSource) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList list;
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *ptr) {
|
||||
auto name = obs_source_get_name(filter);
|
||||
QStringList *list = reinterpret_cast<QStringList *>(ptr);
|
||||
*list << QString(name);
|
||||
};
|
||||
|
||||
auto s = obs_weak_source_get_source(weakSource);
|
||||
obs_source_enum_filters(s, enumFilters, &list);
|
||||
obs_source_release(s);
|
||||
return list;
|
||||
}
|
||||
|
||||
void PopulateSourceSelection(QComboBox *list, bool addSelect)
|
||||
{
|
||||
auto sources = GetSourceNames();
|
||||
@@ -815,18 +834,11 @@ void PopulateSourcesWithFilterSelection(QComboBox *list)
|
||||
|
||||
void PopulateFilterSelection(QComboBox *list, OBSWeakSource weakSource)
|
||||
{
|
||||
auto enumFilters = [](obs_source_t *, obs_source_t *filter, void *ptr) {
|
||||
QComboBox *list = reinterpret_cast<QComboBox *>(ptr);
|
||||
auto name = obs_source_get_name(filter);
|
||||
list->addItem(name);
|
||||
};
|
||||
|
||||
auto s = obs_weak_source_get_source(weakSource);
|
||||
obs_source_enum_filters(s, enumFilters, list);
|
||||
list->model()->sort(0);
|
||||
auto filters = GetFilterNames(weakSource);
|
||||
filters.sort();
|
||||
list->addItems(filters);
|
||||
AddSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectFilter"));
|
||||
obs_source_release(s);
|
||||
list->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ QStringList GetMediaSourceNames();
|
||||
QStringList GetVideoSourceNames();
|
||||
QStringList GetSceneNames();
|
||||
QStringList GetSourceNames();
|
||||
QStringList GetFilterNames(OBSWeakSource weakSource);
|
||||
|
||||
/* Populate list helpers */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user