mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-04-05 00:35:46 -05:00
Add generic item selection and settings configuration widgets
To be used for configuring variables and connections
This commit is contained in:
parent
a59d15a77a
commit
3ac4e22600
|
|
@ -238,6 +238,8 @@ target_sources(
|
|||
src/utils/curl-helper.hpp
|
||||
src/utils/duration-control.cpp
|
||||
src/utils/duration-control.hpp
|
||||
src/utils/item-selection-helpers.cpp
|
||||
src/utils/item-selection-helpers.hpp
|
||||
src/utils/file-selection.cpp
|
||||
src/utils/file-selection.hpp
|
||||
src/utils/macro-list.cpp
|
||||
|
|
|
|||
|
|
@ -769,6 +769,16 @@ AdvSceneSwitcher.askForMacro="Select macro {{macroSelection}}"
|
|||
AdvSceneSwitcher.close="Close"
|
||||
AdvSceneSwitcher.browse="Browse"
|
||||
|
||||
AdvSceneSwitcher.item.select="--select item--"
|
||||
AdvSceneSwitcher.item.add="Add new item"
|
||||
AdvSceneSwitcher.item.rename="Rename"
|
||||
AdvSceneSwitcher.item.remove="Remove"
|
||||
AdvSceneSwitcher.item.properties="Properties"
|
||||
AdvSceneSwitcher.item.newName="New name:"
|
||||
AdvSceneSwitcher.item.emptyName="Empty name not allowed!"
|
||||
AdvSceneSwitcher.item.nameNotAvailable="Name not available!"
|
||||
AdvSceneSwitcher.item.nameReserved="Name reserved!"
|
||||
|
||||
AdvSceneSwitcher.connection.select="--select connection--"
|
||||
AdvSceneSwitcher.connection.add="Add new connection"
|
||||
AdvSceneSwitcher.connection.rename="Rename"
|
||||
|
|
|
|||
317
src/utils/item-selection-helpers.cpp
Normal file
317
src/utils/item-selection-helpers.cpp
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
#include "item-selection-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "name-dialog.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QLayout>
|
||||
#include <obs-module.h>
|
||||
|
||||
Q_DECLARE_METATYPE(Item *);
|
||||
|
||||
Item::Item(std::string name) : _name(name) {}
|
||||
|
||||
static Item *GetItemByName(const std::string &name,
|
||||
std::deque<std::shared_ptr<Item>> &items)
|
||||
{
|
||||
for (auto &item : items) {
|
||||
if (item->Name() == name) {
|
||||
return item.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Item *GetItemByName(const QString &name,
|
||||
std::deque<std::shared_ptr<Item>> &items)
|
||||
{
|
||||
return GetItemByName(name.toStdString(), items);
|
||||
}
|
||||
|
||||
bool ItemNameAvailable(const QString &name,
|
||||
std::deque<std::shared_ptr<Item>> &items)
|
||||
{
|
||||
return !GetItemByName(name, items);
|
||||
}
|
||||
|
||||
bool ItemNameAvailable(const std::string &name,
|
||||
std::deque<std::shared_ptr<Item>> &items)
|
||||
{
|
||||
return ItemNameAvailable(QString::fromStdString(name), items);
|
||||
}
|
||||
|
||||
ItemSelection::ItemSelection(std::deque<std::shared_ptr<Item>> &items,
|
||||
CreateItemFunc create, SettingsCallback callback,
|
||||
std::string_view select, std::string_view add,
|
||||
QWidget *parent)
|
||||
: QWidget(parent),
|
||||
_selection(new QComboBox),
|
||||
_modify(new QPushButton),
|
||||
_create(create),
|
||||
_askForSettings(callback),
|
||||
_items(items),
|
||||
_selectStr(select),
|
||||
_addStr(add)
|
||||
{
|
||||
_modify->setMaximumWidth(22);
|
||||
setButtonIcon(_modify, ":/settings/images/settings/general.svg");
|
||||
_modify->setFlat(true);
|
||||
|
||||
// Connect to slots
|
||||
QWidget::connect(_selection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(ChangeSelection(const QString &)));
|
||||
QWidget::connect(_modify, SIGNAL(clicked()), this,
|
||||
SLOT(ModifyButtonClicked()));
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->addWidget(_selection);
|
||||
layout->addWidget(_modify);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
|
||||
for (const auto &i : items) {
|
||||
_selection->addItem(QString::fromStdString(i->_name));
|
||||
}
|
||||
_selection->model()->sort(0);
|
||||
addSelectionEntry(_selection, obs_module_text(_selectStr.data()));
|
||||
_selection->insertSeparator(_selection->count());
|
||||
_selection->addItem(obs_module_text(_addStr.data()));
|
||||
}
|
||||
|
||||
void ItemSelection::SetItem(const std::string &item)
|
||||
{
|
||||
const QSignalBlocker blocker(_selection);
|
||||
if (!!GetItemByName(item, _items)) {
|
||||
_selection->setCurrentText(QString::fromStdString(item));
|
||||
} else {
|
||||
_selection->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSelection::ChangeSelection(const QString &sel)
|
||||
{
|
||||
if (sel == obs_module_text(_addStr.data())) {
|
||||
auto item = _create();
|
||||
bool accepted = _askForSettings(this, *item.get());
|
||||
if (!accepted) {
|
||||
_selection->setCurrentIndex(0);
|
||||
return;
|
||||
}
|
||||
_items.emplace_back(item);
|
||||
const QSignalBlocker b(_selection);
|
||||
const QString name = QString::fromStdString(item->_name);
|
||||
AddItem(name);
|
||||
_selection->setCurrentText(name);
|
||||
emit ItemAdded(name);
|
||||
emit SelectionChanged(name);
|
||||
return;
|
||||
}
|
||||
auto item = GetCurrentItem();
|
||||
if (item) {
|
||||
emit SelectionChanged(QString::fromStdString(item->_name));
|
||||
} else {
|
||||
emit SelectionChanged("");
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSelection::ModifyButtonClicked()
|
||||
{
|
||||
auto item = GetCurrentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
auto properties = [&]() {
|
||||
const auto oldName = item->_name;
|
||||
bool accepted = _askForSettings(this, *item);
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
if (oldName != item->_name) {
|
||||
emit ItemRenamed(QString::fromStdString(oldName),
|
||||
QString::fromStdString(item->_name));
|
||||
}
|
||||
};
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
QAction *action = new QAction(
|
||||
obs_module_text("AdvSceneSwitcher.item.rename"), &menu);
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(RenameItem()));
|
||||
action->setProperty("connetion", QVariant::fromValue(item));
|
||||
menu.addAction(action);
|
||||
|
||||
action = new QAction(obs_module_text("AdvSceneSwitcher.item.remove"),
|
||||
&menu);
|
||||
connect(action, SIGNAL(triggered()), this, SLOT(RemoveItem()));
|
||||
menu.addAction(action);
|
||||
|
||||
action = new QAction(
|
||||
obs_module_text("AdvSceneSwitcher.item.properties"), &menu);
|
||||
connect(action, &QAction::triggered, properties);
|
||||
menu.addAction(action);
|
||||
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void ItemSelection::RenameItem()
|
||||
{
|
||||
QAction *action = reinterpret_cast<QAction *>(sender());
|
||||
QVariant variant = action->property("connetion");
|
||||
Item *item = variant.value<Item *>();
|
||||
|
||||
std::string name;
|
||||
bool accepted = AdvSSNameDialog::AskForName(
|
||||
this, obs_module_text("AdvSceneSwitcher.windowTitle"),
|
||||
obs_module_text("AdvSceneSwitcher.item.newName"), name,
|
||||
QString::fromStdString(name));
|
||||
if (!accepted) {
|
||||
return;
|
||||
}
|
||||
if (name.empty()) {
|
||||
DisplayMessage("AdvSceneSwitcher.item.emptyName");
|
||||
return;
|
||||
}
|
||||
if (_selection->currentText().toStdString() != name &&
|
||||
!ItemNameAvailable(name, _items)) {
|
||||
DisplayMessage("AdvSceneSwitcher.item.nameNotAvailable");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto oldName = item->_name;
|
||||
item->_name = name;
|
||||
emit ItemRenamed(QString::fromStdString(oldName),
|
||||
QString::fromStdString(name));
|
||||
}
|
||||
|
||||
void ItemSelection::RenameItem(const QString &oldName, const QString &name)
|
||||
{
|
||||
int idx = _selection->findText(oldName);
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
_selection->setItemText(idx, name);
|
||||
}
|
||||
|
||||
void ItemSelection::AddItem(const QString &name)
|
||||
{
|
||||
if (_selection->findText(name) == -1) {
|
||||
_selection->insertItem(1, name);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSelection::RemoveItem()
|
||||
{
|
||||
auto item = GetCurrentItem();
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = _selection->findText(QString::fromStdString(item->_name));
|
||||
if (idx == -1 || idx == _selection->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto name = item->_name;
|
||||
for (auto it = _items.begin(); it != _items.end(); ++it) {
|
||||
if (it->get()->_name == item->_name) {
|
||||
_items.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit ItemRemoved(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
void ItemSelection::RemoveItem(const QString &name)
|
||||
{
|
||||
const int idx = _selection->findText(name);
|
||||
if (idx == _selection->currentIndex()) {
|
||||
_selection->setCurrentIndex(0);
|
||||
}
|
||||
_selection->removeItem(idx);
|
||||
}
|
||||
|
||||
Item *ItemSelection::GetCurrentItem()
|
||||
{
|
||||
return GetItemByName(_selection->currentText(), _items);
|
||||
}
|
||||
|
||||
ItemSettingsDialog::ItemSettingsDialog(const Item &settings,
|
||||
std::deque<std::shared_ptr<Item>> &items,
|
||||
std::string_view select,
|
||||
std::string_view add, QWidget *parent)
|
||||
: QDialog(parent),
|
||||
_name(new QLineEdit()),
|
||||
_nameHint(new QLabel),
|
||||
_buttonbox(new QDialogButtonBox(QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel)),
|
||||
_items(items),
|
||||
_selectStr(select),
|
||||
_addStr(add)
|
||||
{
|
||||
setModal(true);
|
||||
setWindowModality(Qt::WindowModality::WindowModal);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setFixedWidth(555);
|
||||
setMinimumHeight(100);
|
||||
|
||||
_buttonbox->setCenterButtons(true);
|
||||
_buttonbox->button(QDialogButtonBox::Ok)->setDisabled(true);
|
||||
|
||||
_name->setText(QString::fromStdString(settings._name));
|
||||
|
||||
QWidget::connect(_name, SIGNAL(textEdited(const QString &)), this,
|
||||
SLOT(NameChanged(const QString &)));
|
||||
QWidget::connect(_buttonbox, &QDialogButtonBox::accepted, this,
|
||||
&QDialog::accept);
|
||||
QWidget::connect(_buttonbox, &QDialogButtonBox::rejected, this,
|
||||
&QDialog::reject);
|
||||
|
||||
NameChanged(_name->text());
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::NameChanged(const QString &text)
|
||||
{
|
||||
|
||||
if (text != _name->text() && !ItemNameAvailable(text, _items)) {
|
||||
SetNameWarning(obs_module_text(
|
||||
"AdvSceneSwitcher.item.nameNotAvailable"));
|
||||
return;
|
||||
}
|
||||
if (text.isEmpty()) {
|
||||
SetNameWarning(
|
||||
obs_module_text("AdvSceneSwitcher.item.emptyName"));
|
||||
return;
|
||||
}
|
||||
if (text == obs_module_text(_selectStr.data()) ||
|
||||
text == obs_module_text(_addStr.data())) {
|
||||
SetNameWarning(
|
||||
obs_module_text("AdvSceneSwitcher.item.nameReserved"));
|
||||
return;
|
||||
}
|
||||
SetNameWarning("");
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::SetNameWarning(const QString warn)
|
||||
{
|
||||
if (warn.isEmpty()) {
|
||||
_nameHint->hide();
|
||||
_buttonbox->button(QDialogButtonBox::Ok)->setDisabled(false);
|
||||
return;
|
||||
}
|
||||
_nameHint->setText(warn);
|
||||
_nameHint->show();
|
||||
_buttonbox->button(QDialogButtonBox::Ok)->setDisabled(true);
|
||||
}
|
||||
|
||||
void Item::Load(obs_data_t *obj)
|
||||
{
|
||||
_name = obs_data_get_string(obj, "name");
|
||||
}
|
||||
|
||||
void Item::Save(obs_data_t *obj) const
|
||||
{
|
||||
obs_data_set_string(obj, "name", _name.c_str());
|
||||
}
|
||||
101
src/utils/item-selection-helpers.hpp
Normal file
101
src/utils/item-selection-helpers.hpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#pragma once
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QSpinBox>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <deque>
|
||||
#include <obs.hpp>
|
||||
#include <websocket-helpers.hpp>
|
||||
|
||||
class ItemSelection;
|
||||
class ItemSettingsDialog;
|
||||
|
||||
class Item {
|
||||
public:
|
||||
Item(std::string name);
|
||||
Item() = default;
|
||||
virtual ~Item() = default;
|
||||
|
||||
virtual void Load(obs_data_t *obj);
|
||||
virtual void Save(obs_data_t *obj) const;
|
||||
std::string Name() const { return _name; }
|
||||
|
||||
protected:
|
||||
std::string _name = "";
|
||||
|
||||
friend ItemSelection;
|
||||
friend ItemSettingsDialog;
|
||||
};
|
||||
|
||||
class ItemSettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ItemSettingsDialog(const Item &, std::deque<std::shared_ptr<Item>> &,
|
||||
std::string_view = "AdvSceneSwitcher.item.select",
|
||||
std::string_view = "AdvSceneSwitcher.item.select",
|
||||
QWidget *parent = 0);
|
||||
virtual ~ItemSettingsDialog() = default;
|
||||
|
||||
private slots:
|
||||
void NameChanged(const QString &);
|
||||
|
||||
protected:
|
||||
void SetNameWarning(const QString);
|
||||
|
||||
QLineEdit *_name;
|
||||
QLabel *_nameHint;
|
||||
QDialogButtonBox *_buttonbox;
|
||||
std::deque<std::shared_ptr<Item>> &_items;
|
||||
std::string_view _selectStr;
|
||||
std::string_view _addStr;
|
||||
};
|
||||
|
||||
typedef bool (*SettingsCallback)(QWidget *, Item &);
|
||||
typedef std::shared_ptr<Item> (*CreateItemFunc)();
|
||||
|
||||
class ItemSelection : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ItemSelection(std::deque<std::shared_ptr<Item>> &, CreateItemFunc,
|
||||
SettingsCallback,
|
||||
std::string_view = "AdvSceneSwitcher.item.select",
|
||||
std::string_view = "AdvSceneSwitcher.item.select",
|
||||
QWidget *parent = 0);
|
||||
virtual ~ItemSelection() = default;
|
||||
void SetItem(const std::string &);
|
||||
|
||||
private slots:
|
||||
void ModifyButtonClicked();
|
||||
void ChangeSelection(const QString &);
|
||||
void RenameItem();
|
||||
void RenameItem(const QString &oldName, const QString &name);
|
||||
void AddItem(const QString &);
|
||||
void RemoveItem();
|
||||
void RemoveItem(const QString &);
|
||||
signals:
|
||||
void SelectionChanged(const QString &);
|
||||
void ItemAdded(const QString &);
|
||||
void ItemRemoved(const QString &);
|
||||
void ItemRenamed(const QString &oldName, const QString &name);
|
||||
|
||||
protected:
|
||||
Item *GetCurrentItem();
|
||||
|
||||
QComboBox *_selection;
|
||||
QPushButton *_modify;
|
||||
CreateItemFunc _create;
|
||||
SettingsCallback _askForSettings;
|
||||
std::deque<std::shared_ptr<Item>> &_items;
|
||||
std::string_view _selectStr;
|
||||
std::string_view _addStr;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user