mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-16 14:19:02 -05:00
Add MQTT helpers
This commit is contained in:
284
plugins/mqtt/topic-selection.cpp
Normal file
284
plugins/mqtt/topic-selection.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#include "topic-selection.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
MqttTopicListWidget::MqttTopicListWidget(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
_table(new QTableWidget(0, 2, this)),
|
||||
_controls(new ListControls(this, false))
|
||||
{
|
||||
_table->setHorizontalHeaderLabels(
|
||||
QStringList()
|
||||
<< obs_module_text("AdvSceneSwitcher.mqttConnection.topic")
|
||||
<< obs_module_text("AdvSceneSwitcher.mqttConnection.qos"));
|
||||
_table->horizontalHeader()->setStretchLastSection(true);
|
||||
_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
_table->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
_table->setEditTriggers(QAbstractItemView::DoubleClicked |
|
||||
QAbstractItemView::SelectedClicked);
|
||||
_table->verticalHeader()->hide();
|
||||
_table->horizontalHeader()->setSectionResizeMode(0,
|
||||
QHeaderView::Stretch);
|
||||
_table->horizontalHeader()->setSectionResizeMode(
|
||||
1, QHeaderView::ResizeToContents);
|
||||
|
||||
connect(_table, &QTableWidget::itemChanged, this,
|
||||
&MqttTopicListWidget::ModifyRow);
|
||||
connect(_controls, &ListControls::Add, this,
|
||||
&MqttTopicListWidget::AddTopic);
|
||||
connect(_controls, &ListControls::Remove, this,
|
||||
&MqttTopicListWidget::RemoveSelectedRow);
|
||||
|
||||
auto mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addWidget(_table);
|
||||
mainLayout->addWidget(_controls);
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::SetValues(const std::vector<std::string> &topics,
|
||||
const std::vector<int> &qos)
|
||||
{
|
||||
assert(topics.size() == qos.size());
|
||||
if (topics.size() != qos.size()) {
|
||||
blog(LOG_WARNING, "%s topics and qos size mismatch", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
_table->setRowCount(0);
|
||||
_topicSet.clear();
|
||||
|
||||
std::vector<std::pair<QString, int>> entries;
|
||||
for (size_t i = 0; i < topics.size(); ++i) {
|
||||
auto topic = QString::fromStdString(topics[i]).trimmed();
|
||||
int qos_ = qos[i];
|
||||
if (topic.isEmpty()) {
|
||||
blog(LOG_INFO, "%s ignoring empty topic entry",
|
||||
__func__);
|
||||
continue;
|
||||
}
|
||||
if (_topicSet.contains(topic)) {
|
||||
blog(LOG_INFO, "%s discarding duplicate topic \"%s\"",
|
||||
__func__, topics[i].c_str());
|
||||
continue;
|
||||
}
|
||||
if (qos_ < 0 || qos_ > 2) {
|
||||
blog(LOG_INFO,
|
||||
"%s discard invalid QoS level \"%d\" and set to \"1\"",
|
||||
__func__, qos[i]);
|
||||
qos_ = 1;
|
||||
}
|
||||
entries.emplace_back(topic, qos_);
|
||||
_topicSet.insert(topic);
|
||||
}
|
||||
|
||||
for (const auto &entry : entries) {
|
||||
int row = _table->rowCount();
|
||||
_table->insertRow(row);
|
||||
_table->setItem(row, 0, new QTableWidgetItem(entry.first));
|
||||
_table->setItem(
|
||||
row, 1,
|
||||
new QTableWidgetItem(QString::number(entry.second)));
|
||||
}
|
||||
|
||||
SortTable();
|
||||
}
|
||||
|
||||
std::vector<std::string> MqttTopicListWidget::GetTopics()
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
for (int i = 0; i < _table->rowCount(); ++i) {
|
||||
auto topic = _table->item(i, 0)->text().trimmed();
|
||||
result.push_back(topic.toStdString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int> MqttTopicListWidget::GetQoS()
|
||||
{
|
||||
std::vector<int> result;
|
||||
for (int i = 0; i < _table->rowCount(); ++i) {
|
||||
bool isValidInt = false;
|
||||
int qos = _table->item(i, 1)->text().toInt(&isValidInt);
|
||||
result.push_back(isValidInt ? qos : 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::AddTopic()
|
||||
{
|
||||
AddMqttTopicDialog dialog(this);
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto topic = dialog.Topic();
|
||||
int qos = dialog.QoS();
|
||||
|
||||
if (topic.isEmpty()) {
|
||||
ShowTopicEmptyWarning();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_topicSet.contains(topic)) {
|
||||
ShowTopicDuplicateWarning();
|
||||
return;
|
||||
}
|
||||
|
||||
InsertSorted(topic, qos);
|
||||
_topicSet.insert(topic);
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::InsertSorted(const QString &topic, int qos)
|
||||
{
|
||||
int row = 0;
|
||||
while (row < _table->rowCount()) {
|
||||
QString current = _table->item(row, 0)->text();
|
||||
if (topic.compare(current, Qt::CaseInsensitive) < 0)
|
||||
break;
|
||||
++row;
|
||||
}
|
||||
|
||||
_table->insertRow(row);
|
||||
_table->setItem(row, 0, new QTableWidgetItem(topic));
|
||||
_table->setItem(row, 1, new QTableWidgetItem(QString::number(qos)));
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::SortTable()
|
||||
{
|
||||
_table->sortItems(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::ShowTopicDuplicateWarning()
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.duplicateTopic.title"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.duplicateTopic"));
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::ShowTopicEmptyWarning()
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.emptyTopic.title"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.emptyTopic"));
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::ShowQoSRangeWarning()
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.qosRange.title"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.mqttConnection.inputWarning.qosRange"));
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::RemoveSelectedRow()
|
||||
{
|
||||
auto selected = _table->currentRow();
|
||||
if (selected >= 0) {
|
||||
QString topic = _table->item(selected, 0)->text();
|
||||
_topicSet.remove(topic);
|
||||
_table->removeRow(selected);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttTopicListWidget::ModifyRow(QTableWidgetItem *item)
|
||||
{
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
int row = item->row();
|
||||
auto tableItemTopic = _table->item(row, 0);
|
||||
auto tableItemQos = _table->item(row, 1);
|
||||
if (!tableItemTopic || !tableItemQos) {
|
||||
return;
|
||||
}
|
||||
QString topic = tableItemTopic->text().trimmed();
|
||||
QString qosStr = tableItemQos->text().trimmed();
|
||||
|
||||
// Validate topic column
|
||||
if (item->column() == 0) {
|
||||
QString oldTopic = _topicSet.values().value(row);
|
||||
if (topic.isEmpty()) {
|
||||
ShowTopicEmptyWarning();
|
||||
item->setText(oldTopic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_topicSet.contains(topic) && topic != oldTopic) {
|
||||
ShowTopicDuplicateWarning();
|
||||
item->setText(oldTopic);
|
||||
return;
|
||||
}
|
||||
|
||||
_topicSet.remove(oldTopic);
|
||||
_topicSet.insert(topic);
|
||||
SortTable();
|
||||
}
|
||||
|
||||
// Validate QoS column
|
||||
if (item->column() == 1) {
|
||||
bool isValidInt;
|
||||
int qos = qosStr.toInt(&isValidInt);
|
||||
if (!isValidInt || qos < 0 || qos > 2) {
|
||||
ShowQoSRangeWarning();
|
||||
item->setText("1");
|
||||
}
|
||||
}
|
||||
SortTable();
|
||||
}
|
||||
|
||||
AddMqttTopicDialog::AddMqttTopicDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
_topicEdit(new QLineEdit(this)),
|
||||
_qosSpin(new QSpinBox(this))
|
||||
{
|
||||
setWindowTitle(
|
||||
obs_module_text("AdvSceneSwitcher.mqttConnection.add.title"));
|
||||
_topicEdit->setText("/#");
|
||||
_qosSpin->setRange(0, 2);
|
||||
_qosSpin->setValue(1);
|
||||
|
||||
auto buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel);
|
||||
buttonbox->setCenterButtons(true);
|
||||
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto inputLayout = new QHBoxLayout();
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.mqttConnection.add.layout"),
|
||||
inputLayout, {{"{{topic}}", _topicEdit}, {"{{QoS}}", _qosSpin}},
|
||||
false);
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(inputLayout);
|
||||
layout->addWidget(buttonbox);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
QString AddMqttTopicDialog::Topic() const
|
||||
{
|
||||
return _topicEdit->text().trimmed();
|
||||
}
|
||||
|
||||
int AddMqttTopicDialog::QoS() const
|
||||
{
|
||||
return _qosSpin->value();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
Reference in New Issue
Block a user