From 76c411d1e21e2e81f5caa9829058d5e2ea5fccd5 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 4 Mar 2023 15:27:46 +0100 Subject: [PATCH] Extract argument list to generic string list class and widget To be used for http header support. --- CMakeLists.txt | 2 + src/utils/process-config.cpp | 179 +++----------------------------- src/utils/process-config.hpp | 18 +--- src/utils/string-list.cpp | 194 +++++++++++++++++++++++++++++++++++ src/utils/string-list.hpp | 49 +++++++++ 5 files changed, 264 insertions(+), 178 deletions(-) create mode 100644 src/utils/string-list.cpp create mode 100644 src/utils/string-list.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 35ee5cb0..3cdc2f44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -272,6 +272,8 @@ target_sources( src/utils/slider-spinbox.hpp src/utils/source-selection.cpp src/utils/source-selection.hpp + src/utils/string-list.cpp + src/utils/string-list.hpp src/utils/striped-frame.cpp src/utils/striped-frame.hpp src/utils/transition-selection.cpp diff --git a/src/utils/process-config.cpp b/src/utils/process-config.cpp index 1114360b..23fab6e9 100644 --- a/src/utils/process-config.cpp +++ b/src/utils/process-config.cpp @@ -11,17 +11,7 @@ bool ProcessConfig::Save(obs_data_t *obj) const obs_data_set_string(data, "path", _path.c_str()); obs_data_set_string(data, "workingDirectory", _workingDirectory.c_str()); - obs_data_array_t *args = obs_data_array_create(); - for (auto &arg : _args) { - obs_data_t *array_obj = obs_data_create(); - obs_data_set_string(array_obj, "arg", - arg.toStdString().c_str()); - obs_data_array_push_back(args, array_obj); - obs_data_release(array_obj); - } - obs_data_set_array(data, "args", args); - obs_data_array_release(args); - + _args.Save(data, "args", "arg"); obs_data_set_obj(obj, "processConfig", data); obs_data_release(data); return true; @@ -34,30 +24,14 @@ bool ProcessConfig::Load(obs_data_t *obj) _path = obs_data_get_string(obj, "path"); _workingDirectory = obs_data_get_string(obj, "workingDirectory"); - obs_data_array_t *args = obs_data_get_array(obj, "args"); - size_t count = obs_data_array_count(args); - for (size_t i = 0; i < count; i++) { - obs_data_t *array_obj = obs_data_array_item(args, i); - _args << QString::fromStdString( - obs_data_get_string(array_obj, "arg")); - obs_data_release(array_obj); - } - obs_data_array_release(args); + _args.Load(obj, "args", "arg"); return true; } auto data = obs_data_get_obj(obj, "processConfig"); _path = obs_data_get_string(data, "path"); _workingDirectory = obs_data_get_string(data, "workingDirectory"); - obs_data_array_t *args = obs_data_get_array(data, "args"); - size_t count = obs_data_array_count(args); - for (size_t i = 0; i < count; i++) { - obs_data_t *array_obj = obs_data_array_item(args, i); - _args << QString::fromStdString( - obs_data_get_string(array_obj, "arg")); - obs_data_release(array_obj); - } - obs_data_array_release(args); + _args.Load(data, "args", "arg"); obs_data_release(data); return true; } @@ -68,43 +42,21 @@ ProcessConfigEdit::ProcessConfigEdit(QWidget *parent) _showAdvancedSettings(new QPushButton( obs_module_text("AdvSceneSwitcher.process.showAdvanced"))), _advancedSettingsLayout(new QVBoxLayout()), - _argList(new QListWidget()), - _addArg(new QPushButton()), - _removeArg(new QPushButton()), - _argUp(new QPushButton()), - _argDown(new QPushButton()), + _argList(new StringListEdit( + this, obs_module_text("AdvSceneSwitcher.process.addArgument"), + obs_module_text( + "AdvSceneSwitcher.process.addArgumentDescription"))), _workingDirectory(new FileSelection(FileSelection::Type::FOLDER)) { _advancedSettingsLayout->setContentsMargins(0, 0, 0, 0); - _addArg->setMaximumWidth(22); - _addArg->setProperty("themeID", - QVariant(QString::fromUtf8("addIconSmall"))); - _addArg->setFlat(true); - _removeArg->setMaximumWidth(22); - _removeArg->setProperty("themeID", - QVariant(QString::fromUtf8("removeIconSmall"))); - _removeArg->setFlat(true); - _argUp->setMaximumWidth(22); - _argUp->setProperty("themeID", - QVariant(QString::fromUtf8("upArrowIconSmall"))); - _argUp->setFlat(true); - _argDown->setMaximumWidth(22); - _argDown->setProperty( - "themeID", QVariant(QString::fromUtf8("downArrowIconSmall"))); - _argDown->setFlat(true); - QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this, SLOT(PathChanged(const QString &))); QWidget::connect(_showAdvancedSettings, SIGNAL(clicked()), this, SLOT(ShowAdvancedSettingsClicked())); - QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg())); - QWidget::connect(_removeArg, SIGNAL(clicked()), this, - SLOT(RemoveArg())); - QWidget::connect(_argUp, SIGNAL(clicked()), this, SLOT(ArgUp())); - QWidget::connect(_argDown, SIGNAL(clicked()), this, SLOT(ArgDown())); - QWidget::connect(_argList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), - this, SLOT(ArgItemClicked(QListWidgetItem *))); + QWidget::connect(_argList, + SIGNAL(StringListChanged(const StringList &)), this, + SLOT(ArgsChanged(const StringList &))); QWidget::connect(_workingDirectory, SIGNAL(PathChanged(const QString &)), this, SLOT(WorkingDirectoryChanged(const QString &))); @@ -118,17 +70,6 @@ ProcessConfigEdit::ProcessConfigEdit(QWidget *parent) placeWidgets(obs_module_text("AdvSceneSwitcher.process.entry"), entryLayout, widgetPlaceholders, false); - auto argButtonLayout = new QHBoxLayout; - argButtonLayout->addWidget(_addArg); - argButtonLayout->addWidget(_removeArg); - QFrame *line = new QFrame(); - line->setFrameShape(QFrame::VLine); - line->setFrameShadow(QFrame::Sunken); - argButtonLayout->addWidget(line); - argButtonLayout->addWidget(_argUp); - argButtonLayout->addWidget(_argDown); - argButtonLayout->addStretch(); - auto workingDirectoryLayout = new QHBoxLayout; placeWidgets(obs_module_text( "AdvSceneSwitcher.process.entry.workingDirectory"), @@ -137,7 +78,6 @@ ProcessConfigEdit::ProcessConfigEdit(QWidget *parent) _advancedSettingsLayout->addWidget(new QLabel( obs_module_text("AdvSceneSwitcher.process.arguments"))); _advancedSettingsLayout->addWidget(_argList); - _advancedSettingsLayout->addLayout(argButtonLayout); _advancedSettingsLayout->addLayout(workingDirectoryLayout); auto *mainLayout = new QVBoxLayout; @@ -153,13 +93,9 @@ void ProcessConfigEdit::SetProcessConfig(const ProcessConfig &conf) { _conf = conf; _filePath->SetPath(QString::fromStdString(conf._path)); - for (const auto &arg : conf._args) { - QListWidgetItem *item = new QListWidgetItem(arg, _argList); - item->setData(Qt::UserRole, arg); - } + _argList->SetStringList(conf._args); _workingDirectory->SetPath( QString::fromStdString(conf._workingDirectory)); - SetArgListSize(); ShowAdvancedSettings(!_conf._args.empty() || !_conf._workingDirectory.empty()); } @@ -176,105 +112,18 @@ void ProcessConfigEdit::ShowAdvancedSettingsClicked() emit ConfigChanged(_conf); // Just to make sure resizing is handled } -void ProcessConfigEdit::AddArg() -{ - std::string name; - bool accepted = AdvSSNameDialog::AskForName( - this, obs_module_text("AdvSceneSwitcher.process.addArgument"), - obs_module_text( - "AdvSceneSwitcher.process.addArgumentDescription"), - name, "", 170, false); - - if (!accepted || name.empty()) { - return; - } - auto arg = QString::fromStdString(name); - QVariant v = QVariant::fromValue(arg); - QListWidgetItem *item = new QListWidgetItem(arg, _argList); - item->setData(Qt::UserRole, arg); - - _conf._args << arg; - SetArgListSize(); - - emit ConfigChanged(_conf); -} - -void ProcessConfigEdit::RemoveArg() -{ - int idx = _argList->currentRow(); - if (idx == -1) { - return; - } - _conf._args.removeAt(idx); - - QListWidgetItem *item = _argList->currentItem(); - if (!item) { - return; - } - delete item; - SetArgListSize(); - - emit ConfigChanged(_conf); -} - -void ProcessConfigEdit::ArgUp() -{ - int idx = _argList->currentRow(); - if (idx != -1 && idx != 0) { - _argList->insertItem(idx - 1, _argList->takeItem(idx)); - _argList->setCurrentRow(idx - 1); - - _conf._args.move(idx, idx - 1); - } - emit ConfigChanged(_conf); -} - -void ProcessConfigEdit::ArgDown() -{ - int idx = _argList->currentRow(); - if (idx != -1 && idx != _argList->count() - 1) { - _argList->insertItem(idx + 1, _argList->takeItem(idx)); - _argList->setCurrentRow(idx + 1); - - _conf._args.move(idx, idx + 1); - } - emit ConfigChanged(_conf); -} - -void ProcessConfigEdit::ArgItemClicked(QListWidgetItem *item) -{ - std::string name; - bool accepted = AdvSSNameDialog::AskForName( - this, obs_module_text("AdvSceneSwitcher.process.addArgument"), - obs_module_text( - "AdvSceneSwitcher.process.addArgumentDescription"), - name, item->text(), 170, false); - - if (!accepted || name.empty()) { - return; - } - - auto arg = QString::fromStdString(name); - QVariant v = QVariant::fromValue(arg); - item->setText(arg); - item->setData(Qt::UserRole, arg); - int idx = _argList->currentRow(); - _conf._args[idx] = arg; - - emit ConfigChanged(_conf); -} - void ProcessConfigEdit::WorkingDirectoryChanged(const QString &path) { _conf._workingDirectory = path.toStdString(); emit ConfigChanged(_conf); } -void ProcessConfigEdit::SetArgListSize() +void ProcessConfigEdit::ArgsChanged(const StringList &args) { - setHeightToContentHeight(_argList); + _conf._args = args; adjustSize(); updateGeometry(); + emit ConfigChanged(_conf); } void ProcessConfigEdit::ShowAdvancedSettings(bool showAdvancedSettings) diff --git a/src/utils/process-config.hpp b/src/utils/process-config.hpp index e3a0a3d3..40c4192c 100644 --- a/src/utils/process-config.hpp +++ b/src/utils/process-config.hpp @@ -1,5 +1,6 @@ #pragma once #include "file-selection.hpp" +#include "string-list.hpp" #include #include @@ -16,12 +17,12 @@ public: std::string Path() const { return _path; } std::string WorkingDir() const { return _workingDirectory; } - QStringList Args() const { return _args; } + StringList Args() const { return _args; } private: std::string _path = obs_module_text("AdvSceneSwitcher.enterPath"); std::string _workingDirectory = ""; - QStringList _args; + StringList _args; friend class ProcessConfigEdit; }; @@ -36,17 +37,12 @@ public: private slots: void PathChanged(const QString &); void ShowAdvancedSettingsClicked(); - void AddArg(); - void RemoveArg(); - void ArgUp(); - void ArgDown(); - void ArgItemClicked(QListWidgetItem *); void WorkingDirectoryChanged(const QString &); + void ArgsChanged(const StringList &); signals: void ConfigChanged(const ProcessConfig &); private: - void SetArgListSize(); void ShowAdvancedSettings(bool); ProcessConfig _conf; @@ -54,10 +50,6 @@ private: FileSelection *_filePath; QPushButton *_showAdvancedSettings; QVBoxLayout *_advancedSettingsLayout; - QListWidget *_argList; - QPushButton *_addArg; - QPushButton *_removeArg; - QPushButton *_argUp; - QPushButton *_argDown; + StringListEdit *_argList; FileSelection *_workingDirectory; }; diff --git a/src/utils/string-list.cpp b/src/utils/string-list.cpp new file mode 100644 index 00000000..99c6bd23 --- /dev/null +++ b/src/utils/string-list.cpp @@ -0,0 +1,194 @@ +#include "string-list.hpp" +#include "name-dialog.hpp" +#include "utility.hpp" + +#include + +bool StringList::Save(obs_data_t *obj, const char *name, + const char *elementName) const +{ + obs_data_array_t *strings = obs_data_array_create(); + for (auto &string : *this) { + obs_data_t *array_obj = obs_data_create(); + obs_data_set_string(array_obj, elementName, + string.toStdString().c_str()); + obs_data_array_push_back(strings, array_obj); + obs_data_release(array_obj); + } + obs_data_set_array(obj, name, strings); + obs_data_array_release(strings); + return true; +} + +bool StringList::Load(obs_data_t *obj, const char *name, + const char *elementName) +{ + clear(); + obs_data_array_t *strings = obs_data_get_array(obj, name); + size_t count = obs_data_array_count(strings); + for (size_t i = 0; i < count; i++) { + obs_data_t *array_obj = obs_data_array_item(strings, i); + *this << QString::fromStdString( + obs_data_get_string(array_obj, elementName)); + obs_data_release(array_obj); + } + obs_data_array_release(strings); + return true; +} + +StringListEdit::StringListEdit(QWidget *parent, const QString &addString, + const QString &addStringDescription) + : QWidget(parent), + _list(new QListWidget()), + _add(new QPushButton()), + _remove(new QPushButton()), + _up(new QPushButton()), + _down(new QPushButton()), + _addString(addString), + _addStringDescription(addStringDescription) +{ + _add->setMaximumWidth(22); + _add->setProperty("themeID", + QVariant(QString::fromUtf8("addIconSmall"))); + _add->setFlat(true); + _remove->setMaximumWidth(22); + _remove->setProperty("themeID", + QVariant(QString::fromUtf8("removeIconSmall"))); + _remove->setFlat(true); + _up->setMaximumWidth(22); + _up->setProperty("themeID", + QVariant(QString::fromUtf8("upArrowIconSmall"))); + _up->setFlat(true); + _down->setMaximumWidth(22); + _down->setProperty("themeID", + QVariant(QString::fromUtf8("downArrowIconSmall"))); + _down->setFlat(true); + + QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add())); + QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove())); + QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up())); + QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down())); + QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), + this, SLOT(Clicked(QListWidgetItem *))); + + auto controlLayout = new QHBoxLayout; + controlLayout->setContentsMargins(0, 0, 0, 0); + controlLayout->addWidget(_add); + controlLayout->addWidget(_remove); + QFrame *line = new QFrame(); + line->setFrameShape(QFrame::VLine); + line->setFrameShadow(QFrame::Sunken); + controlLayout->addWidget(line); + controlLayout->addWidget(_up); + controlLayout->addWidget(_down); + controlLayout->addStretch(); + + auto mainLayout = new QVBoxLayout; + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(_list); + mainLayout->addLayout(controlLayout); + setLayout(mainLayout); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); +} + +void StringListEdit::SetStringList(const StringList &list) +{ + _stringList = list; + _list->clear(); + for (const auto &string : list) { + QListWidgetItem *item = new QListWidgetItem(string, _list); + item->setData(Qt::UserRole, string); + } + SetListSize(); +} + +void StringListEdit::Add() +{ + std::string name; + bool accepted = AdvSSNameDialog::AskForName( + this, _addString, _addStringDescription, name, "", 170, false); + + if (!accepted || name.empty()) { + return; + } + auto string = QString::fromStdString(name); + QVariant v = QVariant::fromValue(string); + QListWidgetItem *item = new QListWidgetItem(string, _list); + item->setData(Qt::UserRole, string); + + _stringList << string; + SetListSize(); + + StringListChanged(_stringList); +} + +void StringListEdit::Remove() +{ + int idx = _list->currentRow(); + if (idx == -1) { + return; + } + _stringList.removeAt(idx); + + QListWidgetItem *item = _list->currentItem(); + if (!item) { + return; + } + delete item; + SetListSize(); + + StringListChanged(_stringList); +} + +void StringListEdit::Up() +{ + int idx = _list->currentRow(); + if (idx != -1 && idx != 0) { + _list->insertItem(idx - 1, _list->takeItem(idx)); + _list->setCurrentRow(idx - 1); + + _stringList.move(idx, idx - 1); + } + StringListChanged(_stringList); +} + +void StringListEdit::Down() +{ + int idx = _list->currentRow(); + if (idx != -1 && idx != _list->count() - 1) { + _list->insertItem(idx + 1, _list->takeItem(idx)); + _list->setCurrentRow(idx + 1); + + _stringList.move(idx, idx + 1); + } + StringListChanged(_stringList); +} + +void StringListEdit::Clicked(QListWidgetItem *item) +{ + std::string name; + bool accepted = AdvSSNameDialog::AskForName(this, _addString, + _addStringDescription, name, + item->text(), 170, false); + + if (!accepted || name.empty()) { + return; + } + + auto string = QString::fromStdString(name); + QVariant v = QVariant::fromValue(string); + item->setText(string); + item->setData(Qt::UserRole, string); + int idx = _list->currentRow(); + _stringList[idx] = string; + + StringListChanged(_stringList); +} + +void StringListEdit::SetListSize() +{ + setHeightToContentHeight(_list); + adjustSize(); + updateGeometry(); +} diff --git a/src/utils/string-list.hpp b/src/utils/string-list.hpp new file mode 100644 index 00000000..cf7b37b6 --- /dev/null +++ b/src/utils/string-list.hpp @@ -0,0 +1,49 @@ +#pragma once +#include +#include + +#include +#include +#include + +class StringList : public QStringList { +public: + bool Save(obs_data_t *obj, const char *name, + const char *elementName = "string") const; + bool Load(obs_data_t *obj, const char *name, + const char *elementName = "string"); + + friend class StringListEdit; +}; + +class StringListEdit : public QWidget { + Q_OBJECT + +public: + StringListEdit(QWidget *parent, const QString &addString = "", + const QString &addStringDescription = ""); + void SetStringList(const StringList &); + +private slots: + void Add(); + void Remove(); + void Up(); + void Down(); + void Clicked(QListWidgetItem *); +signals: + void StringListChanged(const StringList &); + +private: + void SetListSize(); + + StringList _stringList; + + QListWidget *_list; + QPushButton *_add; + QPushButton *_remove; + QPushButton *_up; + QPushButton *_down; + + QString _addString; + QString _addStringDescription; +};