1
0
Fork 0
OpenLCP/example/sACN Explorer/multiversewindow.cpp

324 lines
12 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->actionMergeModeHTP, &QAction::toggled,
this, [this](bool state) {
auto selected = ui->multiverseView->currentIndex();
auto data = selected.data(Qt::EditRole);
auto univ = data.value<QSacnUniverse*>();
if (state)
univ->setMergeMode(sACN::UniverseArbitrator::MERGE_HTP);
else
univ->setMergeMode(sACN::UniverseArbitrator::MERGE_LTP);
});
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 &current,
const QModelIndex &previous)
{
Q_UNUSED(previous)
ui->actionTerminate->setEnabled(false);
ui->actionUnsubscribe->setEnabled(false);
ui->actionInspect->setEnabled(false);
ui->actionUniverseHoldLastLook->setEnabled(false);
ui->menuMerge_Mode->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());
switch (univ->getMergeMode()){
case sACN::UniverseArbitrator::MERGE_HTP:
ui->actionMergeModeHTP->setChecked(true);
break;
case sACN::UniverseArbitrator::MERGE_LTP:
ui->actionMergeModeLTP->setChecked(true);
break;
default:
break;
}
if (univ->isEditable())
ui->actionTerminate->setEnabled(true);
else
{
ui->actionUnsubscribe->setEnabled(true);
if (univ->hasSources())
{
ui->actionUniverseHoldLastLook->setEnabled(true);
ui->menuMerge_Mode->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();
}