300 lines
11 KiB
C++
300 lines
11 KiB
C++
#include "adduniversedialog.h"
|
|
#include "lineeditdialog.h"
|
|
#include "multiversewindow.h"
|
|
#include "multiversemodel.h"
|
|
#include "ui_multiversewindow.h"
|
|
#include "universewindow.h"
|
|
#include <QActionGroup>
|
|
#include <QMessageBox>
|
|
#include <QStringBuilder>
|
|
|
|
/**
|
|
* @brief MultiverseWindow::MultiverseWindow
|
|
* @param parent
|
|
*/
|
|
MultiverseWindow::MultiverseWindow(QWidget *parent, QSacnNode *node)
|
|
: QMainWindow(parent)
|
|
, ui(new Ui::MultiverseWindow)
|
|
, node(node)
|
|
, model(new MultiverseModel(this, node))
|
|
, sortProxy(new QSortFilterProxyModel(this))
|
|
{
|
|
// build the UI
|
|
ui->setupUi(this);
|
|
ui->menubar->setNativeMenuBar(false);
|
|
auto mergeMode = new QActionGroup(this);
|
|
mergeMode->addAction(ui->actionMergeModeHTP);
|
|
mergeMode->addAction(ui->actionMergeModeLTP);
|
|
|
|
// initial states
|
|
ui->actionTerminate->setEnabled(false);
|
|
ui->actionUnsubscribe->setEnabled(false);
|
|
ui->actionInspect->setEnabled(false);
|
|
ui->actionIPv4->setChecked(node->isEnabledIPv4());
|
|
ui->actionIPv6->setChecked(node->isEnabledIPv6());
|
|
ui->actionDiscovery->setChecked(node->discoveryEnabled());
|
|
|
|
// setup the model
|
|
sortProxy->setSourceModel(model);
|
|
ui->multiverseView->setModel(sortProxy);
|
|
ui->multiverseView->setSortingEnabled(true);
|
|
ui->multiverseView->sortByColumn(MultiverseModel::Column::Universe,
|
|
Qt::SortOrder::AscendingOrder);
|
|
ui->multiverseView->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
ui->multiverseView->expandAll();
|
|
for (int i = 0; i < ui->multiverseView->model()->rowCount(); i++)
|
|
ui->multiverseView->setFirstColumnSpanned(i, QModelIndex(), true);
|
|
|
|
// model connections
|
|
connect(ui->multiverseView->selectionModel(), &QItemSelectionModel::currentChanged,
|
|
this, &MultiverseWindow::selectionChanged);
|
|
connect(ui->multiverseView, &QTreeView::customContextMenuRequested,
|
|
this, &MultiverseWindow::openContextMenu);
|
|
connect(ui->multiverseView, &QTreeView::doubleClicked,
|
|
this, &MultiverseWindow::openUniverseEditor);
|
|
|
|
// action connections
|
|
connect(ui->actionUACN, &QAction::triggered,
|
|
this, &MultiverseWindow::openUacnEditor);
|
|
connect(ui->actionIPv4, &QAction::toggled,
|
|
node, &QSacnNode::setIPv4);
|
|
connect(ui->actionIPv6, &QAction::toggled,
|
|
node, &QSacnNode::setIPv6);
|
|
connect(ui->actionDiscovery, &QAction::toggled,
|
|
node, [&, node](bool checked) {
|
|
checked ? node->discoveryStart() : node->discoveryStop();
|
|
});
|
|
connect(ui->actionCreate, &QAction::triggered,
|
|
this, [this, node]() {
|
|
auto dialog = new AddUniverseDialog(this, 1);
|
|
connect(dialog, &AddUniverseDialog::submit,
|
|
node, &QSacnNode::create);
|
|
dialog->setWindowTitle(tr("Create"));
|
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
dialog->open();
|
|
});
|
|
connect(ui->actionTerminate, &QAction::triggered,
|
|
this, [&, node]() {
|
|
auto index = ui->multiverseView->currentIndex();
|
|
auto data = index.data(Qt::EditRole);
|
|
if (data.metaType().id() == qMetaTypeId<QSacnUniverse*>())
|
|
{
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
if (univ->isEditable())
|
|
node->terminate(univ->number());
|
|
}
|
|
});
|
|
connect(ui->actionSubscribe, &QAction::triggered,
|
|
this, [this, node]() {
|
|
auto val = QVariant(1);
|
|
auto index = ui->multiverseView->currentIndex();
|
|
if (index.isValid())
|
|
{
|
|
auto actual = sortProxy->mapToSource(index);
|
|
auto item = static_cast<MultiverseItem*>(actual.internalPointer());
|
|
val = item->data(MultiverseModel::Column::Universe, Qt::DisplayRole);
|
|
}
|
|
auto dialog = new AddUniverseDialog(this, val.toInt());
|
|
connect(dialog, &AddUniverseDialog::submit,
|
|
node, &QSacnNode::subscribe);
|
|
dialog->setWindowTitle(tr("Subscribe"));
|
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
dialog->open();
|
|
});
|
|
connect(ui->actionUnsubscribe, &QAction::triggered,
|
|
this, [&, node]() {
|
|
auto index = ui->multiverseView->currentIndex();
|
|
auto data = index.data(Qt::EditRole);
|
|
if (data.metaType().id() == qMetaTypeId<QSacnUniverse*>())
|
|
{
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
if (!univ->isEditable())
|
|
node->unsubscribe(univ->number());
|
|
}
|
|
});
|
|
connect(ui->actionInspect, &QAction::triggered,
|
|
this, [this]() {
|
|
auto selected = ui->multiverseView->currentIndex();
|
|
openUniverseEditor(selected);
|
|
});
|
|
connect(ui->actionUniverseHoldLastLook, &QAction::toggled,
|
|
this, [this](bool state) {
|
|
auto selected = ui->multiverseView->currentIndex();
|
|
auto data = selected.data(Qt::EditRole);
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
univ->setHoldLastLook(state);
|
|
});
|
|
connect(ui->actionAbout, &QAction::triggered,
|
|
this, [this](){
|
|
QString title = tr("About") % " " % qAppName();
|
|
QString text = QApplication::organizationName() % "\n"
|
|
% "https://" % QApplication::organizationDomain() % "\n\n"
|
|
% QApplication::applicationName() % " is a demonstration of the capabilities "
|
|
% "of the sACN implimentation in the OpenLCP protocol library using the "
|
|
% "QsACN platform driver." % "\n\n"
|
|
% "© 2020-2022 Kevin Matz" % "\n\n"
|
|
% "Permission is hereby granted, free of charge, to any person obtaining a copy"
|
|
% "of this software and associated documentation files (the \"Software\"), "
|
|
% "to deal in the Software without restriction, including without limitation "
|
|
% "the rights to use, copy, modify, merge, publish, distribute, sublicense, "
|
|
% "and/or sell copies of the Software, and to permit persons to whom the "
|
|
% "Software is furnished to do so, subject to the following conditions:" % "\n\n"
|
|
% "The above copyright notice and this permission notice shall be included in "
|
|
% "all copies or substantial portions of the Software." % "\n\n"
|
|
% "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR "
|
|
% "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, "
|
|
% "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE "
|
|
% "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER "
|
|
% "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING "
|
|
% "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER "
|
|
% "DEALINGS IN THE SOFTWARE.";
|
|
QMessageBox::about(this, title, text);
|
|
});
|
|
connect(ui->actionAbout_Qt, &QAction::triggered,
|
|
this, [this](){QMessageBox::aboutQt(this);});
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief MultiverseWindow::~MultiverseWindow
|
|
*/
|
|
MultiverseWindow::~MultiverseWindow()
|
|
{
|
|
qDeleteAll(mInspectors);
|
|
delete ui;
|
|
}
|
|
|
|
|
|
void MultiverseWindow::closeEvent(QCloseEvent *)
|
|
{
|
|
// close all universe windows
|
|
foreach (const auto & inspector, mInspectors)
|
|
inspector->close();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief MultiverseWindow::selectionChanged
|
|
* @param selected
|
|
* @param deselected
|
|
*/
|
|
void MultiverseWindow::selectionChanged(const QModelIndex ¤t,
|
|
const QModelIndex &previous)
|
|
{
|
|
Q_UNUSED(previous)
|
|
|
|
ui->actionTerminate->setEnabled(false);
|
|
ui->actionUnsubscribe->setEnabled(false);
|
|
ui->actionInspect->setEnabled(false);
|
|
ui->actionUniverseHoldLastLook->setEnabled(false);
|
|
|
|
auto data = current.data(Qt::EditRole);
|
|
|
|
// Data universes:
|
|
if (data.metaType().id() == qMetaTypeId<QSacnUniverse*>())
|
|
{
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
ui->actionInspect->setEnabled(true);
|
|
ui->actionUniverseHoldLastLook->setChecked(univ->getHoldLastLook());
|
|
if (univ->isEditable())
|
|
ui->actionTerminate->setEnabled(true);
|
|
else
|
|
{
|
|
ui->actionUnsubscribe->setEnabled(true);
|
|
if (univ->hasSources())
|
|
ui->actionUniverseHoldLastLook->setEnabled(true);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief MultiverseWindow::openContextMenu
|
|
* @param pos
|
|
*/
|
|
void MultiverseWindow::openContextMenu(const QPoint &pos)
|
|
{
|
|
auto menu = new QMenu(ui->multiverseView);
|
|
menu->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
|
auto globalpos = ui->multiverseView->mapToGlobal(pos);
|
|
auto data = ui->multiverseView->indexAt(pos).data(Qt::EditRole);
|
|
|
|
if (data.metaType().id() == qMetaTypeId<QSacnUniverse*>())
|
|
{ // Data universes:
|
|
menu->addAction(ui->actionInspect);
|
|
menu->addSeparator();
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
if (univ->isEditable())
|
|
menu->addAction(ui->actionTerminate);
|
|
else
|
|
menu->addAction(ui->actionUnsubscribe);
|
|
menu->popup(globalpos);
|
|
}
|
|
else if (data.metaType().id() ==
|
|
qMetaTypeId<sACN::EXTENDED::DISCOVERY::discoveredUniverse*>())
|
|
{ // Discovery universes:
|
|
menu->addAction(ui->actionSubscribe);
|
|
menu->popup(globalpos);
|
|
}
|
|
else
|
|
// unknow metaType
|
|
menu->deleteLater();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief MultiverseWindow::openUniverseEditor
|
|
* @param index
|
|
*/
|
|
void MultiverseWindow::openUniverseEditor(const QModelIndex &index)
|
|
{
|
|
auto data = index.data(Qt::EditRole);
|
|
|
|
// Data universes:
|
|
if (data.metaType().id() == qMetaTypeId<QSacnUniverse*>())
|
|
{
|
|
auto univ = data.value<QSacnUniverse*>();
|
|
foreach (const auto & inspector, mInspectors)
|
|
if (inspector->universe() == univ)
|
|
return inspector->show();
|
|
auto view = new UniverseWindow(nullptr, univ);
|
|
mInspectors.insert(view);
|
|
connect(view, &QObject::destroyed, this, [this, view](){mInspectors.remove(view);});
|
|
connect(univ, &QObject::destroyed, view, &QMainWindow::close);
|
|
view->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
view->show();
|
|
return;
|
|
}
|
|
|
|
// Discovery universes:
|
|
if (data.metaType().id() ==
|
|
qMetaTypeId<sACN::EXTENDED::DISCOVERY::discoveredUniverse*>())
|
|
{
|
|
auto disc = data.value<sACN::EXTENDED::DISCOVERY::discoveredUniverse*>();
|
|
auto dialog = new AddUniverseDialog(this, disc->universe);
|
|
connect(dialog, &AddUniverseDialog::submit,
|
|
node, &QSacnNode::subscribe);
|
|
dialog->setWindowTitle(tr("Create"));
|
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
dialog->open();
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief MultiverseWindow::openUacnEditor
|
|
*/
|
|
void MultiverseWindow::openUacnEditor()
|
|
{
|
|
auto editor = new LineEditDialog(this, "Name", 63,
|
|
node->userName().c_str(), node->fixedName().c_str());
|
|
connect(editor, &LineEditDialog::submit,
|
|
this, [&](const QString name) {node->assignUserName(name.toStdString());});
|
|
editor->setWindowTitle("User Assigned Component Name");
|
|
editor->setAttribute(Qt::WA_DeleteOnClose);
|
|
editor->open();
|
|
}
|