From 24a93a50253b030fef1eedc06c4b7c14490ff7ba Mon Sep 17 00:00:00 2001 From: Srivats P Date: Sun, 13 Mar 2016 19:51:32 +0530 Subject: [PATCH] Device Emulation (contd.): PortsWindow - refactored all device related widgets into a separate DevicesWidget for better modularity. --- client/deviceswidget.cpp | 217 +++++++++++++++++++++++++++++++++++++++ client/deviceswidget.h | 57 ++++++++++ client/deviceswidget.ui | 110 ++++++++++++++++++++ client/ostinato.pro | 3 + client/portswindow.cpp | 181 ++------------------------------ client/portswindow.h | 14 +-- client/portswindow.ui | 138 ++----------------------- 7 files changed, 411 insertions(+), 309 deletions(-) create mode 100644 client/deviceswidget.cpp create mode 100644 client/deviceswidget.h create mode 100644 client/deviceswidget.ui diff --git a/client/deviceswidget.cpp b/client/deviceswidget.cpp new file mode 100644 index 0000000..9aa5bf5 --- /dev/null +++ b/client/deviceswidget.cpp @@ -0,0 +1,217 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#include "deviceswidget.h" + +#include "devicegroupdialog.h" +#include "port.h" +#include "portgrouplist.h" + +#include + +DevicesWidget::DevicesWidget(QWidget *parent) + : QWidget(parent), portGroups_(NULL) +{ + setupUi(this); + deviceGroupList->setVisible(deviceConfig->isChecked()); + deviceList->setVisible(deviceInfo->isChecked()); + refresh->setVisible(deviceInfo->isChecked()); + + deviceGroupList->verticalHeader()->setDefaultSectionSize( + deviceGroupList->verticalHeader()->minimumSectionSize()); + deviceList->verticalHeader()->setDefaultSectionSize( + deviceList->verticalHeader()->minimumSectionSize()); + + // Populate DeviceGroup Context Menu Actions + deviceGroupList->addAction(actionNewDeviceGroup); + deviceGroupList->addAction(actionEditDeviceGroup); + deviceGroupList->addAction(actionDeleteDeviceGroup); + + // DevicesWidget's actions is an aggegate of all sub-widget's actions + addActions(deviceGroupList->actions()); +} + +void DevicesWidget::setPortGroupList(PortGroupList *portGroups) +{ + portGroups_ = portGroups; + + deviceGroupList->setModel(portGroups_->getDeviceGroupModel()); + deviceList->setModel(portGroups_->getDeviceModel()); + + connect(portGroups_->getDeviceGroupModel(), + SIGNAL(rowsInserted(QModelIndex, int, int)), + SLOT(updateDeviceViewActions())); + connect(portGroups_->getDeviceGroupModel(), + SIGNAL(rowsRemoved(QModelIndex, int, int)), + SLOT(updateDeviceViewActions())); + + connect(deviceGroupList->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + SLOT(updateDeviceViewActions())); + connect(deviceGroupList->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + SLOT(updateDeviceViewActions())); + + // FIXME: hardcoding + deviceGroupList->resizeColumnToContents(1); // Vlan Count + deviceGroupList->resizeColumnToContents(2); // Device Count + + // FIXME: hardcoding + deviceList->resizeColumnToContents(1); // Vlan Id(s) + deviceList->resizeColumnToContents(6); // ARP Info + deviceList->resizeColumnToContents(7); // NDP Info + + updateDeviceViewActions(); +} + +void DevicesWidget::setCurrentPortIndex(const QModelIndex &portIndex) +{ + Port *port = NULL; + + if (!portGroups_) + return; + + // XXX: We assume portIndex corresponds to sourceModel, not proxyModel + if (portGroups_->isPort(portIndex)) + port = &portGroups_->port(portIndex); + + portGroups_->getDeviceGroupModel()->setPort(port); + portGroups_->getDeviceModel()->setPort(port); + currentPortIndex_ = portIndex; + + updateDeviceViewActions(); +} + +void DevicesWidget::updateDeviceViewActions() +{ + QItemSelectionModel *devSel = deviceGroupList->selectionModel(); + + if (!portGroups_) + return; + + // For some reason hasSelection() returns true even if selection size is 0 + // so additional check for size introduced + if (devSel->hasSelection() && (devSel->selection().size() > 0)) { + // If more than one non-contiguous ranges selected, + // disable "New" and "Edit" + if (devSel->selection().size() > 1) { + actionNewDeviceGroup->setDisabled(true); + actionEditDeviceGroup->setDisabled(true); + } + else { + actionNewDeviceGroup->setEnabled(true); + + // Enable "Edit" only if the single range has a single row + if (devSel->selection().at(0).height() > 1) + actionEditDeviceGroup->setDisabled(true); + else + actionEditDeviceGroup->setEnabled(true); + } + + // Delete is always enabled as long as we have a selection + actionDeleteDeviceGroup->setEnabled(true); + } + else { + qDebug("No device selection"); + if (portGroups_->isPort(currentPortIndex_)) + actionNewDeviceGroup->setEnabled(true); + else + actionNewDeviceGroup->setDisabled(true); + actionEditDeviceGroup->setDisabled(true); + actionDeleteDeviceGroup->setDisabled(true); + } +} + +// +// DeviceGroup slots +// + +void DevicesWidget::on_deviceInfo_toggled(bool checked) +{ + refresh->setVisible(checked); + deviceGroupList->setHidden(checked); + deviceList->setVisible(checked); +} + +void DevicesWidget::on_actionNewDeviceGroup_triggered() +{ + // In case nothing is selected, insert 1 row at the top + int row = 0, count = 1; + QItemSelection selection = deviceGroupList->selectionModel()->selection(); + + if (!portGroups_) + return; + + // In case we have a single range selected; insert as many rows as + // in the singe selected range before the top of the selected range + if (selection.size() == 1) { + row = selection.at(0).top(); + count = selection.at(0).height(); + } + + portGroups_->getDeviceGroupModel()->insertRows(row, count); +} + +void DevicesWidget::on_actionDeleteDeviceGroup_triggered() +{ + QModelIndex index; + + if (!portGroups_) + return; + + if (deviceGroupList->selectionModel()->hasSelection()) { + while(deviceGroupList->selectionModel()->selectedRows().size()) { + index = deviceGroupList->selectionModel()->selectedRows().at(0); + portGroups_->getDeviceGroupModel()->removeRows(index.row(), 1); + } + } +} + +void DevicesWidget::on_actionEditDeviceGroup_triggered() +{ + QItemSelection selection = deviceGroupList->selectionModel()->selection(); + + // Ensure we have only one range selected which contains only one row + if ((selection.size() == 1) && (selection.at(0).height() == 1)) + on_deviceGroupList_activated(selection.at(0).topLeft()); +} + +void DevicesWidget::on_deviceGroupList_activated(const QModelIndex &index) +{ + if (!index.isValid() || !portGroups_) + return; + + DeviceGroupDialog dgd(&portGroups_->port(currentPortIndex_), index.row()); + dgd.exec(); +} + +void DevicesWidget::on_refresh_clicked() +{ + if (!portGroups_) + return; + + Q_ASSERT(portGroups_->isPort(currentPortIndex_)); + QModelIndex curPortGroup = portGroups_->getPortModel() + ->parent(currentPortIndex_); + Q_ASSERT(curPortGroup.isValid()); + Q_ASSERT(portGroups_->isPortGroup(curPortGroup)); + + portGroups_->portGroup(curPortGroup) + .getDeviceInfo(portGroups_->port(currentPortIndex_).id()); +} diff --git a/client/deviceswidget.h b/client/deviceswidget.h new file mode 100644 index 0000000..fb15ef6 --- /dev/null +++ b/client/deviceswidget.h @@ -0,0 +1,57 @@ +/* +Copyright (C) 2016 Srivats P. + +This file is part of "Ostinato" + +This is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +#ifndef _DEVICES_WIDGET_H +#define _DEVICES_WIDGET_H + +#include "ui_deviceswidget.h" +#include + +class PortGroupList; + +class DevicesWidget: public QWidget, private Ui::DevicesWidget +{ + Q_OBJECT + +public: + DevicesWidget(QWidget *parent = NULL); + void setPortGroupList(PortGroupList *portGroups); + +public slots: + void setCurrentPortIndex(const QModelIndex &portIndex); + +private slots: + void updateDeviceViewActions(); + + void on_deviceInfo_toggled(bool checked); + + void on_actionNewDeviceGroup_triggered(); + void on_actionDeleteDeviceGroup_triggered(); + void on_actionEditDeviceGroup_triggered(); + void on_deviceGroupList_activated(const QModelIndex &index); + + void on_refresh_clicked(); + +private: + PortGroupList *portGroups_; + QModelIndex currentPortIndex_; +}; + +#endif + diff --git a/client/deviceswidget.ui b/client/deviceswidget.ui new file mode 100644 index 0000000..7753e8f --- /dev/null +++ b/client/deviceswidget.ui @@ -0,0 +1,110 @@ + + DevicesWidget + + + + 0 + 0 + 675 + 328 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Configuration + + + true + + + + + + + Information + + + + + + + Qt::Horizontal + + + + 131 + 23 + + + + + + + + Refresh + + + + + + + + + Qt::ActionsContextMenu + + + QFrame::StyledPanel + + + 1 + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectRows + + + + + + + + + + New Device Group + + + + + Delete Device Group + + + + + Edit Device Group + + + + + + diff --git a/client/ostinato.pro b/client/ostinato.pro index 228f818..7c20029 100644 --- a/client/ostinato.pro +++ b/client/ostinato.pro @@ -36,6 +36,7 @@ HEADERS += \ devicegroupdialog.h \ devicegroupmodel.h \ devicemodel.h \ + deviceswidget.h \ dumpview.h \ hexlineedit.h \ mainwindow.h \ @@ -61,6 +62,7 @@ HEADERS += \ FORMS += \ about.ui \ devicegroupdialog.ui \ + deviceswidget.ui \ mainwindow.ui \ portconfigdialog.ui \ portstatsfilter.ui \ @@ -74,6 +76,7 @@ SOURCES += \ devicegroupdialog.cpp \ devicegroupmodel.cpp \ devicemodel.cpp \ + deviceswidget.cpp \ dumpview.cpp \ stream.cpp \ hexlineedit.cpp \ diff --git a/client/portswindow.cpp b/client/portswindow.cpp index 4d21367..5d62225 100644 --- a/client/portswindow.cpp +++ b/client/portswindow.cpp @@ -20,7 +20,7 @@ along with this program. If not, see #include "portswindow.h" #include "abstractfileformat.h" -#include "devicegroupdialog.h" +#include "deviceswidget.h" #include "portconfigdialog.h" #include "settings.h" #include "streamconfigdialog.h" @@ -45,7 +45,7 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) plm = pgl; setupUi(this); - refresh->setVisible(deviceInfo->isChecked()); + devicesWidget->setPortGroupList(plm); tvPortList->header()->hide(); @@ -53,10 +53,6 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) tvStreamList->verticalHeader()->setDefaultSectionSize( tvStreamList->verticalHeader()->minimumSectionSize()); - deviceGroupList->verticalHeader()->setDefaultSectionSize( - deviceGroupList->verticalHeader()->minimumSectionSize()); - deviceList->verticalHeader()->setDefaultSectionSize( - deviceList->verticalHeader()->minimumSectionSize()); // Populate PortList Context Menu Actions tvPortList->addAction(actionNew_Port_Group); @@ -67,7 +63,7 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) tvPortList->addAction(actionExclusive_Control); tvPortList->addAction(actionPort_Configuration); - // Populate StramList Context Menu Actions + // Populate StreamList Context Menu Actions tvStreamList->addAction(actionNew_Stream); tvStreamList->addAction(actionEdit_Stream); tvStreamList->addAction(actionDuplicate_Stream); @@ -80,12 +76,7 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) tvStreamList->addAction(actionOpen_Streams); tvStreamList->addAction(actionSave_Streams); - // Populate DeviceGroup Context Menu Actions - deviceGroupList->addAction(actionNewDeviceGroup); - deviceGroupList->addAction(actionEditDeviceGroup); - deviceGroupList->addAction(actionDeleteDeviceGroup); - - // PortList, StreamList, DeviceGroupList actions combined + // PortList, StreamList, DeviceWidget actions combined // make this window's actions addActions(tvPortList->actions()); sep = new QAction(this); @@ -95,11 +86,9 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) sep = new QAction(this); sep->setSeparator(true); addAction(sep); - addActions(deviceGroupList->actions()); + addActions(devicesWidget->actions()); tvStreamList->setModel(plm->getStreamModel()); - deviceGroupList->setModel(plm->getDeviceGroupModel()); - deviceList->setModel(plm->getDeviceModel()); // XXX: It would be ideal if we only needed to do the below to // get the proxy model to do its magic. However, the QModelIndex @@ -130,6 +119,9 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(when_portView_currentChanged(const QModelIndex&, const QModelIndex&))); + connect(this, + SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)), + devicesWidget, SLOT(setCurrentPortIndex(const QModelIndex&))); connect(plm->getStreamModel(), SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(updateStreamViewActions())); @@ -146,34 +138,10 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) tvStreamList->resizeColumnToContents(StreamModel::StreamIcon); tvStreamList->resizeColumnToContents(StreamModel::StreamStatus); - connect(plm->getDeviceGroupModel(), - SIGNAL(rowsInserted(QModelIndex, int, int)), - SLOT(updateDeviceViewActions())); - connect(plm->getDeviceGroupModel(), - SIGNAL(rowsRemoved(QModelIndex, int, int)), - SLOT(updateDeviceViewActions())); - - connect(deviceGroupList->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - SLOT(updateDeviceViewActions())); - connect(deviceGroupList->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - SLOT(updateDeviceViewActions())); - - // FIXME: hardcoding - deviceGroupList->resizeColumnToContents(1); // Vlan Count - deviceGroupList->resizeColumnToContents(2); // Device Count - - // FIXME: hardcoding - deviceList->resizeColumnToContents(1); // Vlan Id(s) - deviceList->resizeColumnToContents(6); // ARP Info - deviceList->resizeColumnToContents(7); // NDP Info - // Initially we don't have any ports/streams/devices // - so send signal triggers when_portView_currentChanged(QModelIndex(), QModelIndex()); updateStreamViewActions(); - updateDeviceViewActions(); connect(plm->getStreamModel(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), @@ -246,7 +214,6 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex, { QModelIndex current = currentIndex; QModelIndex previous = previousIndex; - Port *port = NULL; if (proxyPortModel) { current = proxyPortModel->mapToSource(current); @@ -256,15 +223,9 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex, plm->getStreamModel()->setCurrentPortIndex(current); updatePortViewActions(currentIndex); updateStreamViewActions(); - updateDeviceViewActions(); qDebug("In %s", __FUNCTION__); - if (plm->isPort(current)) - port = &(plm->port(current)); - plm->getDeviceGroupModel()->setPort(port); - plm->getDeviceModel()->setPort(port); - if (previous.isValid() && plm->isPort(previous)) { disconnect(&(plm->port(previous)), SIGNAL(portRateChanged(int, int)), @@ -290,6 +251,8 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& currentIndex, SLOT(updatePortRates())); } } + + emit currentPortChanged(current, previous); } void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft, @@ -418,51 +381,6 @@ void PortsWindow::updateStreamViewActions() actionSave_Streams->setEnabled(tvStreamList->model()->rowCount() > 0); } -void PortsWindow::updateDeviceViewActions() -{ - QModelIndex current = tvPortList->currentIndex(); - QItemSelectionModel *devSel = deviceGroupList->selectionModel(); - - if (proxyPortModel) - current = proxyPortModel->mapToSource(current); - - // For some reason hasSelection() returns true even if selection size is 0 - // so additional check for size introduced - if (devSel->hasSelection() && (devSel->selection().size() > 0)) - { - // If more than one non-contiguous ranges selected, - // disable "New" and "Edit" - if (devSel->selection().size() > 1) - { - actionNewDeviceGroup->setDisabled(true); - actionEditDeviceGroup->setDisabled(true); - } - else - { - actionNewDeviceGroup->setEnabled(true); - - // Enable "Edit" only if the single range has a single row - if (devSel->selection().at(0).height() > 1) - actionEditDeviceGroup->setDisabled(true); - else - actionEditDeviceGroup->setEnabled(true); - } - - // Delete is always enabled as long as we have a selection - actionDeleteDeviceGroup->setEnabled(true); - } - else - { - qDebug("No device selection"); - if (plm->isPort(current)) - actionNewDeviceGroup->setEnabled(true); - else - actionNewDeviceGroup->setDisabled(true); - actionEditDeviceGroup->setDisabled(true); - actionDeleteDeviceGroup->setDisabled(true); - } -} - void PortsWindow::updatePortViewActions(const QModelIndex& currentIndex) { QModelIndex current = currentIndex; @@ -897,83 +815,4 @@ _exit: return; } -// -// DeviceGroup slots -// -void PortsWindow::on_deviceInfo_toggled(bool checked) -{ - refresh->setVisible(checked); - devicesWidget->setCurrentIndex(checked ? 1 : 0); -} - -void PortsWindow::on_actionNewDeviceGroup_triggered() -{ - // In case nothing is selected, insert 1 row at the top - int row = 0, count = 1; - QItemSelection selection = deviceGroupList->selectionModel()->selection(); - - // In case we have a single range selected; insert as many rows as - // in the singe selected range before the top of the selected range - if (selection.size() == 1) - { - row = selection.at(0).top(); - count = selection.at(0).height(); - } - - plm->getDeviceGroupModel()->insertRows(row, count); -} - -void PortsWindow::on_actionDeleteDeviceGroup_triggered() -{ - QModelIndex index; - - if (deviceGroupList->selectionModel()->hasSelection()) - { - while(deviceGroupList->selectionModel()->selectedRows().size()) - { - index = deviceGroupList->selectionModel()->selectedRows().at(0); - plm->getDeviceGroupModel()->removeRows(index.row(), 1); - } - } -} - -void PortsWindow::on_actionEditDeviceGroup_triggered() -{ - QItemSelection selection = deviceGroupList->selectionModel()->selection(); - - // Ensure we have only one range selected which contains only one row - if ((selection.size() == 1) && (selection.at(0).height() == 1)) - on_deviceGroupList_activated(selection.at(0).topLeft()); -} - -void PortsWindow::on_deviceGroupList_activated(const QModelIndex &index) -{ - if (!index.isValid()) - return; - - QModelIndex currentPort = tvPortList->currentIndex(); - if (proxyPortModel) - currentPort = proxyPortModel->mapToSource(currentPort); - - DeviceGroupDialog dgd(&plm->port(currentPort), index.row(), this); - dgd.exec(); -} - -void PortsWindow::on_refresh_clicked() -{ - QModelIndex curPort; - QModelIndex curPortGroup; - - curPort = tvPortList->selectionModel()->currentIndex(); - if (proxyPortModel) - curPort = proxyPortModel->mapToSource(curPort); - Q_ASSERT(curPort.isValid()); - Q_ASSERT(plm->isPort(curPort)); - - curPortGroup = plm->getPortModel()->parent(curPort); - Q_ASSERT(curPortGroup.isValid()); - Q_ASSERT(plm->isPortGroup(curPortGroup)); - - plm->portGroup(curPortGroup).getDeviceInfo(plm->port(curPort).id()); -} diff --git a/client/portswindow.h b/client/portswindow.h index a6d3e62..9d8e6ef 100644 --- a/client/portswindow.h +++ b/client/portswindow.h @@ -39,6 +39,10 @@ public: PortsWindow(PortGroupList *pgl, QWidget *parent = 0); ~PortsWindow(); +signals: + void currentPortChanged(const QModelIndex ¤t, + const QModelIndex &previous); + private: QString lastNewPortGroup; QAbstractItemDelegate *delegate; @@ -50,7 +54,6 @@ public slots: private slots: void updatePortViewActions(const QModelIndex& currentIndex); void updateStreamViewActions(); - void updateDeviceViewActions(); void on_averagePacketsPerSec_editingFinished(); void on_averageBitsPerSec_editingFinished(); @@ -81,15 +84,6 @@ private slots: void on_actionSave_Streams_triggered(); void streamModelDataChanged(); - - void on_deviceInfo_toggled(bool checked); - - void on_actionNewDeviceGroup_triggered(); - void on_actionDeleteDeviceGroup_triggered(); - void on_actionEditDeviceGroup_triggered(); - void on_deviceGroupList_activated(const QModelIndex &index); - - void on_refresh_clicked(); }; #endif diff --git a/client/portswindow.ui b/client/portswindow.ui index 4d61998..7835329 100644 --- a/client/portswindow.ui +++ b/client/portswindow.ui @@ -5,7 +5,7 @@ 0 0 - 710 + 663 352 @@ -178,118 +178,7 @@ - - - - - Configuration - - - true - - - - - - - Information - - - - - - - Qt::Horizontal - - - - 131 - 23 - - - - - - - - Refresh - - - - - - - - - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 1 - - - - Qt::ActionsContextMenu - - - QFrame::StyledPanel - - - 1 - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::SelectRows - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - + @@ -403,22 +292,15 @@ Duplicate Stream - - - New Device Group - - - - - Delete Device Group - - - - - Edit Device Group - - + + + DevicesWidget + QWidget +
deviceswidget.h
+ 1 +
+