mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 15:24:07 +00:00
UI: Add editable list property to properties view
Implemented as a multi-selection QListWidget. Individual values in the list are saved to the settings in an obs_data_array_t item.
This commit is contained in:
parent
a752b32b83
commit
9d1204a8bc
|
@ -135,6 +135,11 @@ Basic.PropertiesWindow.SelectFont="Select font"
|
|||
Basic.PropertiesWindow.ConfirmTitle="Settings Changed"
|
||||
Basic.PropertiesWindow.Confirm="There are unsaved changes. Do you want to keep them?"
|
||||
Basic.PropertiesWindow.NoProperties="No properties available"
|
||||
Basic.PropertiesWindow.AddFiles="Add Files"
|
||||
Basic.PropertiesWindow.AddURL="Add Path/URL"
|
||||
Basic.PropertiesWindow.AddEditableListFiles="Add files to '%1'"
|
||||
Basic.PropertiesWindow.AddEditableListEntry="Add entry to '%1'"
|
||||
Basic.PropertiesWindow.EditEditableListEntry="Edit entry from '%1'"
|
||||
|
||||
# interaction window
|
||||
Basic.InteractionWindow="Interacting with '%1'"
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
#include <QSlider>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItem>
|
||||
#include <QFileDialog>
|
||||
#include <QColorDialog>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QMenu>
|
||||
#include "double-slider.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
#include "properties-view.hpp"
|
||||
|
@ -470,6 +473,65 @@ QWidget *OBSPropertiesView::AddList(obs_property_t *prop, bool &warning)
|
|||
return combo;
|
||||
}
|
||||
|
||||
static void NewButton(QLayout *layout, WidgetInfo *info,
|
||||
const char *themeIcon,
|
||||
void (WidgetInfo::*method)())
|
||||
{
|
||||
QPushButton *button = new QPushButton();
|
||||
button->setProperty("themeID", themeIcon);
|
||||
button->setFlat(true);
|
||||
button->setMaximumSize(22, 22);
|
||||
button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
|
||||
QObject::connect(button, &QPushButton::clicked, info, method);
|
||||
|
||||
layout->addWidget(button);
|
||||
}
|
||||
|
||||
void OBSPropertiesView::AddEditableList(obs_property_t *prop,
|
||||
QFormLayout *layout, QLabel *&label)
|
||||
{
|
||||
const char *name = obs_property_name(prop);
|
||||
obs_data_array_t *array = obs_data_get_array(settings, name);
|
||||
QListWidget *list = new QListWidget();
|
||||
size_t count = obs_data_array_count(array);
|
||||
|
||||
list->setSortingEnabled(false);
|
||||
list->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *item = obs_data_array_item(array, i);
|
||||
list->addItem(QT_UTF8(obs_data_get_string(item, "value")));
|
||||
obs_data_release(item);
|
||||
}
|
||||
|
||||
WidgetInfo *info = new WidgetInfo(this, prop, list);
|
||||
|
||||
QVBoxLayout *sideLayout = new QVBoxLayout();
|
||||
NewButton(sideLayout, info, "addIconSmall",
|
||||
&WidgetInfo::EditListAdd);
|
||||
NewButton(sideLayout, info, "removeIconSmall",
|
||||
&WidgetInfo::EditListRemove);
|
||||
NewButton(sideLayout, info, "configIconSmall",
|
||||
&WidgetInfo::EditListEdit);
|
||||
NewButton(sideLayout, info, "upArrowIconSmall",
|
||||
&WidgetInfo::EditListUp);
|
||||
NewButton(sideLayout, info, "downArrowIconSmall",
|
||||
&WidgetInfo::EditListDown);
|
||||
sideLayout->addStretch(0);
|
||||
|
||||
QHBoxLayout *subLayout = new QHBoxLayout();
|
||||
subLayout->addWidget(list);
|
||||
subLayout->addLayout(sideLayout);
|
||||
|
||||
children.emplace_back(info);
|
||||
|
||||
label = new QLabel(QT_UTF8(obs_property_description(prop)));
|
||||
layout->addRow(label, subLayout);
|
||||
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
QWidget *OBSPropertiesView::AddButton(obs_property_t *prop)
|
||||
{
|
||||
const char *desc = obs_property_description(prop);
|
||||
|
@ -611,6 +673,9 @@ void OBSPropertiesView::AddProperty(obs_property_t *property,
|
|||
case OBS_PROPERTY_BUTTON:
|
||||
widget = AddButton(property);
|
||||
break;
|
||||
case OBS_PROPERTY_EDITABLE_LIST:
|
||||
AddEditableList(property, layout, label);
|
||||
break;
|
||||
}
|
||||
|
||||
if (widget && !obs_property_enabled(property))
|
||||
|
@ -809,6 +874,26 @@ bool WidgetInfo::FontChanged(const char *setting)
|
|||
return true;
|
||||
}
|
||||
|
||||
void WidgetInfo::EditableListChanged()
|
||||
{
|
||||
const char *setting = obs_property_name(property);
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
obs_data_array *array = obs_data_array_create();
|
||||
|
||||
for (int i = 0; i < list->count(); i++) {
|
||||
QListWidgetItem *item = list->item(i);
|
||||
obs_data_t *arrayItem = obs_data_create();
|
||||
obs_data_set_string(arrayItem, "value",
|
||||
QT_TO_UTF8(item->text()));
|
||||
|
||||
obs_data_array_push_back(array, arrayItem);
|
||||
obs_data_release(arrayItem);
|
||||
}
|
||||
|
||||
obs_data_set_array(view->settings, setting, array);
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
void WidgetInfo::ButtonClicked()
|
||||
{
|
||||
if (obs_property_button_clicked(property, view->obj)) {
|
||||
|
@ -847,6 +932,7 @@ void WidgetInfo::ControlChanged()
|
|||
case OBS_PROPERTY_PATH:
|
||||
if (!PathChanged(setting))
|
||||
return;
|
||||
case OBS_PROPERTY_EDITABLE_LIST: return;
|
||||
}
|
||||
|
||||
if (view->callback && !view->deferUpdate)
|
||||
|
@ -860,3 +946,225 @@ void WidgetInfo::ControlChanged()
|
|||
Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
class EditableItemDialog : public QDialog {
|
||||
QLineEdit *edit;
|
||||
QString filter;
|
||||
QString default_path;
|
||||
|
||||
void BrowseClicked()
|
||||
{
|
||||
QString curPath = QFileInfo(edit->text()).absoluteDir().path();
|
||||
|
||||
if (curPath.isEmpty())
|
||||
curPath = default_path;
|
||||
|
||||
QString path = QFileDialog::getOpenFileName(
|
||||
App()->GetMainWindow(), QTStr("Browse"),
|
||||
curPath, filter);
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
edit->setText(path);
|
||||
}
|
||||
|
||||
public:
|
||||
EditableItemDialog(QWidget *parent, const QString &text,
|
||||
bool browse, const char *filter_ = nullptr,
|
||||
const char *default_path_ = nullptr)
|
||||
: QDialog (parent),
|
||||
filter (QT_UTF8(filter_)),
|
||||
default_path (QT_UTF8(default_path_))
|
||||
{
|
||||
QHBoxLayout *topLayout = new QHBoxLayout();
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
|
||||
edit = new QLineEdit();
|
||||
edit->setText(text);
|
||||
topLayout->addWidget(edit);
|
||||
topLayout->setAlignment(edit, Qt::AlignVCenter);
|
||||
|
||||
if (browse) {
|
||||
QPushButton *browseButton =
|
||||
new QPushButton(QTStr("Browse"));
|
||||
topLayout->addWidget(browseButton);
|
||||
topLayout->setAlignment(browseButton, Qt::AlignVCenter);
|
||||
|
||||
connect(browseButton, &QPushButton::clicked, this,
|
||||
&EditableItemDialog::BrowseClicked);
|
||||
}
|
||||
|
||||
QDialogButtonBox::StandardButtons buttons =
|
||||
QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel;
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(buttons);
|
||||
buttonBox->setCenterButtons(true);
|
||||
|
||||
mainLayout->addLayout(topLayout);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
resize(QSize(400, 80));
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
inline QString GetText() const {return edit->text();}
|
||||
};
|
||||
|
||||
void WidgetInfo::EditListAdd()
|
||||
{
|
||||
bool allow_files = obs_property_editable_list_allow_files(property);
|
||||
if (!allow_files) {
|
||||
EditListAddText();
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu popup(view->window());
|
||||
|
||||
QAction *action;
|
||||
|
||||
action = new QAction(QTStr("Basic.PropertiesWindow.AddFiles"), this);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &WidgetInfo::EditListAddFiles);
|
||||
popup.addAction(action);
|
||||
|
||||
action = new QAction(QTStr("Basic.PropertiesWindow.AddURL"), this);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &WidgetInfo::EditListAddText);
|
||||
popup.addAction(action);
|
||||
|
||||
popup.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListAddText()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
const char *desc = obs_property_description(property);
|
||||
|
||||
EditableItemDialog dialog(widget->window(), QString(), false);
|
||||
auto title = QTStr("Basic.PropertiesWindow.AddEditableListEntry").arg(
|
||||
QT_UTF8(desc));
|
||||
dialog.setWindowTitle(title);
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
||||
QString text = dialog.GetText();
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
list->addItem(text);
|
||||
EditableListChanged();
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListAddFiles()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
const char *desc = obs_property_description(property);
|
||||
const char *filter = obs_property_editable_list_filter(property);
|
||||
const char *default_path =
|
||||
obs_property_editable_list_default_path(property);
|
||||
|
||||
QString title = QTStr("Basic.PropertiesWindow.AddEditableListFiles")
|
||||
.arg(QT_UTF8(desc));
|
||||
|
||||
QStringList files = QFileDialog::getOpenFileNames(
|
||||
App()->GetMainWindow(), title, QT_UTF8(default_path),
|
||||
QT_UTF8(filter));
|
||||
|
||||
if (files.count() == 0)
|
||||
return;
|
||||
|
||||
list->addItems(files);
|
||||
EditableListChanged();
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListRemove()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
QList<QListWidgetItem*> items = list->selectedItems();
|
||||
|
||||
for (QListWidgetItem *item : items)
|
||||
delete item;
|
||||
EditableListChanged();
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListEdit()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
bool allow_files = obs_property_editable_list_allow_files(property);
|
||||
const char *desc = obs_property_description(property);
|
||||
const char *filter = obs_property_editable_list_filter(property);
|
||||
QList<QListWidgetItem*> selectedItems = list->selectedItems();
|
||||
|
||||
if (!selectedItems.count())
|
||||
return;
|
||||
|
||||
QListWidgetItem *item = selectedItems[0];
|
||||
EditableItemDialog dialog(widget->window(), item->text(), allow_files,
|
||||
filter);
|
||||
auto title = QTStr("Basic.PropertiesWindow.EditEditableListEntry").arg(
|
||||
QT_UTF8(desc));
|
||||
dialog.setWindowTitle(title);
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
||||
QString text = dialog.GetText();
|
||||
if (text.isEmpty())
|
||||
return;
|
||||
|
||||
item->setText(text);
|
||||
EditableListChanged();
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListUp()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
int lastItemRow = -1;
|
||||
|
||||
for (int i = 0; i < list->count(); i++) {
|
||||
QListWidgetItem *item = list->item(i);
|
||||
if (!item->isSelected())
|
||||
continue;
|
||||
|
||||
int row = list->row(item);
|
||||
|
||||
if ((row - 1) != lastItemRow) {
|
||||
lastItemRow = row - 1;
|
||||
list->takeItem(row);
|
||||
list->insertItem(lastItemRow, item);
|
||||
item->setSelected(true);
|
||||
} else {
|
||||
lastItemRow = row;
|
||||
}
|
||||
}
|
||||
|
||||
EditableListChanged();
|
||||
}
|
||||
|
||||
void WidgetInfo::EditListDown()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget*>(widget);
|
||||
int lastItemRow = list->count();
|
||||
|
||||
for (int i = list->count() - 1; i >= 0; i--) {
|
||||
QListWidgetItem *item = list->item(i);
|
||||
if (!item->isSelected())
|
||||
continue;
|
||||
|
||||
int row = list->row(item);
|
||||
|
||||
if ((row + 1) != lastItemRow) {
|
||||
lastItemRow = row + 1;
|
||||
list->takeItem(row);
|
||||
list->insertItem(lastItemRow, item);
|
||||
item->setSelected(true);
|
||||
} else {
|
||||
lastItemRow = row;
|
||||
}
|
||||
}
|
||||
|
||||
EditableListChanged();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ private:
|
|||
void ListChanged(const char *setting);
|
||||
bool ColorChanged(const char *setting);
|
||||
bool FontChanged(const char *setting);
|
||||
void EditableListChanged();
|
||||
void ButtonClicked();
|
||||
|
||||
void TogglePasswordText(bool checked);
|
||||
|
@ -46,6 +47,15 @@ public:
|
|||
public slots:
|
||||
|
||||
void ControlChanged();
|
||||
|
||||
/* editable list */
|
||||
void EditListAdd();
|
||||
void EditListAddText();
|
||||
void EditListAddFiles();
|
||||
void EditListRemove();
|
||||
void EditListEdit();
|
||||
void EditListUp();
|
||||
void EditListDown();
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -84,6 +94,8 @@ private:
|
|||
void AddFloat(obs_property_t *prop, QFormLayout *layout,
|
||||
QLabel**label);
|
||||
QWidget *AddList(obs_property_t *prop, bool &warning);
|
||||
void AddEditableList(obs_property_t *prop, QFormLayout *layout,
|
||||
QLabel *&label);
|
||||
QWidget *AddButton(obs_property_t *prop);
|
||||
void AddColor(obs_property_t *prop, QFormLayout *layout, QLabel *&label);
|
||||
void AddFont(obs_property_t *prop, QFormLayout *layout, QLabel *&label);
|
||||
|
|
Loading…
Reference in a new issue