#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(_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(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 == -1 || name.isEmpty()) { return s; } 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(); 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(-1); } FilterSelectionWidget::FilterSelectionWidget(QWidget *parent, SourceSelectionWidget *sources, bool addVariables) : FilterComboBox(parent, obs_module_text("AdvSceneSwitcher.selectFilter")), _addVariables(addVariables) { setDuplicatesEnabled(true); QWidget::connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectionChanged(int))); 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 = -1; switch (filter.GetType()) { case FilterSelection::Type::SOURCE: { if (_filterEndIdx == -1) { idx = -1; break; } idx = FindIdxInRagne(this, _variablesEndIdx, _filterEndIdx, filter.ToString()); break; } case FilterSelection::Type::VARIABLE: { if (_variablesEndIdx == -1) { idx = -1; break; } idx = FindIdxInRagne(this, _selectIdx, _variablesEndIdx, filter.ToString()); break; default: idx = -1; 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(int) { _currentSelection = CurrentSelection(); 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