Add source selection helpers

This commit is contained in:
WarmUpTill 2022-12-04 08:37:17 +01:00 committed by WarmUpTill
parent e4f9ccec3f
commit cd74534e4c
3 changed files with 317 additions and 0 deletions

View File

@ -264,6 +264,8 @@ target_sources(
src/utils/section.hpp
src/utils/slider-spinbox.cpp
src/utils/slider-spinbox.hpp
src/utils/source-selection.cpp
src/utils/source-selection.hpp
src/utils/transition-selection.cpp
src/utils/transition-selection.hpp
src/utils/utility.cpp

View File

@ -0,0 +1,246 @@
#include "source-selection.hpp"
#include "advanced-scene-switcher.hpp"
constexpr std::string_view typeSaveName = "type";
constexpr std::string_view nameSaveName = "name";
void SourceSelection::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(),
GetWeakSourceName(_source).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 SourceSelection::Load(obs_data_t *obj, const char *name)
{
auto data = obs_data_get_obj(obj, name);
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
auto targetName = obs_data_get_string(data, nameSaveName.data());
switch (_type) {
case Type::SOURCE:
_source = GetWeakSourceByName(targetName);
break;
case Type::VARIABLE:
_variable = GetWeakVariableByName(targetName);
break;
default:
break;
}
if (!obs_data_has_user_value(data, typeSaveName.data())) {
LoadFallback(obj, name);
}
obs_data_release(data);
}
void SourceSelection::LoadFallback(obs_data_t *obj, const char *name)
{
blog(LOG_INFO, "Falling back to Load() without variable support");
_type = Type::SOURCE;
auto targetName = obs_data_get_string(obj, name);
_source = GetWeakSourceByName(targetName);
}
OBSWeakSource SourceSelection::GetSource() const
{
switch (_type) {
case Type::SOURCE:
return _source;
case Type::VARIABLE: {
auto var = _variable.lock();
if (!var) {
return nullptr;
}
return GetWeakSourceByName(var->Value().c_str());
}
default:
break;
}
return nullptr;
}
void SourceSelection::SetSource(OBSWeakSource source)
{
_type = Type::SOURCE;
_source = source;
}
std::string SourceSelection::ToString() const
{
switch (_type) {
case Type::SOURCE:
return GetWeakSourceName(_source);
case Type::VARIABLE: {
auto var = _variable.lock();
if (!var) {
return "";
}
return var->Name();
}
default:
break;
}
return "";
}
SourceSelection SourceSelectionWidget::CurrentSelection()
{
SourceSelection s;
const int idx = currentIndex();
const auto name = currentText();
if (idx < _variablesEndIdx) {
s._type = SourceSelection::Type::VARIABLE;
s._variable = GetWeakVariableByQString(name);
} else if (idx < _sourcesEndIdx) {
s._type = SourceSelection::Type::SOURCE;
s._source = GetWeakSourceByQString(name);
}
return s;
}
void SourceSelectionWidget::Reset()
{
auto previousSel = _currentSelection;
PopulateSelection();
SetSource(previousSel);
}
void SourceSelectionWidget::PopulateSelection()
{
clear();
addSelectionEntry(this,
obs_module_text("AdvSceneSwitcher.selectSource"));
insertSeparator(count());
if (_addVariables) {
const QStringList variables = GetVariablesNameList();
addSelectionGroup(this, variables);
}
_variablesEndIdx = count();
addSelectionGroup(this, _sourceNames);
_sourcesEndIdx = count();
// Remove last separator
removeItem(count() - 1);
setCurrentIndex(0);
}
SourceSelectionWidget::SourceSelectionWidget(QWidget *parent,
const QStringList &sourceNames,
bool addVariables)
: QComboBox(parent),
_addVariables(addVariables),
_sourceNames(sourceNames)
{
setDuplicatesEnabled(true);
PopulateSelection();
QWidget::connect(this, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(SelectionChanged(const QString &)));
// 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 SourceSelectionWidget::SetSource(const SourceSelection &s)
{
int idx = 0;
switch (s.GetType()) {
case SourceSelection::Type::SOURCE: {
if (_sourcesEndIdx == -1) {
idx = 0;
break;
}
idx = findIdxInRagne(this, _variablesEndIdx, _sourcesEndIdx,
s.ToString());
break;
}
case SourceSelection::Type::VARIABLE: {
if (_variablesEndIdx == -1) {
idx = 0;
break;
}
idx = findIdxInRagne(this, _selectIdx, _variablesEndIdx,
s.ToString());
break;
default:
idx = 0;
break;
}
}
setCurrentIndex(idx);
_currentSelection = s;
}
void SourceSelectionWidget::SetSourceNameList(const QStringList &list)
{
_sourceNames = list;
Reset();
}
void SourceSelectionWidget::SelectionChanged(const QString &)
{
_currentSelection = CurrentSelection();
emit SourceChanged(_currentSelection);
}
void SourceSelectionWidget::ItemAdd(const QString &)
{
blockSignals(true);
Reset();
blockSignals(false);
}
bool SourceSelectionWidget::NameUsed(const QString &name)
{
if (_currentSelection._type == SourceSelection::Type::VARIABLE) {
auto var = _currentSelection._variable.lock();
if (var && var->Name() == name.toStdString()) {
return true;
}
}
return false;
}
void SourceSelectionWidget::ItemRemove(const QString &name)
{
if (!NameUsed(name)) {
blockSignals(true);
}
Reset();
blockSignals(false);
}
void SourceSelectionWidget::ItemRename(const QString &, const QString &)
{
blockSignals(true);
Reset();
blockSignals(false);
}

View File

@ -0,0 +1,69 @@
#pragma once
#include "variable.hpp"
#include "utility.hpp"
#include <QComboBox>
class SourceSelection {
public:
void Save(obs_data_t *obj, const char *name = "source") const;
void Load(obs_data_t *obj, const char *name = "source");
enum class Type {
SOURCE,
VARIABLE,
};
Type GetType() const { return _type; }
OBSWeakSource GetSource() const;
void SetSource(OBSWeakSource);
std::string ToString() const;
private:
// TODO: Remove in future version
// Used for backwards compatability to older settings versions
void LoadFallback(obs_data_t *obj, const char *name);
OBSWeakSource _source;
std::weak_ptr<Variable> _variable;
Type _type = Type::SOURCE;
friend class SourceSelectionWidget;
};
class SourceSelectionWidget : public QComboBox {
Q_OBJECT
public:
SourceSelectionWidget(QWidget *parent, const QStringList &sourceNames,
bool addVariables = true);
void SetSource(const SourceSelection &);
void SetSourceNameList(const QStringList &);
signals:
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();
SourceSelection CurrentSelection();
void PopulateSelection();
bool NameUsed(const QString &name);
bool _addVariables;
QStringList _sourceNames;
SourceSelection _currentSelection;
// Order of entries
// 1. "select entry" entry
// 2. Variables
// 3. Regular sources
const int _selectIdx = 0;
int _variablesEndIdx = -1;
int _sourcesEndIdx = -1;
};