Skip to content

Commit

Permalink
UI: Refactor editable list modification
Browse files Browse the repository at this point in the history
Previously would unnecessarily recreating the data array for every
modification (adding/removing/reordering/editing). This clears the
fields in the associated data array that other code/scripts would add,
such as an ID field for each item that could be used to distinguish
each item from their duplicates in the list.

I initially wanted to remove EditableListChanged, but it no longer saved
the item selection whenever the list is modified, so I kept the function
and just changed it to update the selected state in the data array.
  • Loading branch information
CodeYan01 committed Aug 12, 2024
1 parent 5854f3b commit aa4ea1a
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 10 deletions.
97 changes: 87 additions & 10 deletions UI/properties-view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,11 @@ void OBSPropertiesView::AddEditableList(obs_property_t *prop,
{
const char *name = obs_property_name(prop);
OBSDataArrayAutoRelease array = obs_data_get_array(settings, name);
if (array == NULL) {
array = obs_data_array_create();
obs_data_set_array(settings, name, array);
}

QListWidget *list = new QListWidget();
size_t count = obs_data_array_count(array);

Expand All @@ -745,8 +750,8 @@ void OBSPropertiesView::AddEditableList(obs_property_t *prop,
WidgetInfo *info = new WidgetInfo(this, prop, list);

list->setDragDropMode(QAbstractItemView::InternalMove);
connect(list->model(), &QAbstractItemModel::rowsMoved,
[info]() { info->EditableListChanged(); });
connect(list->model(), &QAbstractItemModel::rowsMoved, info,
&WidgetInfo::EditListReordered);

QVBoxLayout *sideLayout = new QVBoxLayout();
NewButton(sideLayout, info, "addIconSmall", &WidgetInfo::EditListAdd);
Expand Down Expand Up @@ -2012,24 +2017,52 @@ void WidgetInfo::GroupChanged(const char *setting)
: true);
}

void WidgetInfo::EditListReordered(const QModelIndex &sourceParent,
int sourceStart, int sourceEnd,
const QModelIndex &destinationParent,
int destinationRow)
{
UNUSED_PARAMETER(sourceParent);
UNUSED_PARAMETER(destinationParent);

const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

for (int i = sourceStart; i <= sourceEnd; i++) {
OBSDataAutoRelease arrayItem = obs_data_array_item(array, i);
obs_data_array_insert(array, destinationRow, arrayItem);
// if moved to top, destination row increases
obs_data_array_erase(array, (i > destinationRow) ? i + 1 : i);
++destinationRow;
}
EditableListChanged();
}

void WidgetInfo::EditableListArrayPushBack(obs_data_array_t *array,
const char *text)
{
OBSDataAutoRelease arrayItem = obs_data_create();
obs_data_set_string(arrayItem, "value", text);
obs_data_set_bool(arrayItem, "selected", false);
obs_data_set_bool(arrayItem, "hidden", false);
obs_data_array_push_back(array, arrayItem);
}

void WidgetInfo::EditableListChanged()
{
const char *setting = obs_property_name(property);
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
OBSDataArrayAutoRelease array = obs_data_array_create();
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

for (int i = 0; i < list->count(); i++) {
QListWidgetItem *item = list->item(i);
OBSDataAutoRelease arrayItem = obs_data_create();
obs_data_set_string(arrayItem, "value",
QT_TO_UTF8(item->text()));
OBSDataAutoRelease arrayItem = obs_data_array_item(array, i);
obs_data_set_bool(arrayItem, "selected", item->isSelected());
obs_data_set_bool(arrayItem, "hidden", item->isHidden());
obs_data_array_push_back(array, arrayItem);
}

obs_data_set_array(view->settings, setting, array);

ControlChanged();
}

Expand Down Expand Up @@ -2283,6 +2316,9 @@ void WidgetInfo::EditListAddText()
{
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
const char *desc = obs_property_description(property);
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

EditableItemDialog dialog(widget->window(), QString(), false);
auto title = QTStr("Basic.PropertiesWindow.AddEditableListEntry")
Expand All @@ -2296,6 +2332,7 @@ void WidgetInfo::EditListAddText()
return;

list->addItem(text);
EditableListArrayPushBack(array, QT_TO_UTF8(text));
EditableListChanged();
}

Expand All @@ -2306,6 +2343,9 @@ void WidgetInfo::EditListAddFiles()
const char *filter = obs_property_editable_list_filter(property);
const char *default_path =
obs_property_editable_list_default_path(property);
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

QString title = QTStr("Basic.PropertiesWindow.AddEditableListFiles")
.arg(QT_UTF8(desc));
Expand All @@ -2321,6 +2361,9 @@ void WidgetInfo::EditListAddFiles()
return;

list->addItems(files);
for (QString &file : files) {
EditableListArrayPushBack(array, QT_TO_UTF8(file));
}
EditableListChanged();
}

Expand All @@ -2330,6 +2373,9 @@ void WidgetInfo::EditListAddDir()
const char *desc = obs_property_description(property);
const char *default_path =
obs_property_editable_list_default_path(property);
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

QString title = QTStr("Basic.PropertiesWindow.AddEditableListDir")
.arg(QT_UTF8(desc));
Expand All @@ -2345,16 +2391,23 @@ void WidgetInfo::EditListAddDir()
return;

list->addItem(dir);
EditableListArrayPushBack(array, QT_TO_UTF8(dir));
EditableListChanged();
}

void WidgetInfo::EditListRemove()
{
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
QList<QListWidgetItem *> items = list->selectedItems();
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

for (QListWidgetItem *item : items)
for (qsizetype i = items.size() - 1; i >= 0; i--) {
QListWidgetItem *item = items.at(i);
obs_data_array_erase(array, list->row(item));
delete item;
}
EditableListChanged();
}

Expand All @@ -2363,6 +2416,7 @@ void WidgetInfo::EditListEdit()
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
enum obs_editable_list_type type =
obs_property_editable_list_type(property);
const char *setting = obs_property_name(property);
const char *desc = obs_property_description(property);
const char *filter = obs_property_editable_list_filter(property);
QList<QListWidgetItem *> selectedItems = list->selectedItems();
Expand All @@ -2371,6 +2425,10 @@ void WidgetInfo::EditListEdit()
return;

QListWidgetItem *item = selectedItems[0];
int row = list->row(item);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);
OBSDataAutoRelease arrayItem = obs_data_array_item(array, row);

if (type == OBS_EDITABLE_LIST_TYPE_FILES) {
QDir pathDir(item->text());
Expand All @@ -2387,6 +2445,7 @@ void WidgetInfo::EditListEdit()
return;

item->setText(path);
obs_data_set_string(arrayItem, "value", QT_TO_UTF8(path));
EditableListChanged();
return;
}
Expand All @@ -2405,13 +2464,17 @@ void WidgetInfo::EditListEdit()
return;

item->setText(text);
obs_data_set_string(arrayItem, "value", QT_TO_UTF8(text));
EditableListChanged();
}

void WidgetInfo::EditListUp()
{
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
int lastItemRow = -1;
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

for (int i = 0; i < list->count(); i++) {
QListWidgetItem *item = list->item(i);
Expand All @@ -2425,6 +2488,11 @@ void WidgetInfo::EditListUp()
list->takeItem(row);
list->insertItem(lastItemRow, item);
item->setSelected(true);

OBSDataAutoRelease arrayItem =
obs_data_array_item(array, row);
obs_data_array_insert(array, lastItemRow, arrayItem);
obs_data_array_erase(array, row + 1);
} else {
lastItemRow = row;
}
Expand All @@ -2437,6 +2505,9 @@ void WidgetInfo::EditListDown()
{
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
int lastItemRow = list->count();
const char *setting = obs_property_name(property);
OBSDataArrayAutoRelease array =
obs_data_get_array(view->settings, setting);

for (int i = list->count() - 1; i >= 0; i--) {
QListWidgetItem *item = list->item(i);
Expand All @@ -2450,6 +2521,12 @@ void WidgetInfo::EditListDown()
list->takeItem(row);
list->insertItem(lastItemRow, item);
item->setSelected(true);

OBSDataAutoRelease arrayItem =
obs_data_array_item(array, row);
obs_data_array_insert(array, lastItemRow + 1,
arrayItem);
obs_data_array_erase(array, row);
} else {
lastItemRow = row;
}
Expand Down
6 changes: 6 additions & 0 deletions UI/properties-view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class WidgetInfo : public QObject {
void ButtonClicked();

void TogglePasswordText(bool checked);
void EditableListArrayPushBack(obs_data_array_t *array,
const char *text);

public:
inline WidgetInfo(OBSPropertiesView *view_, obs_property_t *prop,
Expand Down Expand Up @@ -79,6 +81,10 @@ public slots:
void EditListEdit();
void EditListUp();
void EditListDown();
void EditListReordered(const QModelIndex &sourceParent, int sourceStart,
int sourceEnd,
const QModelIndex &destinationParent,
int destinationRow);
};

/* ------------------------------------------------------------------------- */
Expand Down

0 comments on commit aa4ea1a

Please sign in to comment.