#include "devicewindow.h" #include "metadatadialog.h" #include "ui_devicewindow.h" #include #include DeviceWindow::DeviceWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::DeviceWindow) , model(new WidgetModel(this)) , sortProxy(new QSortFilterProxyModel(this)) { // build the UI ui->setupUi(this); ui->menubar->setNativeMenuBar(false); // workaround for poor Qt6 support in KDE 5 // setup the model sortProxy->setSourceModel(model); ui->widgetView->setModel(sortProxy); ui->widgetView->setSortingEnabled(true); ui->widgetView->sortByColumn(WidgetModel::PortName, Qt::SortOrder::AscendingOrder); ui->widgetView->setColumnWidth(WidgetModel::Manufacturer, 128); ui->widgetView->setColumnWidth(WidgetModel::Description, 196); ui->widgetView->setColumnWidth(WidgetModel::SerialNumber, 96); // model connections connect(ui->widgetView->selectionModel(), &QItemSelectionModel::currentChanged, this, &DeviceWindow::selectionChanged); connect(model, &WidgetModel::dataChanged, this, [this](){ auto selected = ui->widgetView->currentIndex(); if (selected.isValid() && model->rowCount()) ui->widgetView->selectRow(selected.row()); }); connect(ui->actionOpen, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (selected.isValid()) selected.data(Qt::EditRole).value()->open(); }); connect(ui->actionClose, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (selected.isValid()) selected.data(Qt::EditRole).value()->close(); }); connect(ui->actionDMX, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (!selected.isValid()) return; openDmxWindow(selected); }); connect(ui->actionRDM, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (!selected.isValid()) return; /// \todo Add an action to monitor RDM. }); connect(ui->actionParameter, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (!selected.isValid()) return; MetadataDialog dlg(selected.data(Qt::EditRole).value>().get(), this); dlg.exec(); }); connect(ui->actionUserData, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (!selected.isValid()) return; /// \todo Add an action to manage user configuraion data. }); connect(ui->actionFirmware, &QAction::triggered, this, [this]() { auto selected = ui->widgetView->currentIndex(); if (!selected.isValid()) return; /// \todo Add a notice about firmware support. }); // action connections connect(ui->actionRefreshList, &QAction::triggered, model, &WidgetModel::rescanPorts); connect(ui->actionRefreshList, &QAction::triggered, this, [this](){ ui->widgetView->clearSelection(); selectionChanged(QModelIndex(), QModelIndex()); }); 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 DMX-USB-Pro driver implimentation in the OpenLCP protocol library." % "\n\n" % "© 2023 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);}); } DeviceWindow::~DeviceWindow() { qDeleteAll(inspectors_); delete ui; } void DeviceWindow::selectionChanged(const QModelIndex ¤t, const QModelIndex &previous) { Q_UNUSED(previous) bool valid = false; bool connected = false; bool hasdmx = false; bool hasrdm = false; if (current.isValid()) { auto index = model->index(current.row(), 0, current.parent()); auto wdgt = index.data(Qt::EditRole).value>(); valid = true; connected = wdgt->isConnected(); hasdmx = connected & wdgt->featureDMX(); hasrdm = connected & wdgt->featureRDM(); } ui->menuWidget->setEnabled(valid); ui->actionOpen->setEnabled(!connected); ui->actionClose->setEnabled(connected); ui->actionDMX->setEnabled(hasdmx); ui->actionRDM->setEnabled(hasrdm); ui->actionParameter->setEnabled(connected); ui->actionUserData->setEnabled(connected); ui->actionFirmware->setEnabled(false); } /** * @brief DeviceWindow::openDmxWindow * @param index */ void DeviceWindow::openDmxWindow(const QModelIndex &index) { auto wdgt = index.data(Qt::EditRole).value>(); auto univ = std::static_pointer_cast(wdgt); foreach (const auto & inspector, inspectors_) if (inspector->universe() == univ) return inspector->show(); auto view = new UniverseWindow(nullptr, univ); inspectors_.insert(view); connect(view, &QObject::destroyed, this, [this, view]() { inspectors_.remove(view); }); view->setWindowTitle(QString("%1 '%2'").arg( wdgt->isEditable() ? tr("Editing") : tr("Viewing"), wdgt->portName())); view->setAttribute(Qt::WA_DeleteOnClose, true); view->show(); }