2016-03-13 09:21:32 -05:00
|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "deviceswidget.h"
|
|
|
|
|
2020-03-14 10:43:24 -05:00
|
|
|
#include "clipboardhelper.h"
|
2016-03-13 09:21:32 -05:00
|
|
|
#include "devicegroupdialog.h"
|
|
|
|
#include "port.h"
|
|
|
|
#include "portgrouplist.h"
|
|
|
|
|
|
|
|
#include <QHeaderView>
|
2016-03-14 11:09:01 -05:00
|
|
|
#include <QKeyEvent>
|
2016-03-13 09:21:32 -05:00
|
|
|
|
2020-03-14 10:43:24 -05:00
|
|
|
extern ClipboardHelper *clipboardHelper;
|
|
|
|
|
2016-03-13 09:21:32 -05:00
|
|
|
DevicesWidget::DevicesWidget(QWidget *parent)
|
|
|
|
: QWidget(parent), portGroups_(NULL)
|
|
|
|
{
|
|
|
|
setupUi(this);
|
|
|
|
deviceGroupList->setVisible(deviceConfig->isChecked());
|
|
|
|
deviceList->setVisible(deviceInfo->isChecked());
|
2019-01-21 07:48:36 -06:00
|
|
|
setDeviceInfoButtonsVisible(deviceInfo->isChecked());
|
2016-03-14 09:41:40 -05:00
|
|
|
deviceDetail->hide();
|
2016-03-13 09:21:32 -05:00
|
|
|
|
|
|
|
deviceGroupList->verticalHeader()->setDefaultSectionSize(
|
|
|
|
deviceGroupList->verticalHeader()->minimumSectionSize());
|
|
|
|
deviceList->verticalHeader()->setDefaultSectionSize(
|
|
|
|
deviceList->verticalHeader()->minimumSectionSize());
|
2016-03-14 09:41:40 -05:00
|
|
|
deviceDetail->verticalHeader()->setDefaultSectionSize(
|
|
|
|
deviceDetail->verticalHeader()->minimumSectionSize());
|
2016-03-13 09:21:32 -05:00
|
|
|
|
|
|
|
// 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());
|
2020-03-14 10:43:24 -05:00
|
|
|
|
|
|
|
// Add the clipboard actions to the context menu of deviceGroupList
|
|
|
|
// but not to DeviceWidget's actions since they are already available
|
|
|
|
// in the global Edit Menu
|
|
|
|
QAction *sep = new QAction("Clipboard", this);
|
|
|
|
sep->setSeparator(true);
|
|
|
|
deviceGroupList->addAction(sep);
|
|
|
|
deviceGroupList->addActions(clipboardHelper->actions());
|
2016-03-13 09:21:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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()));
|
|
|
|
|
2016-03-14 09:41:40 -05:00
|
|
|
connect(deviceList->selectionModel(),
|
|
|
|
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
|
|
|
SLOT(when_deviceList_currentChanged(const QModelIndex&)));
|
|
|
|
|
2016-03-13 09:21:32 -05:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2016-03-14 11:09:01 -05:00
|
|
|
void DevicesWidget::keyPressEvent(QKeyEvent *event)
|
|
|
|
{
|
|
|
|
if (event->key() == Qt::Key_Escape) {
|
|
|
|
deviceDetail->hide();
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
|
2016-03-13 09:21:32 -05:00
|
|
|
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)
|
|
|
|
{
|
2019-01-21 07:48:36 -06:00
|
|
|
setDeviceInfoButtonsVisible(checked);
|
2016-03-13 09:21:32 -05:00
|
|
|
deviceGroupList->setHidden(checked);
|
|
|
|
deviceList->setVisible(checked);
|
2016-03-14 09:41:40 -05:00
|
|
|
deviceDetail->hide();
|
2016-03-13 09:21:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DevicesWidget::on_actionNewDeviceGroup_triggered()
|
|
|
|
{
|
|
|
|
if (!portGroups_)
|
|
|
|
return;
|
|
|
|
|
2017-09-14 10:31:56 -05:00
|
|
|
// In case nothing is selected, insert 1 row at the end
|
|
|
|
int row = portGroups_->getDeviceGroupModel()->rowCount(), count = 1;
|
|
|
|
QItemSelection selection = deviceGroupList->selectionModel()->selection();
|
|
|
|
|
2016-03-13 09:21:32 -05:00
|
|
|
// 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));
|
|
|
|
|
2016-03-14 11:09:01 -05:00
|
|
|
deviceDetail->hide();
|
2016-03-13 09:21:32 -05:00
|
|
|
portGroups_->portGroup(curPortGroup)
|
|
|
|
.getDeviceInfo(portGroups_->port(currentPortIndex_).id());
|
|
|
|
}
|
2016-03-14 09:41:40 -05:00
|
|
|
|
2019-01-21 07:48:36 -06:00
|
|
|
void DevicesWidget::on_resolveNeighbors_clicked()
|
|
|
|
{
|
|
|
|
if (!portGroups_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Q_ASSERT(portGroups_->isPort(currentPortIndex_));
|
|
|
|
QModelIndex curPortGroup = portGroups_->getPortModel()
|
|
|
|
->parent(currentPortIndex_);
|
|
|
|
Q_ASSERT(curPortGroup.isValid());
|
|
|
|
Q_ASSERT(portGroups_->isPortGroup(curPortGroup));
|
|
|
|
|
|
|
|
deviceDetail->hide();
|
|
|
|
QList<uint> portList({portGroups_->port(currentPortIndex_).id()});
|
|
|
|
portGroups_->portGroup(curPortGroup).resolveDeviceNeighbors(&portList);
|
|
|
|
portGroups_->portGroup(curPortGroup).getDeviceInfo(portList.at(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DevicesWidget::on_clearNeighbors_clicked()
|
|
|
|
{
|
|
|
|
if (!portGroups_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Q_ASSERT(portGroups_->isPort(currentPortIndex_));
|
|
|
|
QModelIndex curPortGroup = portGroups_->getPortModel()
|
|
|
|
->parent(currentPortIndex_);
|
|
|
|
Q_ASSERT(curPortGroup.isValid());
|
|
|
|
Q_ASSERT(portGroups_->isPortGroup(curPortGroup));
|
|
|
|
|
|
|
|
deviceDetail->hide();
|
|
|
|
QList<uint> portList({portGroups_->port(currentPortIndex_).id()});
|
|
|
|
portGroups_->portGroup(curPortGroup).clearDeviceNeighbors(&portList);
|
|
|
|
portGroups_->portGroup(curPortGroup).getDeviceInfo(portList.at(0));
|
|
|
|
}
|
|
|
|
|
2016-03-14 09:41:40 -05:00
|
|
|
void DevicesWidget::when_deviceList_currentChanged(const QModelIndex &index)
|
|
|
|
{
|
|
|
|
if (!index.isValid() || !portGroups_)
|
|
|
|
return;
|
|
|
|
|
|
|
|
QAbstractItemModel *detailModel = portGroups_->getDeviceModel()
|
|
|
|
->detailModel(index);
|
|
|
|
|
|
|
|
deviceDetail->setModel(detailModel);
|
|
|
|
deviceDetail->setVisible(detailModel != NULL);
|
|
|
|
}
|
2019-01-21 07:48:36 -06:00
|
|
|
|
|
|
|
void DevicesWidget::setDeviceInfoButtonsVisible(bool show)
|
|
|
|
{
|
|
|
|
refresh->setVisible(show);
|
|
|
|
arpNdpLabel->setVisible(show);
|
|
|
|
resolveNeighbors->setVisible(show);
|
|
|
|
clearNeighbors->setVisible(show);
|
|
|
|
}
|