mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 01:44:49 -05:00
1268 lines
36 KiB
C++
1268 lines
36 KiB
C++
#include "scene-item-selection.hpp"
|
|
#include "layout-helpers.hpp"
|
|
#include "obs-module-helper.hpp"
|
|
#include "selection-helpers.hpp"
|
|
#include "source-helpers.hpp"
|
|
#include "ui-helpers.hpp"
|
|
|
|
#include <set>
|
|
#include <variant>
|
|
|
|
using NameClashMode = advss::SceneItemSelectionWidget::NameClashMode;
|
|
using ConflictIndex = std::variant<int, NameClashMode>;
|
|
|
|
Q_DECLARE_METATYPE(NameClashMode)
|
|
Q_DECLARE_METATYPE(ConflictIndex);
|
|
|
|
namespace advss {
|
|
|
|
using NameConflictSelection = SceneItemSelection::NameConflictSelection;
|
|
|
|
constexpr std::string_view typeSaveName = "type";
|
|
constexpr std::string_view itemSaveName = "item";
|
|
constexpr std::string_view indexSaveName = "index";
|
|
constexpr std::string_view indexEndSaveName = "indexEnd";
|
|
constexpr std::string_view nameConflictIndexSaveName = "idx";
|
|
constexpr std::string_view nameConflictIndexSelectionSaveName = "idxType";
|
|
constexpr std::string_view patternSaveName = "pattern";
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
struct NameMatchData {
|
|
std::string name;
|
|
std::vector<OBSSceneItem> items = {};
|
|
};
|
|
|
|
static bool getSceneItemsByNameHelper(obs_scene_t *, obs_sceneitem_t *item,
|
|
void *ptr)
|
|
{
|
|
auto itemInfo = reinterpret_cast<NameMatchData *>(ptr);
|
|
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
|
if (itemInfo->name == sourceName) {
|
|
itemInfo->items.emplace_back(item);
|
|
}
|
|
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, getSceneItemsByNameHelper, ptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static std::vector<OBSSceneItem> getSceneItemsWithName(obs_scene_t *scene,
|
|
const std::string &name)
|
|
{
|
|
NameMatchData itemInfo = {name};
|
|
obs_scene_enum_items(scene, getSceneItemsByNameHelper, &itemInfo);
|
|
return itemInfo.items;
|
|
}
|
|
|
|
struct NamePatternMatchData {
|
|
std::string pattern;
|
|
const RegexConfig ®ex;
|
|
std::vector<OBSSceneItem> items = {};
|
|
};
|
|
|
|
static bool getSceneItemsByPatternHelper(obs_scene_t *, obs_sceneitem_t *item,
|
|
void *ptr)
|
|
{
|
|
auto data = reinterpret_cast<NamePatternMatchData *>(ptr);
|
|
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
|
|
if (data->regex.Matches(sourceName, data->pattern)) {
|
|
data->items.emplace_back(item);
|
|
}
|
|
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, getSceneItemsByPatternHelper, ptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct ItemCountData {
|
|
std::string name;
|
|
int count = 0;
|
|
};
|
|
|
|
static bool countSceneItemName(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|
{
|
|
auto data = reinterpret_cast<ItemCountData *>(ptr);
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, countSceneItemName, ptr);
|
|
}
|
|
auto name = obs_source_get_name(obs_sceneitem_get_source(item));
|
|
if (name == data->name) {
|
|
data->count++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int getCountOfSceneItemOccurance(const SceneSelection &s,
|
|
const std::string &name,
|
|
bool enumAllScenes = true)
|
|
{
|
|
ItemCountData data{name};
|
|
if (enumAllScenes && (s.GetType() != SceneSelection::Type::SCENE)) {
|
|
auto enumScenes = [](void *param, obs_source_t *source) {
|
|
if (!source) {
|
|
return true;
|
|
}
|
|
auto data = reinterpret_cast<ItemCountData *>(param);
|
|
auto scene = obs_scene_from_source(source);
|
|
obs_scene_enum_items(scene, countSceneItemName, data);
|
|
return true;
|
|
};
|
|
OBSCanvasAutoRelease canvas = OBSGetStrongRef(s.GetCanvas());
|
|
obs_canvas_enum_scenes(canvas, enumScenes, &data);
|
|
} else {
|
|
auto source = obs_weak_source_get_source(s.GetScene(false));
|
|
auto scene = obs_scene_from_source(source);
|
|
obs_scene_enum_items(scene, countSceneItemName, &data);
|
|
obs_source_release(source);
|
|
}
|
|
return data.count;
|
|
}
|
|
|
|
struct IdxData {
|
|
int idxStart = 0;
|
|
int idxEnd = -1;
|
|
int curIdx = 0;
|
|
std::vector<OBSSceneItem> items = {};
|
|
};
|
|
|
|
static bool getSceneItemAtIdx(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|
{
|
|
auto data = reinterpret_cast<IdxData *>(ptr);
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, getSceneItemAtIdx, ptr);
|
|
}
|
|
if (data->curIdx > data->idxEnd) {
|
|
return false;
|
|
}
|
|
if (data->curIdx >= data->idxStart && data->curIdx <= data->idxEnd) {
|
|
data->items.emplace_back(item);
|
|
}
|
|
data->curIdx++;
|
|
return true;
|
|
}
|
|
|
|
struct GroupData {
|
|
std::string type;
|
|
std::vector<OBSSceneItem> items = {};
|
|
};
|
|
|
|
static bool getSceneItemsOfType(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|
{
|
|
auto data = reinterpret_cast<GroupData *>(ptr);
|
|
auto sourceTypeName = obs_source_get_display_name(
|
|
obs_source_get_id(obs_sceneitem_get_source(item)));
|
|
if (sourceTypeName && data->type == sourceTypeName) {
|
|
data->items.emplace_back(item);
|
|
}
|
|
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, getSceneItemsOfType, ptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool getAllSceneItems(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|
{
|
|
auto items = reinterpret_cast<std::vector<OBSSceneItem> *>(ptr);
|
|
items->emplace_back(item);
|
|
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, getAllSceneItems, ptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
void SceneItemSelection::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));
|
|
obs_data_set_int(data, nameConflictIndexSelectionSaveName.data(),
|
|
static_cast<int>(_nameConflictSelectionType));
|
|
if (_nameConflictSelectionType == NameConflictSelection::INDIVIDUAL) {
|
|
obs_data_set_int(data, nameConflictIndexSaveName.data(),
|
|
_nameConflictSelectionIndex);
|
|
} else {
|
|
obs_data_set_int(data, nameConflictIndexSaveName.data(), 0);
|
|
}
|
|
|
|
switch (_type) {
|
|
case SceneItemSelection::Type::SOURCE_NAME:
|
|
obs_data_set_string(data, itemSaveName.data(),
|
|
GetWeakSourceName(_source).c_str());
|
|
break;
|
|
case SceneItemSelection::Type::VARIABLE_NAME: {
|
|
auto var = _variable.lock();
|
|
if (var) {
|
|
obs_data_set_string(data, itemSaveName.data(),
|
|
var->Name().c_str());
|
|
}
|
|
break;
|
|
}
|
|
case SceneItemSelection::Type::SOURCE_NAME_PATTERN:
|
|
_pattern.Save(data, patternSaveName.data());
|
|
_regex.Save(data);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_GROUP:
|
|
obs_data_set_string(data, itemSaveName.data(),
|
|
GetWeakSourceName(_source).c_str());
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_TYPE:
|
|
obs_data_set_string(obj, "sourceGroup", _sourceType.c_str());
|
|
break;
|
|
case SceneItemSelection::Type::INDEX:
|
|
_index.Save(data, indexSaveName.data());
|
|
break;
|
|
case SceneItemSelection::Type::INDEX_RANGE:
|
|
_index.Save(data, indexSaveName.data());
|
|
_indexEnd.Save(data, indexEndSaveName.data());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
obs_data_set_obj(obj, name, data);
|
|
obs_data_release(data);
|
|
}
|
|
|
|
// TODO: Remove in future version
|
|
void SceneItemSelection::Load(obs_data_t *obj, const char *name,
|
|
const char *typeName, const char *idxName)
|
|
{
|
|
_type = Type::SOURCE_NAME;
|
|
_nameConflictSelectionType = static_cast<NameConflictSelection>(
|
|
obs_data_get_int(obj, typeName));
|
|
_nameConflictSelectionIndex = obs_data_get_int(obj, idxName);
|
|
auto sceneItemName = obs_data_get_string(obj, name);
|
|
_source = GetWeakSourceByName(sceneItemName);
|
|
}
|
|
|
|
void SceneItemSelection::Load(obs_data_t *obj, const char *name)
|
|
{
|
|
// TODO: Remove in future version
|
|
if (!obs_data_has_user_value(obj, name)) {
|
|
Load(obj, "sceneItem", "sceneItemTarget", "sceneItemIdx");
|
|
return;
|
|
}
|
|
|
|
auto data = obs_data_get_obj(obj, name);
|
|
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
|
|
_nameConflictSelectionType = static_cast<NameConflictSelection>(
|
|
obs_data_get_int(data,
|
|
nameConflictIndexSelectionSaveName.data()));
|
|
_nameConflictSelectionIndex =
|
|
obs_data_get_int(data, nameConflictIndexSaveName.data());
|
|
const auto itemName = obs_data_get_string(data, itemSaveName.data());
|
|
switch (_type) {
|
|
case SceneItemSelection::Type::SOURCE_NAME:
|
|
_source = GetWeakSourceByName(itemName);
|
|
break;
|
|
case SceneItemSelection::Type::VARIABLE_NAME:
|
|
_variable = GetWeakVariableByName(itemName);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_NAME_PATTERN:
|
|
_pattern.Load(data, patternSaveName.data());
|
|
_regex.Load(data);
|
|
_regex.SetEnabled(true); // No reason to disable it
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_GROUP:
|
|
_source = GetWeakSourceByName(itemName);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_TYPE:
|
|
_sourceType = obs_data_get_string(obj, "sourceGroup");
|
|
break;
|
|
case SceneItemSelection::Type::INDEX:
|
|
_index.Load(data, indexSaveName.data());
|
|
break;
|
|
case SceneItemSelection::Type::INDEX_RANGE:
|
|
_index.Load(data, indexSaveName.data());
|
|
_indexEnd.Load(data, indexEndSaveName.data());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
obs_data_release(data);
|
|
}
|
|
|
|
void SceneItemSelection::SetSourceTypeSelection(const char *type)
|
|
{
|
|
_type = Type::SOURCE_TYPE;
|
|
_sourceType = type;
|
|
}
|
|
|
|
void SceneItemSelection::ResolveVariables()
|
|
{
|
|
_index.ResolveVariables();
|
|
_indexEnd.ResolveVariables();
|
|
_pattern = std::string(_pattern);
|
|
|
|
if (_type != Type::VARIABLE_NAME) {
|
|
return;
|
|
}
|
|
_type = Type::SOURCE_NAME;
|
|
|
|
auto variable = _variable.lock();
|
|
if (variable) {
|
|
_source = GetWeakSourceByName(variable->Value().c_str());
|
|
} else {
|
|
_source = nullptr;
|
|
}
|
|
}
|
|
|
|
void SceneItemSelection::ReduceBasedOnIndexSelection(
|
|
std::vector<OBSSceneItem> &items) const
|
|
{
|
|
if (_nameConflictSelectionType ==
|
|
SceneItemSelection::NameConflictSelection::ALL ||
|
|
_nameConflictSelectionType ==
|
|
SceneItemSelection::NameConflictSelection::ANY) {
|
|
return;
|
|
}
|
|
// Index order starts at the bottom and increases to the top
|
|
// As this might be confusing reverse that order internally
|
|
int idx = items.size() - 1 - _nameConflictSelectionIndex;
|
|
if (idx < 0 || idx >= (int)items.size()) {
|
|
items.clear();
|
|
return;
|
|
}
|
|
|
|
items = {items[idx]};
|
|
}
|
|
|
|
std::vector<OBSSceneItem> SceneItemSelection::GetSceneItemsByName(
|
|
const SceneSelection &sceneSelection) const
|
|
{
|
|
auto s = obs_weak_source_get_source(sceneSelection.GetScene(false));
|
|
OBSSceneAutoRelease scene = obs_scene_from_source(s);
|
|
std::string name;
|
|
if (_type == Type::VARIABLE_NAME) {
|
|
auto var = _variable.lock();
|
|
if (!var) {
|
|
return {};
|
|
}
|
|
name = var->Value();
|
|
} else {
|
|
name = GetWeakSourceName(_source);
|
|
}
|
|
auto items = getSceneItemsWithName(scene, name);
|
|
ReduceBasedOnIndexSelection(items);
|
|
return items;
|
|
}
|
|
|
|
std::vector<OBSSceneItem> SceneItemSelection::GetSceneItemsByPattern(
|
|
const SceneSelection &sceneSelection) const
|
|
{
|
|
auto s = obs_weak_source_get_source(sceneSelection.GetScene(false));
|
|
auto scene = obs_scene_from_source(s);
|
|
NamePatternMatchData data{_pattern, _regex};
|
|
obs_scene_enum_items(scene, getSceneItemsByPatternHelper, &data);
|
|
obs_source_release(s);
|
|
ReduceBasedOnIndexSelection(data.items);
|
|
return data.items;
|
|
}
|
|
|
|
std::vector<OBSSceneItem> SceneItemSelection::GetSceneItemsOfGroup() const
|
|
{
|
|
OBSSourceAutoRelease group = OBSGetStrongRef(_source);
|
|
obs_scene_t *groupScene = obs_group_from_source(group);
|
|
std::vector<OBSSceneItem> sceneItems;
|
|
obs_scene_enum_items(groupScene, getAllSceneItems, &sceneItems);
|
|
return sceneItems;
|
|
}
|
|
|
|
std::vector<OBSSceneItem> SceneItemSelection::GetSceneItemsByType(
|
|
const SceneSelection &sceneSelection) const
|
|
{
|
|
if (_sourceType.empty()) {
|
|
return {};
|
|
}
|
|
|
|
auto s = obs_weak_source_get_source(sceneSelection.GetScene(false));
|
|
auto scene = obs_scene_from_source(s);
|
|
GroupData data{_sourceType};
|
|
obs_scene_enum_items(scene, getSceneItemsOfType, &data);
|
|
obs_source_release(s);
|
|
ReduceBasedOnIndexSelection(data.items);
|
|
return data.items;
|
|
}
|
|
|
|
std::vector<OBSSceneItem> SceneItemSelection::GetSceneItemsByIdx(
|
|
const SceneSelection &sceneSelection) const
|
|
{
|
|
if (!_index.HasValidValue()) {
|
|
return {};
|
|
}
|
|
|
|
auto sceneWeakSource = sceneSelection.GetScene(false);
|
|
int count = GetSceneItemCount(sceneWeakSource);
|
|
if (count == 0) {
|
|
return {};
|
|
}
|
|
|
|
// Index order starts at the bottom and increases to the top
|
|
// As this might be confusing reverse that order internally
|
|
//
|
|
// Also subtract 1 as the user facing index starts at 1
|
|
int idx = count - _index.GetValue();
|
|
int idxEnd = _type == Type::INDEX_RANGE ? count - _indexEnd.GetValue()
|
|
: idx;
|
|
if (idx > idxEnd) {
|
|
std::swap(idx, idxEnd);
|
|
}
|
|
|
|
IdxData data{idx, idxEnd};
|
|
auto s = obs_weak_source_get_source(sceneWeakSource);
|
|
auto scene = obs_scene_from_source(s);
|
|
obs_scene_enum_items(scene, getSceneItemAtIdx, &data);
|
|
obs_source_release(s);
|
|
return data.items;
|
|
}
|
|
|
|
std::vector<OBSSceneItem>
|
|
SceneItemSelection::GetAllSceneItems(const SceneSelection &sceneSelection) const
|
|
{
|
|
auto s = obs_weak_source_get_source(sceneSelection.GetScene(false));
|
|
auto scene = obs_scene_from_source(s);
|
|
std::vector<OBSSceneItem> items;
|
|
obs_scene_enum_items(scene, getAllSceneItems, &items);
|
|
obs_source_release(s);
|
|
return items;
|
|
}
|
|
|
|
SceneItemSelection::NameConflictSelection
|
|
SceneItemSelection::GetIndexType() const
|
|
{
|
|
return _nameConflictSelectionType;
|
|
}
|
|
|
|
std::vector<OBSSceneItem>
|
|
SceneItemSelection::GetSceneItems(const SceneSelection &sceneSelection) const
|
|
{
|
|
switch (_type) {
|
|
case Type::SOURCE_NAME:
|
|
case Type::VARIABLE_NAME:
|
|
return GetSceneItemsByName(sceneSelection);
|
|
case Type::SOURCE_NAME_PATTERN:
|
|
return GetSceneItemsByPattern(sceneSelection);
|
|
case Type::SOURCE_GROUP:
|
|
return GetSceneItemsOfGroup();
|
|
case Type::SOURCE_TYPE:
|
|
return GetSceneItemsByType(sceneSelection);
|
|
case Type::INDEX:
|
|
case Type::INDEX_RANGE:
|
|
return GetSceneItemsByIdx(sceneSelection);
|
|
case Type::ALL:
|
|
case Type::ANY:
|
|
return GetAllSceneItems(sceneSelection);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
bool SceneItemSelection::IsSelectionOfTypeAny() const
|
|
{
|
|
if (_type == Type::ANY) {
|
|
return true;
|
|
}
|
|
|
|
if (_type == Type::ALL) {
|
|
return false;
|
|
}
|
|
|
|
if (_type == Type::INDEX_RANGE) {
|
|
return false;
|
|
}
|
|
|
|
if (_nameConflictSelectionType == NameConflictSelection::ANY) {
|
|
return true;
|
|
}
|
|
|
|
if (_nameConflictSelectionType == NameConflictSelection::ALL) {
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::string SceneItemSelection::ToString(bool resolve) const
|
|
{
|
|
switch (_type) {
|
|
case Type::SOURCE_NAME:
|
|
return GetWeakSourceName(_source);
|
|
case Type::VARIABLE_NAME: {
|
|
auto var = _variable.lock();
|
|
if (!var) {
|
|
return "";
|
|
}
|
|
if (resolve) {
|
|
return var->Name() + "[" + var->Value() + "]";
|
|
}
|
|
return var->Name();
|
|
}
|
|
case Type::SOURCE_NAME_PATTERN:
|
|
if (resolve) {
|
|
return std::string(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern")) +
|
|
" \"" + std::string(_pattern) + "\"";
|
|
}
|
|
return "";
|
|
case Type::SOURCE_GROUP:
|
|
if (resolve) {
|
|
return std::string(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceGroup")) +
|
|
" \"" + GetWeakSourceName(_source) + "\"";
|
|
}
|
|
return _sourceType;
|
|
case Type::SOURCE_TYPE:
|
|
if (resolve) {
|
|
return std::string(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceType")) +
|
|
" \"" + std::string(_sourceType) + "\"";
|
|
}
|
|
return _sourceType;
|
|
case Type::INDEX:
|
|
if (resolve) {
|
|
return std::string(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.index")) +
|
|
" " + std::to_string(_index);
|
|
}
|
|
return "";
|
|
case Type::INDEX_RANGE:
|
|
if (resolve) {
|
|
return std::string(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.indexRange")) +
|
|
" " + std::to_string(_index) + " - " +
|
|
std::to_string(_indexEnd);
|
|
}
|
|
return "";
|
|
case Type::ALL:
|
|
return obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.all");
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
static bool populateSceneItemSelectionHelper(obs_scene_t *,
|
|
obs_sceneitem_t *item, void *ptr)
|
|
{
|
|
auto names = reinterpret_cast<QStringList *>(ptr);
|
|
if (obs_sceneitem_is_group(item)) {
|
|
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
|
obs_scene_enum_items(scene, populateSceneItemSelectionHelper,
|
|
ptr);
|
|
}
|
|
auto name = obs_source_get_name(obs_sceneitem_get_source(item));
|
|
names->append(name);
|
|
return true;
|
|
}
|
|
|
|
static QStringList getSceneItemsList(SceneSelection &s)
|
|
{
|
|
QStringList names;
|
|
if (s.GetType() != SceneSelection::Type::SCENE) {
|
|
auto enumScenes = [](void *param, obs_source_t *source) {
|
|
if (!source) {
|
|
return true;
|
|
}
|
|
auto names = reinterpret_cast<QStringList *>(param);
|
|
auto scene = obs_scene_from_source(source);
|
|
obs_scene_enum_items(
|
|
scene, populateSceneItemSelectionHelper, names);
|
|
return true;
|
|
};
|
|
|
|
OBSCanvasAutoRelease canvas = OBSGetStrongRef(s.GetCanvas());
|
|
obs_canvas_enum_scenes(canvas, enumScenes, &names);
|
|
} else {
|
|
auto source = obs_weak_source_get_source(s.GetScene(false));
|
|
auto scene = obs_scene_from_source(source);
|
|
obs_scene_enum_items(scene, populateSceneItemSelectionHelper,
|
|
&names);
|
|
obs_source_release(source);
|
|
}
|
|
|
|
names.removeDuplicates();
|
|
names.sort();
|
|
return names;
|
|
}
|
|
|
|
void SceneItemSelectionWidget::PopulateItemSelection()
|
|
{
|
|
_sources->clear();
|
|
const QStringList sceneItems = getSceneItemsList(_scene);
|
|
AddSelectionGroup(_sources, sceneItems, false);
|
|
_sources->setCurrentIndex(-1);
|
|
}
|
|
|
|
static inline void populateMessageTypeSelection(
|
|
QComboBox *list,
|
|
const std::vector<SceneItemSelection::Type> &allowedTypes)
|
|
{
|
|
const static std::map<SceneItemSelection::Type, std::string> types = {
|
|
{SceneItemSelection::Type::SOURCE_NAME,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceName"},
|
|
{SceneItemSelection::Type::VARIABLE_NAME,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceVariable"},
|
|
{SceneItemSelection::Type::SOURCE_NAME_PATTERN,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern"},
|
|
{SceneItemSelection::Type::SOURCE_GROUP,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceGroup"},
|
|
{SceneItemSelection::Type::SOURCE_TYPE,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceType"},
|
|
{SceneItemSelection::Type::INDEX,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.index"},
|
|
{SceneItemSelection::Type::INDEX_RANGE,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.indexRange"},
|
|
{SceneItemSelection::Type::ALL,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.all"},
|
|
{SceneItemSelection::Type::ANY,
|
|
"AdvSceneSwitcher.sceneItemSelection.type.any"},
|
|
};
|
|
|
|
for (const auto &type : allowedTypes) {
|
|
const auto it = types.find(type);
|
|
assert(it != types.end());
|
|
const auto &[_, name] = *it;
|
|
list->addItem(obs_module_text(name.c_str()),
|
|
static_cast<int>(type));
|
|
}
|
|
}
|
|
|
|
static void
|
|
populateTypeList(std::set<QString> &list,
|
|
std::function<bool(size_t idx, const char **id)> enumFunc)
|
|
{
|
|
size_t idx = 0;
|
|
char buffer[512] = {};
|
|
const char **idPtr = (const char **)(&buffer);
|
|
while (enumFunc(idx++, idPtr)) {
|
|
// The audio_line source type is only used OBS internally
|
|
if (strcmp(*idPtr, "audio_line") == 0) {
|
|
continue;
|
|
}
|
|
QString name = obs_source_get_display_name(*idPtr);
|
|
if (name.isEmpty()) {
|
|
list.insert(*idPtr);
|
|
} else {
|
|
list.insert(name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void populateSourceTypeSelection(QComboBox *list)
|
|
{
|
|
std::set<QString> sourceTypes;
|
|
populateTypeList(sourceTypes, obs_enum_source_types);
|
|
std::set<QString> filterTypes;
|
|
populateTypeList(filterTypes, obs_enum_filter_types);
|
|
std::set<QString> transitionTypes;
|
|
populateTypeList(transitionTypes, obs_enum_transition_types);
|
|
|
|
for (const auto &name : sourceTypes) {
|
|
if (name.isEmpty()) {
|
|
continue;
|
|
}
|
|
if (filterTypes.find(name) == filterTypes.end() &&
|
|
transitionTypes.find(name) == transitionTypes.end()) {
|
|
list->addItem(name);
|
|
}
|
|
}
|
|
|
|
list->model()->sort(0);
|
|
AddSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem"));
|
|
list->setCurrentIndex(0);
|
|
}
|
|
|
|
static void populateSourceGroupSelection(QComboBox *list)
|
|
{
|
|
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
|
{
|
|
QStringList *list = reinterpret_cast<QStringList *>(param);
|
|
if (obs_source_is_group(source)) {
|
|
*list << obs_source_get_name(source);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
QStringList names;
|
|
obs_enum_sources(sourceEnum, &names);
|
|
|
|
for (const auto &name : names) {
|
|
if (name.isEmpty()) {
|
|
continue;
|
|
}
|
|
list->addItem(name);
|
|
}
|
|
|
|
list->model()->sort(0);
|
|
AddSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectItem"));
|
|
list->setCurrentIndex(0);
|
|
}
|
|
|
|
SceneItemSelectionWidget::SceneItemSelectionWidget(
|
|
QWidget *parent,
|
|
const std::vector<SceneItemSelection::Type> &selections,
|
|
NameClashMode mode)
|
|
: QWidget(parent),
|
|
_controlsLayout(new QHBoxLayout),
|
|
_sources(new FilterComboBox(
|
|
this, obs_module_text("AdvSceneSwitcher.selectItem"))),
|
|
_sourceGroups(new FilterComboBox(
|
|
this, obs_module_text("AdvSceneSwitcher.selectItem"))),
|
|
_variables(new VariableSelection(this)),
|
|
_nameConflictIndex(new QComboBox(this)),
|
|
_index(new VariableSpinBox(this)),
|
|
_indexEnd(new VariableSpinBox(this)),
|
|
_sourceTypes(new QComboBox(this)),
|
|
_pattern(new VariableLineEdit(this)),
|
|
_regex(new RegexConfigWidget(this, false)),
|
|
_changeType(new QPushButton(this)),
|
|
_nameClashMode(mode),
|
|
_selectionTypes(selections)
|
|
{
|
|
static bool setupDone = false;
|
|
if (setupDone) {
|
|
setupDone = true;
|
|
qRegisterMetaType<NameClashMode>("NameClashMode");
|
|
qRegisterMetaType<ConflictIndex>("ConflictIndex");
|
|
}
|
|
|
|
_sources->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
_sourceGroups->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
_nameConflictIndex->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
|
_changeType->setMaximumWidth(22);
|
|
SetButtonIcon(_changeType,
|
|
GetThemeTypeName() == "Light"
|
|
? ":/settings/images/settings/general.svg"
|
|
: "theme:Dark/settings/general.svg");
|
|
_changeType->setFlat(true);
|
|
_changeType->setToolTip(obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.configure"));
|
|
|
|
_index->setMinimum(1);
|
|
_index->setMaximum(999);
|
|
_index->setSuffix(".");
|
|
_indexEnd->setMinimum(1);
|
|
_indexEnd->setMaximum(999);
|
|
_indexEnd->setSuffix(".");
|
|
|
|
populateSourceGroupSelection(_sourceGroups);
|
|
populateSourceTypeSelection(_sourceTypes);
|
|
|
|
QWidget::connect(_sources, SIGNAL(currentIndexChanged(int)), this,
|
|
SLOT(SourceChanged(int)));
|
|
QWidget::connect(_sourceGroups, SIGNAL(currentIndexChanged(int)), this,
|
|
SLOT(SourceGroupChanged(int)));
|
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
|
this, SLOT(VariableChanged(const QString &)));
|
|
QWidget::connect(_nameConflictIndex, SIGNAL(currentIndexChanged(int)),
|
|
this, SLOT(NameConflictIndexChanged(int)));
|
|
QWidget::connect(_sourceTypes,
|
|
SIGNAL(currentTextChanged(const QString &)), this,
|
|
SLOT(SourceTypeChanged(const QString &)));
|
|
QWidget::connect(
|
|
_index,
|
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
|
this, SLOT(IndexChanged(const NumberVariable<int> &)));
|
|
QWidget::connect(
|
|
_indexEnd,
|
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
|
this, SLOT(IndexEndChanged(const NumberVariable<int> &)));
|
|
QWidget::connect(_pattern, SIGNAL(editingFinished()), this,
|
|
SLOT(PatternChanged()));
|
|
QWidget::connect(_regex,
|
|
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
|
SLOT(RegexChanged(const RegexConfig &)));
|
|
QWidget::connect(_changeType, SIGNAL(clicked()), this,
|
|
SLOT(ChangeType()));
|
|
|
|
_controlsLayout->setContentsMargins(0, 0, 0, 0);
|
|
auto layout = new QHBoxLayout;
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->addLayout(_controlsLayout);
|
|
layout->addWidget(_changeType);
|
|
setLayout(layout);
|
|
_nameConflictIndex->hide();
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SetSceneItem(const SceneItemSelection &item)
|
|
{
|
|
_sources->setCurrentIndex(_sources->findText(
|
|
QString::fromStdString(GetWeakSourceName(item._source))));
|
|
_sourceGroups->setCurrentText(
|
|
QString::fromStdString(GetWeakSourceName(item._source)));
|
|
_variables->SetVariable(item._variable);
|
|
_index->SetValue(item._index);
|
|
_indexEnd->SetValue(item._indexEnd);
|
|
_sourceTypes->setCurrentIndex(_sourceTypes->findText(
|
|
QString::fromStdString(item._sourceType)));
|
|
_pattern->setText(item._pattern);
|
|
_regex->SetRegexConfig(item._regex);
|
|
|
|
_currentSelection = item;
|
|
|
|
{
|
|
const QSignalBlocker b(_nameConflictIndex);
|
|
SetNameConflictVisibility();
|
|
}
|
|
|
|
auto type = item._nameConflictSelectionType;
|
|
|
|
if (type == NameConflictSelection::INDIVIDUAL) {
|
|
const int selection = item._nameConflictSelectionIndex;
|
|
const int idx = _nameConflictIndex->findData(
|
|
QVariant::fromValue(ConflictIndex(selection)));
|
|
_nameConflictIndex->setCurrentIndex(idx);
|
|
} else {
|
|
const auto selection = type == NameConflictSelection::ANY
|
|
? NameClashMode::ANY
|
|
: NameClashMode::ALL;
|
|
const int idx = _nameConflictIndex->findData(
|
|
QVariant::fromValue(ConflictIndex(selection)));
|
|
_nameConflictIndex->setCurrentIndex(idx);
|
|
}
|
|
|
|
SetWidgetVisibility();
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SetScene(const SceneSelection &s)
|
|
{
|
|
|
|
_scene = s;
|
|
_nameConflictIndex->hide();
|
|
if (_currentSelection._type != SceneItemSelection::Type::SOURCE_NAME) {
|
|
PopulateItemSelection();
|
|
return;
|
|
}
|
|
|
|
auto previous = _currentSelection;
|
|
PopulateItemSelection();
|
|
SetSceneItem(previous);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::showEvent(QShowEvent *event)
|
|
{
|
|
QWidget::showEvent(event);
|
|
const QSignalBlocker b1(_sources);
|
|
const QSignalBlocker b2(this);
|
|
PopulateItemSelection();
|
|
SetSceneItem(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SceneChanged(const SceneSelection &s)
|
|
{
|
|
SetScene(s);
|
|
adjustSize();
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SetNameConflictVisibility()
|
|
{
|
|
int sceneItemCount = 0;
|
|
|
|
switch (_currentSelection._type) {
|
|
case SceneItemSelection::Type::SOURCE_NAME:
|
|
case SceneItemSelection::Type::VARIABLE_NAME: {
|
|
QString name = "";
|
|
if (_currentSelection._type ==
|
|
SceneItemSelection::Type::VARIABLE_NAME) {
|
|
auto var = _currentSelection._variable.lock();
|
|
if (var) {
|
|
name = QString::fromStdString(var->Value());
|
|
}
|
|
}
|
|
if (_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_NAME) {
|
|
name = _sources->currentText();
|
|
}
|
|
if (name.isEmpty()) {
|
|
break;
|
|
}
|
|
sceneItemCount = getCountOfSceneItemOccurance(
|
|
_scene, name.toStdString());
|
|
break;
|
|
}
|
|
|
|
case SceneItemSelection::Type::SOURCE_GROUP:
|
|
sceneItemCount = _currentSelection.GetSceneItems(_scene).size();
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_NAME_PATTERN:
|
|
case SceneItemSelection::Type::SOURCE_TYPE:
|
|
sceneItemCount = GetSceneItemCount(_scene.GetScene(false));
|
|
break;
|
|
case SceneItemSelection::Type::INDEX:
|
|
case SceneItemSelection::Type::INDEX_RANGE:
|
|
case SceneItemSelection::Type::ALL:
|
|
case SceneItemSelection::Type::ANY:
|
|
break;
|
|
}
|
|
|
|
if (_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_NAME_PATTERN) {
|
|
int sceneItemCount = GetSceneItemCount(_scene.GetScene(false));
|
|
if (sceneItemCount == 0) {
|
|
_nameConflictIndex->hide();
|
|
return;
|
|
}
|
|
SetupNameConflictIdxSelection(sceneItemCount);
|
|
_nameConflictIndex->show();
|
|
return;
|
|
}
|
|
|
|
if (sceneItemCount == 0) {
|
|
_nameConflictIndex->hide();
|
|
return;
|
|
}
|
|
if (sceneItemCount > 1) {
|
|
SetupNameConflictIdxSelection(sceneItemCount);
|
|
_nameConflictIndex->show();
|
|
} else {
|
|
_nameConflictIndex->hide();
|
|
}
|
|
}
|
|
|
|
void SceneItemSelectionWidget::VariableChanged(const QString &text)
|
|
{
|
|
_currentSelection._variable = GetWeakVariableByQString(text);
|
|
SetNameConflictVisibility();
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SourceChanged(int)
|
|
{
|
|
_currentSelection._source =
|
|
GetWeakSourceByQString(_sources->currentText());
|
|
SetNameConflictVisibility();
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SourceGroupChanged(int)
|
|
{
|
|
_currentSelection._source =
|
|
GetWeakSourceByQString(_sourceGroups->currentText());
|
|
SetNameConflictVisibility();
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::IndexChanged(const IntVariable &index)
|
|
{
|
|
_currentSelection._index = index;
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::IndexEndChanged(const IntVariable &index)
|
|
{
|
|
_currentSelection._indexEnd = index;
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::NameConflictIndexChanged(int idx)
|
|
{
|
|
if (idx < 0) {
|
|
return;
|
|
}
|
|
|
|
QVariant data = _nameConflictIndex->currentData(Qt::UserRole);
|
|
if (!data.canConvert<ConflictIndex>()) {
|
|
return;
|
|
}
|
|
|
|
const auto setSelection = [this](int val, NameConflictSelection type) {
|
|
_currentSelection._nameConflictSelectionIndex = val;
|
|
_currentSelection._nameConflictSelectionType = type;
|
|
};
|
|
|
|
const auto visit = [this, &setSelection](auto &&val) {
|
|
using T = std::decay_t<decltype(val)>;
|
|
if constexpr (std::is_same_v<T, int>) {
|
|
setSelection(val, NameConflictSelection::INDIVIDUAL);
|
|
} else if constexpr (std::is_same_v<T, NameClashMode>) {
|
|
setSelection(0, val == NameClashMode::ANY
|
|
? NameConflictSelection::ANY
|
|
: NameConflictSelection::ALL);
|
|
}
|
|
};
|
|
|
|
const auto variant = data.value<ConflictIndex>();
|
|
std::visit(visit, variant);
|
|
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::PatternChanged()
|
|
{
|
|
_currentSelection._pattern = _pattern->text().toStdString();
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::RegexChanged(const RegexConfig ®ex)
|
|
{
|
|
_currentSelection._regex = regex;
|
|
// No reason for the regex to be disabled
|
|
_currentSelection._regex.SetEnabled(true);
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SourceTypeChanged(const QString &text)
|
|
{
|
|
if (text == obs_module_text("AdvSceneSwitcher.selectItem")) {
|
|
_currentSelection._sourceType = "";
|
|
} else {
|
|
_currentSelection._sourceType = text.toStdString();
|
|
}
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::ChangeType()
|
|
{
|
|
bool accepted = SceneItemTypeSelection::AskForSettings(
|
|
this, _currentSelection._type, _selectionTypes);
|
|
if (!accepted) {
|
|
return;
|
|
}
|
|
|
|
SetNameConflictVisibility();
|
|
SetWidgetVisibility();
|
|
emit SceneItemChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SetupNameConflictIdxSelection(int sceneItemCount)
|
|
{
|
|
_nameConflictIndex->clear();
|
|
|
|
switch (_nameClashMode) {
|
|
case NameClashMode::NONE:
|
|
break;
|
|
case NameClashMode::ALL:
|
|
_nameConflictIndex->addItem(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.all"),
|
|
QVariant::fromValue(ConflictIndex(NameClashMode::ALL)));
|
|
break;
|
|
case NameClashMode::ANY:
|
|
_nameConflictIndex->addItem(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.any"),
|
|
QVariant::fromValue(ConflictIndex(NameClashMode::ANY)));
|
|
break;
|
|
case NameClashMode::ANY_AND_ALL:
|
|
_nameConflictIndex->addItem(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.any"),
|
|
QVariant::fromValue(ConflictIndex(NameClashMode::ANY)));
|
|
_nameConflictIndex->addItem(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.all"),
|
|
QVariant::fromValue(ConflictIndex(NameClashMode::ALL)));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for (int i = 1; i <= sceneItemCount; ++i) {
|
|
_nameConflictIndex->addItem(
|
|
QString::number(i) + ".",
|
|
QVariant::fromValue(ConflictIndex(i - 1)));
|
|
};
|
|
|
|
adjustSize();
|
|
updateGeometry();
|
|
}
|
|
|
|
void SceneItemSelectionWidget::ClearWidgets()
|
|
{
|
|
_controlsLayout->removeWidget(_nameConflictIndex);
|
|
_controlsLayout->removeWidget(_sources);
|
|
_controlsLayout->removeWidget(_sourceGroups);
|
|
_controlsLayout->removeWidget(_variables);
|
|
_controlsLayout->removeWidget(_pattern);
|
|
_controlsLayout->removeWidget(_regex);
|
|
_controlsLayout->removeWidget(_sourceTypes);
|
|
_controlsLayout->removeWidget(_index);
|
|
_controlsLayout->removeWidget(_indexEnd);
|
|
ClearLayout(_controlsLayout);
|
|
}
|
|
|
|
void SceneItemSelectionWidget::SetWidgetVisibility()
|
|
{
|
|
ClearWidgets();
|
|
const std::unordered_map<std::string, QWidget *> widgetMap = {
|
|
{"{{nameConflictIndex}}", _nameConflictIndex},
|
|
{"{{sourceName}}", _sources},
|
|
{"{{sourceGroups}}", _sourceGroups},
|
|
{"{{variable}}", _variables},
|
|
{"{{pattern}}", _pattern},
|
|
{"{{regex}}", _regex},
|
|
{"{{sourceTypes}}", _sourceTypes},
|
|
{"{{index}}", _index},
|
|
{"{{indexEnd}}", _indexEnd},
|
|
};
|
|
|
|
switch (_currentSelection._type) {
|
|
case SceneItemSelection::Type::SOURCE_NAME:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceName.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::VARIABLE_NAME:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_NAME_PATTERN:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_GROUP:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::SOURCE_TYPE:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.sourceType.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::INDEX:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.index.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::INDEX_RANGE:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.indexRange.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::ALL:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.all.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
case SceneItemSelection::Type::ANY:
|
|
PlaceWidgets(
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.sceneItemSelection.type.any.layout"),
|
|
_controlsLayout, widgetMap, false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Name based
|
|
_sources->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_NAME);
|
|
_variables->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::VARIABLE_NAME);
|
|
|
|
const bool isRegexSelection =
|
|
_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_NAME_PATTERN;
|
|
_pattern->setVisible(isRegexSelection);
|
|
_regex->setVisible(isRegexSelection);
|
|
|
|
const bool isNameSelection =
|
|
_currentSelection._type ==
|
|
SceneItemSelection::Type::VARIABLE_NAME ||
|
|
_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_NAME;
|
|
|
|
// Group based
|
|
_sourceGroups->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_GROUP);
|
|
|
|
_sourceTypes->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::SOURCE_TYPE);
|
|
|
|
if (!isNameSelection && !isRegexSelection &&
|
|
_currentSelection._type != SceneItemSelection::Type::SOURCE_TYPE &&
|
|
_currentSelection._type != SceneItemSelection::Type::SOURCE_GROUP) {
|
|
_nameConflictIndex->hide();
|
|
}
|
|
|
|
// Index based
|
|
_index->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::INDEX ||
|
|
_currentSelection._type ==
|
|
SceneItemSelection::Type::INDEX_RANGE);
|
|
_indexEnd->setVisible(_currentSelection._type ==
|
|
SceneItemSelection::Type::INDEX_RANGE);
|
|
|
|
if (_nameClashMode == NameClashMode::HIDE) {
|
|
_nameConflictIndex->hide();
|
|
}
|
|
|
|
adjustSize();
|
|
updateGeometry();
|
|
}
|
|
|
|
SceneItemTypeSelection::SceneItemTypeSelection(
|
|
QWidget *parent, const SceneItemSelection::Type &type)
|
|
: QDialog(parent),
|
|
_typeSelection(new QComboBox(this)),
|
|
_buttonbox(new QDialogButtonBox(QDialogButtonBox::Ok |
|
|
QDialogButtonBox::Cancel))
|
|
{
|
|
setModal(true);
|
|
setWindowModality(Qt::WindowModality::WindowModal);
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
_typeSelection->setCurrentIndex(
|
|
_typeSelection->findData(static_cast<int>(type)));
|
|
|
|
QWidget::connect(_buttonbox, &QDialogButtonBox::accepted, this,
|
|
&QDialog::accept);
|
|
QWidget::connect(_buttonbox, &QDialogButtonBox::rejected, this,
|
|
&QDialog::reject);
|
|
auto layout = new QVBoxLayout();
|
|
layout->addWidget(_typeSelection);
|
|
layout->addWidget(_buttonbox, Qt::AlignHCenter);
|
|
setLayout(layout);
|
|
}
|
|
|
|
bool SceneItemTypeSelection::AskForSettings(
|
|
QWidget *parent, SceneItemSelection::Type &type,
|
|
const std::vector<SceneItemSelection::Type> &allowedTypes)
|
|
{
|
|
SceneItemTypeSelection dialog(parent, type);
|
|
dialog._typeSelection->clear();
|
|
populateMessageTypeSelection(dialog._typeSelection, allowedTypes);
|
|
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
|
if (dialog.exec() != DialogCode::Accepted) {
|
|
return false;
|
|
}
|
|
|
|
type = static_cast<SceneItemSelection::Type>(
|
|
dialog._typeSelection->currentData().toInt());
|
|
return true;
|
|
}
|
|
|
|
} // namespace advss
|